下面以ntdll32!ZwQueryInformationProcess API为例分析 x86代码与x64代码之间的切换过程,
32bit的test程序:
step1:
ntdll32!ZwQueryInformationProcess:
775bfb18 b816000000 mov eax,16h
775bfb1d 33c9 xor ecx,ecx
775bfb1f 8d542404 lea edx,[esp+4]
775bfb23 64ff15c0000000 call dword ptr fs:[0C0h] fs:0053:000000c0=00000000
775bfb2a 83c404 add esp,4
775bfb2d c21400 ret 14h
在win32系统中 teb保存的是fs:[0]地址,
0:000:x86> dt _teb @$teb
+0x000 NtTib : _NT_TIB
+0x01c EnvironmentPointer : (null)
+0x020 ClientId : _CLIENT_ID
+0x028 ActiveRpcHandle : (null)
+0x02c ThreadLocalStoragePointer : (null)
+0x030 ProcessEnvironmentBlock : 0x7efdb000 _PEB
+0x034 LastErrorValue : 0
+0x038 CountOfOwnedCriticalSections : 0
+0x03c CsrClientThread : (null)
+0x040 Win32ThreadInfo : 0x00001a04 Void
+0x044 User32Reserved : [26] 0
+0x0ac UserReserved : [5] 0
+0x0c0 WOW32Reserved : (null)
+0x0c4 CurrentLocale : 0
+other field
step into 775bfb23:
wow64cpu!X86SwitchTo64BitMode:
74b82320 ea1e27b8743300 jmp 0033:74B8271E
0:000:x86> dd esp
0015f368 775bfb2a 775e7177 ffffffff 00000024
0015f378 0015f384 00000004 00000000 00000000
0015f388 00000000 0015f3a8 775da902 776a2038
0015f398 00000000 00000000 00000000 776a4224
0015f3a8 0015f3c8 775e4e51 776a2038 775e715f
0015f3b8 00000000 00000000 00000000 776a4224
0015f3c8 0015f410 775e4e15 776a4224 00000000
0015f3d8 7efde000 7efde000 775e774d 0015f3c0
栈地址0015f368 保存的是返回地址,该地址是 775bfb23 的 call dword ptr fs:[0C0h] 指令自动压入栈的。
step2:
step into 74b82320 指令:
wow64cpu!CpupReturnFromSimulatedCode:
00000000`74b8271e 67448b0424 mov r8d,dword ptr [esp] ds:00000000`0015f368=775bfb2a ;//已切换成64bit mode, 保存x86的返回地址到r8d中。
00000000`74b82723 458985bc000000 mov dword ptr [r13+0BCh],r8d ; //保存x86的返回地址到内存 [r13+0BCh]中,
00000000`74b8272a 4189a5c8000000 mov dword ptr [r13+0C8h],esp //保存x86的esp到内存 [r13+0C8h]中,
00000000`74b82731 498ba42480140000 mov rsp,qword ptr [r12+1480h]
00000000`74b82739 4983a4248014000000 and qword ptr [r12+1480h],0
00000000`74b82742 448bda mov r11d,edx
wow64cpu!TurboDispatchJumpAddressStart:
00000000`74b82745 41ff24cf jmp qword ptr [r15+rcx*8] ds:00000000`74b82450={wow64cpu!TurboDispatchJumpAddressEnd 00000000`74b82749)}
wow64cpu!TurboDispatchJumpAddressEnd:
00000000`74b82749 4189b5a4000000 mov dword ptr [r13+0A4h],esi ds:00000000`001cfdc4=776a4224
00000000`74b82750 4189bda0000000 mov dword ptr [r13+0A0h],edi
00000000`74b82757 41899da8000000 mov dword ptr [r13+0A8h],ebx
00000000`74b8275e 4189adb8000000 mov dword ptr [r13+0B8h],ebp
00000000`74b82765 9c pushfq
00000000`74b82766 5b pop rbx
00000000`74b82767 41899dc4000000 mov dword ptr [r13+0C4h],ebx
00000000`74b8276e 8bc8 mov ecx,eax
00000000`74b82770 ff150ae9ffff call qword ptr [wow64cpu!_imp_Wow64SystemServiceEx (00000000`74b81080)] //调用系统调用
00000000`74b82776 418985b4000000 mov dword ptr [r13+0B4h],eax
00000000`74b8277d e98ffeffff jmp wow64cpu!CpuSimulate+0x61 (00000000`74b82611)
step3:
wow64cpu!CpuSimulate
00000000`74b82611 4183a5d002000001 and dword ptr [r13+2D0h],1 ds:00000000`001cfff0=00000000
00000000`74b82619 0f84af000000 je wow64cpu!CpuSimulate+0x11e (00000000`74b826ce)
00000000`74b8261f 410f288570010000 movaps xmm0,xmmword ptr [r13+170h]
00000000`74b82627 410f288d80010000 movaps xmm1,xmmword ptr [r13+180h]
00000000`74b8262f 410f289590010000 movaps xmm2,xmmword ptr [r13+190h]
00000000`74b82637 410f289da0010000 movaps xmm3,xmmword ptr [r13+1A0h]
00000000`74b8263f 410f28a5b0010000 movaps xmm4,xmmword ptr [r13+1B0h]
00000000`74b82647 410f28adc0010000 movaps xmm5,xmmword ptr [r13+1C0h]
00000000`74b8264f 418b8db0000000 mov ecx,dword ptr [r13+0B0h]
00000000`74b82656 418b95ac000000 mov edx,dword ptr [r13+0ACh]
00000000`74b8265d 4183a5d0020000fe and dword ptr [r13+2D0h],0FFFFFFFEh
00000000`74b82665 418bbda0000000 mov edi,dword ptr [r13+0A0h]
00000000`74b8266c 418bb5a4000000 mov esi,dword ptr [r13+0A4h]
00000000`74b82673 418b9da8000000 mov ebx,dword ptr [r13+0A8h]
00000000`74b8267a 418badb8000000 mov ebp,dword ptr [r13+0B8h]
00000000`74b82681 418b85b4000000 mov eax,dword ptr [r13+0B4h]
00000000`74b82688 4989a42480140000 mov qword ptr [r12+1480h],rsp
00000000`74b82690 66c74424082300 mov word ptr [rsp+8],23h
00000000`74b82697 66c74424202b00 mov word ptr [rsp+20h],2Bh
00000000`74b8269e 458b85c4000000 mov r8d,dword ptr [r13+0C4h]
00000000`74b826a5 4181a5c4000000fffeffff and dword ptr [r13+0C4h],0FFFFFEFFh
00000000`74b826b0 4489442410 mov dword ptr [rsp+10h],r8d
00000000`74b826b5 458b85c8000000 mov r8d,dword ptr [r13+0C8h]
00000000`74b826bc 4c89442418 mov qword ptr [rsp+18h],r8
00000000`74b826c1 458b85bc000000 mov r8d,dword ptr [r13+0BCh]
00000000`74b826c8 4c890424 mov qword ptr [rsp],r8
00000000`74b826cc 48cf iretq
00000000`74b826ce 418bbda0000000 mov edi,dword ptr [r13+0A0h]
00000000`74b826d5 418bb5a4000000 mov esi,dword ptr [r13+0A4h]
00000000`74b826dc 418b9da8000000 mov ebx,dword ptr [r13+0A8h]
00000000`74b826e3 418badb8000000 mov ebp,dword ptr [r13+0B8h]
00000000`74b826ea 418b85b4000000 mov eax,dword ptr [r13+0B4h]
00000000`74b826f1 4989a42480140000 mov qword ptr [r12+1480h],rsp
000060000`74b826f9 41c7460423000000 mov dword ptr [r14+4],23h
00000000`74b82701 41b82b000000 mov r8d,2Bh
00000000`74b82707 418ed0 mov ss,r8w
00000000`74b8270a 418ba5c8000000 mov esp,dword ptr [r13+0C8h] //读取x86的esp
00000000`74b82711 458b8dbc000000 mov r9d,dword ptr [r13+0BCh] //读取x86的返回地址
00000000`74b82718 45890e mov dword ptr [r14],r9d
00000000`74b8271b 41ff2e jmp fword ptr [r14] //跳转到x86的返回地址:775bfb2a
step4:
跳转到x86的返回地址,继续执行x86的代码:
ntdll32!ZwQueryInformationProcess:
775bfb2a 83c404 add esp,4
775bfb2d c21400 ret 14h