From 93ad5090da2d75144843e976a44703b194ac8d84 Mon Sep 17 00:00:00 2001 From: "SND\\kernelnet_cp" Date: Wed, 13 Nov 2013 07:11:40 +0000 Subject: [PATCH] [0.3.x] fixed : dbgCommand('g') hangs up git-svn-id: https://pykd.svn.codeplex.com/svn@86399 9b283d60-5439-405e-af05-b73fd8c4d996 --- pykd-0.3-2010.sln | 3 + pykd/pydbgio.h | 32 +++++- pykd/pymod.cpp | 9 ++ pykd/windbgext.cpp | 15 ++- snippets/ssdt.py | 73 +++++++++++++ snippets/stkdelta.py | 100 ++++++++++++++++++ snippets/stkwalk.py | 238 +++++++++++++++++++++++++++++++++++++++++++ 7 files changed, 463 insertions(+), 7 deletions(-) create mode 100644 snippets/ssdt.py create mode 100644 snippets/stkdelta.py create mode 100644 snippets/stkwalk.py diff --git a/pykd-0.3-2010.sln b/pykd-0.3-2010.sln index 5fb569d..21a89bb 100644 --- a/pykd-0.3-2010.sln +++ b/pykd-0.3-2010.sln @@ -61,6 +61,9 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "snippets", "snippets", "{AA snippets\ndis.py = snippets\ndis.py snippets\ntobj.py = snippets\ntobj.py snippets\pytowiki.py = snippets\pytowiki.py + snippets\ssdt.py = snippets\ssdt.py + snippets\stkdelta.py = snippets\stkdelta.py + snippets\stkwalk.py = snippets\stkwalk.py EndProjectSection EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "um", "um", "{EEFC9510-DFA7-439E-801E-48FCE72766AD}" diff --git a/pykd/pydbgio.h b/pykd/pydbgio.h index edc662f..0d7abaf 100644 --- a/pykd/pydbgio.h +++ b/pykd/pydbgio.h @@ -12,10 +12,6 @@ class DbgOut : public kdlib::windbg::WindbgOut { public: - DbgOut() { - int a = 10; - } - void flush() { } @@ -42,4 +38,32 @@ public: /////////////////////////////////////////////////////////////////////////////// +class SysDbgOut : public DbgOut +{ +public: + + virtual void write( const std::wstring& str) { + python::object sys = python::import("sys"); + sys.attr("stdout").attr("write")( str ); + } + + virtual void writedml( const std::wstring& str) { + write(str); + } +}; + +/////////////////////////////////////////////////////////////////////////////// + +class SysDbgIn : public DbgIn +{ +public: + + virtual std::wstring readline() { + python::object sys = python::import("sys"); + return python::extract( sys.attr("stdin").attr("readline") ); + } +}; + +/////////////////////////////////////////////////////////////////////////////// + } diff --git a/pykd/pymod.cpp b/pykd/pymod.cpp index 6d21cd2..3821f72 100644 --- a/pykd/pymod.cpp +++ b/pykd/pymod.cpp @@ -73,9 +73,17 @@ BOOST_PYTHON_FUNCTION_OVERLOADS( TypeInfo_ptrTo, TypeInfoAdapter::ptrTo, 1, 2 ); //BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS( Module_findSymbol, Module::getSymbolNameByVa, 1, 2 ); +pykd::SysDbgOut sysPykdOut; +pykd::SysDbgOut sysPykdErr; +pykd::SysDbgIn sysPykdIn; BOOST_PYTHON_MODULE( pykd ) { + // использовать вместо консоли потоки из sys + kdlib::dbgout =&sysPykdOut; + kdlib::dbgerr = &sysPykdErr; + kdlib::dbgin = &sysPykdIn; + python::scope().attr("version") = pykdVersion; // DbgEng services @@ -747,6 +755,7 @@ BOOST_PYTHON_MODULE( pykd ) pykd::exception( "MemoryException", "Target memory access exception class" ); pykd::exception( "SymbolException", "Symbol exception" ); pykd::exception( "TypeException", "type exception" ); + } ////////////////////////////////////////////////////////////////////////////////// diff --git a/pykd/windbgext.cpp b/pykd/windbgext.cpp index 2a5ebd0..86e2534 100644 --- a/pykd/windbgext.cpp +++ b/pykd/windbgext.cpp @@ -27,6 +27,11 @@ bool PykdExt::isInit() { extern "C" void initpykd(); +pykd::DbgOut pykdOut; +pykd::DbgOut pykdErr; +pykd::DbgIn pykdIn; + + void PykdExt::setUp() { WindbgExtension::setUp(); @@ -56,11 +61,15 @@ void PykdExt::setUp() } // перенаправление стандартных потоков ВВ + kdlib::dbgout =&pykdOut; + kdlib::dbgerr = &pykdErr; + kdlib::dbgin = &pykdIn; + python::object sys = python::import("sys"); - sys.attr("stdout") = python::object( pykd::DbgOut() ); - sys.attr("stderr") = python::object( pykd::DbgOut() ); - sys.attr("stdin") = python::object( pykd::DbgIn() ); + sys.attr("stdout") = python::object( &pykdOut ); + sys.attr("stderr") = python::object( &pykdErr ); + sys.attr("stdin") = python::object( &pykdIn ); python::list pathList(sys.attr("path")); diff --git a/snippets/ssdt.py b/snippets/ssdt.py new file mode 100644 index 0000000..272e1b6 --- /dev/null +++ b/snippets/ssdt.py @@ -0,0 +1,73 @@ +from pykd import * +import sys + + +nt = module( "nt" ) + +def getServiceAddrWlh(Start, Offset): + return Start + (Offset / 16) + +def getServiceAddr2k3(Start, Offset): + return Start + (Offset & ~0xf) + +if ptrWord( nt.offset("NtBuildNumber")) == 3790: + getServiceAddr = getServiceAddr2k3 +else: + getServiceAddr = getServiceAddrWlh + +def getSymbolString(addr): + try: + return findSymbol(addr) + except BaseException: + pass + return " !!! 0x%x" % addr + +def checkSSDT(): + + if is64bitSystem(): + + serviceTableHeader = loadQWords( nt.offset("KeServiceDescriptorTable"), 4 ) + serviceTableStart = serviceTableHeader[0] + serviceCount = serviceTableHeader[2] + + dprintln( "ServiceTable start: %(1)x count: %(2)x" % { "1" : serviceTableStart, "2" : serviceCount } ) + + serviceTable = loadSignDWords( serviceTableStart, serviceCount ) + + for i in range( 0, serviceCount ): + + routineAddress = getServiceAddr(serviceTableStart, serviceTable[i]); + dprintln( "[%u] " % i + getSymbolString( routineAddress ) ) + + + else: + + serviceTableHeader = loadDWords( nt.offset("KeServiceDescriptorTable"), 4 ) + serviceTableStart = serviceTableHeader[0] + serviceCount = serviceTableHeader[2] + + dprintln( "ServiceTable start: %(1)x count: %(2)x" % { "1" : serviceTableStart, "2" : serviceCount } ) + + serviceTable = loadPtrs( serviceTableStart, serviceCount ) + + for i in range( 0, serviceCount ): + dprintln( "[%u] " % i + getSymbolString( serviceTable[i] ) ) + +if __name__ == "__main__": + + + while True: + + if not isWindbgExt(): + if not loadDump( sys.argv[1] ): + dprintln( sys.argv[1] + " - load failed" ) + break + + if not isKernelDebugging(): + dprintln( "not a kernel debugging" ) + break + + checkSSDT() + break + + \ No newline at end of file diff --git a/snippets/stkdelta.py b/snippets/stkdelta.py new file mode 100644 index 0000000..e2fbf2b --- /dev/null +++ b/snippets/stkdelta.py @@ -0,0 +1,100 @@ + +from pykd import * +import sys + +def printThreadInfo(): + + nt = module("nt") + + thread = nt.typedVar( "_KTHREAD", getThreadOffset( getCurrentThread() ) ) + + stackPointer = addr64( reg("rsp") if is64bitSystem() else reg("esp") ) + + dprintln("") + + dprintln( "Stack Base: %x Limit: %x Current: %x Used: %x Unused: %x" % + ( thread.InitialStack, thread.StackLimit, stackPointer, thread.InitialStack - stackPointer, stackPointer - thread.StackLimit ) ) + + +def printDeltaStat(): + + dprintln("") + + printThreadInfo() + + stk = getStack() + + moduleLst = {} + funcLst = {} + + for i in range( 0, len(stk) -1 ): + + try: + mod = module( stk[i].returnOffset ) + except BaseException: + continue + + delta = stk[i+1].frameOffset - stk[i].frameOffset + if delta > 0: + + moduleName = mod.name() + + if moduleName in moduleLst: + moduleLst[moduleName] = moduleLst[moduleName] + delta + else: + moduleLst[moduleName] = delta + + func = moduleName + "!" + mod.findSymbol( stk[i].returnOffset, showDisplacement = False ) + + if func in funcLst: + funcLst[func] = funcLst[func] + delta + else: + funcLst[func] = delta + + nt = module("nt") + + thread = nt.typedVar( "_KTHREAD", getImplicitThread() ) + + stackSize = thread.InitialStack - thread.StackLimit + + dprintln("") + dprintln( "%12s\t%s" % ("Stack usage:", "Module:" ) ) + dprintln( "="*30 ) + + for mod,delta in sorted( moduleLst.iteritems(), key=lambda x: x[1], reverse=True ): + dprintln( "%7d%5s\t%s" % (delta, "(%%%d)" % (delta*100/stackSize), mod ) ) + + dprintln("") + dprintln( "%12s\t%s" % ("Stack usage:", "Function" ) ) + dprintln( "="*30 ) + + for func,delta in sorted( funcLst.iteritems(), key=lambda x: x[1], reverse=True ): + dprintln( "%7d%5s\t%s" % (delta, "(%%%d)" % (delta*100/stackSize), func ) ) + +def printDeltaStack(): + + printThreadInfo() + + stk = getStack() + + dprintln( "Stack Delta:\tFunction:") + + for i in range( 0, len(stk) -1 ): + dprint( "%12s\t" % long( stk[i+1].frameOffset - stk[i].frameOffset) ) + try: + mod = module( stk[i].returnOffset ) + dprintln( "%s!%s"% ( mod.name(), mod.findSymbol( stk[i].returnOffset, showDisplacement = False ) ) ) + except BaseException: + dprintln( findSymbol( stk[i].returnOffset ) ) + +def main(): + + if len(sys.argv) > 1: + if sys.argv[1] == "stat": + printDeltaStat() + return + + printDeltaStack() + +if __name__ == "__main__": + main() diff --git a/snippets/stkwalk.py b/snippets/stkwalk.py new file mode 100644 index 0000000..cf70970 --- /dev/null +++ b/snippets/stkwalk.py @@ -0,0 +1,238 @@ + +from pykd import * +from optparse import OptionParser +from fnmatch import fnmatch +import traceback +import sys + +nt = None + +class PrintOptions: + def __init__(self): + self.ignoreNotActiveThread = True + self.ignoreNotActiveProcess = True + self.showWow64stack = True + self.showIP = True + self.showSP = True + self.showUnique = False + +def applayThreadFilter(thread,threadFilter,moduleFilter,funcFilter,printopt,stackHashes): + + filterMatch = False + + if not moduleFilter and not funcFilter and not threadFilter: + if printopt.showUnique == False: + return True + else: + filterMatch = True + + if threadFilter and threadFilter( thread.Tcb, thread.Cid.UniqueThread ): + if printopt.showUnique == False: + return True + else: + filterMatch = True + + try: + + setImplicitThread(thread) + + stk = getStack() + + strStack = "" + + for frame in stk: + m = module( frame.instructionOffset ) + if filterMatch == False and moduleFilter and moduleFilter( m, m.name() ): + filterMatch = True + if printopt.showUnique == False: + return True + + sym = m.findSymbol( frame.instructionOffset, showDisplacement = False ) + if filterMatch == False and funcFilter and funcFilter( sym ): + filterMatch = True + if printopt.showUnique == False: + return True + + if printopt.showUnique == True: + strStack += sym + + if is64bitSystem(): + processorMode = getProcessorMode() + try: + setProcessorMode("X86") + dbgCommand( ".reload /user" ) + stk = getStackWow64() + for frame in stk: + m = module( frame.instructionOffset ) + if filterMatch == False and moduleFilter and moduleFilter( m, m.name() ): + filterMatch = True + if printopt.showUnique == False: + return True + + sym = m.findSymbol( frame.instructionOffset, showDisplacement = False ) + if filterMatch == False and funcFilter and funcFilter( sym ): + filterMatch = True + if printopt.showUnique == False: + return True + + if printopt.showUnique == True: + strStack += sym + except BaseException: + pass + setProcessorMode(processorMode) + + if printopt.showUnique == False or filterMatch == False: + return filterMatch + + hashStack = hash( strStack ) + if hashStack in stackHashes: + return False + + stackHashes.add( hashStack ) + + return True + + except BaseException: + pass + + return False + +def printFrame(frame, printopt): + if printopt.showIP: + dprint( "%016x\t" % frame.instructionOffset ) + if printopt.showSP: + dprint( "%016x\t" % frame.stackOffset ) + + dprintln( findSymbol( frame.instructionOffset ) ) + + +def printThread(process,thread,printopt): + + try: + setImplicitThread(thread) + + stk = getStack() + + dprintln( "Thread %x, Process: %s (%x)" % ( thread, loadCStr( process.ImageFileName ), process ) ) + for frame in stk: + printFrame(frame, printopt) + + if is64bitSystem(): + processorMode = getProcessorMode() + try: + setProcessorMode("X86") + stk = getStackWow64() + dprintln("\nWOW64 stack") + for frame in stk: + printFrame(frame, printopt) + except BaseException: + pass + setProcessorMode(processorMode) + + dprintln("") + + except BaseException: + + if not printopt.ignoreNotActiveThread: + dprintln( "Thread %x, Process: %s" % ( thread, loadCStr( process.ImageFileName ) ) ) + dprintln( "Failed to switch into thread context\n") + dprintln("") + + + +def printProcess(process,processFilter,threadFilter,moduleFilter,funcFilter,printopt): + + processName = loadCStr( process.ImageFileName ) + + if processFilter and not processFilter(process, process.UniqueProcessId, processName ): + return + + try: + #setCurrentProcess(process) + dbgCommand(".process /p %x" % process ) + + dbgCommand( ".reload /user" ) + + threadLst = nt.typedVarList(process.ThreadListHead, "_ETHREAD", "ThreadListEntry.Flink") + filteredThreadLst = [] + stackHashes = set() + + for thread in threadLst: + if applayThreadFilter( thread, threadFilter, moduleFilter, funcFilter, printopt, stackHashes ): + filteredThreadLst.append( thread ) + + if filteredThreadLst == []: + return + + dprintln( "Process %x" % process ) + dprintln( "Name: %s Pid: %#x" % ( processName, process.UniqueProcessId ) ) + dprintln( "" ) + + for thread in filteredThreadLst: + printThread(process,thread, printopt) + + except BaseException: + if not printopt.ignoreNotActiveProcess: + dprintln( "Process %x" % process ) + dprintln( "Name: %s" % processName ) + dprintln( "Failed to switch into process context\n") + dprintln( "" ) + + +def main(): + dprintln("Stack walker. ver 1.0") + + if not isKernelDebugging(): + dprintln("This script is only for kernel debugging") + return + + global nt + nt = module("nt") + + parser = OptionParser() + parser.add_option("-p", "--process", dest="processfilter", + help="process filter: boolean expression with python syntax" ) + parser.add_option("-m", "--module", dest="modulefilter", + help="module filter: boolean expression with python syntax" ) + parser.add_option("-f", "--function", dest="funcfilter", + help="function filter: boolean expression with python syntax" ) + parser.add_option("-t", "--thread", dest="threadfilter", + help="thread filter: boolean expresion with python syntax" ) + parser.add_option("-u", "--unique", action="store_true", dest="uniquestack", + help="show only unique stacks" ) + + (options, args) = parser.parse_args() + + processFilter = None + moduleFilter = None + funcFilter = None + threadFilter = None + + if options.processfilter: + processFilter = lambda process, pid, name: eval( options.processfilter ) + + if options.modulefilter: + moduleFilter = lambda module, name: eval(options.modulefilter) + + if options.funcfilter: + funcFilter = lambda name: eval( options.funcfilter) + + if options.threadfilter: + threadFilter = lambda thread, tid: eval( options.threadfilter) + + printopt = PrintOptions() + printopt.showUnique = True if options.uniquestack else False + + currentProcess = getCurrentProcess() + currentThread = getImplicitThread() + + processLst = nt.typedVarList( nt.PsActiveProcessHead, "_EPROCESS", "ActiveProcessLinks.Flink") + for process in processLst: + printProcess( process, processFilter, threadFilter, moduleFilter, funcFilter, printopt ) + + setCurrentProcess(currentProcess) + setImplicitThread(currentThread) + + +if __name__ == "__main__": + main()