x86 Code Injection into an x86 Process from a x64 Process

允我心安 提交于 2019-12-01 06:21:14

Use VirtualAllocEx() to allocate a block of executable memory inside of the target process, then use WriteProcessMemory() to write x86 or x64 machine instructions into that memory block as needed. Have those instructions call LoadLibrary(), GetProcAddress(), an the exported DLL function as needed. Then use CreateRemoteThread() to execute the memory block. Your injector cannot call the exported DLL function directly if it is running in a separate process. The exported function has to be loaded and called within the context of the target process. And do not subtract the return value of LoadLibrary() from the return value of GetProcAddress(). GetProcAddress() returns a direct memory pointer to the function so it can be called directly.

Update: a variation of this is to put all of your injected code inside of the DLL's entry point (or have the entry point spawn a thread to run the code) when it is called with the DLL_ATTACH_PROCESS reason. Thus no need to export any functions from the DLL. Then you can use VirtualAllocEx() and WriteProcessMemory() to store the DLL's path into the target process, and then use CreateRemoteThread() to invoke LoadLibrary() directly. Kernel functions always have the same memory address across processes, so your injecting process can call GetProcAddress() within its own address space to get the address of LoadLibrary() and then pass that pointer to the lpStartAddress parameter of CreateRemoteThread(). This way, you don't have to worry about writing any x86/x64 assembly code.

This technique is described in more detail in Section 3 of this article:

Three Ways to Inject Your Code into Another Process

In case someone finds this question and is still confused after reading through the comments, you can find an (admittedly ugly) proof of concept here. Assuming you already know the normal strategy for DLL injection, here's an explanation of the what you'll need to do differently. (with the relevant code):


Locating our Exports (injdll32_64.c)

Normally we could go with the LoadLibrary/GetProcAddress route, but since the two modules in question are targeted for different processors, we need to do things differently. As Remy Lebeau suggested in his answer, we could do this completely on the assembly side. From my perspective, however, writing assembly to locate the base address of kernel32.dll, find the export table, and locate LoadLibrary and GetProcAddress seemed like a pain in the ass. Instead, I handled it on the C side by reading in each DLL, searching the IMAGE_EXPORT_DIRECTORY for the necessary exports, and storing their RVA's for later use.


Calling our Exports by RVA (injdll32.c, x86.final.asm)

For my purposes, I needed to have the injected DLL execute within the main thread of the target application. To do that, I suspended the main thread of the target application, allocated memory for my pre-assembled machine code, filled in the placeholders with the appropriate export RVAs, changed the EIP of the target application with calls to GetThreadContext/SetThreadContext, and resumed the suspended thread. (Not necessarily in that order) Unfortunately, I never got around to writing a mechanism for freeing up the memory we VirtualAlloc'ed in our target application, but one of the solutions for doing so would be to implement a mechanism for notifying the injector when the target process returns to its original EIP. At that point, it would be safe for the injector to VirtualFree the allocated memory. (Alternatively, you could always find a suitable code cave and eliminate the even worry about freeing up memory)

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!