Wow64(32位進程)註入DLL到64位進程
轉載自: https://blog.poxiao.me/p/wow64-process-inject-dll-into-x64-process/
向其他進程註入DLL通常的做法是通過調用CreateRemoteThread
這個API在目標進程內創建一個遠程線程,用這個線程來調用LoadLibraryA
或LoadLibraryW
(下文統稱LoadLibrary)以實現讓目標進程加載指定的DLL文件。使用CreateRemoteThread創建一個遠程線程需要傳入一個線程過程函數的地址,並且這個函數地址是需要在目標進程中有效的。由於LoadLibrary是kernel32.dll的導出函數,所以對於運行在同一個系統上的同為32位的進程或同為64位的進程可以假定彼此進程內的LoadLibrary函數的地址是相同的。並且CreateRemoteThread的線程過程函數和LoadLibrary的參數個數相同,且參數都是指針,因此通常都是直接將LoadLibrary作為CreateRemoteThread的過程函數。然後使用VirtualAllocEx
WriteProcessMemory
往這塊內存中寫入DLL文件路徑,將這塊內存的地址作為線程過程函數(LoadLibrary)的參數。
在64位的Windows操作系統上32位進程中的LoadLibrary函數地址與64位進程的函數地址不同,因此如果想對64位進程註入DLL,簡單的做法就是使用64位進程來執行註入工作。但是如果能讓32位進程註入DLL到64位進程顯然更好。
在一番Google之後找到了這篇文章。這篇文章的作者研究出來一種在Wow64進程中執行x64代碼的方法,並且將其封裝成了這個庫。
本文就是介紹如何使用這個庫實現Wow64環境下32位進程向64位進程註入DLL。
Wow64環境下32位進程註入64位進程
32位進程難以註入DLL進64位進程是由於兩個進程內LoadLibrary的地址不同,32位進程無法知道64位進程的LoadLibrary函數地址。使用wow64ext這個庫在Wow64環境下可以讓32位進程獲取到64位的ntdll.dll的導出函數(得到的地址與64進程的地址是一樣的)。
本文使用ntdll中的這3個未文檔的函數來註入DLL。
1
|
NTSTATUS
|
使用RtlCreateUserThread
創建遠程線程,在遠程線程中調用LdrLoadDll
加載要註入的DLL文件,最後在遠程線程中調用RtlExitUserThread
退出線程。
為了在遠程線程中調用兩個函數(LdrLoadDll、RtlExitUserThread),需要將要執行的x64代碼寫入目標進程,然後讓遠程線程執行這段代碼,在這之前需要了解一些預備知識。可以看MSDN中的這篇文章。通過這個篇文章我們知道了。
- 在調用約定上Windows在x64進行了統一,也就是說不管你有沒有顯式指定調用約定,指定了何種調用約定,最終編譯後都使用
__fastcall
這一種調用約定。 - 在參數傳遞上對於Integer類型(含指針)前4個參數通過
RCX
、RDX
、R8
、R9
寄存器傳遞,其他參數通過棧傳遞。
LdrLoadDll有4個參數都是指針,RtlExitUserThread只有1個參數是Integer類型。為這兩個函數傳遞參數只通過寄存器就足夠了。
當然我們不需要自己去寫匯編代碼再將匯編代碼轉成機器碼,首先先寫下面這樣一段代碼。
1
|
typedef unsigned long long DWORD64;
|
然後使用VC編譯器將其編譯成x64的代碼,再反匯編它。
跟據內存地址,容易得到下面的機器碼與匯編代碼的對應關系。
1
|
0x48 0x89 0x4c 0x24 0x08 mov qword ptr [rsp+8],rcx
0x57 push rdi
0x48 0x83 0xec 0x20 sub rsp,20h
0x48 0x8b 0xfc mov rdi,rsp
0xb9 0x08 0x00 0x00 0x00 mov ecx,8
0xb8 0xcc 0xcc 0xcc 0xcc mov eac,0CCCCCCCCh
0xf3 0xab rep stos dword ptr [rdi]
0x48 0x8b 0x4c 0x24 0x30 mov rcx,qword ptr [__formal]
0x49 0xb9 0x44 0x44 0x44 0x44 0x44 0x44 0x44 0x44 mov r9,4444444444444444h
0x49 0xb8 0x33 0x33 0x33 0x33 0x33 0x33 0x33 0x33 mov r8,3333333333333333h
0x48 0xba 0x22 0x22 0x22 0x22 0x22 0x22 0x22 0x22 mov rdx,2222222222222222h
0x48 0xb9 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 mov rcx,1111111111111111h
0x48 0xb8 0x56 0x34 0x12 0x90 0x78 0x56 0x34 0x12 mov rax,1234567890123456h
0xff 0xd0 call rax
0x48 0xb9 0x55 0x55 0x55 0x55 0x55 0x55 0x55 0x55 mov rcx,5555555555555555h
0x48 0xb8 0x21 0x43 0x65 0x87 0x09 0x21 0x43 0x65 mov rax,6543210987654321h
0xff 0xd0 call rax
|
只要在運行的時候根據獲取到的函數地址和參數地址替換對應機器碼然後將機器碼寫入目標進程,創建線程執行這段代碼就能夠實現Wow64進程註入DLL到64位進程了。
完整的實現代碼如下(VS2012編譯通過,Windows 8 x64測試註入成功)。
1
|
#include <memory> |