32位程序注入64位DLL到64位进程

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 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29NTSTATUS
NTAPI
RtlCreateUserThread(
_In_ HANDLE processHandle,
_In_ SECURITY_DESCRIPTOR* securityDescriptor,    _In_ BOOLEAN createSuspended,
_In_ ULONG stackZeroBits,
_Inout_opt_ size_t* stackReserved,
_Inout_opt_ size_t* stackCommit,
drifts
_In_ const void* startAddress,
_In_ void* startParameter,
_Inout_ HANDLE* threadHandle,
_Inout_opt_ CLIENT_ID* clientID
);
NTSTATUS
NTAPI
LdrLoadDll(
_In_opt_ PWSTR SearchPath,
_In_opt_ PULONG LoadFlags,
_In_ PUNICODE_STRING Name,
_Out_opt_ PVOID *BaseAddress
);
VOID
NTAPI
RtlExitUserThread(
_In_ NTSTATUS Status
);
使⽤RtlCreateUserThread创建远程线程,在远程线程中调⽤LdrLoadDll载⼊要注⼊的DLL⽂件。最后在远程线程中调⽤RtlExitUserThread退出线程。
为了在远程线程中调⽤两个函数(LdrLoadDll、RtlExitUserThread)。须要将要运⾏的x64代码写⼊⽬标进程,然后让远程线程运⾏这段代码,在这之前须要了解⼀些预备知识。能够看MSDN中的。
通过这个篇⽂章我们知道了。
在调⽤约定上Windows在x64进⾏了统⼀,也就是说⽆论你有没有显式指定调⽤约定,指定了何种调⽤约定。终于编译后都使⽤__fastcall这⼀种调⽤约定。
在參数传递上对于Integer类型(含指针)前4个參数通过RCX、RDX、R8、R9寄存器传递,其它參数通过栈传递。
LdrLoadDll有4个參数都是指针,RtlExitUserThread仅仅有1个參数是Integer类型。为这两个函数传递參数仅仅通过寄存器就⾜够了。
当然我们不须要⾃⼰去写汇编代码再将汇编代码转成机器码,⾸先先写以下这样⼀段代码。
1 2 3 4 5 6 7 8 9 10typedef unsigned long long DWORD64;
typedef DWORD64 (*Func4_Type)(DWORD64, DWORD64, DWORD64, DWORD64);
typedef DWORD64 (*Func1_Type)(DWORD64);
void ThreadProc(void*)
{
((Func4_Type)(0x1234567890123456))(0x1111111111111111, 0x2222222222222222, 0x3333333333333333, 0x4444444444444444);    ((Func1_Type)(0x6543210987654321))(0x5555555555555555);
}
然后使⽤VC编译器将其编译成x64的代码,再反汇编它。
VS2013 Debug 反汇编的结果
跟据内存地址。easy得到以下的机器码与汇编代码的相应关系。
10x48 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 2 3 4#include <memory> #include <string>
#include <Windows.h>
5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127#include "wow64ext.h"
enum class InjectResult {
OK,
Error_OpenProcess,
Error_VirtualAllocEx,
Error_GetProcAddress,
Error_WriteProcessMemory,
Error_CreateRemoteThread
};
template<typename Res, typename Deleter>
class ScopeResource {
Res res;
Deleter deleter;
三叔丁基膦
ScopeResource(const ScopeResource&) {}
public:
Res get() const {
return this->res;
}
ScopeResource(Res res, Deleter deleter) : res(res), deleter(deleter) {}
~ScopeResource() {
this->deleter(this->res);
}
};
InjectResult Wow64InjectWin64(DWORD dwProcessId, const std::wstring& filename)
{
DWORD dwDesiredAccess = PROCESS_CREATE_THREAD | PROCESS_QUERY_INFORMATION | PROCESS_VM_OPERATION | PROCESS_VM_WRITE | PROCESS_VM_READ;
auto closeProcessHandle = [](HANDLE hProcess) {
if(hProcess != NULL) CloseHandle(hProcess);
};
ScopeResource<HANDLE, decltype(closeProcessHandle)> targetProcessHandle(OpenProcess(dwDesiredAccess, FALSE, dwProcessId), closeProcessHandle);
() == NULL) {
return InjectResult::Error_OpenProcess;
}
unsigned char injectCode[] = {
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, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // mov      r9,0
阿穆尔0x49, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // mov      r8,0
0x48, 0xba, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // mov      rdx,0
0x48, 0xb9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // mov      rcx,0
0x48, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // mov      rax,0
0xff, 0xd0,                                                // call      rax
0x48, 0xb9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // mov      rcx,0
0x48, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // mov      rax,0
0xff, 0xd0                                                  // call      rax
};
size_t parametersMemSize = sizeof(DWORD64) + sizeof(_UNICODE_STRING_T<DWORD64>) + (filename.size() + 1) * sizeof(wchar_t);
auto freeInjectCodeMem = [&targetProcessHandle, &injectCode](DWORD64 address) {
if(address != 0) (), address, sizeof(injectCode), MEM_COMMIT | MEM_RESERVE);
};
ScopeResource<DWORD64, decltype(freeInjectCodeMem)> injectCodeMem((), NULL, sizeof(injectCode), MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE), freeInjectCodeMe    auto freeParametersMem = [&targetProcessHandle, parametersMemSize](DWORD64 address) {
if(address != 0) (), address, parametersMemSize, MEM_COMMIT | MEM_RESERVE);
};
ScopeResource<DWORD64, decltype(freeParametersMem)> parametersMem((), NULL, parametersMemSize, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE), freeParametersMem);
if (() == 0 || () == 0) {
return InjectResult::Error_VirtualAllocEx;
}
DWORD64 ntdll64 = GetModuleHandle64(L"ntdll.dll");
DWORD64 ntdll_LdrLoadDll = GetProcAddress64(ntdll64, "LdrLoadDll");
DWORD64 ntdll_RtlExitUserThread = GetProcAddress64(ntdll64, "RtlExitUserThread");
DWORD64 ntdll_RtlCreateUserThread = GetProcAddress64(ntdll64, "RtlCreateUserThread");
if(ntdll_LdrLoadDll == 0 || ntdll_RtlExitUserThread == 0 || ntdll_RtlCreateUserThread == 0) {
return InjectResult::Error_GetProcAddress;
}
std::unique_ptr<unsigned char[]> parameters(new unsigned char[parametersMemSize]);
std::(), 0, parametersMemSize);
_UNICODE_STRING_T<DWORD64>* upath = reinterpret_cast<_UNICODE_STRING_T<DWORD64>*>(() + sizeof(DWORD64));
牛顿物理仿真upath->Length = filename.size() * sizeof(wchar_t);
upath->MaximumLength = (filename.size() + 1) * sizeof(wchar_t);
wchar_t* path = reinterpret_cast<wchar_t*>(() + sizeof(DWORD64) + sizeof(_UNICODE_STRING_T<DWORD64>));
std::copy(filename.begin(), d(), path);
upath->Buffer = () + sizeof(DWORD64) + sizeof(_UNICODE_STRING_T<DWORD64>);
union {
DWORD64 from;
unsigned char to[8];
} cvt;
// r9
cvt.from = ();
std::memcpy(injectCode + 32, , ));
// r8
cvt.from = () + sizeof(DWORD64);
std::memcpy(injectCode + 42, , ));
// rax = LdrLoadDll
cvt.from = ntdll_LdrLoadDll;
std::memcpy(injectCode + 72, , ));
// rax = RtlExitUserThread
cvt.from = ntdll_RtlExitUserThread;
std::memcpy(injectCode + 94, , ));
if(FALSE == (), (), injectCode, sizeof(injectCode), NULL)
|| FALSE == (), (), (), parametersMemSize, NULL)) {
return InjectResult::Error_WriteProcessMemory;
}
DWORD64 hRemoteThread = 0;
struct {
DWORD64 UniqueProcess;
DWORD64 UniqueThread;
} client_id;
X64Call(ntdll_RtlCreateUserThread, 10,
((), // ProcessHandle
(DWORD64)NULL,                      // SecurityDescriptor
(DWORD64)FALSE,                    // CreateSuspended
(DWORD64)0,                        // StackZeroBits
(DWORD64)NULL,                      // StackReserved
(DWORD64)NULL,                      // StackCommit
128 129 130 131 132 133 134 135 136 137        (),                // StartAddress
(DWORD64)NULL,                      // StartParameter
(DWORD64)&hRemoteThread,            // ThreadHandle        (DWORD64)&client_id);              // ClientID
回归热螺旋体
if(hRemoteThread != 0) {
CloseHandle((HANDLE)hRemoteThread);
return InjectResult::OK;
}
return InjectResult::Error_CreateRemoteThread;
}
这段代码在创建远程线程成功即觉得注⼊成功,为了更加准确的推断是否注⼊成功能够在注⼊的机器码添加额外的代码来推断是否注⼊成功。

本文发布于:2024-09-22 09:42:58,感谢您对本站的认可!

本文链接:https://www.17tex.com/xueshu/648540.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

标签:进程   线程   函数   地址   代码   參数   远程
留言与评论(共有 0 条评论)
   
验证码:
Copyright ©2019-2024 Comsenz Inc.Powered by © 易纺专利技术学习网 豫ICP备2022007602号 豫公网安备41160202000603 站长QQ:729038198 关于我们 投诉建议