【问题标题】:Parse PDB Symbol and Resolve Address解析 PDB 符号并解析地址
【发布时间】:2015-03-23 10:51:20
【问题描述】:

使用我在下面的说明(示例)中找到的基于 python 的反汇编器 + 调试器。现在我想解析微软提供的公共符号来找到它调用的确切函数。

我想知道有哪些可用的选项/模块来做同样的事情。我们是否可以简单地从静态 PDB 文件中获取信息,或者在调试时将其加载到内存中?

call ntdll!0x33dec
call ntdll!0x22280
call ntdll!0x2df40
call ntdll!0x33cdb
call ntdll!0x2df29
call ntdll!0x325a0
call ntdll!0x32a96
call ntdll!0x32a79
call ntdll!0x220a4

【问题讨论】:

    标签: python debugging windbg pdb pydbg


    【解决方案1】:

    使用capstone for dis-assemblydbghelp apis 进行立即E8 调用的符号解析的示例

    import sys  #for argv[]
    import binascii #for hexlify repr() spits out ugly mix like
            #'\xe8y\xff\' instead of  '\xe8\x79\xff' :(
    from ctypes import *
    from capstone import *
    class SYMBOL_INFO(Structure):
        _fields_ = [
        ( 'SizeOfStruct', c_ulong ),
        ( 'TypeIndex', c_ulong ),
        ( 'Reserved', c_ulonglong * 2 ),
        ( 'Index', c_ulong ),
        ( 'Size', c_ulong ),
        ( 'ModBase', c_ulonglong ),
        ( 'Flags', c_ulong ),
        ( 'Value', c_ulonglong ),
        ( 'Address', c_ulonglong ),
        ( 'Register', c_ulong ),
        ( 'Scope', c_ulong ),
        ( 'Tag' , c_ulong ),
        ( 'NameLen', c_ulong ),
        ( 'MaxNameLen', c_ulong ),
        ( 'Name', c_char * 2001 )
    ]   
    modname = sys.argv[1]
    offset  = long(sys.argv[2],16)
    sympath = "xxx:\\yyyyy"  # substitute actual path
    base    = windll.LoadLibrary(modname)._handle
    symaddr = c_ulonglong(base + offset)
    print "Module name = %s\nModule Base = %s\nSymFromAddr = %s" % \
        (modname,hex(base),hex(symaddr.value))
    dbghelp = windll.dbghelp
    k32 =     windll.kernel32
    hproc = k32.GetCurrentProcess()
    dbghelp.SymInitialize(hproc,sympath,1)
    sinfo = SYMBOL_INFO()
    sinfo.SizeOfStruct = sizeof(SYMBOL_INFO) - 2000
    sinfo.MaxNameLen = 2000
    Displacement = c_ulonglong()
    dbghelp.SymFromAddr(hproc,symaddr,addressof(Displacement),addressof(sinfo))
    print "Sym At Addr = %s + %s" % (sinfo.Name,str(hex(Displacement.value)))
    opcodebuff     = create_string_buffer(16)
    memmove(opcodebuff,symaddr.value,16)
    for i in range(0,16,1):
        print binascii.hexlify(opcodebuff.raw[i]),
    print
    MyDisasm = Cs(CS_ARCH_X86, CS_MODE_32)
    for i in MyDisasm.disasm(opcodebuff, symaddr,1):
        print "0x%x: %s %s  %s" %  ( i.address ,binascii.hexlify(i.bytes),
         i.mnemonic, i.op_str)
        if(i.mnemonic == 'call'):
            try:
                symaddr = c_ulonglong(long(i.op_str,16))
                dbghelp.SymFromAddr(hproc,symaddr,addressof(Displacement),addressof(sinfo))
                print "(%s+%s)" % (sinfo.Name,str(hex(Displacement.value))),
                print "(%s+0x%X)"% (modname ,long(i.op_str,16)-base)
            except:
                print "Indirect/register Calls Not Handled Yet"
                pass
    

    用法如下

    python dumpsym.py ntdll 1041

    first argument is a string that represents a module 
    
    second argument is a string that represents an offset in the module
    
    so if module is loaded at 0xxxxxxxxx offset 1041 will point to the address 
    0xxxxxxxxx+0x1041 
    

    输出

    Module name = ntdll
    Module Base = 0x7c900000
    SymFromAddr = 0x7c901041L
    Sym At Addr = RtlEnterCriticalSection + 0x41L
    e8 79 a1 01 00 64 8b 0d 18 00 00 00 8b 54 24 04
    0x7c901041: e879a10100 call  0x7c91b1bf
    (RtlpWaitForCriticalSection+0x0L) (ntdll+0x1B1BF)
    

    【讨论】:

    • 一个问题,“offset = long(offs,16)”这个偏移量是什么意思,它期望什么?
    • 关闭 ?你的意思是 sys.argv[2] ?如果是,它是传递给脚本的第二个参数,它表示第一个参数指向的模块的偏移量,即 c:\>python.exe xxx.py yyyyyy 417 其中 xxx.py 是 copypastedsaved 脚本 yyyyyyyy 是模块名称 myuselessdll 可能在 0xDEADFACE 加载,并且 417 偏移到模块中,因此 DEADFACE + 0x417 成为偏移 DEADFEE5
    【解决方案2】:

    您可以使用DbgHelp API 从 PDB 文件中获取符号。这与 WinDbg 使用的 API 相同,您可以使用它来调试实时进程以及根据加载模块的偏移量简单地提取符号。在您的情况下,SymFromAddr 函数最容易用于从地址获取符号。

    【讨论】:

      【解决方案3】:

      一种非自动化但快速的方法是:

      1. 在调试器中加载 ntdll.dll 作为转储文件。
      2. 使用公共符号路径或本地缓存加载符号。
      3. 使用ln 命令。喜欢:ln ntdll!0x33dec

      【讨论】:

        猜你喜欢
        • 2016-05-03
        • 1970-01-01
        • 2022-06-15
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多