diff --git a/pykd/dbgclient.h b/pykd/dbgclient.h index 23ee0c9..a2aeb9c 100644 --- a/pykd/dbgclient.h +++ b/pykd/dbgclient.h @@ -128,6 +128,10 @@ public: std::wstring loadWChars( ULONG64 offset, ULONG count, bool phyAddr = FALSE ); + std::string loadCStr( ULONG64 offset ); + + std::wstring loadWStr( ULONG64 offset ); + ULONG ptrSize(); ULONG64 ptrByte( ULONG64 offset ); diff --git a/pykd/dbgext.cpp b/pykd/dbgext.cpp index cef6f65..2f97a68 100644 --- a/pykd/dbgext.cpp +++ b/pykd/dbgext.cpp @@ -183,6 +183,10 @@ BOOST_PYTHON_MODULE( pykd ) "Load string from target memory" ) ) .def( "loadWChars", &DebugClient::loadWChars, DebugClient_loadWChars( python::args( "offset", "count", "phyAddr" ), "Load string from target memory" ) ) + .def( "loadCStr", &DebugClient::loadCStr, + "Load string from the target buffer containing 0-terminated ansi-string" ) + .def( "loadWStr", &DebugClient::loadWStr, + "Load string from the target buffer containing 0-terminated unicode-string" ) .def( "ptrByte", &DebugClient::ptrByte, "Read an unsigned 1-byte integer from the target memory" ) .def( "ptrWord", &DebugClient::ptrWord, @@ -288,6 +292,10 @@ BOOST_PYTHON_MODULE( pykd ) "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( "ptrByte", &ptrByte, "Read an unsigned 1-byte integer from the target memory" ); python::def( "ptrWord", &ptrWord, diff --git a/pykd/dbgmem.cpp b/pykd/dbgmem.cpp index 59c7402..f0641a7 100644 --- a/pykd/dbgmem.cpp +++ b/pykd/dbgmem.cpp @@ -158,6 +158,64 @@ std::wstring loadWChars( ULONG64 address, ULONG number, bool phyAddr ) ///////////////////////////////////////////////////////////////////////////////////// +std::string DebugClient::loadCStr( ULONG64 address ) +{ + const size_t maxLength = 0x1000; + + address = addr64( address ); + + std::vector buffer(maxLength); + + HRESULT hres = + m_dataSpaces->ReadMultiByteStringVirtual( + address, + maxLength, + &buffer[0], + maxLength, + NULL ); + + if ( FAILED( hres ) ) + throw MemoryException( address ); + + return std::string( &buffer[0] ); +} + +std::string loadCStr( ULONG64 offset ) +{ + return g_dbgClient->loadCStr( offset ); +} + +///////////////////////////////////////////////////////////////////////////////////// + +std::wstring DebugClient::loadWStr( ULONG64 address ) +{ + const size_t maxLength = 0x2000; + + address = addr64( address ); + + std::vector buffer(maxLength); + + HRESULT hres = + m_dataSpaces->ReadMultiByteStringVirtual( + address, + maxLength, + &buffer[0], + maxLength, + NULL ); + + if ( FAILED( hres ) ) + throw MemoryException( address ); + + return std::wstring( (wchar_t*)&buffer[0] ); +} + +std::wstring loadWStr( ULONG64 offset ) +{ + return g_dbgClient->loadWStr( offset ); +} + +///////////////////////////////////////////////////////////////////////////////////// + python::list DebugClient::loadBytes( ULONG64 offset, ULONG count, bool phyAddr ) { return loadArray( offset, count, phyAddr ); diff --git a/pykd/dbgmem.h b/pykd/dbgmem.h index a2ce649..afffe0c 100644 --- a/pykd/dbgmem.h +++ b/pykd/dbgmem.h @@ -24,6 +24,10 @@ std::string loadChars( ULONG64 address, ULONG number, bool phyAddr = FALSE ); std::wstring loadWChars( ULONG64 address, ULONG number, bool phyAddr = FALSE ); +std::string loadCStr( ULONG64 offset ); + +std::wstring loadWStr( ULONG64 offset ); + python::list loadBytes( ULONG64 offset, ULONG count, bool phyAddr = FALSE ); python::list loadWords( ULONG64 offset, ULONG count, bool phyAddr = FALSE ); diff --git a/pykd/dbgobj.h b/pykd/dbgobj.h index 76d44b7..cdeebbc 100644 --- a/pykd/dbgobj.h +++ b/pykd/dbgobj.h @@ -32,7 +32,7 @@ protected: if ( FAILED( hres ) ) throw DbgException("QueryInterface IDebugAdvanced2 failed"); - hres = client->QueryInterface( __uuidof(IDebugDataSpaces), (void**)&m_dataSpaces ); + hres = client->QueryInterface( __uuidof(IDebugDataSpaces4), (void**)&m_dataSpaces ); if ( FAILED( hres ) ) throw DbgException("QueryInterface IDebugDataSpaces failed"); @@ -48,7 +48,7 @@ protected: CComPtr m_control; CComPtr m_symbols; CComPtr m_advanced; - CComPtr m_dataSpaces; + CComPtr m_dataSpaces; CComPtr m_registers; }; diff --git a/snippets/export.py b/snippets/export.py index 34320ac..c49ccff 100644 --- a/snippets/export.py +++ b/snippets/export.py @@ -9,8 +9,8 @@ from pykd import * def export( moduleName, mask = "*" ): - module = loadModule( moduleName ) - dprintln( "Module: " + moduleName + " base: %x" % module.begin() + " end: %x" % module.end() ) + modObj = loadModule( moduleName ) + dprintln( "Module: " + moduleName + " base: %x" % modObj.begin() + " end: %x" % modObj.end() ) if isKernelDebugging(): systemModule = loadModule( "nt" ) @@ -19,12 +19,12 @@ def export( moduleName, mask = "*" ): if is64bitSystem(): - ntHeader = typedVar( systemModule.name(), "_IMAGE_NT_HEADERS64", module.begin() + ptrDWord( module.begin() + 0x3c ) ) + ntHeader = systemModule.typedVar( "_IMAGE_NT_HEADERS64", modObj.begin() + ptrDWord( modObj.begin() + 0x3c ) ) if ntHeader.OptionalHeader.Magic == 0x10b: systemModule = loadModule( "ntdll32" ) - ntHeader = typedVar( systemModule.name(), "_IMAGE_NT_HEADERS", module.begin() + ptrDWord( module.begin() + 0x3c ) ) + ntHeader = systemModule.typedVar( "_IMAGE_NT_HEADERS", modObj.begin() + ptrDWord( modObj.begin() + 0x3c ) ) else: - ntHeader = typedVar( systemModule.name(), "_IMAGE_NT_HEADERS", module.begin() + ptrDWord( module.begin() + 0x3c ) ) + ntHeader = systemModule.typedVar("_IMAGE_NT_HEADERS", modObj.begin() + ptrDWord( modObj.begin() + 0x3c ) ) dprintln( "Export RVA: %x Size: %x" % ( ntHeader.OptionalHeader.DataDirectory[0].VirtualAddress, ntHeader.OptionalHeader.DataDirectory[0].Size ) ) @@ -33,14 +33,14 @@ def export( moduleName, mask = "*" ): if ntHeader.OptionalHeader.DataDirectory[0].Size == 0: return - exportDirAddr = module.begin() + ntHeader.OptionalHeader.DataDirectory[0].VirtualAddress; + exportDirAddr = modObj.begin() + ntHeader.OptionalHeader.DataDirectory[0].VirtualAddress; namesCount = ptrDWord( exportDirAddr + 0x18 ) - namesRva = module.begin() + ptrDWord( exportDirAddr + 0x20 ) + namesRva = modObj.begin() + ptrDWord( exportDirAddr + 0x20 ) for i in range( 0, namesCount ): - exportName = loadCStr( module.begin() + ptrDWord( namesRva + 4 * i ) ) + exportName = loadCStr( modObj.begin() + ptrDWord( namesRva + 4 * i ) ) if fnmatch.fnmatch( exportName, mask ): dprintln( exportName ) diff --git a/test/scripts/memtest.py b/test/scripts/memtest.py index 5caa77d..4251775 100644 --- a/test/scripts/memtest.py +++ b/test/scripts/memtest.py @@ -77,3 +77,7 @@ class MemoryTest( unittest.TestCase ): def testCompare( self ): self.assertTrue( pykd.compareMemory( target.module.helloStr, pykd.ptrPtr(target.module.strArray), 5 ) ) self.assertFalse( pykd.compareMemory( target.module.helloStr, target.module.helloWStr, 5 ) ) + + def testCStr( self ): + self.assertEqual( 'Hello', pykd.loadCStr( target.module.helloStr ) ) + self.assertEqual( u'Hello', pykd.loadWStr( target.module.helloWStr ) )