使用CreateRemoteThread向多参数函数传递变量的实现方法咨询
CreateRemoteThread 多参数传递实现方案
CreateRemoteThread 的lpParameter参数仅支持传递单个指针,要传递多参数只需将所有参数打包到同一个结构体中,传递结构体的指针即可,具体实现步骤如下:
实现步骤
- 定义多参数承载结构体
把需要传递的所有参数封装到一个自定义结构体中:
// 定义结构体存储需要传递的所有参数 typedef struct _RemoteThreadParams { int x; LPCWSTR foo; } RemoteThreadParams, *PRemoteThreadParams;
- 在目标进程中分配参数内存
因为参数需要被目标进程访问,不能直接使用本地进程的内存地址,需要调用VirtualAllocEx在目标进程中分别申请结构体、字符串的内存空间:
int localX = 0; LPCWSTR localFoo = L"Hello World"; // 先给字符串申请远程内存,写入字符串内容 size_t strSize = (wcslen(localFoo) + 1) * sizeof(WCHAR); LPVOID remoteStrAddr = VirtualAllocEx(hProcess, NULL, strSize, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE); WriteProcessMemory(hProcess, remoteStrAddr, localFoo, strSize, NULL); // 再给结构体申请远程内存,写入结构体内容 RemoteThreadParams localParams = { .x = localX, .foo = (LPCWSTR)remoteStrAddr // 结构体里存目标进程的字符串地址 }; LPVOID remoteParamsAddr = VirtualAllocEx(hProcess, NULL, sizeof(RemoteThreadParams), MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE); WriteProcessMemory(hProcess, remoteParamsAddr, &localParams, sizeof(RemoteThreadParams), NULL);
- 编写线程入口适配函数
远程线程的入口函数只能接收一个LPVOID类型参数,需要先把参数转为结构体指针,拆分出参数后再调用目标Test函数:
注意:该适配函数需要被注入到目标进程中才能正常执行
DWORD WINAPI RemoteThreadEntry(LPVOID lpParam) { PRemoteThreadParams pParams = (PRemoteThreadParams)lpParam; // 拆分参数调用目标函数 LPCWSTR ret = Test(pParams->x, pParams->foo); // 执行完后释放远程内存(也可以在本地进程等线程结束后释放) VirtualFree(pParams->foo, 0, MEM_RELEASE); VirtualFree(pParams, 0, MEM_RELEASE); return 0; }
- 调用CreateRemoteThread传递参数
把目标进程中结构体的内存地址作为lpParameter传入即可:
// pRemoteEntry是适配函数RemoteThreadEntry在目标进程中的内存地址 CreateRemoteThread(hProcess, NULL, 0, (LPTHREAD_START_ROUTINE)pRemoteEntry, remoteParamsAddr, 0, NULL);
注意事项
- 所有要被目标进程访问的内容(包括字符串、结构体)都必须在目标进程中单独分配内存、写入数据,直接传入本地进程的地址会导致目标进程访问内存报错。
- 该方案是兼容性最高的多参数传递方案,不需要依赖汇编thunk,适配32/64位系统。
内容的提问来源于stack exchange,提问作者user16839617
相关产品推荐
相关产品推荐

