C++ 创建远程线程正在使进程崩溃
我正在尝试在另一个进程中注入代码,到目前为止已经取得了一些成功,我可以在目标进程中注入数据和方法。我可以执行远程线程,只有当线程函数没有主体时,线程完成后才会得到返回值。例如,如果我从ThreadFunc中省略MessageBox行,那么它将工作,但不存在std::cout/printf/MessageBox,也不存在windows api调用。要么我立即从那个函数返回,要么做一些简单的数学运算 编译代码C++ 创建远程线程正在使进程崩溃,c++,winapi,C++,Winapi,我正在尝试在另一个进程中注入代码,到目前为止已经取得了一些成功,我可以在目标进程中注入数据和方法。我可以执行远程线程,只有当线程函数没有主体时,线程完成后才会得到返回值。例如,如果我从ThreadFunc中省略MessageBox行,那么它将工作,但不存在std::cout/printf/MessageBox,也不存在windows api调用。要么我立即从那个函数返回,要么做一些简单的数学运算 编译代码 #include <windows.h> #include <tlhel
#include <windows.h>
#include <tlhelp32.h>
#include <string.h>
#include <iostream>
using namespace std;
#define cbNewProc 1600
typedef struct {
HWND hwnd;
} INJDATA, *PINJDATA;
static const char *err_str(void) {
static char buf[2048];
if ( FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, GetLastError(), 0, buf,
sizeof(buf), NULL))
return buf;
return "Unknown error";
}
// entry point in remote process
static LRESULT CALLBACK ThreadFunc(LPVOID param) {
MessageBox(NULL, "I am inside remote process", "Hiiii", 0);
return 1;
}
static int inject_code(DWORD pid) {
cout << "Process found: " << pid << endl;
HANDLE hp = OpenProcess(PROCESS_CREATE_THREAD | PROCESS_QUERY_INFORMATION |
PROCESS_VM_OPERATION | PROCESS_VM_WRITE | PROCESS_VM_READ, FALSE, pid);
if (!hp) {
fprintf(stderr, "OpenProcess( %s )\n", err_str());
return 0;
}
int size = sizeof(INJDATA) + cbNewProc;
BYTE* pDataRemote = (BYTE*) VirtualAllocEx(hp, NULL, size,
MEM_COMMIT, PAGE_EXECUTE_READWRITE);
if (!pDataRemote) {
fprintf(stderr, "VirtualAllocEx( %s )\n", err_str());
CloseHandle(hp);
return 0;
}
SIZE_T dwNumBytesXferred;
BYTE* pNewProcRemote = pDataRemote + sizeof(INJDATA);
if (!WriteProcessMemory(hp, pNewProcRemote, (void*) &ThreadFunc,
cbNewProc, &dwNumBytesXferred)) {
fprintf(stderr, "WriteProcessMemory( %s )\n", err_str());
VirtualFreeEx(hp, pDataRemote, size, MEM_RELEASE);
CloseHandle(hp);
return 0;
}
INJDATA DataLocal;
ZeroMemory(&DataLocal, sizeof(INJDATA));
if (!WriteProcessMemory(hp, pDataRemote, &DataLocal, sizeof(INJDATA),
&dwNumBytesXferred)) {
fprintf(stderr, "WriteProcessMemory( %s )\n", err_str());
VirtualFreeEx(hp, pDataRemote, size, MEM_RELEASE);
CloseHandle(hp);
return 0;
}
printf("pDataRemote=%ld\n", pDataRemote);
printf("pNewProcRemote1=%ld\n", pNewProcRemote);
printf("pNewProcRemote2=%ld\n", pNewProcRemote + cbNewProc);
int nSuccess = 0;
DWORD dwThreadId;
HANDLE hThread = CreateRemoteThread(hp, NULL, 0,
(LPTHREAD_START_ROUTINE) pNewProcRemote, pDataRemote, 0,
&dwThreadId);
if (hThread == 0) {
cout << "CreateRemoteThread failed" << endl;
return 0;
}
WaitForSingleObject(hThread, INFINITE);
GetExitCodeThread(hThread, (PDWORD) &nSuccess);
VirtualFreeEx(hp, pDataRemote, size, MEM_RELEASE);
cout << "nSuccess=" << nSuccess << ", size=" << size << endl;
CloseHandle(hp);
return 1;
}
int main() {
cout << "Remote Thread" << endl;
HANDLE h;
PROCESSENTRY32 p;
h = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if (h == INVALID_HANDLE_VALUE) {
fprintf(stderr, "CreateToolHelp32Snapshot( %s )\n", err_str());
return 0;
}
p.dwSize = sizeof(p);
if (!Process32First(h, &p)) {
fprintf(stderr, "Process32First( %s )\n", err_str());
goto out_close;
}
do {
if (strcasecmp(p.szExeFile, "dllexp.exe"))
continue;
inject_code(p.th32ProcessID);
} while (Process32Next(h, &p));
out_close: CloseHandle(h);
return 0;
}
#包括
#包括
#包括
#包括
使用名称空间std;
#定义cbnewproc1600
类型定义结构{
HWND-HWND;
}INJDATA,*PINJDATA;
静态常量字符*err_str(void){
静态字符buf[2048];
if(FormatMessage)(FORMAT_MESSAGE_FROM_SYSTEM,NULL,GetLastError(),0,buf,
sizeof(buf,NULL))
返回buf;
返回“未知错误”;
}
//远程进程中的入口点
静态LRESULT回调ThreadFunc(LPVOID参数){
MessageBox(空,“我在远程进程内”,“Hiiii”,0);
返回1;
}
静态int注入_代码(DWORD pid){
cout这是注定要失败的。您的代码基于这样的假设:在目标进程中,程序中MessageBoxA
的地址也将是MessageBoxA
的地址。没有理由这样做。您的代码基于这样的假设:目标进程将在ame地址作为调用程序,同样没有理由期望。没有理由期望目标进程与您的进程具有相同的运行时,位于相同的地址。依此类推
通过CreateRemoteThread
进行注入时,有两种常用方法:
如果您同时控制这两个进程,那么您可以安排目标进程拥有一个线程函数,该函数的地址可以通过IPC获得。换句话说,您将线程函数编译到目标进程中,它就在那里等待您
线程函数的签名与LoadLibrary
的签名兼容。因此,您可以传递LoadLibrary
的地址(在目标进程中)并传递一个参数,该参数是在目标进程中分配的以null结尾的字符数组的地址。该字符数组包含到DLL的路径,该DLL随后加载到目标进程中,然后在其DllMain
中启动另一个线程,该线程执行需要执行的任何工作
这两种方法的示例都可以在websearch中找到。这是注定要失败的。您的代码基于这样的假设,即在目标进程中,程序中的MessageBoxA
的地址也将是MessageBoxA
的地址。没有理由这样做。您的代码是b假设目标进程将包含与调用程序位于同一地址的字符串文本,同样,没有理由期望。没有理由期望目标进程与您的进程具有相同的运行时,位于相同的地址。依此类推
通过CreateRemoteThread
进行注入时,有两种常用方法:
如果您同时控制这两个进程,那么您可以安排目标进程拥有一个线程函数,该函数的地址可以通过IPC获得。换句话说,您将线程函数编译到目标进程中,它就在那里等待您
线程函数的签名与LoadLibrary
的签名兼容。因此,您可以传递LoadLibrary
的地址(在目标进程中)并传递一个参数,该参数是在目标进程中分配的以null结尾的字符数组的地址。该字符数组包含到DLL的路径,该DLL随后加载到目标进程中,然后在其DllMain
中启动另一个线程,该线程执行需要执行的任何工作
这两种方法的示例都很普遍,可以在websearch中找到。你说dll注入是唯一的可能性,但是guy提到了一种没有dll路由的方法,我似乎无法让它工作。你没有遵守上面列出的所有注意事项。我相信我已经遵循了1-10的步骤,然后改为“释放”build,也是MessageBox在user32中,作者说模块user32在当前进程和远程进程中都映射在同一位置。如果您能看一下,我已经粘贴了示例中的代码。-顺便说一句,我使用的是mingw编译器,这能起到作用吗?我认为没有理由相信user32将在稳定的地址加载。此外,根据使用的链接器,MessageBoxA
可能指向存根,而不是user32中的函数。您违反了该文章中的第2条警告。对,当我通过injdata(string memcpied)发送字符串时,我违反了第2条,仍然是失败的,所以可能正如你所说的,问题在于api地址映射错误。你是说dll注入是唯一的可能性,但是guy提到了一种没有dll路由的方法,我似乎无法让它工作。你没有遵守这里列出的所有注意事项。我相信我遵循了1-10的步骤,然后进行了更改“释放”build,也是MessageBox在user32中,作者说模块user32在当前进程和远程进程中都映射在同一位置。如果您能看一下,我已经粘贴了示例中的代码。-顺便说一句,我使用的是mingw编译器,这能起到作用吗?我认为没有理由相信user32将在稳定的地址加载。此外,根据使用的链接器,MessageBoxA
可能指向存根而不是user32中的函数。您违反了该文章中的第2条警告。对,当我通过injdata(string memcpied)发送字符串时,我违反了第2条