Windbg _imp__xxx адрес символа разыменовывается с помощью регистра сегмента данных
Я изучаю Windbg. А для практики я отлаживаю 64-битное бесплатное приложение, которое создает процесс. Я добавил точку останова на 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)), хотя это не имеет смысла, потому что я читал, что сегменты не используются в современной архитектуре (за исключением регистров fs и gs, которые содержат адрес TCB)
Мои вопросы:
что там происходит?
почему CreateProcessW отсутствует в kernel32.dll (только заглушка). MSDN говорят, что CreateProcess находится в kernel32.dll
что за символы, начинающиеся с беса Являются ли они линкерами?
Спасибо!!!
Примечание: я запускаю.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
1 ответ
IIRC __imp_ и заглушки были введены, чтобы заботиться о SxS. Вы заметите, что большинство, если не все вызовы kernel32 и kernelbase в конечном итоге вызывают __imp_. Что касается окурков, быстрый пример
IsDebuggerPresent()
Выполнение GetProcAddress для этого вернет адрес IsDebuggerPresentStub, который перейдет к IsDebuggerPresent, который, в свою очередь, перейдет к:
_imp__IsDebuggerPresent
По сути, вы правы. _Imp__XXX работает немного как VFT.