From 82df396b220426931713b67531c53fbce7706d13 Mon Sep 17 00:00:00 2001 From: "SND\\kernelnet_cp" Date: Tue, 31 Jul 2012 15:53:49 +0000 Subject: [PATCH] [0.2.x] refactored : memory management API git-svn-id: https://pykd.svn.codeplex.com/svn@78411 9b283d60-5439-405e-af05-b73fd8c4d996 --- pykd/dbgengine.h | 3 + pykd/dbgmem.cpp | 253 ++++++++++++++++++++++++++++++++++++++++++++ pykd/dbgmem.h | 26 +++++ pykd/pymod.cpp | 61 ++++++++--- pykd/win/dbgeng.cpp | 16 +++ pykd/win/memory.cpp | 102 +++++++++++++++++- 6 files changed, 443 insertions(+), 18 deletions(-) diff --git a/pykd/dbgengine.h b/pykd/dbgengine.h index e7128bb..82b5ecf 100644 --- a/pykd/dbgengine.h +++ b/pykd/dbgengine.h @@ -9,6 +9,9 @@ void terminateProcess( ULONG processId = -1); void debugGo(); +// system properties +ULONG ptrSize(); + //manage debug module ULONG64 findModuleBase( const std::string &moduleName ); ULONG64 findModuleBase( ULONG64 offset ); diff --git a/pykd/dbgmem.cpp b/pykd/dbgmem.cpp index ee9a687..b253639 100644 --- a/pykd/dbgmem.cpp +++ b/pykd/dbgmem.cpp @@ -5,6 +5,131 @@ namespace pykd { ///////////////////////////////////////////////////////////////////////////////////// +bool compareMemory( ULONG64 addr1, ULONG64 addr2, ULONG length, bool phyAddr = FALSE ) +{ + bool result = false; + + addr1 = addr64( addr1 ); + addr2 = addr64( addr2 ); + + std::vector m1(length); + std::vector m2(length); + + readMemory( addr1, &m1[0], length, phyAddr ); + readMemory( addr2, &m2[0], length, phyAddr ); + + return std::equal( m1.begin(), m1.end(), m2.begin() ); +} + +///////////////////////////////////////////////////////////////////////////////////// + +ULONG64 ptrByte( ULONG64 offset ) +{ + unsigned char val = 0; + + readMemory( offset, &val, sizeof(val), false ); + + return val; +} + +///////////////////////////////////////////////////////////////////////////////////// + +ULONG64 ptrWord( ULONG64 offset ) +{ + unsigned short val = 0; + + readMemory( offset, &val, sizeof(val), false ); + + return val; +} + +///////////////////////////////////////////////////////////////////////////////////// + +ULONG64 ptrDWord( ULONG64 offset ) +{ + unsigned long val = 0; + + readMemory( offset, &val, sizeof(val), false ); + + return val; +} + +///////////////////////////////////////////////////////////////////////////////////// + +ULONG64 ptrQWord( ULONG64 offset ) +{ + unsigned __int64 val = 0; + + readMemory( offset, &val, sizeof(val), false ); + + return val; +} + +///////////////////////////////////////////////////////////////////////////////////// + +ULONG64 ptrMWord( ULONG64 offset ) +{ + return ptrSize() == 8 ? ptrQWord( offset ) : ptrDWord(offset ); +} + +ULONG64 ptrPtr( ULONG64 offset ) +{ + return ptrMWord( offset ); +} + +///////////////////////////////////////////////////////////////////////////////////// + +LONG64 ptrSignByte( ULONG64 offset ) +{ + char val = 0; + + readMemory( offset, &val, sizeof(val), false ); + + return val; +} + +///////////////////////////////////////////////////////////////////////////////////// + +LONG64 ptrSignWord( ULONG64 offset ) +{ + short val = 0; + + readMemory( offset, &val, sizeof(val), false ); + + return val; +} + +///////////////////////////////////////////////////////////////////////////////////// + +LONG64 ptrSignDWord( ULONG64 offset ) +{ + long val = 0; + + readMemory( offset, &val, sizeof(val), false ); + + return val; +} + +///////////////////////////////////////////////////////////////////////////////////// + +LONG64 ptrSignQWord( ULONG64 offset ) +{ + __int64 val = 0; + + readMemory( offset, &val, sizeof(val), false ); + + return val; +} + +///////////////////////////////////////////////////////////////////////////////////// + +LONG64 ptrSignMWord( ULONG64 offset ) +{ + return ptrSize() == 8 ? ptrSignQWord( offset ) : ptrSignDWord(offset); +} + +///////////////////////////////////////////////////////////////////////////////////// + template struct PyListType { @@ -92,6 +217,134 @@ python::list loadSignQWords( ULONG64 offset, ULONG count, bool phyAddr ) ///////////////////////////////////////////////////////////////////////////////////// +std::string loadChars( ULONG64 offset, ULONG number, bool phyAddr ) +{ + std::vector buffer(number); + + ULONG bufferSize = (ULONG)( sizeof(std::vector::value_type)*buffer.size() ); + + if (number) + readMemory( offset, &buffer[0], bufferSize, phyAddr ); + + return std::string( buffer.begin(), buffer.end() ); +} + +///////////////////////////////////////////////////////////////////////////////////// + +std::wstring loadWChars( ULONG64 offset, ULONG number, bool phyAddr ) +{ + std::vector buffer(number); + + ULONG bufferSize = (ULONG)( sizeof(std::vector::value_type)*buffer.size() ); + + if (number) + readMemory( offset, &buffer[0], bufferSize, phyAddr ); + + return std::wstring( buffer.begin(), buffer.end() ); +} + +///////////////////////////////////////////////////////////////////////////////////// + +python::list loadPtrList( ULONG64 offset ) +{ + offset = addr64( offset ); + + ULONG64 entryAddress = 0; + + python::list lst; + + for( entryAddress = ptrPtr( offset ); entryAddress != offset && entryAddress != 0; entryAddress = ptrPtr( entryAddress ) ) + lst.append( entryAddress ); + + return lst; +} + +///////////////////////////////////////////////////////////////////////////////////// + +python::list loadPtrArray( ULONG64 offset, ULONG number ) +{ + offset = addr64( offset ); + + python::list lst; + + for ( ULONG i = 0; i < number; ++i ) + lst.append( ptrPtr( offset + i*ptrSize() ) ); + + return lst; +} + +///////////////////////////////////////////////////////////////////////////////////// + +std::wstring loadUnicodeStr( ULONG64 offset ) +{ + USHORT length; + USHORT maximumLength; + ULONG64 buffer = 0; + ULONG ptrsize = ptrSize(); + + offset = addr64( offset ); + + readMemory( offset, &length, sizeof( length ) ); + + if ( length == 0 ) + return L""; + + offset += sizeof( length ); + + readMemory( offset, &maximumLength, sizeof( maximumLength ) ); + + offset += sizeof( maximumLength ); + + offset += offset % ptrsize ? ( ptrsize - offset % ptrsize ) : 0 ; // выравнивание + + buffer = addr64( ptrPtr( offset ) ); + + offset += ptrsize; + + std::vector str(length / 2); + + readMemory( buffer, &str[0], length ); + + return std::wstring (&str[0], length/2); +} + +///////////////////////////////////////////////////////////////////////////////////// + +std::string loadAnsiStr( ULONG64 offset ) +{ + USHORT length; + USHORT maximumLength; + ULONG64 buffer = 0; + ULONG ptrsize = ptrSize(); + + offset = addr64( offset ); + + readMemory( offset, &length, sizeof( length ) ); + + if ( length == 0 ) + return ""; + + offset += sizeof( length ); + + readMemory( offset, &maximumLength, sizeof( maximumLength ) ); + + offset += sizeof( maximumLength ); + + offset += offset % ptrsize ? ( ptrsize - offset % ptrsize ) : 0 ; // выравнивание + + buffer = addr64( ptrPtr( offset ) ); + + offset += ptrsize; + + std::vector str(length); + + readMemory( buffer, &str[0], length ); + + return std::string (&str[0], length); +} + +///////////////////////////////////////////////////////////////////////////////////// + }; // end pykd namespace diff --git a/pykd/dbgmem.h b/pykd/dbgmem.h index 2f9c3c2..868bbaf 100644 --- a/pykd/dbgmem.h +++ b/pykd/dbgmem.h @@ -4,6 +4,21 @@ namespace pykd { /////////////////////////////////////////////////////////////////////////////////// +bool isVaValid( ULONG64 addr ); +bool compareMemory( ULONG64 addr1, ULONG64 addr2, ULONG length, bool phyAddr = FALSE ); + +ULONG64 ptrByte( ULONG64 offset ); +ULONG64 ptrWord( ULONG64 offset ); +ULONG64 ptrDWord( ULONG64 offset ); +ULONG64 ptrQWord( ULONG64 offset ); +ULONG64 ptrMWord( ULONG64 offset ); +LONG64 ptrSignByte( ULONG64 offset ); +LONG64 ptrSignWord( ULONG64 offset ); +LONG64 ptrSignDWord( ULONG64 offset ); +LONG64 ptrSignQWord( ULONG64 offset ); +LONG64 ptrSignMWord( ULONG64 offset ); +ULONG64 ptrPtr( ULONG64 offset ); + python::list loadBytes( ULONG64 offset, ULONG count, bool phyAddr = FALSE ); python::list loadWords( ULONG64 offset, ULONG count, bool phyAddr = FALSE ); python::list loadDWords( ULONG64 offset, ULONG count, bool phyAddr = FALSE ); @@ -13,6 +28,17 @@ python::list loadSignWords( ULONG64 offset, ULONG count, bool phyAddr = FALSE ); python::list loadSignDWords( ULONG64 offset, ULONG count, bool phyAddr = FALSE ); python::list loadSignQWords( ULONG64 offset, ULONG count, bool phyAddr = FALSE ); +python::list loadPtrList( ULONG64 offset ); +python::list loadPtrArray( ULONG64 offset, ULONG number ); + +std::string loadChars( ULONG64 offset, ULONG number, bool phyAddr = FALSE ); +std::wstring loadWChars( ULONG64 offset, ULONG number, bool phyAddr = FALSE ); + +std::string loadCStr( ULONG64 offset ); +std::wstring loadWStr( ULONG64 offset ); + +std::string loadAnsiStr( ULONG64 offset ); +std::wstring loadUnicodeStr( ULONG64 offset ); /////////////////////////////////////////////////////////////////////////////////// diff --git a/pykd/pymod.cpp b/pykd/pymod.cpp index b3a232a..4fc11f4 100644 --- a/pykd/pymod.cpp +++ b/pykd/pymod.cpp @@ -37,6 +37,7 @@ BOOST_PYTHON_FUNCTION_OVERLOADS( loadSignBytes_, loadSignBytes, 2, 3 ); BOOST_PYTHON_FUNCTION_OVERLOADS( loadSignWords_, loadSignWords, 2, 3 ); BOOST_PYTHON_FUNCTION_OVERLOADS( loadSignDWords_, loadSignDWords, 2, 3 ); BOOST_PYTHON_FUNCTION_OVERLOADS( loadSignQWords_, loadSignQWords, 2, 3 ); +BOOST_PYTHON_FUNCTION_OVERLOADS( compareMemory_, compareMemory, 3, 4 ); BOOST_PYTHON_MODULE( pykd ) @@ -56,6 +57,34 @@ BOOST_PYTHON_MODULE( pykd ) "Go debugging" ); // Manage target memory access + python::def( "isValid", &isVaValid, + "Check if the virtual address is valid" ); + python::def( "compareMemory", &compareMemory, compareMemory_( python::args( "offset1", "offset2", "length", "phyAddr" ), + "Compare two memory buffers by virtual or physical addresses" ) ); + + python::def( "ptrByte", &ptrByte, + "Read an unsigned 1-byte integer from the target memory" ); + python::def( "ptrWord", &ptrWord, + "Read an unsigned 2-byte integer from the target memory" ); + python::def( "ptrDWord", (ULONG64(*)(ULONG64))&ptrDWord, + "Read an unsigned 4-byte integer from the target memory" ); + python::def( "ptrQWord", (ULONG64(*)(ULONG64))&ptrQWord, + "Read an unsigned 8-byte integer from the target memory" ); + python::def( "ptrMWord", (ULONG64(*)(ULONG64))&ptrMWord, + "Read an unsigned mashine's word wide integer from the target memory" ); + python::def( "ptrSignByte", &ptrSignByte, + "Read an signed 1-byte integer from the target memory" ); + python::def( "ptrSignWord", &ptrSignWord, + "Read an signed 2-byte integer from the target memory" ); + python::def( "ptrSignDWord", &ptrSignDWord, + "Read an signed 4-byte integer from the target memory" ); + python::def( "ptrSignQWord", &ptrSignQWord, + "Read an signed 8-byte integer from the target memory" ); + python::def( "ptrSignMWord", &ptrSignMWord, + "Read an signed mashine's word wide integer from the target memory" ); + python::def( "ptrPtr", (ULONG64(*)(ULONG64))&ptrPtr, + "Read an pointer value from the target memory" ); + python::def( "loadBytes", &loadBytes, loadBytes_( python::args( "offset", "count", "phyAddr" ), "Read the block of the target's memory and return it as liat of unsigned bytes" ) ); python::def( "loadWords", &loadWords, loadWords_( python::args( "offset", "count", "phyAddr" ), @@ -72,22 +101,22 @@ BOOST_PYTHON_MODULE( pykd ) "Read the block of the target's memory and return it as list of signed longs" ) ); python::def( "loadSignQWords", &loadSignQWords, loadSignQWords_( python::args( "offset", "count", "phyAddr" ), "Read the block of the target's memory and return it as list of signed long longs" ) ); - //python::def( "loadChars", &loadChars, loadChars_( python::args( "address", "count", "phyAddr" ), - // "Load string from target memory" ) ); - //python::def( "loadWChars", &loadWChars, loadWChars_( python::args( "address", "count", "phyAddr" ), - // "Load string from target memory" ) ); - //python::def( "loadCStr", &loadCStr, - // "Load string from the target buffer containing 0-terminated ansi-string" ); - //python::def( "loadWStr", &loadWStr, - // "Load string from the target buffer containing 0-terminated unicode-string" ); - //python::def( "loadUnicodeString", &loadUnicodeStr, - // "Return string represention of windows UNICODE_STRING type" ); - //python::def( "loadAnsiString", &loadAnsiStr, - // "Return string represention of windows ANSU_STRING type" ); - //python::def( "loadPtrList", &loadPtrList, - // "Return list of pointers, each points to next" ); - //python::def( "loadPtrs", &loadPtrArray, - // "Read the block of the target's memory and return it as a list of pointers" ); + python::def( "loadChars", &loadChars, loadChars_( python::args( "address", "count", "phyAddr" ), + "Load string from target memory" ) ); + python::def( "loadWChars", &loadWChars, loadWChars_( python::args( "address", "count", "phyAddr" ), + "Load string from target memory" ) ); + python::def( "loadCStr", &loadCStr, + "Load string from the target buffer containing 0-terminated ansi-string" ); + python::def( "loadWStr", &loadWStr, + "Load string from the target buffer containing 0-terminated unicode-string" ); + python::def( "loadUnicodeString", &loadUnicodeStr, + "Return string represention of windows UNICODE_STRING type" ); + python::def( "loadAnsiString", &loadAnsiStr, + "Return string represention of windows ANSI_STRING type" ); + python::def( "loadPtrList", &loadPtrList, + "Return list of pointers, each points to next" ); + python::def( "loadPtrs", &loadPtrArray, + "Read the block of the target's memory and return it as a list of pointers" ); python::class_( "intBase", "intBase", python::no_init ) diff --git a/pykd/win/dbgeng.cpp b/pykd/win/dbgeng.cpp index 03afe71..9f5d963 100644 --- a/pykd/win/dbgeng.cpp +++ b/pykd/win/dbgeng.cpp @@ -227,6 +227,22 @@ std::string getModuleSymbolFileName( ULONG64 baseOffset ) /////////////////////////////////////////////////////////////////////////////////// +ULONG ptrSize() +{ + PyThread_StateRestore pyThreadRestore( g_dbgEng->pystate ); + + HRESULT hres; + + hres = g_dbgEng->control->IsPointer64Bit(); + + if ( FAILED( hres ) ) + throw DbgException( "IDebugControl::IsPointer64Bit failed" ); + + return S_OK == hres ? 8 : 4; +} + +/////////////////////////////////////////////////////////////////////////////////// + }; diff --git a/pykd/win/memory.cpp b/pykd/win/memory.cpp index 2d53d42..5a534bd 100644 --- a/pykd/win/memory.cpp +++ b/pykd/win/memory.cpp @@ -41,6 +41,30 @@ ULONG64 addr64( ULONG64 addr ) /////////////////////////////////////////////////////////////////////////////////// +bool isVaValid( ULONG64 addr ) +{ + PyThread_StateRestore pyThreadRestore( g_dbgEng->pystate ); + + HRESULT hres; + ULONG offsetInfo; + + hres = + g_dbgEng->dataspace->GetOffsetInformation( + DEBUG_DATA_SPACE_VIRTUAL, + DEBUG_OFFSINFO_VIRTUAL_SOURCE, + addr64NoSafe( addr ), + &offsetInfo, + sizeof( offsetInfo ), + NULL ); + + if ( FAILED( hres ) ) + throw DbgException( "IDebugDataSpace4::GetOffsetInformation failed" ); + + return offsetInfo != DEBUG_VSOURCE_INVALID; +} + +/////////////////////////////////////////////////////////////////////////////////// + void readMemory( ULONG64 offset, PVOID buffer, ULONG length, bool phyAddr ) { PyThread_StateRestore pyThreadRestore( g_dbgEng->pystate ); @@ -53,8 +77,7 @@ void readMemory( ULONG64 offset, PVOID buffer, ULONG length, bool phyAddr ) // workitem/10473 workaround ULONG64 nextAddress; - hres = - g_dbgEng->dataspace->GetNextDifferentlyValidOffsetVirtual( offset, &nextAddress ); + hres = g_dbgEng->dataspace->GetNextDifferentlyValidOffsetVirtual( offset, &nextAddress ); DBG_UNREFERENCED_LOCAL_VARIABLE(nextAddress); @@ -71,4 +94,79 @@ void readMemory( ULONG64 offset, PVOID buffer, ULONG length, bool phyAddr ) /////////////////////////////////////////////////////////////////////////////////// +std::string loadCStr( ULONG64 offset ) +{ + PyThread_StateRestore pyThreadRestore( g_dbgEng->pystate ); + + const size_t maxLength = 0x10000; + + offset = addr64NoSafe( offset ); + + ULONG strLength = 0; + + HRESULT hres = + g_dbgEng->dataspace->ReadMultiByteStringVirtual( + offset, + maxLength, + NULL, + 0, + &strLength ); + + if ( FAILED( hres ) ) + throw MemoryException( offset ); + + std::vector buffer(strLength); + + hres = + g_dbgEng->dataspace->ReadMultiByteStringVirtual( + offset, + strLength, + &buffer[0], + strLength, + NULL ); + + if ( FAILED( hres ) ) + throw MemoryException( offset ); + + return std::string( &buffer[0] ); +} + +/////////////////////////////////////////////////////////////////////////////////// + +std::wstring loadWStr( ULONG64 offset ) +{ + PyThread_StateRestore pyThreadRestore( g_dbgEng->pystate ); + + const size_t maxLength = 0x10000; + + offset = addr64NoSafe( offset ); + + ULONG strLength = 0; + + HRESULT hres = + g_dbgEng->dataspace->ReadUnicodeStringVirtualWide( + offset, + maxLength, + NULL, + 0, + &strLength ); + + std::vector buffer(strLength); + + hres = + g_dbgEng->dataspace->ReadUnicodeStringVirtualWide( + offset, + strLength, + &buffer[0], + strLength, + NULL ); + + if ( FAILED( hres ) ) + throw MemoryException( offset ); + + return std::wstring( &buffer[0] ); +} + +/////////////////////////////////////////////////////////////////////////////////// + }; //namespace pykd \ No newline at end of file