龙马谷

 找回密码
 立即注册

QQ登录

只需一步,快速开始

龙马谷VIP会员办理客服QQ:82926983(如果临时会话没有收到回复,请先加QQ好友再发。)
1 [已完结] GG修改器新手入门与实战教程 31课 2 [已完结] GG修改器美化修改教程 6课 3 [已完结] GG修改器Lua脚本新手入门教程 12课
4 [已完结] 触动精灵脚本新手入门必学教程 22课 5 [已完结] 手游自动化脚本入门实战教程 9课 6 [已完结] C++射击游戏方框骨骼透视与自瞄教程 27课
7 [已完结] C++零基础UE4逆向开发FPS透视自瞄教程 29课 8 [已完结] C++零基础大漠模拟器手游自动化辅助教程 22课 9 [已完结] C++零基础开发DXF内存脚本辅助教程 32课
以下是天马阁VIP教程,本站与天马阁合作,赞助VIP可以获得天马阁对应VIP会员,名额有限! 点击进入天马阁论坛
1 [已完结] x64CE与x64dbg入门基础教程 7课 2 [已完结] x64汇编语言基础教程 16课 3 [已完结] x64辅助入门基础教程 9课
4 [已完结] C++x64内存辅助实战技术教程 149课 5 [已完结] C++x64内存检测与过检测技术教程 10课 6 [已完结] C+x64二叉树分析遍历与LUA自动登陆教程 19课
7 [已完结] C++BT功能原理与x64实战教程 29课 8 [已完结] C+FPS框透视与自瞄x64实现原理及防护思路
查看: 1613|回复: 1

远程注入代码利用SetTimer函数实现异常处理

[复制链接]

20

主题

6

回帖

35

积分

编程入门

Rank: 1

龙马币
88

windows默认会用异常处理程序包含SetTimer的回调函数TimerProc,所以可以利用这一点给远程注入代码加上异常处理过程,防止注入代码导致远程程序异常崩溃。并且异常处理过程由windows自动处理,不需要编写额外代码,非常方便。

微软文档所述:
Windows 会将其对 TimerProc 的 调用括起来,其中包含使用和放弃所有异常的异常处理程序。 这是自 Windows 2000 以来的默认行为,但在 Windows 的未来版本中,这一行为可能会更改。 https://learn.microsoft.com/zh-cn/windows/win32/api/winuser/nf-winuser-setuserobjectinformationw

验证SetTimer函数自带异常处理
首先必须知道的是由windows消息队列来调用TimerProc函数。具体的说是SetTimer函数带回调函数时,由DispatchMessage函数调用TimerProc函数,且触发异常后,异常以后的代码不会被执行。

新建VS工程,选windows控制台程序,完整代码如下。
  1. #include <windows.h>
  2. #include <iostream>

  3. using namespace std;

  4. // 计时器回调函数
  5. VOID CALLBACK Timerproc(
  6.   HWND hwnd,        // handle to window for timer messages
  7.   UINT message,     // WM_TIMER message
  8.   UINT idTimer,     // timer identifier
  9.   DWORD dwTime)     // current system time
  10. {
  11.   cout << "Timerproc" << endl;
  12.   int a = 1, b = 0, c = 0;
  13.   c = a / b;  // 这句代码会引发异常,除数为零
  14.   cout << c << endl;
  15. }

  16. int main() {
  17.   //const HWND hwnd = GetConsoleWindow(); // 获取本进程句柄

  18.   const UINT_PTR timer_id = SetTimer(nullptr,      // 绑定的窗口句柄
  19.                                      0,            // timer ID
  20.                                      0x0,          // 倒计时数,毫秒
  21.                                      Timerproc);   // 回调函数
  22.   int Counter = 0;
  23.   MSG msg;
  24.   while (GetMessage(&msg, nullptr, 0, 0)) {
  25.     ++Counter;
  26.     cout << "Counter: " << Counter << "; message: " << msg.message << '\n';
  27.     DispatchMessage(&msg);
  28.   }
  29.   return 0;
  30. }
复制代码


调试运行,VS输出标签里重复提示除数为零异常,但程序仍然正常运行,没有显示cout << c << endl;这句代码,说明异常处理程序确实包含了TimerProc函数。


新线程内执行TimerProc函数
控制台程序
远程注入的代码是通过CreateRemoteThread函数执行,也就是新建一个线程。所以先来模拟本地新线程执行情景。
  1. #include <windows.h>
  2. #include <iostream>
  3. #include <process.h>

  4. using namespace std;

  5. HANDLE hEvent;
  6. // 计时器回调函数
  7. VOID CALLBACK Timerproc(
  8.   HWND hwnd,        // handle to window for timer messages
  9.   UINT message,     // WM_TIMER message
  10.   UINT idTimer,     // timer identifier
  11.   DWORD dwTime)     // current system time
  12. {
  13.   cout << "Timerproc" << endl;
  14.   KillTimer(hwnd, idTimer);
  15.   int a = 1, b = 0, c = 0;
  16.   c = a / b;  // 这句代码会引发异常,除数为零
  17.   cout << c << endl;
  18.   SetEvent(hEvent);
  19. }

  20. DWORD WINAPI thread(_In_ LPVOID lpParameter) {
  21.   HWND process_hwnd = *(HWND*)lpParameter;
  22.   cout << "process_hwnd=" << process_hwnd << endl;
  23.   cout << "thread start PID=" << GetCurrentThreadId() << endl;
  24.   UINT_PTR timer_id;
  25.   const HANDLE thread_hwnd = GetCurrentThread();
  26.   timer_id = SetTimer(nullptr, 0, 0, nullptr);
  27.   timer_id = SetTimer(process_hwnd,      // 绑定的窗口句柄
  28.                       timer_id,     // timer ID
  29.                       0x0,          // 倒计时数,毫秒
  30.                       Timerproc);   // 回调函数

  31.   hEvent = CreateEvent(nullptr, FALSE, FALSE, nullptr);
  32.   WaitForSingleObject(hEvent, 5000);
  33.   cout << "WaitForSingleObject end" << endl;
  34.   CloseHandle(hEvent);
  35.   return 0;
  36. }

  37. int main() {
  38.   //HANDLE process_handle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, GetCurrentProcessId());
  39.   //cout << "process_handle=" << process_handle << endl;

  40.   HWND process_hwnd = GetConsoleWindow();
  41.   cout << "process_hwnd=" << process_hwnd << endl;
  42.   const HANDLE thread_handle = CreateThread(nullptr, 0, thread, &process_hwnd, 0, nullptr);
  43.   cout << "CreateThread thread_handle=" << thread_handle << endl;
  44.   BOOL bRet;
  45.   int Counter = 0;
  46.   MSG msg;
  47.   while ((bRet = GetMessage(&msg, nullptr, 0, 0)) != 0) {
  48.     if (bRet == -1) {
  49.       // handle the error and possibly exit
  50.     }
  51.     else {
  52.       ++Counter;
  53.       cout << "Counter: " << Counter << "; message: " << msg.message << '\n';
  54.       TranslateMessage(&msg);
  55.       DispatchMessage(&msg);
  56.     }

  57.   }
  58.   return 0;
  59. }
复制代码

上面的代码无法运行成功,原因是TimeProc函数并未执行。没有执行是因为消息队列没有消息,那么GetMessage就会阻塞进程,不执行while循环体。不进入循环体,DispatchMessage函数就无法调用TimeProc函数。

至于为什么这里SetTimer函数没有触发消息……我也不知道。

窗口程序
控制台程序无法成功运行,但是换窗口程序却可以成功运行。

代码流程:

WinMain函数是主函数,主函数中创建新线程执行thread函数。

thread函数中创建事件,新建空计时器。新建空计时器是为了避免覆盖注入进程中已有的计时器(当SetTimer函数的第1、2参数为0时,windows会自动在当前进程创建新的计时器ID)。然后再次设置计时器,传入注入进程句柄、新建空计时器ID、Timerproc回调函数。最后执行WaitForSingleObject函数阻塞等待事件信号,如果Timerproc函数触发异常了,则会超时指定时间后继续执行。
Timerproc函数可以自动处理异常,需要注意的是触发异常后的代码不会被执行。函数首先关闭计时器,接着直接插入注入代码或调用call函数,最后设置信号为有状态,以便让WaitForSingleObject函数接收信号。

call函数有没有都可以,单独的call函数方便编程和调试。

改进的代码如下:
  1. #include <iostream>
  2. #include <windows.h>

  3. using namespace std;

  4. static const TCHAR gc_szClassName[] = TEXT("Test");
  5. static const TCHAR gc_szWindowTitle[] = TEXT("Test");

  6. HANDLE hEvent;

  7. void call() {
  8.   int a = 1, b = 0, c = 0;
  9.   c = a / b;  // 这句代码会引发异常,除数为零
  10.   cout << c << endl;
  11. }

  12. // 计时器回调函数
  13. VOID CALLBACK Timerproc(
  14.   HWND hwnd,        // handle to window for timer messages
  15.   UINT message,     // WM_TIMER message
  16.   UINT idTimer,     // timer identifier
  17.   DWORD dwTime)     // current system time
  18. {
  19.   cout << "Timerproc" << endl;
  20.   if (KillTimer(hwnd, idTimer))
  21.     cout << "KillTimer done" << endl;
  22.   else
  23.     cout << "KillTimer error" << endl;
  24.   call(); // 如果函数内异常导致退出,则不会执行下面的代码
  25.   SetEvent(hEvent);
  26. }

  27. DWORD WINAPI thread(_In_ LPVOID lpParameter) {
  28.   HWND process_hwnd = *(HWND*)lpParameter;
  29.   cout << "process_hwnd=" << process_hwnd << endl;
  30.   cout << "thread start PID=" << GetCurrentThreadId() << endl;
  31.   UINT_PTR timer_id;
  32.   const HANDLE thread_hwnd = GetCurrentThread();
  33.   hEvent = CreateEvent(nullptr, FALSE, FALSE, nullptr);
  34.   timer_id = SetTimer(nullptr, 0, 0, nullptr);
  35.   timer_id = SetTimer(process_hwnd,      // 绑定的窗口句柄
  36.                       timer_id,     // timer ID
  37.                       0x0,          // 倒计时数,毫秒
  38.                       Timerproc);   // 回调函数
  39.   cout << "timer_id=" << timer_id << endl;
  40.   WaitForSingleObject(hEvent, 5000);
  41.   cout << "WaitForSingleObject end" << endl;
  42.   CloseHandle(hEvent);
  43.   return 0;
  44. }

  45. LRESULT CALLBACK WndProc(HWND hWnd, UINT uMessage, WPARAM wParam, LPARAM lParam) {
  46.   switch (uMessage) {
  47.   case WM_CREATE:
  48.     break;

  49.   case WM_CLOSE:
  50.     DestroyWindow(hWnd);
  51.     break;

  52.   case WM_DESTROY:
  53.     PostQuitMessage(EXIT_SUCCESS);
  54.     break;
  55.   default:;
  56.   }

  57.   return DefWindowProc(hWnd, uMessage, wParam, lParam);
  58. }

  59. int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpszCommandLine, int nShowCommand) {
  60.   // define variables
  61.   HWND hWnd;
  62.   WNDCLASS wc;
  63.   MSG msg;

  64.   // unused parameters
  65.   UNREFERENCED_PARAMETER(hPrevInstance);
  66.   UNREFERENCED_PARAMETER(lpszCommandLine);
  67.   UNREFERENCED_PARAMETER(nShowCommand);

  68.   // initialize WNDCLASS structure
  69.   ZeroMemory(&wc, sizeof(wc));
  70.   wc.lpfnWndProc = WndProc;
  71.   wc.hInstance = hInstance;
  72.   wc.lpszClassName = gc_szClassName;

  73.   // attempt to register the class
  74.   if (RegisterClass(&wc) != 0) {
  75.     // show console
  76.     AllocConsole();
  77.     std::ignore = freopen_s((FILE**)stdout, "CONOUT$", "w", stdout);
  78.     std::ignore = freopen_s((FILE**)stdout, "CONOUT$", "w", stderr);
  79.     std::ignore = freopen_s((FILE**)stdout, "CONIN$", "r", stdin);
  80.     std::cout.clear();
  81.     std::clog.clear();
  82.     std::cerr.clear();
  83.     std::cin.clear();

  84.     // attempt to create the window
  85.     hWnd = CreateWindow(gc_szClassName, gc_szWindowTitle, WS_CAPTION | WS_SYSMENU | WS_VISIBLE, 100, 100, 100, 100, NULL, NULL, hInstance, NULL);
  86.     cout << "window hwnd=" << hWnd << endl;

  87.     const HANDLE thread_handle = CreateThread(nullptr, 0, thread, &hWnd, 0, nullptr);

  88.     int Counter = 0;
  89.     // retrieve messages
  90.     while (GetMessage(&msg, NULL, 0, 0) > 0) {
  91.       ++Counter;
  92.       std::cout << "Counter: " << Counter << "; message: " << msg.message << '\n';
  93.       TranslateMessage(&msg);
  94.       DispatchMessage(&msg);
  95.     }
  96.     // use the return-code from the window
  97.     return (int)msg.wParam;
  98.   }
  99.   return EXIT_FAILURE;
  100. }
复制代码


QQ截图20241126160617.jpg


将注入函数转为汇编语言
转为汇编语言这一步骤我卡住好几天。转为汇编语言本进程执行很简单,但如果要把thread()、timerproc()、call()三个函数在远程进程运行则有难度。主要难度为注入到远程进程后,由于没有基址重定位,无法执行call系统函数语句CALL KillTimer,也无法执行call自有函数语句CALL call。

研究了几天之后发现受限于内联汇编的功能局限性,不能用内联汇编完成目的。所以简单学习了一下asmjit,改用asmjit汇编引擎实现功能。

本进程执行代码
接下来需要将thread()、Timerproc()、call()函数转换为汇编语言。转换后的完整代码如下:
  1. #include <iostream>
  2. #include <windows.h>

  3. using namespace std;

  4. HANDLE hEvent;

  5. void call() {
  6.   //cout << "func call start" << endl;
  7.   //int a = 1, b = 0, c = 0;
  8.   //c = a / b;  // 这句代码会引发异常,除数为零
  9.   //cout << "func call end" << endl;

  10.   char start[] = "func call start\n";
  11.   char end[] = "func call end\n";
  12.   __asm {
  13.     lea eax, start
  14.     push eax
  15.     call printf
  16.     xor eax, eax
  17.     div eax // 0除以0 异常语句
  18.     lea eax, end
  19.     push eax
  20.     call printf
  21.   }
  22. }

  23. // 计时器回调函数
  24. VOID CALLBACK Timerproc(
  25.   HWND hwnd,        // handle to window for timer messages
  26.   UINT message,     // WM_TIMER message
  27.   UINT idTimer,     // timer identifier
  28.   DWORD dwTime)     // current system time
  29. {
  30.   //cout << "Timerproc" << endl;
  31.   //if (KillTimer(hwnd, idTimer))
  32.   //  cout << "KillTimer done" << endl;
  33.   //else
  34.   //  cout << "KillTimer error" << endl;
  35.   //call(); // 如果函数内异常导致退出,则不会执行下面的代码
  36.   //SetEvent(hEvent);

  37.   __asm {
  38.     push idTimer
  39.     push hwnd
  40.     call KillTimer
  41.     call call
  42.     //mov dword ptr ds : [0x12345678] , eax;  // 把call函数的返回值结果存放到指定的内存地址
  43.     push hEvent
  44.     call SetEvent
  45.   }
  46. }

  47. DWORD WINAPI thread(_In_ LPVOID lpParameter) {
  48.   HWND process_hwnd = *(HWND*)lpParameter;
  49.   UINT_PTR timer_id;
  50.   //cout << "process_hwnd=" << process_hwnd << endl;
  51.   //cout << "thread start PID=" << GetCurrentThreadId() << endl;
  52.   //const HANDLE thread_hwnd = GetCurrentThread();
  53.   ////hEvent = CreateEvent(nullptr, FALSE, FALSE, nullptr);
  54.   //timer_id = SetTimer(nullptr, 0, 0, nullptr);
  55.   //timer_id = SetTimer(process_hwnd,      // 绑定的窗口句柄
  56.   //                    timer_id,     // timer ID
  57.   //                    0x0,          // 倒计时数,毫秒
  58.   //                    Timerproc);   // 回调函数
  59.   //cout << "timer_id=" << timer_id << endl;
  60.   //WaitForSingleObject(hEvent, 5000);
  61.   //cout << "WaitForSingleObject end" << endl;
  62.   //CloseHandle(hEvent);

  63.   char start[] = "func thread start\n";
  64.   char end[] = "func thread end\n";
  65.   __asm {
  66.     lea eax, start
  67.     push eax
  68.     call printf
  69.     push 0
  70.     push 0
  71.     push 0
  72.     push 0
  73.     call CreateEvent
  74.     mov hEvent, eax
  75.     push 0
  76.     push 0
  77.     push 0
  78.     push 0
  79.     call SetTimer
  80.     push Timerproc
  81.     push 0
  82.     push eax
  83.     push process_hwnd
  84.     call SetTimer
  85.     mov timer_id, eax
  86.     push 0x1388; 5000毫秒
  87.     push hEvent
  88.     call WaitForSingleObject
  89.     push hEvent
  90.     call CloseHandle
  91.     lea eax, end
  92.     push eax
  93.     call printf
  94.   }
  95.   return 0;
  96. }

  97. LRESULT CALLBACK WndProc(HWND hWnd, UINT uMessage, WPARAM wParam, LPARAM lParam) {
  98.   switch (uMessage) {
  99.   case WM_CREATE:
  100.     break;

  101.   case WM_CLOSE:
  102.     DestroyWindow(hWnd);
  103.     break;

  104.   case WM_DESTROY:
  105.     PostQuitMessage(EXIT_SUCCESS);
  106.     break;
  107.   default:;
  108.   }

  109.   return DefWindowProc(hWnd, uMessage, wParam, lParam);
  110. }

  111. int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpszCommandLine, int nShowCommand) {
  112.   // define variables
  113.   HWND hWnd;
  114.   WNDCLASS wc;
  115.   MSG msg;

  116.   // unused parameters
  117.   UNREFERENCED_PARAMETER(hPrevInstance);
  118.   UNREFERENCED_PARAMETER(lpszCommandLine);
  119.   UNREFERENCED_PARAMETER(nShowCommand);

  120.   // initialize WNDCLASS structure
  121.   ZeroMemory(&wc, sizeof(wc));
  122.   wc.lpfnWndProc = WndProc;
  123.   wc.hInstance = hInstance;
  124.   wc.lpszClassName = TEXT("class name");

  125.   // attempt to register the class
  126.   if (RegisterClass(&wc) != 0) {
  127.     AllocConsole();
  128.     std::ignore = freopen_s((FILE**)stdout, "CONOUT$", "w", stdout);
  129.     std::ignore = freopen_s((FILE**)stdout, "CONOUT$", "w", stderr);
  130.     std::ignore = freopen_s((FILE**)stdout, "CONIN$", "r", stdin);
  131.     std::cout.clear();
  132.     std::clog.clear();
  133.     std::cerr.clear();
  134.     std::cin.clear();

  135.     // attempt to create the window
  136.     hWnd = CreateWindow(TEXT("class name"), TEXT("window title"), WS_CAPTION | WS_SYSMENU | WS_VISIBLE, 1100, 600, 100, 100, NULL, NULL, hInstance, NULL);
  137.     cout << "window hwnd=" << hWnd << endl;

  138.     const HANDLE thread_handle = CreateThread(nullptr, 0, thread, &hWnd, 0, nullptr);

  139.     int Counter = 0;
  140.     // retrieve messages
  141.     while (GetMessage(&msg, NULL, 0, 0) > 0) {
  142.       ++Counter;
  143.       std::cout << "Counter: " << Counter << "; message: " << msg.message << '\n';
  144.       TranslateMessage(&msg);
  145.       DispatchMessage(&msg);
  146.     }
  147.     // use the return-code from the window
  148.     return (int)msg.wParam;
  149.   }
  150.   return EXIT_FAILURE;
  151. }
复制代码


02.jpg

运行成功。实际应用时可以把call函数里的两个调试printf语句删了。

远程进程执行代码
代码只适用于x86程序,如果你系统是64位系统,测试用的笔记本程序需要使用c:\windows\SysWOW64\notepad.exe
  1. #include <algorithm>
  2. #include <format>
  3. #include <iomanip>
  4. #include <windows.h>
  5. #include <iostream>
  6. #include <psapi.h>
  7. #include <string>
  8. #include <asmjit/asmjit.h>

  9. using namespace std;
  10. using namespace asmjit;
  11. using namespace x86;

  12. struct THREAD_PARAM {
  13.   DWORD ret_value;    // alloc_addr + 0x0
  14.   FARPROC settimer;   // alloc_addr + 0x4
  15.   FARPROC killtimer;  // alloc_addr + 0x8
  16.   HWND remote_hwnd;   // alloc_addr + 0xC
  17.   DWORD timerproc;    // alloc_addr + 0x10
  18.   DWORD timer_id;     // alloc_addr + 0x14
  19.   DWORD custom_call;  // alloc_addr + 0x18
  20. };

  21. /**
  22. * \brief 获取指定进程中的模块函数句柄
  23. * \param hRemoteProcess 指定进程句柄
  24. * \param lpModuleName 指定函数名所在的模块名,大小写任意
  25. * \param lpProcName 指定要获取的函数名,大小写必须匹配
  26. * \return 成功则返回指定的函数地址,未找到返回空指针
  27. * \note 可至微软learn网站查询函数所在的模块
  28. */
  29. FARPROC GetRemoteModule(_In_ const HANDLE hRemoteProcess, _In_ const LPCWSTR lpModuleName, _In_ const LPCSTR lpProcName) {
  30.   // https://learn.microsoft.com/zh-cn/windows/win32/psapi/enumerating-all-modules-for-a-process

  31.   // 获取远程模块信息
  32.   HMODULE hModule[MAX_PATH];
  33.   DWORD cbNeeded;
  34.   if (!EnumProcessModules(hRemoteProcess, hModule, MAX_PATH, &cbNeeded))
  35.     return nullptr;

  36.   // 遍历枚举到的模块
  37.   for (size_t i = 0; i < cbNeeded / sizeof(HMODULE); i++) {
  38.     TCHAR szModName[MAX_PATH];

  39.     // Get the full path to the module's file.
  40.     if (GetModuleFileNameEx(hRemoteProcess, hModule[i], szModName,
  41.                             sizeof(szModName) / sizeof(TCHAR))) {
  42.       // 转为wstring字符串,并全部转换为小写以便比较
  43.       wstring ModName(szModName);
  44.       wstring ModuleName(lpModuleName);
  45.       ranges::transform(ModName, ModName.begin(), ::tolower);
  46.       ranges::transform(ModuleName, ModuleName.begin(), ::tolower);

  47.       //wcout << format(L"\t0x{:08X} {}\n", (DWORD)hModule[i], ModName);

  48.       // 如果是要找的模块
  49.       if (ModName.find(ModuleName) != wstring::npos)
  50.         // 如果GetProcAddress函数成功,则返回值是导出的函数或变量的地址。如果GetProcAddress函数失败,则返回值为 NULL。 要获得更多的错误信息,请调用 GetLastError。
  51.         return GetProcAddress(hModule[i], lpProcName);
  52.     }
  53.   }
  54.   return nullptr;
  55. }

  56. int main() {
  57.   const HWND remote_hwnd =
  58.     FindWindow(L"Notepad", nullptr);
  59.   cout << "remote_hwnd=" << remote_hwnd << endl;

  60.   DWORD remote_pid = 0;
  61.   GetWindowThreadProcessId(remote_hwnd, &remote_pid);
  62.   cout << "remote_pid=" << remote_pid << endl;

  63.   const HANDLE remote_handle = OpenProcess(PROCESS_ALL_ACCESS, false, remote_pid);
  64.   if (!remote_handle)
  65.     return 0;

  66.   // 获取远程进程模块函数信息
  67.   auto settimer = GetRemoteModule(remote_handle, TEXT("User32.dll"), "SetTimer");
  68.   auto killtimer = GetRemoteModule(remote_handle, TEXT("User32.dll"), "KillTimer");
  69.   //cout << format("SetTimer addr=0x{:08X}\n", (DWORD)settimer);
  70.   //cout << format("KillTimer addr=0x{:08X}\n", (DWORD)killtimer);

  71.   // 申请远程空间,写入和执行权限
  72.   DWORD alloc_addr = (DWORD)VirtualAllocEx(remote_handle, nullptr, MAX_PATH, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
  73.   if (!alloc_addr) {
  74.     cout << "GetLastError()=" << GetLastError() << endl;
  75.     return 0;
  76.   }
  77.   cout << setw(8) << setfill('0') << hex << "VirtualAlloc addr=0x" << alloc_addr << endl;
  78.   DWORD addr_param = alloc_addr;  // 参数内存地址
  79.   DWORD addr_call = alloc_addr + 0x21;  // 函数地址

  80.   // 构造和写入函数
  81.   THREAD_PARAM thread_param{};
  82.   thread_param.remote_hwnd = remote_hwnd;
  83.   thread_param.settimer = settimer;
  84.   thread_param.killtimer = killtimer;

  85.   // 生成代码
  86.   JitRuntime rt;
  87.   auto a = x86::Assembler();
  88.   CodeHolder code;
  89.   code.init(rt.environment(), rt.cpuFeatures());
  90.   code.attach(&a);

  91.   // 构造thread函数
  92.   a.push(0);
  93.   a.push(0);
  94.   a.push(0);
  95.   a.push(0);
  96.   a.call(dword_ptr(alloc_addr + 0x4));  // settimer
  97.   a.mov(dword_ptr(alloc_addr + 0x14), eax); //timer_id
  98.   a.push(dword_ptr(alloc_addr + 0x10));  // timerproc
  99.   a.push(0);
  100.   a.push(eax);
  101.   a.push(dword_ptr(alloc_addr + 0xC));  // remote_hwnd
  102.   a.call(dword_ptr(alloc_addr + 0x4));  // settimer
  103.   a.ret();
  104.   CodeBuffer& thread = code.textSection()->buffer();  // 获取对应的机器码
  105.   // 打印生成的机器码
  106.   //cout << "assembly=";
  107.   //for (auto& i : thread)
  108.   //  cout << format("{:02X} ", i);
  109.   //cout << endl;

  110.   size_t nSize = thread.size();
  111.   cout << format("线程函数写入地址=0x{:08X} 大小=0x{:08X}\n", addr_call, nSize);
  112.   WriteProcessMemory(remote_handle, (LPVOID)addr_call, thread.data(), nSize, nullptr);
  113.   DWORD thread_addr = addr_call; // 记录线程函数地址
  114.   addr_call = addr_call + nSize + 0x8;

  115.   // 重置并复用CodeHolder变量code
  116.   code.reset();
  117.   code.init(rt.environment(), rt.cpuFeatures());
  118.   code.attach(&a);

  119.   // 构造timerproc
  120.   a.push(dword_ptr(alloc_addr + 0x14)); // idTimer
  121.   a.push(dword_ptr(alloc_addr + 0xC));  // hwnd
  122.   a.call(dword_ptr(alloc_addr + 0x8)); // call KillTimer
  123.   a.call(dword_ptr(alloc_addr + 0x18)); // custom_call
  124.   a.ret();
  125.   CodeBuffer& timerproc = code.textSection()->buffer();

  126.   thread_param.timerproc = addr_call; // 记录therad地址
  127.   nSize = timerproc.size();
  128.   cout << format("回调函数写入地址=0x{:08X} 大小=0x{:08X}\n", addr_call, nSize);
  129.   WriteProcessMemory(remote_handle, (LPVOID)addr_call, timerproc.data(), nSize, nullptr);
  130.   addr_call = addr_call + nSize + 0x8;

  131.   // 重置并复用CodeHolder变量code
  132.   code.reset();
  133.   code.init(rt.environment(), rt.cpuFeatures());
  134.   code.attach(&a);

  135.   // 构造自定函数
  136.   a.xor_(eax, eax);
  137.   a.div(eax); // 异常语句
  138.   a.mov(dword_ptr(alloc_addr), eax);  // 写入返回值到alloc_addr,程序读取alloc_addr地址的数值即可知道返回值
  139.   a.ret();
  140.   CodeBuffer& custom_call = code.textSection()->buffer();

  141.   thread_param.custom_call = addr_call; // 记录custom_call地址
  142.   nSize = custom_call.size();
  143.   cout << format("自定函数写入地址=0x{:08X} 大小=0x{:08X}\n", addr_call, nSize);
  144.   WriteProcessMemory(remote_handle, (LPVOID)addr_call, custom_call.data(), nSize, nullptr);
  145.   addr_call = addr_call + nSize + 0x8;

  146.   // 写入参数
  147.   cout << format("线程参数写入地址=0x{:08X} 大小=0x{:08X}\n", addr_param, sizeof(THREAD_PARAM));
  148.   WriteProcessMemory(remote_handle, (LPVOID)addr_param, &thread_param, sizeof(THREAD_PARAM), nullptr);

  149.   const HANDLE hRemoteThread = CreateRemoteThread(remote_handle, nullptr, 0, (LPTHREAD_START_ROUTINE)thread_addr, (LPVOID)addr_param, 0, nullptr);

  150.   //system("pause");
  151.   return 0;
  152. }
复制代码

03.jpg

0

主题

22

回帖

23

积分

编程入门

Rank: 1

龙马币
8
vipsnadong | 显示全部楼层
远程注入代码利用SetTimer函数实现异常处理
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

龙马谷| C/C++辅助教程| 安卓逆向安全| 论坛导航| 免责申明|Archiver|
拒绝任何人以任何形式在本论坛发表与中华人民共和国法律相抵触的言论,本站内容均为会员发表,并不代表龙马谷立场!
任何人不得以任何方式翻录、盗版或出售本站视频,一经发现我们将追究其相关责任!
我们一直在努力成为最好的编程论坛!
Copyright© 2018-2021 All Right Reserved.
在线客服
快速回复 返回顶部 返回列表