Mixing x86 with x64 code (混合編寫x86和x64代碼)

摘要: 幾個月前我小小的研究了在WOW64下的32位進程中運行native x64代碼。第二個設想是在64位進程下運行x86代碼。它們都是能夠的,如我google的同樣,已經有人在使用這兩種方法了:●http://vx.netlux.org/lib/vrg02.html ...

幾個月前我小小的研究了在WOW64下的32位進程中運行native x64代碼。
第二個設想是在64位進程下運行x86代碼。它們都是能夠的,如我google的同樣,已經有人在使用這兩種方法了:
●http://vx.netlux.org/lib/vrg02.html
●http://www.corsix.org/content/dll-injection-and-wow64
●http://int0h.wordpress.com/2009/12/24/the-power-of-wow64/
●http://int0h.wordpress.com/2011/02/22/anti-anti-debugging-via-wow64/
當我研究的時候尚未看上面搜索到的結果,因此下面僅僅表明我本身的看法;
x86 <-> x64 Transition(x86和x64之間的轉換)
最先來檢查x86到x64轉換的方法,是觀察windows中32位版本和64位版本的ntdll.dll中的任意syscall:

正如你所見,在64位系統上新的call fs:[0xC0](wow64cpu!X86SwitchTo64BitMode) 代替了標準call ntdll.KiFastSystemCall.               
wow64cpu!X86SwitchTo64BitMode 執行了一個簡單的遠跳轉到64位的段中了:
wow64cpu!X86SwitchTo64BitMode:
748c2320 jmp     0033:748C271E   ;wow64cpu!CpupReturnFromSimulatedCode
這就是64位Windows系統上轉換x64和x86後面的魔術。
此外它也能在非WoW64進程中運行(標準的native 64位應用程序),因此32位代碼也能運行在64位應用程序中。
總結一下,運行在64位Windows中的每一個進程(x86和x64),都分配了兩個代碼段:
●cs = 0×23 -> x86 mode
●cs = 0×33 -> x64 mode
Running x64 code inside 32-bits process(在32位進程中運行x64代碼)
首先,我準備了一些宏,將用它來標記64位代碼的開始和結尾:

執行完X64_Start()宏後,CPU直接轉換到x64模式,執行完X64_End()宏後當即回到x86模式。
因爲遠返回的opcode,以上宏都是位置獨立的。
可以調用x64版本的APIs是很是有用的。我嘗試加載過x64版本的kernel32.dll,它不是一個微不足道的任務,而且我失敗了,因此我須要堅持使用Native API。x64版本的kernel32.dll的主要問題是在已經加載x86版本的kernel32.dll的狀況下,x64 kernel32.dll有一些額外的檢查來阻止正常的加載。我相信經過一些猥瑣的hook來攔截kernel32!BaseDllInitialize能達到目的,可是這是很是複雜的任務。當我開始研究的時候,我是在WIndowsVista上,而且我能加載(用一些hacks)64位版本的kernel32和user32庫,可是他們沒有完整的功能,同時我又轉換到Windows7,使用在Vista上的方法不可以正常工做了。
讓咱們回到主題上,爲了使用Native APIs,我須要定位內存中你給的x64版本的ntdll.dll。爲了完成這個任務,我須要解析_PEB_LDR_DATA結構中的InLoadOrderModuleLi
-st。64位的_PEB被64位的_TEB包含,而且64位_TEB相似於x86平臺的(在x64上咱們須要使用gs段代替fs):
mov   eax, gs:[0x30]
它甚至能夠更簡單,由於 wow64cpu!CpuSimulate(負責轉換CPU到x86模式的函數)將gs:[0x30]的值移動到r12寄存器中,因此咱們的getTEB64()版本看起來像這樣

WOW64名字空間定義在「os_structs.h」文件中,隨後將會和其餘示例代碼添加到文章尾部。
負責定位64位ntdll.dll函數定義以下:

爲了完整支持x64 Native API調用,咱們還須要等價於GetProcAddress的函數,經過ntdll!LdrGetProcedureAddress更容易的交流。下面代碼負責獲取LdrGetProcedureAddress的地址:
爲了錦上添花,我將介紹有用的函數,能讓我在x86的C/C++代碼中直接的調用x64 Native APIs:

相關文章
相關標籤/搜索