Dump Windows Service Table in WinDbg
buri write a great article <Windows Service Table Dumper for WinDbg> show how to use the built-in script language in WinDbg to do a real job: dump the windows service table. But this script is short of readability, because the build-in script in WinDbg is very strange like its command design.
So, why we can't implement it more easy and readable, base on a friendly python script through PyDbgExt, my python extension for WinDbg :)
First we need define a script module, such as dumpServiceTable.py, which includes a function dumpServiceTable to dump that table, and import the dependence modules
To make the code more readable, we define some utility functions: getSymbol can get the symbol object with its name or offset; readDWORD read unsigned long from the offset. According to the result type of VirtualDataSpace.Read function is a buffer object, we need use unpack_from function to decode the buffer.
So, why we can't implement it more easy and readable, base on a friendly python script through PyDbgExt, my python extension for WinDbg :)
First we need define a script module, such as dumpServiceTable.py, which includes a function dumpServiceTable to dump that table, and import the dependence modules
from PyDbgEng import *Next, we got the common base object, such as DebugClient.Current which is the current debug session in windbg; Symbols and DataSpaces.Virtual will support us query the debug symbol and read/write the virtual address space.
from struct import *
c = DebugClient.Current
s = c.Symbols
v = c.DataSpaces.Virtual
def getSymbol(name):
return s.GetSymbols(name).popitem()[1][0]
def getSymbol(offset):
return s.GetSymbols(offset).popitem()[1][0]
def readDWORD(offset):
return unpack_from("L", v.Read(offset, 4))[0]
To make the code more readable, we define some utility functions: getSymbol can get the symbol object with its name or offset; readDWORD read unsigned long from the offset. According to the result type of VirtualDataSpace.Read function is a buffer object, we need use unpack_from function to decode the buffer.
def dumpServiceTable():The last part of code read and dump the service table:
KiServiceTable = getSymbol("nt!KiServiceTable")
KiServiceLimit = getSymbol("nt!KiServiceLimit")
idx = 0
for addr in v.ReadPointers(KiServiceTable.Offset, readDWORD(KiServiceLimit.Offset)):
try:
symbol = getSymbol(addr)
symbolName = "%s!%s" % (symbol.Module.ModuleName, symbol.Name)
except:
symbolName = ""
print "%03d %08x %s" % (idx, addr & 0xFFFFFFFF, symbolName)
idx = idx + 1
- get the symbol object of nt!KiServiceTable and nt!KiServiceLimit
- read a group of pointers from the begin of table
- try to get the symbol object for every entry in table
- if the symbol exists, dump it's address, module and name
- if the symbol nonexists, just show warning. we can provide more information about this in future
lkd> .extpath+ D:\Study\Win32\PyDbgExt\Binary\debugIf there some wrong in script, just edit it and reload it with python build-in function
Extension search path is: ...;D:\Study\Win32\PyDbgExt\Binary\debug
lkd> .load PyDbgExt
lkd> .chain
Extension DLL search Path:
...
Extension DLL chain:
PyDbgExt: API 1.0.0, built Sat May 26 02:17:49 2007
[path: D:\Study\Win32\PyDbgExt\Binary\debug\PyDbgExt.dll]
dbghelp: image 6.7.0005.0, API 6.0.6, built Fri Mar 30 02:08:09 2007
[path: D:\MS\Debugging Tools for Windows\dbghelp.dll]
...
lkd> !import dumpServiceTable
Importsucceeded.
lkd> !eval dumpServiceTable.dumpServiceTable()
000 8092023a nt!NtAcceptConnectPort
001 8096b71e nt!NtAccessCheck
002 8096f9be nt!NtAccessCheckAndAuditAlarm
...
032 808b9810 nt!NtCompressKey
033 f4bed0d2
034 8088d0c8 nt!NtContinue
...
lkd> !eval reload(dumpServiceTable)Enjoy it :)
1 comment:
This is fantastic!
Post a Comment