簡體   English   中英

實現x86到x64匯編代碼的切換

[英]Implement x86 to x64 assembly code switch

我一直在尋找NtDll如何用於x86進程,並使用IDA PRO調試了功能NtCreateFile 其代碼如下:

mov     eax, 55h        ; NtCreateFile
mov     edx, offset _Wow64SystemServiceCall@0 ; 
call    edx ; Wow64SystemServiceCall() ; 
retn    2Ch

Wow64SystemServiceCall()

mov     edx, large fs:30h
mov     edx, [edx+464h]
test    edx, 2
jz      short loc_7738B5C8
int     2Eh             ; DOS 2+ internal - EXECUTE COMMAND
                        ; DS:SI -> counted CR-terminated command string
retn
loc_7738B5C8:                           ; CODE XREF: 
jmp     far ptr byte_7738B8FF

我查找了jmp far ptr byte_7738B8FF的命令代碼,它是EA CF B5 38 77 33 00 ,它跳轉到另一個段0x33 jmp 0x33:0x7738b5cf 因此,從我在Internet上閱讀的內容來看,這是64位系統上進程的x64段基礎,對嗎? 不幸的是,我無法進一步調試,因為ida並沒有跟上跳轉。 但是我制作了另一個針對x64編譯的簡單C應用程序,名為CreateFile ,附加了x64 IDA PRO Remote調試器,並進行了反匯編,而NtCreateFile看起來像這樣:

x64_NtCreateFile proc near  
mov     r10, rcx
mov     eax, 55h
test    byte ptr ds:7FFE0308h, 1
jnz     short loc_7FFED6695B85
syscall
retn
loc_7FFED6695B85:                     
int     2Eh             ; DOS 2+ internal - EXECUTE COMMAND
                        ; DS:SI -> counted CR-terminated command string
retn

所以我有幾個問題,如何從附加了ntdll的x86進程跳轉遠跳轉到jmp 0x33:0x7738b5cf才進入第一個指令x64_NtCreateFile 從x86到x64的切換在這種情況下究竟如何發生? 基本上,我可以制作x86應用程序,並通過跳轉切換段,然后在其中執行x64代碼,我可以通過執行db (0x00) ; x64 machine code commands類的操作來創建該代碼db (0x00) ; x64 machine code commands db (0x00) ; x64 machine code commands ,對嗎?

如果查看地址0x7738b5cf的字節,您會看到類似

41 FF A7 F8 00 00 00 (至少在Windows 8.1或更高版本上)

對應於單個x86_64指令jmp QWORD PTR [r15+0xf8]

在通過遠跳轉從32位代碼執行切換到64位代碼執行之后, R15寄存器將始終指向wow64cpu.dll的特殊跳轉表( R15寄存器設置為從64位代碼指向該表,在應用程序的32位入口點之前執行)。

[r15+0xf8]恰好指向CpupReturnFromSimulatedCode內方法wow64cpu.dll ,其將設置正確的上下文並執行實際的系統調用(在你的情況下NtCreateFile使用) syscall指令。

有關詳細信息,請參閱:

是的,我可以確認人們可以在64位Windows上運行的32位Windows應用程序中執行64位代碼。

將x86與x64代碼混合在一起將提供說明和操作方法示例。

這是我嘗試過的(適用於我的Smaller C編譯器,並使用它編譯):

#define EM(a) asm("db " #a);

#define X64_Start_with_CS(_cs) \
{ \
    EM(0x6A) EM(_cs)                     /*  push   _cs                   */ \
    EM(0xE8) EM(0) EM(0) EM(0) EM(0)     /*  call   $+5                   */ \
    EM(0x83) EM(4) EM(0x24) EM(5)        /*  add    dword [esp], 5        */ \
    EM(0xCB)                             /*  retf                         */ \
}

#define X64_End_with_CS(_cs) \
{ \
    EM(0xE8) EM(0) EM(0) EM(0) EM(0)     /*  call   $+5                   */ \
    EM(0xC7) EM(0x44) EM(0x24) EM(4)     /*                               */ \
    EM(_cs) EM(0) EM(0) EM(0)            /*  mov    dword [rsp + 4], _cs  */ \
    EM(0x83) EM(4) EM(0x24) EM(0xD)      /*  add    dword [rsp], 0xD      */ \
    EM(0xCB)                             /*  retf                         */ \
}

#define X64_Start() X64_Start_with_CS(0x33)
#define X64_End() X64_End_with_CS(0x23)

#define __break() asm("int3")

int main(void)
{
  __break();
  X64_Start();
  EM(0x48) EM(0x8D) EM(0x05) EM(0xF9) EM(0xFF) EM(0xFF) EM(0xFF) // lea rax, [$] ; rip-relative
  X64_End();
  __break();
}

然后,我在調試器下運行它,並注意到當擊中第二個斷點時,eax包含64位指令“ lea rax,[$]”的地址。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM