远程线程注入数据框架

远程线程注入数据框架

通过远程线程注入的方式,不能直接调用本程序里的函数,因此需要将被调用的函数和相应的数据写入到对方的内存中,再去调用。

步骤:

  • 在对方内存分配空间

  • 获取系统dll(例如kernel.dll)的地址

    • 在不同exe中一般在同一地址
  • 将系统dll的地址和需要用到的参数数据写入到对方的内存中

  • 将注入的函数写入到对方的内存中

  • 开启一个远程线程,执行注入的函数,调用所用的dll函数

// InjectDll2Exe.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//
#include <Windows.h>
#include <tchar.h>
#include <iostream>

using std::cin;
using std::cout;
using std::endl;

using f_LoadLibrary = unsigned long long(WINAPI*)(wchar_t* dllName);
using f_GetProcAddress = FARPROC(WINAPI*)(unsigned long long hModule, char* lpProcName);

struct RemoteCall //数据框架,用于注入到对方的内存来被函数调用
{
wchar_t dllName[0x100] = {}; // 被注入的dll名字
char funcName[0x20] = { "main_loop_window" };
wchar_t kernelName[0x10] = { _T("kernel32.dll") };
f_LoadLibrary pLoadLiarbry; // LoadLibrary函数地址
f_GetProcAddress pGetProcAddress;
};


void Inject() // 注入的远程函数
{
unsigned long long address = 0xCCCCCCCCCCCCCCCC;
RemoteCall* p = (RemoteCall*)address;
auto libAddr = p->pLoadLiarbry(p->dllName);
auto myfunc = p->pGetProcAddress(libAddr, p->funcName);
myfunc();
}

RemoteCall* WriteData(HANDLE &hProcess) // 写入RemoteCall到目标进程,返回写入地址
{
RemoteCall data;
auto loadLibraryAddr = GetProcAddress(LoadLibraryW(_T("kernel32.dll")), "LoadLibraryW");
if (!loadLibraryAddr)
{
cout << "get loadLibrary failed!";
exit(-1);
}
data.pLoadLiarbry = (f_LoadLibrary)loadLibraryAddr;

auto getProcAddressAddr = GetProcAddress(LoadLibraryW(_T("kernel32.dll")), "GetProcAddress");
if (!getProcAddressAddr)
{
cout << "get getProcAddress failed!";
exit(-1);
}
data.pGetProcAddress = (f_GetProcAddress)getProcAddressAddr;

// 计算dll名字的长度,写入数据
size_t lenth{};
//const wchar_t* dllName = L"C:/Users/10654/Documents/WeChat Files/wxid_7jgdmcfyfwjq22/FileStorage/File/2023-12/SharkTeeth_ImGui_DLL/x64/Release/SharkTeeth_ImGui_DLL.dll";
//const wchar_t* dllName = L"D:/codeSpace/IDE-Project/vs2022/TestDll/x64/Release/TestDll.dll";
const wchar_t* dllName = L"D:/codeSpace/IDE-Project/vs2022/inject-window-dll/x64/Release/inject-window-dll.dll";
for (lenth = 0; dllName[lenth++];);
memcpy(data.dllName, dllName, (lenth + 1) * 2);

auto data_address = VirtualAllocEx(hProcess, 0, sizeof(data), MEM_COMMIT, PAGE_EXECUTE_READWRITE);
if (!data_address)
{
cout << "remote data inject failed!";
exit(-1);
}
WriteProcessMemory(hProcess, data_address, (LPCVOID)&data, sizeof(data), NULL);

return (RemoteCall*)data_address;
}

void* WriteCode(HANDLE &hProcess, RemoteCall* data_address) // 写入注入函数代码到目标进程,返回代码地址
{
char _code[0x200] = {};
memcpy(_code, Inject, sizeof(_code));
for (size_t i = 0; i < 0x200; i++)
{
unsigned long long * p = (unsigned long long*)&_code[i];
if (*p == 0xCCCCCCCCCCCCCCCC)
{
*p = (unsigned long long)data_address;
break;
}
}
auto remote_code_address = VirtualAllocEx(hProcess, 0, sizeof(_code), MEM_COMMIT, PAGE_EXECUTE_READWRITE);
if (!remote_code_address)
{
cout << "remote code inject failed!";
exit(-1);
}
WriteProcessMemory(hProcess, remote_code_address, (LPCVOID)_code, sizeof(_code), NULL);
return remote_code_address;
}

int main()
{
DWORD pid{};
cout << "请输入Pid:";
cin >> pid;
auto hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid);
if (!hProcess)
{
cout << "OpenProcess failed!" << endl;
return -1;
}
auto data_address = WriteData(hProcess);
auto call_address = WriteCode(hProcess, data_address);

auto hThread = CreateRemoteThread(hProcess, NULL, 0, (LPTHREAD_START_ROUTINE)call_address, NULL, 0, NULL);
if (!hThread)
{
cout << "Create Remote Thread Failed!" << endl;
return -1;
}

//WaitForSingleObject(hThread, INFINITE);
MessageBox(NULL, L"注入成功", L"注入提示", MB_OK);
return 0;
}