32位程序注入64位DLL到64位进程
Posted jzdwajue
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了32位程序注入64位DLL到64位进程相关的知识,希望对你有一定的参考价值。
向其它进程注入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位进程注入64位DLL到64位进程显然更好。
在一番Google之后找到了这篇文章。
这篇文章的作者研究出来一种在Wow64进程中运行x64代码的方法,而且将其封装成了这个库。
本文就是介绍怎样使用这个库实现Wow64环境下32位进程向64位进程注入DLL。
Wow64环境下32位程序注入64位DLL到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的代码,再反汇编它。
跟据内存地址。easy得到以下的机器码与汇编代码的相应关系。
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> |
这段代码在创建远程线程成功即觉得注入成功,为了更加准确的推断是否注入成功能够在注入的机器码添加额外的代码来推断是否注入成功。
以上是关于32位程序注入64位DLL到64位进程的主要内容,如果未能解决你的问题,请参考以下文章