远程线程注入的做法是通过API:CreateRemoteThread在目标进程创建远程线程,让这个线程实现LoadLibrary去加载动态库。LoadLibrary函数通过kernel32导出,在32位和64位下的地址是不同的,所以一般来说32位是无法注入64位的。
在github上有一个开源项目rewolf-wow64ext,该项目的目的是让运行在Wow64下的32位程序可以调用x64下的API。
具体方法是通过该库的函数导出LdrLoadDll,RtlCreateUserThread,RtlExitUserThread三个API,RtlCreateUserThread创建远程线程,LdrLoadDll加载动态库,RtlExitUserThread退出远程线程。代码如下:
// Wow64Injectx64.cpp : 定义控制台应用程序的入口点。 // #include "stdafx.h" #include <Windows.h> #include <iostream> #include <string> #include "shlwapi.h" #include "wow64ext.h" #pragma comment(lib,"shlwapi.lib") #pragma comment(lib,"wow64ext.lib") using namespace std; // unsigned char ShellCode[] = { 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 //PVOID* BaseAddr opt 0x49, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // mov r8,0 //PUNICODE_STRING Name 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 LdrLoadDll 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 }; BOOL Wow64Injectx64(DWORD ProcessID, const TCHAR* FilePath); int main() { cout << "Input ProcessID" << endl; ULONG_PTR ProcessID = 0; cin >> ProcessID; WCHAR FilePath[] = L"C:\\Users\\ChangSungsin\\Desktop\\测试\\Injectx64\\Injectx64\\Dll.dll"; if (Wow64Injectx64(ProcessID, FilePath)) { cout << "Inject Success" << endl; } else { cout << "Failed to Inject" << endl; } return 0; } BOOL Wow64Injectx64(DWORD ProcessID, const TCHAR* FilePath) { if (!PathFileExists(FilePath)) { return FALSE; } HANDLE hTarget = OpenProcess(PROCESS_CREATE_THREAD | PROCESS_QUERY_INFORMATION | PROCESS_VM_OPERATION | PROCESS_VM_WRITE | PROCESS_VM_READ, FALSE, ProcessID); if (INVALID_HANDLE_VALUE == hTarget) { return FALSE; } SIZE_T FilePathLength = (SIZE_T)::_tcslen(FilePath); SIZE_T ParamemterSize = (FilePathLength + 1)*sizeof(TCHAR) + sizeof(_UNICODE_STRING_T<DWORD64>) + sizeof(DWORD64); DWORD64 ParamemterMemAddr = (DWORD64)VirtualAllocEx64(hTarget, NULL, ParamemterSize, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE); DWORD64 ShellCodeAddr = (DWORD64)VirtualAllocEx64(hTarget, NULL, sizeof(ShellCode), MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); if ((!ParamemterMemAddr) || (!ShellCodeAddr)) { return FALSE; } char* ParamemterMemLocal = new char[ParamemterSize]; memset(ParamemterMemLocal, 0, ParamemterSize); _UNICODE_STRING_T<DWORD64>* UnicodeString = (_UNICODE_STRING_T<DWORD64>*)(ParamemterMemLocal + sizeof(DWORD64)); UnicodeString->Length = FilePathLength * sizeof(wchar_t); UnicodeString->MaximumLength = (FilePathLength +1)* 2; wcscpy((WCHAR*)(UnicodeString + 1), FilePath); UnicodeString->Buffer = ParamemterMemAddr + sizeof(DWORD64) + sizeof(_UNICODE_STRING_T<DWORD64>); DWORD64 Ntdll64 = GetModuleHandle64(L"ntdll.dll"); DWORD64 NtdllLdrLoadDll = GetProcAddress64(Ntdll64, "LdrLoadDll"); DWORD64 NtdllRtlCreateUserThread = GetProcAddress64(Ntdll64, "RtlCreateUserThread"); DWORD64 NtdllRtlExitThread = GetProcAddress64(Ntdll64, "RtlExitUserThread"); if (NtdllLdrLoadDll == NULL || NtdllRtlCreateUserThread == NULL || NtdllRtlExitThread == NULL) { return FALSE; } // DWORD转char union { DWORD64 from; unsigned char to[8]; }Convert; // 写入r9寄存器 Convert.from = ParamemterMemAddr; memcpy(ShellCode + 32, Convert.to, sizeof(Convert.to)); // 写入r8寄存器 Convert.from = ParamemterMemAddr + sizeof(DWORD64); memcpy(ShellCode + 42, Convert.to, sizeof(Convert.to)); // 写入LdrLoadDll地址 Convert.from = NtdllLdrLoadDll; memcpy(ShellCode + 72, Convert.to, sizeof(Convert.to)); // 写入NtdllRtlExitThread地址 Convert.from = NtdllRtlExitThread; memcpy(ShellCode + 94, Convert.to, sizeof(Convert.to)); SIZE_T WriteSize = 0; if (!WriteProcessMemory64(hTarget, ParamemterMemAddr, ParamemterMemLocal, ParamemterSize, NULL) || !WriteProcessMemory64(hTarget, ShellCodeAddr, ShellCode, sizeof(ShellCode), NULL)) { return FALSE; } DWORD64 hRemoteThread = 0; struct { DWORD64 UniqueProcess; DWORD64 UniqueThread; }ClientID; int nRet = X64Call(NtdllRtlCreateUserThread, 10, (DWORD64)hTarget, // ProcessHandle (DWORD64)NULL, // SecurityDescriptor (DWORD64)FALSE, // CreateSuspended (DWORD64)0, // StackZeroBits (DWORD64)NULL, // StackReserved (DWORD64)NULL, // StackCommit ShellCodeAddr, // StartAddress (DWORD64)NULL, // StartParameter (DWORD64)&hRemoteThread, // ThreadHandle (DWORD64)&ClientID); // ClientID) if (hRemoteThread != 0) { CloseHandle((HANDLE)hRemoteThread); return TRUE; } return TRUE; }
收藏的用户(0) X
正在加载信息~
推荐阅读
最新回复 (0)
站点信息
- 文章2305
- 用户1336
- 访客11455720
每日一句
Talent without working hard is nothing.
没有努力,天份不代表什么。
没有努力,天份不代表什么。
MySQL 数据库优化
This function has none of DETERMINISTIC, NO SQL, or READS SQL DATA in its de
免ROOT实现模拟点击任意位置
Mobaxterm终端神器
CreateProcessW要注意的细节问题
Autonomous NAT Traversal
【教程】win10 彻底卸载edge浏览器
eclipse工程基于Xposed的一个简单Hook
排名前5的开源在线机器学习
Mac OS最简单及(Karabiner)快捷键设置
发一款C++编写的麻将
VMware NAT端口映射外网访问虚拟机linux
独家发布最新可用My-AutoPost——wordpress 采集器
新会员