【问题标题】:How to display the address of the function in WinDBG for .fnret command?如何在 WinDBG 中为 .fnret 命令显示函数的地址?
【发布时间】:2021-07-09 15:48:27
【问题描述】:

我需要在WinDBG中获取.fnret命令所需函数的地址。 例如,我想获取有关 apphelp!ApphelpCheckRunApp 函数的返回值的信息。 首先,我在这个函数上设置了一个断点:

bp apphelp!ApphelpCheckRunApp

然后我将继续执行,直到它在该函数上中断。

破解后,我正在执行.fnret [Address]命令。

我已经尝试使用断点上显示的77b345d5地址:

Breakpoint 0 hit
eax=77b345d5 ebx=7ed320f5 ecx=7ffac000 edx=7c886920 esi=7ffac000 edi=00000018
eip=77b345d5 esp=0378ce90 ebp=0378d108 iopl=0         nv up ei pl nz ac po cy
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000213
appHelp!ApphelpCheckRunApp:
77b345d5 8bff            mov     edi,edi

但这似乎不是我需要的,因为我收到以下错误:

^ Unknown or unsupported return type in '.fnret 77b345d5'

我还使用了调用堆栈中此函数的返回地址7c818cdf(通过kb 命令获得):

ChildEBP RetAddr  Args to Child
0283ce8c 7c818cdf 00000474 046bb7d0 00000000 appHelp!ApphelpCheckRunApp

但这会导致我犯同样的错误。

我应该使用哪个 WinDBG 命令以及它将显示哪个返回地址(以防断点上尚未显示)?那么它是否适用于.fnret.fnret /s 命令?不幸的是,在 MSDN 上没有任何使用它们的示例,只有文档。

希望得到您的帮助。提前致谢。

【问题讨论】:

    标签: windbg


    【解决方案1】:

    .fnret 仅在您拥有私有 pdb 时才有用
    如果您有公共 pdb,则它没有用,因为它需要检索类型信息

    这是使用私有 pdb 编译代码的示例用法

    0:000> x /t /v /f myst!towlower
    prv func   00007ff6`74ba5f84    7 <function> myst!towlower (unsigned short)
    
    0:000> x /t /v /f myst!toupper
    prv func   00007ff6`74b91b10   2a <function> myst!toupper (int)
    
    0:000> .fnret myst!towlower
    myst!towlower (00007ff6`74ba5f84) = unsigned short 1
    
    0:000> .fnret myst!toupper
    myst!toupper (00007ff6`74b91b10) = int 0n1
    

    一个已知函数的错误,它使用公共剥离的 pdb 返回一个 HANDLE

    0:000> .fnret KERNELBASE!CreateFileA
                                       ^ Unknown or unsupported return type in '.fnret KERNELBASE!CreateFileA'
    

    在具有私有 pdb 的系统文件上成功 它将@rax 中转储的强制返回值转换为类型化返回,并带有类型信息的函数的值

    带有私有 pdb 的系统文件

    0:000> .printf "%y\n" , 0x00000001`800bace0 ; an arbitrary function
    ole32!ToUnicode (00000001`800bace0)
    0:000> .printf "%mu\n" , 00000001`8014c17a  ; an arbitrary wide string 
    guageErrorPointerംА
    0:000> r rax = 00000001`8014c17a  the $retreg is populated with an address of wide string
    0:000> .fnret 0x00000001`800bace0  << fnret casts the $retreg as wide string and prints the resulting widestring 
    ole32!ToUnicode (00000001`800bace0) = wchar_t * 0x00000001`8014c17a
     "guageErrorPointer???"
    

    【讨论】:

    • 谢谢,不知道。所以我仍然想知道:我可以使用公共 PDB 符号(可能通过另一个命令)做同样的事情吗?
    • 是的,如果你知道 c++ 表达式、dx、natvis 评估器等的类型,例如 dx (wchar_t *) @rax 会将返回的 64 位数字转换为宽字符串类型
    • 但是如果我不知道返回数据类型怎么办?那我怎么才能得到呢?我希望至少获得有关返回类型(int、bool、char、string 等)的信息,而不是值本身,如果这在我的情况下是不可能的。
    • 类型信息在公共 pdbs 中被删除。所以 .fnret 无法检索返回类型
    • 好的,在使用公共 PDB 时,该命令根本没有帮助。我在这里找到了更好的解决方案:stackoverflow.com/questions/1025804/…。非常感谢您的帮助!
    【解决方案2】:

    好的,在使用公共 PDB 时,该命令确实毫无帮助。 我在这里找到了更好的解决方案:How to get return value from a function in windbg?

    可以通过使用r命令适当地查看x86/x64上的eax/rax寄存器来获取返回值的内存地址(因为它总是存储在那里)。在断点之后,我只是在 x86 上输入 r eax 或在 x64 上输入 r rax。输出将如下所示:

    eax=[Address]

    然后,我通过 d*(dd、du 等显示数据类型命令)显示接收到的内存地址的值,如下所示:

    du [Address]

    查看输出后,就可以理解返回了哪些数据,以及它的数据类型(至少在大多数情况下)。 但首先要了解使用哪种数据类型,我正在尝试display memory commandsdisplay referenced memory commands 的不同组合。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-01-07
      • 2022-06-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多