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:

相关文章
相关标签/搜索