鱼C论坛

 找回密码
 立即注册
查看: 2079|回复: 14

[已解决]创建远程线程后进程异常退出

[复制链接]
发表于 2022-9-10 10:49:53 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
运行环境WIN10 x64,尝试使用CreateRemoteThread在计算器中创建远程进程后,计算器程序直接异常退出。。GetLastError的返回值为0(差不多是没能找到错误)
想请教以下各位大佬程序为啥会异常退出
以下是代码:

  1. #include<stdio.h>
  2. #include<windows.h>
  3. HWND window_handle;
  4. void t_main();
  5. void t_end();
  6. int main()
  7. {
  8.         HANDLE process_handle;
  9.         HANDLE thread_handle=0;
  10.         DWORD process_ID;
  11.         DWORD64 thread_address;
  12.         DWORD thread_ID;
  13.         BOOL result;
  14.         int code_size=(LPBYTE)t_end-(LPBYTE)t_main;
  15.         printf("待嵌入的代码大小为:%d字节\n",code_size);

  16.         window_handle = FindWindow(NULL, "计算器");
  17.         printf("获取到的窗口句柄为0x%X\n",window_handle);

  18.         GetWindowThreadProcessId(window_handle,&process_ID);
  19.         process_handle=OpenProcess(PROCESS_ALL_ACCESS,FALSE,process_ID);
  20.         printf("获取到的进程句柄为0x%X\n", process_handle);

  21.         thread_address = VirtualAllocEx(process_handle,NULL,code_size,MEM_COMMIT,PAGE_EXECUTE_READ);
  22.         printf("申请到的进程中合适的地址为:0x%X\n",thread_address);

  23.         result = WriteProcessMemory(process_handle,thread_address,&t_main,code_size,NULL);
  24.         if (result != 0)
  25.         {
  26.                 printf("在内存中写入数据成功!\n");
  27.         }
  28.         else
  29.         {
  30.                 printf("在内存中写入数据失败。\n");
  31.         }
  32.         thread_handle = CreateRemoteThread(process_handle,NULL,0,thread_address,NULL,0,NULL);
  33.         printf("创建的线程句柄为0x%X\n", thread_handle);

  34. //        CloseHandle(window_handle);
  35. //        CloseHandle(process_handle);
  36. //        CloseHandle(thread_handle);
  37.         if (GetLastError())
  38.         {
  39.                 printf("出现错误,错误代码为:%d\n", GetLastError());   //运行下来返回值为0
  40.         }
  41.         getchar();
  42. }

  43. static void t_main()
  44. {
  45.         MessageBox(window_handle, "成功!","无",NULL);
  46. }
  47. static void t_end()
  48. {
  49.         ;
  50. }

复制代码
最佳答案
2022-9-10 16:48:30
问你,当前进程的MessageBox地址和目标进程的MessageBox地址一样吗?不一样?那你为什么在目标进程中使用当前进程的MessageBox地址?
在目标进程中如何使用MessageBox ?
LoadLibrary和GetProcAddress了解一下

  1. #include <stdio.h>
  2. #include <windows.h>
  3. #include <psapi.h>

  4. HWND window_handle;

  5. static DWORD WINAPI t_main(LPVOID lpParameter) {
  6.     void *(*parameter)[2] = (void *)lpParameter;
  7.     HMODULE (*LoadLibraryA)(LPCSTR lpLibFileName) = (*parameter)[0];
  8.     FARPROC (*GetProcAddress)(HMODULE hModule, LPCSTR lpProcName) = (*parameter)[1];
  9.     const char str_kernel32[] = "kernel32.dll";
  10.     HMODULE kernel32 = LoadLibraryA(str_kernel32);
  11.     const char str_user32[] = "user32.dll";
  12.     HMODULE user32 = LoadLibraryA(str_user32);
  13.     const char str_FreeLibrary[] = "FreeLibrary";
  14.     BOOL (*FreeLibrary)(HMODULE hLibModule) = (void *)GetProcAddress(kernel32, str_FreeLibrary);
  15.     const char str_MessageBoxA[] = "MessageBoxA";
  16.     int (*MessageBoxA)(HWND hWnd, LPCTSTR lpText, LPCTSTR lpCaption, UINT uType) = (void *)GetProcAddress(user32, str_MessageBoxA);
  17.     const char str_ok[] = "ok!";
  18.     const char str_none[] = "none";
  19.     MessageBoxA(NULL, str_ok, str_none, MB_OK);
  20.     FreeLibrary(user32);
  21.     FreeLibrary(kernel32);
  22.     return 123;
  23. }

  24. static void WINAPI t_end(void) {}

  25. static void *find_proc_address(HANDLE hProcess, const char *proc_name) {
  26.     HMODULE hMods[1024];
  27.     DWORD cbNeeded;
  28.     if(!EnumProcessModules(hProcess, hMods, sizeof(hMods), &cbNeeded)) return NULL;
  29.     for(size_t i = 0; i < cbNeeded / sizeof(HMODULE); ++i) {
  30.         FARPROC proc = GetProcAddress(hMods[i], proc_name);
  31.         if(proc) return proc;
  32.     }
  33.     return NULL;
  34. }

  35. int main(void) {
  36.     HANDLE process_handle;
  37.     HANDLE thread_handle = 0;
  38.     DWORD process_ID;
  39.     LPVOID thread_address;
  40.     BOOL result;
  41.     int code_size = (LPBYTE)t_end - (LPBYTE)t_main;
  42.     printf("待嵌入的代码大小为:%d字节\n", code_size);
  43.     window_handle = FindWindowW(NULL, L"计算器");
  44.     printf("获取到的窗口句柄为%p\n", window_handle);

  45.     GetWindowThreadProcessId(window_handle, &process_ID);
  46.     process_handle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, process_ID);
  47.     printf("获取到的进程句柄为%p\n", process_handle);

  48.     thread_address = VirtualAllocEx(process_handle, NULL, code_size, MEM_COMMIT, PAGE_EXECUTE_READ);
  49.     printf("申请到的进程中合适的地址为:%p\n", thread_address);

  50.     result = WriteProcessMemory(process_handle, thread_address, t_main, code_size, NULL);
  51.     if (result != 0) printf("在内存中写入数据成功!\n");
  52.     else printf("在内存中写入数据失败。\n");

  53.     void *parameter[2] = {find_proc_address(process_handle, "LoadLibraryA"), find_proc_address(process_handle, "GetProcAddress")};
  54.     LPVOID thread_parameter = VirtualAllocEx(process_handle, NULL, sizeof(parameter), MEM_COMMIT, PAGE_READWRITE);
  55.     WriteProcessMemory(process_handle, thread_parameter, &parameter, sizeof(parameter), NULL);

  56.     thread_handle = CreateRemoteThread(process_handle, NULL, 0, thread_address, thread_parameter, 0, NULL);
  57.     printf("创建的线程句柄为%p\n", thread_handle);

  58.     WaitForSingleObject(thread_handle, INFINITE);
  59.     DWORD ExitCode;
  60.     GetExitCodeThread(thread_handle, &ExitCode);
  61.     printf("ExitCode: %u\n", ExitCode);

  62.     CloseHandle(thread_handle);
  63.     VirtualFreeEx(process_handle, thread_parameter, 0, MEM_RELEASE);
  64.     VirtualFreeEx(process_handle, thread_address, 0, MEM_RELEASE);
  65.     CloseHandle(process_handle);
  66.     return 0;
  67. }
复制代码
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

发表于 2022-9-10 16:48:30 | 显示全部楼层    本楼为最佳答案   
问你,当前进程的MessageBox地址和目标进程的MessageBox地址一样吗?不一样?那你为什么在目标进程中使用当前进程的MessageBox地址?
在目标进程中如何使用MessageBox ?
LoadLibrary和GetProcAddress了解一下

  1. #include <stdio.h>
  2. #include <windows.h>
  3. #include <psapi.h>

  4. HWND window_handle;

  5. static DWORD WINAPI t_main(LPVOID lpParameter) {
  6.     void *(*parameter)[2] = (void *)lpParameter;
  7.     HMODULE (*LoadLibraryA)(LPCSTR lpLibFileName) = (*parameter)[0];
  8.     FARPROC (*GetProcAddress)(HMODULE hModule, LPCSTR lpProcName) = (*parameter)[1];
  9.     const char str_kernel32[] = "kernel32.dll";
  10.     HMODULE kernel32 = LoadLibraryA(str_kernel32);
  11.     const char str_user32[] = "user32.dll";
  12.     HMODULE user32 = LoadLibraryA(str_user32);
  13.     const char str_FreeLibrary[] = "FreeLibrary";
  14.     BOOL (*FreeLibrary)(HMODULE hLibModule) = (void *)GetProcAddress(kernel32, str_FreeLibrary);
  15.     const char str_MessageBoxA[] = "MessageBoxA";
  16.     int (*MessageBoxA)(HWND hWnd, LPCTSTR lpText, LPCTSTR lpCaption, UINT uType) = (void *)GetProcAddress(user32, str_MessageBoxA);
  17.     const char str_ok[] = "ok!";
  18.     const char str_none[] = "none";
  19.     MessageBoxA(NULL, str_ok, str_none, MB_OK);
  20.     FreeLibrary(user32);
  21.     FreeLibrary(kernel32);
  22.     return 123;
  23. }

  24. static void WINAPI t_end(void) {}

  25. static void *find_proc_address(HANDLE hProcess, const char *proc_name) {
  26.     HMODULE hMods[1024];
  27.     DWORD cbNeeded;
  28.     if(!EnumProcessModules(hProcess, hMods, sizeof(hMods), &cbNeeded)) return NULL;
  29.     for(size_t i = 0; i < cbNeeded / sizeof(HMODULE); ++i) {
  30.         FARPROC proc = GetProcAddress(hMods[i], proc_name);
  31.         if(proc) return proc;
  32.     }
  33.     return NULL;
  34. }

  35. int main(void) {
  36.     HANDLE process_handle;
  37.     HANDLE thread_handle = 0;
  38.     DWORD process_ID;
  39.     LPVOID thread_address;
  40.     BOOL result;
  41.     int code_size = (LPBYTE)t_end - (LPBYTE)t_main;
  42.     printf("待嵌入的代码大小为:%d字节\n", code_size);
  43.     window_handle = FindWindowW(NULL, L"计算器");
  44.     printf("获取到的窗口句柄为%p\n", window_handle);

  45.     GetWindowThreadProcessId(window_handle, &process_ID);
  46.     process_handle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, process_ID);
  47.     printf("获取到的进程句柄为%p\n", process_handle);

  48.     thread_address = VirtualAllocEx(process_handle, NULL, code_size, MEM_COMMIT, PAGE_EXECUTE_READ);
  49.     printf("申请到的进程中合适的地址为:%p\n", thread_address);

  50.     result = WriteProcessMemory(process_handle, thread_address, t_main, code_size, NULL);
  51.     if (result != 0) printf("在内存中写入数据成功!\n");
  52.     else printf("在内存中写入数据失败。\n");

  53.     void *parameter[2] = {find_proc_address(process_handle, "LoadLibraryA"), find_proc_address(process_handle, "GetProcAddress")};
  54.     LPVOID thread_parameter = VirtualAllocEx(process_handle, NULL, sizeof(parameter), MEM_COMMIT, PAGE_READWRITE);
  55.     WriteProcessMemory(process_handle, thread_parameter, &parameter, sizeof(parameter), NULL);

  56.     thread_handle = CreateRemoteThread(process_handle, NULL, 0, thread_address, thread_parameter, 0, NULL);
  57.     printf("创建的线程句柄为%p\n", thread_handle);

  58.     WaitForSingleObject(thread_handle, INFINITE);
  59.     DWORD ExitCode;
  60.     GetExitCodeThread(thread_handle, &ExitCode);
  61.     printf("ExitCode: %u\n", ExitCode);

  62.     CloseHandle(thread_handle);
  63.     VirtualFreeEx(process_handle, thread_parameter, 0, MEM_RELEASE);
  64.     VirtualFreeEx(process_handle, thread_address, 0, MEM_RELEASE);
  65.     CloseHandle(process_handle);
  66.     return 0;
  67. }
复制代码
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2022-9-10 18:15:09 | 显示全部楼层
人造人 发表于 2022-9-10 16:48
问你,当前进程的MessageBox地址和目标进程的MessageBox地址一样吗?不一样?那你为什么在目标进程中使用当 ...

大佬,顺便问一句,你在电脑上尝试给进程创建远程线程时,进程会异常终止吗
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2022-9-10 18:21:19 | 显示全部楼层
玛丽亚在伯大尼 发表于 2022-9-10 18:15
大佬,顺便问一句,你在电脑上尝试给进程创建远程线程时,进程会异常终止吗

用你的代码会,我改的代码不会
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2022-9-10 19:40:04 | 显示全部楼层
人造人 发表于 2022-9-10 18:21
用你的代码会,我改的代码不会

跪求大佬解答,运行修改好的代码出现了一样的问题显示ExitCode: 3221225477
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2022-9-10 19:44:37 | 显示全部楼层
玛丽亚在伯大尼 发表于 2022-9-10 19:40
跪求大佬解答,运行修改好的代码出现了一样的问题显示ExitCode: 3221225477

那就调试程序么,下断点,一条语句一条语句执行程序,看返回值,看看在哪一行的返回值有问题
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2022-9-11 22:54:22 | 显示全部楼层
人造人 发表于 2022-9-10 19:44
那就调试程序么,下断点,一条语句一条语句执行程序,看返回值,看看在哪一行的返回值有问题

折腾了一天,发现只要远程线程中存在函数调用行为(确定好了地址的)就会出现0xC0000005错误,然后进程异常终止,但是只要没有调用函数,啥问题都没有。不管是我后来写的,还是大佬你给的代码都会出现这样的问题。。敢问大佬,这可能是运行环境的问题吗(win10,vs2017,其他什么没乱动过)
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2022-9-11 23:13:39 | 显示全部楼层
玛丽亚在伯大尼 发表于 2022-9-11 22:54
折腾了一天,发现只要远程线程中存在函数调用行为(确定好了地址的)就会出现0xC0000005错误,然后进程异 ...

你什么时候有时间,远程给你调试一下?
qq:1440332527
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2022-9-11 23:15:14 | 显示全部楼层
玛丽亚在伯大尼 发表于 2022-9-11 22:54
折腾了一天,发现只要远程线程中存在函数调用行为(确定好了地址的)就会出现0xC0000005错误,然后进程异 ...

不应该,重定位过地址的函数是可以调用的,不能调用函数,说明函数的地址没有进行重定位
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2022-9-12 09:37:11 | 显示全部楼层
人造人 发表于 2022-9-11 23:15
不应该,重定位过地址的函数是可以调用的,不能调用函数,说明函数的地址没有进行重定位

最后想不出什么办法,干脆写个程序自己打印MessageBoxA在其中的函数地址,然后在远程线程中使用汇编来调用函数。虽然最终成了,但是还是有一些奇怪的局限性。。
(试过C语言直接改写函数地址然后调用,会出错)

  1. static void t_main()
  2. {
  3.         _asm {
  4.         push 0x0                                //MB_OK
  5.         push 0x4FF85C                        //正文的字符串地址
  6.         push 0x4FF84C                        //标题的字符串地址
  7.         push 0x0                                //父窗口句柄
  8.         mov edi, 0x77A809A0                //MessageBoxA地址,这里很奇怪,直接call 0x77A809A0会出现之前一样的错误。。
  9.         call edi                                //不知道为啥只有这样写才成功?
  10.         }
  11.         return 0;
  12. }

  13. static void t_end()
  14. {
  15.         ;
  16. }
复制代码
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2022-9-12 10:57:17 | 显示全部楼层
玛丽亚在伯大尼 发表于 2022-9-12 09:37
最后想不出什么办法,干脆写个程序自己打印MessageBoxA在其中的函数地址,然后在远程线程中使用汇编来调 ...

我倒是想看看,你那边用我改的程序还不能运行,究竟错哪了
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2022-9-12 15:00:38 | 显示全部楼层
终于改出来一个能用的了 此贴该完结了。

  1. #include <stdio.h>
  2. #include <windows.h>
  3. #include <psapi.h>

  4. HWND window_handle;

  5. static DWORD WINAPI t_main(LPVOID lpParameter) {        //前一个参数的第一个元素是LoadLibraryA的地址,第二个元素是GetProcAddress的地址,第三个元素是字符串资源地址
  6.         void *(*parameter)[3] = (void *)lpParameter;
  7.         HMODULE(*LoadLibraryA)(LPCSTR lpLibFileName);
  8.         LoadLibraryA = (*parameter)[0];
  9.         FARPROC(*GetProcAddress)(HMODULE hModule, LPCSTR lpProcName);
  10.         GetProcAddress = (*parameter)[1];

  11.         char* str_addr = (*parameter)[2];
  12.         char* str_kernel32 = str_addr;
  13.         HMODULE kernel32 = LoadLibraryA(str_kernel32);

  14.         char* str_user32 = (str_addr += 13);
  15.         HMODULE user32 = LoadLibraryA(str_user32);

  16.         char* str_FreeLibrary = (str_addr += 11);
  17.         BOOL(*FreeLibrary)(HMODULE hLibModule);
  18.         FreeLibrary = (void *)GetProcAddress(kernel32, str_FreeLibrary);

  19.         char* str_MessageBoxA = (str_addr += 12);
  20.         int(*MessageBoxA)(HWND hWnd, LPCTSTR lpText, LPCTSTR lpCaption, UINT uType);
  21.         MessageBoxA        = (void *)GetProcAddress(user32, str_MessageBoxA);

  22.         char* str_text = (str_addr += 12);
  23.         char* str_title = (str_addr += 7);
  24.         MessageBoxA(0, str_text, str_title, 0);
  25.         FreeLibrary(user32);
  26.         FreeLibrary(kernel32);
  27.         return 0;
  28. }

  29. static void WINAPI t_end(void) {}

  30. static void *find_proc_address(HANDLE hProcess, const char *proc_name) {
  31.         HMODULE hMods[1024];
  32.         DWORD cbNeeded;
  33.         if (!EnumProcessModules(hProcess, hMods, sizeof(hMods), &cbNeeded)) return NULL;
  34.         for (size_t i = 0; i < cbNeeded / sizeof(HMODULE); ++i) {
  35.                 FARPROC proc = GetProcAddress(hMods[i], proc_name);
  36.                 if (proc) return proc;
  37.         }
  38.         return NULL;
  39. }

  40. int main(void) {
  41.         HANDLE process_handle;
  42.         HANDLE thread_handle = 0;
  43.         DWORD process_ID;
  44.         LPVOID thread_address;
  45.         BOOL result;
  46.         char str_resource[128] = "kernel32.dll\0user32.dll\0FreeLibrary\0MessageBoxA\0Hello?\0Greeting\0";
  47.         int code_size = (LPBYTE)t_end - (LPBYTE)t_main;
  48.         printf("待嵌入的代码大小为:%d字节\n", code_size);
  49.         window_handle = FindWindowW(NULL, L"计算器");
  50.         printf("获取到的窗口句柄为%p\n", window_handle);

  51.         GetWindowThreadProcessId(window_handle, &process_ID);
  52.         process_handle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, process_ID);
  53.         printf("获取到的进程句柄为%p\n", process_handle);

  54.         thread_address = VirtualAllocEx(process_handle, NULL, code_size, MEM_COMMIT, PAGE_EXECUTE_READ);
  55.         printf("申请到的进程中合适的地址为:%p\n", thread_address);

  56.         result = WriteProcessMemory(process_handle, thread_address, t_main, code_size, NULL);
  57.         if (result != 0) printf("在内存中写入数据成功!\n");
  58.         else printf("在内存中写入数据失败。\n");

  59.         LPVOID string_address = VirtualAllocEx(process_handle, NULL, sizeof(str_resource), MEM_COMMIT, PAGE_READWRITE);//将字符串资源载入进程
  60.         WriteProcessMemory(process_handle, string_address, str_resource, 128, NULL);

  61.         void *parameter[3] = { find_proc_address(process_handle, "LoadLibraryA"), find_proc_address(process_handle, "GetProcAddress"), string_address };
  62.         LPVOID thread_parameter = VirtualAllocEx(process_handle, NULL, sizeof(parameter), MEM_COMMIT, PAGE_READWRITE);
  63.         WriteProcessMemory(process_handle, thread_parameter, &parameter, sizeof(parameter), NULL);

  64.         thread_handle = CreateRemoteThread(process_handle, NULL, 0, (LPTHREAD_START_ROUTINE)thread_address, thread_parameter, 0, NULL);
  65.         printf("创建的线程句柄为%p\n", thread_handle);

  66.         WaitForSingleObject(thread_handle, INFINITE);
  67.         DWORD ExitCode;
  68.         GetExitCodeThread(thread_handle, &ExitCode);
  69.         printf("ExitCode: 0x%X\n", ExitCode);

  70.         CloseHandle(thread_handle);
  71.         VirtualFreeEx(process_handle, thread_parameter, 0, MEM_RELEASE);
  72.         VirtualFreeEx(process_handle, thread_address, 0, MEM_RELEASE);
  73.         CloseHandle(process_handle);
  74.         return 0;
  75. }
复制代码
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2022-9-12 15:07:01 | 显示全部楼层
人造人 发表于 2022-9-12 10:57
我倒是想看看,你那边用我改的程序还不能运行,究竟错哪了

我发现在线程内定义的字符串会出问题,然后我把字符串作为资源写入进程中调用就没问题了。还有,把函数定义和函数地址设置写在一起也会有问题,我也不知道为啥,分开就没事。就这两点改一下线程就能正常运行,Exitcode=0,万事大吉。总而言之,这两个问题很奇怪,想不通。
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2022-9-12 15:11:44 | 显示全部楼层
玛丽亚在伯大尼 发表于 2022-9-12 15:07
我发现在线程内定义的字符串会出问题,然后我把字符串作为资源写入进程中调用就没问题了。还有,把函数定 ...

需要帮你调试一下吗?
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2022-9-12 16:38:23 | 显示全部楼层
人造人 发表于 2022-9-12 15:11
需要帮你调试一下吗?

不用了,谢谢
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2025-4-23 22:38

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表