【问题标题】:Windbg _imp__xxx symbol's address seems to be dereferenced using the data segment registerWindbg _imp__xxx 符号的地址似乎使用数据段寄存器取消引用
【发布时间】:2014-05-15 05:13:53
【问题描述】:

我正在学习 Windbg。为了练习,我正在调试一个创建进程的 64 位 fre 应用程序。 我在 CreateProcess (bp KERNEL32!CreateProcessWStub) 上添加了一个断点 当断点被命中时,我反汇编代码(u),它看起来像这样:

Breakpoint 0 hit
KERNEL32!CreateProcessWStub:
000007f9`f8024ab4 4c8bdc          mov     r11,rsp
0:000> u @rip L20
KERNEL32!CreateProcessWStub:
000007f9`f8024ab4 4c8bdc          mov     r11,rsp
000007f9`f8024ab7 4883ec58        sub     rsp,58h
000007f9`f8024abb 488b8424a8000000 mov     rax,qword ptr [rsp+0A8h]
000007f9`f8024ac3 498943f0        mov     qword ptr [r11-10h],rax
000007f9`f8024ac7 488b8424a0000000 mov     rax,qword ptr [rsp+0A0h]
000007f9`f8024acf 498943e8        mov     qword ptr [r11-18h],rax
000007f9`f8024ad3 488b842498000000 mov     rax,qword ptr [rsp+98h]
000007f9`f8024adb 498943e0        mov     qword ptr [r11-20h],rax
000007f9`f8024adf 488b842490000000 mov     rax,qword ptr [rsp+90h]
000007f9`f8024ae7 498943d8        mov     qword ptr [r11-28h],rax
000007f9`f8024aeb 8b842488000000  mov     eax,dword ptr [rsp+88h]
000007f9`f8024af2 89442428        mov     dword ptr [rsp+28h],eax
000007f9`f8024af6 8b842480000000  mov     eax,dword ptr [rsp+80h]
000007f9`f8024afd 89442420        mov     dword ptr [rsp+20h],eax
000007f9`f8024b01 ff1591951100    call    qword ptr [KERNEL32!_imp_CreateProcessW (000007f9`f813e098)]
000007f9`f8024b07 4883c458        add     rsp,58h

对 _imp_CreateProcessW 的调用具有误导性,因为当我跟踪 (t) 到我在该调用处的正确位置时,这就是我所看到的

KERNEL32!CreateProcessWStub+0x4d:
000007f9`f8024b01 ff1591951100    call    qword ptr [KERNEL32!_imp_CreateProcessW (000007f9`f813e098)] ds:000007f9`f813e098={KERNELBASE!CreateProcessW (000007f9`f7578960)}

所以看起来 _imp_CreateProcessW 地址是一个相对地址(链接器留下的?)。 并且数据段寄存器(ds)以某种方式用于解析最终地址(在这种情况下,KERNELBASE!CreateProcessW(000007f9`f7578960)) 这没有任何意义,因为我读到现代架构中不使用段(除了保存 TCB 地址的 fs 和 gs 寄存器)

我的问题是:

  • 那里发生了什么?

  • 为什么在 kernel32.dll 中不存在 CreateProcessW(只有存根存在)。 MSDN 说 CreateProcess 在 kernel32.dll 中

  • imp 开头的符号背后的故事是什么。它们是链接器工件吗?

谢谢!!!

注意:我在开始时运行 .symfix 和 .reload。 那时寄存器的值(就在调用之前):

0:000> r
rax=0000000000000000 rbx=0000000000000048 rcx=0000000000000000
rdx=0000000000535138 rsi=0000000000000000 rdi=0000000000000000
rip=000007f9f8024b01 rsp=00000000004df550 rbp=0000000000000000
 r8=0000000000000000  r9=0000000000000000 r10=0000000000000000
r11=00000000004df5a8 r12=0000000000000000 r13=000007f7abfb1258
r14=0000000000000000 r15=0000000000000000
iopl=0         nv up ei pl nz na po nc
cs=0033  ss=002b  ds=002b  es=002b  fs=0053  gs=002b             efl=00000206

【问题讨论】:

  • Ds 仍在使用,因为处理器需要它。然而,它不再以任何有趣的方式使用。 CreateProcess 的入口点在 kernel32 中。它调用另一个 DLL 的事实是一个实现细节。而“imp”符号是对 PE 导入表的引用。但是你的部分编程问题是什么?是否有您正在尝试修复的错误?
  • 嗨 Raymond,我的问题是为什么 kernel32!_imp_CreateProcessW 出现在程序集中,但它是 kernelbase!CreateProcessW 被调用。但是您的评论间接回答了它。 imp... 是导入表中包含 kernelbase!CreateProcessW 地址的槽。谢谢!!!
  • 如果那是你的问题(你问了三个),那么这里就回答了:call stack and disassembly doubt
  • 有趣。在他的回答中,他谈到了 JMP 指令。从我在调试过程中看到的情况来看,imp... 基本上是导入表中的槽地址,其中包含实际实现的地址(kernelbase!createprocessw)。不涉及 jmp,调用 qword ptr 就可以了。
  • 查看this question的回复。

标签: debugging assembly linker windbg cpu-registers


【解决方案1】:

引入了 IIRC __imp_ 和存根来处理 SxS。您会注意到大多数(如果不是全部) kernel32 和 kernelbase 调用最终都会调用 __imp_。 如果关于存根,一个简单的例子是

IsDebuggerPresent()

对此执行 GetProcAddress 将返回 IsDebuggerPresentStub 的地址,该地址将跳转到 IsDebuggerPresent,而 IsDebuggerPresent 又将跳转到: p>

_imp__IsDebuggerPresent

本质上,你是对的。 _imp__XXX 有点像 VFT。

【讨论】:

  • __imp__ 只是代表 IAT 条目,它绝对与 SxS 无关。
猜你喜欢
  • 2011-12-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多