wking's blog

  • 文章分类
    • 日常随笔
    • IT技术
    • 系统封装
    • 大航海时代
  • 关于博主
GOD'S IN HIS HEAVEN, ALL'S RIGHT WITH THE WORLD.
  1. 首页
  2. IT技术
  3. C++
  4. 正文

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

2024-06-09 434点热度 0人点赞 0条评论

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控制台程序,完整代码如下。

本地SetTimer函数实现异常处理
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
#include <windows.h>
#include <iostream>
 
using namespace std;
 
// 计时器回调函数
VOID CALLBACK Timerproc(
  HWND hwnd,        // handle to window for timer messages
  UINT message,     // WM_TIMER message
  UINT idTimer,     // timer identifier
  DWORD dwTime)     // current system time
{
  cout << "Timerproc" << endl;
  int a = 1, b = 0, c = 0;
  c = a / b;  // 这句代码会引发异常,除数为零
  cout << c << endl;
}
 
int main() {
  //const HWND hwnd = GetConsoleWindow(); // 获取本进程句柄
 
  const UINT_PTR timer_id = SetTimer(nullptr,      // 绑定的窗口句柄
                                     0,            // timer ID
                                     0x0,          // 倒计时数,毫秒
                                     Timerproc);   // 回调函数
  int Counter = 0;
  MSG msg;
  while (GetMessage(&msg, nullptr, 0, 0)) {
    ++Counter;
    cout << "Counter: " << Counter << "; message: " << msg.message << '\n';
    DispatchMessage(&msg);
  }
  return 0;
}

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

新线程内执行TimerProc函数

控制台程序

远程注入的代码是通过CreateRemoteThread函数执行,也就是新建一个线程。所以先来模拟本地新线程执行情景。

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
#include <windows.h>
#include <iostream>
#include <process.h>
 
using namespace std;
 
HANDLE hEvent;
// 计时器回调函数
VOID CALLBACK Timerproc(
  HWND hwnd,        // handle to window for timer messages
  UINT message,     // WM_TIMER message
  UINT idTimer,     // timer identifier
  DWORD dwTime)     // current system time
{
  cout << "Timerproc" << endl;
  KillTimer(hwnd, idTimer);
  int a = 1, b = 0, c = 0;
  c = a / b;  // 这句代码会引发异常,除数为零
  cout << c << endl;
  SetEvent(hEvent);
}
 
DWORD WINAPI thread(_In_ LPVOID lpParameter) {
  HWND process_hwnd = *(HWND*)lpParameter;
  cout << "process_hwnd=" << process_hwnd << endl;
  cout << "thread start PID=" << GetCurrentThreadId() << endl;
  UINT_PTR timer_id;
  const HANDLE thread_hwnd = GetCurrentThread();
  timer_id = SetTimer(nullptr, 0, 0, nullptr);
  timer_id = SetTimer(process_hwnd,      // 绑定的窗口句柄
                      timer_id,     // timer ID
                      0x0,          // 倒计时数,毫秒
                      Timerproc);   // 回调函数
 
  hEvent = CreateEvent(nullptr, FALSE, FALSE, nullptr);
  WaitForSingleObject(hEvent, 5000);
  cout << "WaitForSingleObject end" << endl;
  CloseHandle(hEvent);
  return 0;
}
 
int main() {
  //HANDLE process_handle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, GetCurrentProcessId());
  //cout << "process_handle=" << process_handle << endl;
 
  HWND process_hwnd = GetConsoleWindow();
  cout << "process_hwnd=" << process_hwnd << endl;
  const HANDLE thread_handle = CreateThread(nullptr, 0, thread, &process_hwnd, 0, nullptr);
  cout << "CreateThread thread_handle=" << thread_handle << endl;
  BOOL bRet;
  int Counter = 0;
  MSG msg;
  while ((bRet = GetMessage(&msg, nullptr, 0, 0)) != 0) {
    if (bRet == -1) {
      // handle the error and possibly exit
    }
    else {
      ++Counter;
      cout << "Counter: " << Counter << "; message: " << msg.message << '\n';
      TranslateMessage(&msg);
      DispatchMessage(&msg);
    }
 
  }
  return 0;
}

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

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

窗口程序

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

代码流程:

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

改进的代码如下:

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
#include <iostream>
#include <windows.h>
 
using namespace std;
 
static const TCHAR gc_szClassName[] = TEXT("Test");
static const TCHAR gc_szWindowTitle[] = TEXT("Test");
 
HANDLE hEvent;
 
void call() {
  int a = 1, b = 0, c = 0;
  c = a / b;  // 这句代码会引发异常,除数为零
  cout << c << endl;
}
 
// 计时器回调函数
VOID CALLBACK Timerproc(
  HWND hwnd,        // handle to window for timer messages
  UINT message,     // WM_TIMER message
  UINT idTimer,     // timer identifier
  DWORD dwTime)     // current system time
{
  cout << "Timerproc" << endl;
  if (KillTimer(hwnd, idTimer))
    cout << "KillTimer done" << endl;
  else
    cout << "KillTimer error" << endl;
  call(); // 如果函数内异常导致退出,则不会执行下面的代码
  SetEvent(hEvent);
}
 
DWORD WINAPI thread(_In_ LPVOID lpParameter) {
  HWND process_hwnd = *(HWND*)lpParameter;
  cout << "process_hwnd=" << process_hwnd << endl;
  cout << "thread start PID=" << GetCurrentThreadId() << endl;
  UINT_PTR timer_id;
  const HANDLE thread_hwnd = GetCurrentThread();
  hEvent = CreateEvent(nullptr, FALSE, FALSE, nullptr);
  timer_id = SetTimer(nullptr, 0, 0, nullptr);
  timer_id = SetTimer(process_hwnd,      // 绑定的窗口句柄
                      timer_id,     // timer ID
                      0x0,          // 倒计时数,毫秒
                      Timerproc);   // 回调函数
  cout << "timer_id=" << timer_id << endl;
  WaitForSingleObject(hEvent, 5000);
  cout << "WaitForSingleObject end" << endl;
  CloseHandle(hEvent);
  return 0;
}
 
LRESULT CALLBACK WndProc(HWND hWnd, UINT uMessage, WPARAM wParam, LPARAM lParam) {
  switch (uMessage) {
  case WM_CREATE:
    break;
 
  case WM_CLOSE:
    DestroyWindow(hWnd);
    break;
 
  case WM_DESTROY:
    PostQuitMessage(EXIT_SUCCESS);
    break;
  default:;
  }
 
  return DefWindowProc(hWnd, uMessage, wParam, lParam);
}
 
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpszCommandLine, int nShowCommand) {
  // define variables
  HWND hWnd;
  WNDCLASS wc;
  MSG msg;
 
  // unused parameters
  UNREFERENCED_PARAMETER(hPrevInstance);
  UNREFERENCED_PARAMETER(lpszCommandLine);
  UNREFERENCED_PARAMETER(nShowCommand);
 
  // initialize WNDCLASS structure
  ZeroMemory(&wc, sizeof(wc));
  wc.lpfnWndProc = WndProc;
  wc.hInstance = hInstance;
  wc.lpszClassName = gc_szClassName;
 
  // attempt to register the class
  if (RegisterClass(&wc) != 0) {
    // show console
    AllocConsole();
    std::ignore = freopen_s((FILE**)stdout, "CONOUT$", "w", stdout);
    std::ignore = freopen_s((FILE**)stdout, "CONOUT$", "w", stderr);
    std::ignore = freopen_s((FILE**)stdout, "CONIN$", "r", stdin);
    std::cout.clear();
    std::clog.clear();
    std::cerr.clear();
    std::cin.clear();
 
    // attempt to create the window
    hWnd = CreateWindow(gc_szClassName, gc_szWindowTitle, WS_CAPTION | WS_SYSMENU | WS_VISIBLE, 100, 100, 100, 100, NULL, NULL, hInstance, NULL);
    cout << "window hwnd=" << hWnd << endl;
 
    const HANDLE thread_handle = CreateThread(nullptr, 0, thread, &hWnd, 0, nullptr);
 
    int Counter = 0;
    // retrieve messages
    while (GetMessage(&msg, NULL, 0, 0) > 0) {
      ++Counter;
      std::cout << "Counter: " << Counter << "; message: " << msg.message << '\n';
      TranslateMessage(&msg);
      DispatchMessage(&msg);
    }
    // use the return-code from the window
    return (int)msg.wParam;
  }
  return EXIT_FAILURE;
}

将注入函数转为汇编语言

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

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

本进程执行代码

接下来需要将thread()、Timerproc()、call()函数转换为汇编语言。转换后的完整代码如下:

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
#include <iostream>
#include <windows.h>
 
using namespace std;
 
HANDLE hEvent;
 
void call() {
  //cout << "func call start" << endl;
  //int a = 1, b = 0, c = 0;
  //c = a / b;  // 这句代码会引发异常,除数为零
  //cout << "func call end" << endl;
 
  char start[] = "func call start\n";
  char end[] = "func call end\n";
  __asm {
    lea eax, start
    push eax
    call printf
    xor eax, eax
    div eax // 0除以0 异常语句
    lea eax, end
    push eax
    call printf
  }
}
 
// 计时器回调函数
VOID CALLBACK Timerproc(
  HWND hwnd,        // handle to window for timer messages
  UINT message,     // WM_TIMER message
  UINT idTimer,     // timer identifier
  DWORD dwTime)     // current system time
{
  //cout << "Timerproc" << endl;
  //if (KillTimer(hwnd, idTimer))
  //  cout << "KillTimer done" << endl;
  //else
  //  cout << "KillTimer error" << endl;
  //call(); // 如果函数内异常导致退出,则不会执行下面的代码
  //SetEvent(hEvent);
 
  __asm {
    push idTimer
    push hwnd
    call KillTimer
    call call
    //mov dword ptr ds : [0x12345678] , eax;  // 把call函数的返回值结果存放到指定的内存地址
    push hEvent
    call SetEvent
  }
}
 
DWORD WINAPI thread(_In_ LPVOID lpParameter) {
  HWND process_hwnd = *(HWND*)lpParameter;
  UINT_PTR timer_id;
  //cout << "process_hwnd=" << process_hwnd << endl;
  //cout << "thread start PID=" << GetCurrentThreadId() << endl;
  //const HANDLE thread_hwnd = GetCurrentThread();
  ////hEvent = CreateEvent(nullptr, FALSE, FALSE, nullptr);
  //timer_id = SetTimer(nullptr, 0, 0, nullptr);
  //timer_id = SetTimer(process_hwnd,      // 绑定的窗口句柄
  //                    timer_id,     // timer ID
  //                    0x0,          // 倒计时数,毫秒
  //                    Timerproc);   // 回调函数
  //cout << "timer_id=" << timer_id << endl;
  //WaitForSingleObject(hEvent, 5000);
  //cout << "WaitForSingleObject end" << endl;
  //CloseHandle(hEvent);
 
  char start[] = "func thread start\n";
  char end[] = "func thread end\n";
  __asm {
    lea eax, start
    push eax
    call printf
    push 0
    push 0
    push 0
    push 0
    call CreateEvent
    mov hEvent, eax
    push 0
    push 0
    push 0
    push 0
    call SetTimer
    push Timerproc
    push 0
    push eax
    push process_hwnd
    call SetTimer
    mov timer_id, eax
    push 0x1388; 5000毫秒
    push hEvent
    call WaitForSingleObject
    push hEvent
    call CloseHandle
    lea eax, end
    push eax
    call printf
  }
  return 0;
}
 
LRESULT CALLBACK WndProc(HWND hWnd, UINT uMessage, WPARAM wParam, LPARAM lParam) {
  switch (uMessage) {
  case WM_CREATE:
    break;
 
  case WM_CLOSE:
    DestroyWindow(hWnd);
    break;
 
  case WM_DESTROY:
    PostQuitMessage(EXIT_SUCCESS);
    break;
  default:;
  }
 
  return DefWindowProc(hWnd, uMessage, wParam, lParam);
}
 
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpszCommandLine, int nShowCommand) {
  // define variables
  HWND hWnd;
  WNDCLASS wc;
  MSG msg;
 
  // unused parameters
  UNREFERENCED_PARAMETER(hPrevInstance);
  UNREFERENCED_PARAMETER(lpszCommandLine);
  UNREFERENCED_PARAMETER(nShowCommand);
 
  // initialize WNDCLASS structure
  ZeroMemory(&wc, sizeof(wc));
  wc.lpfnWndProc = WndProc;
  wc.hInstance = hInstance;
  wc.lpszClassName = TEXT("class name");
 
  // attempt to register the class
  if (RegisterClass(&wc) != 0) {
    AllocConsole();
    std::ignore = freopen_s((FILE**)stdout, "CONOUT$", "w", stdout);
    std::ignore = freopen_s((FILE**)stdout, "CONOUT$", "w", stderr);
    std::ignore = freopen_s((FILE**)stdout, "CONIN$", "r", stdin);
    std::cout.clear();
    std::clog.clear();
    std::cerr.clear();
    std::cin.clear();
 
    // attempt to create the window
    hWnd = CreateWindow(TEXT("class name"), TEXT("window title"), WS_CAPTION | WS_SYSMENU | WS_VISIBLE, 1100, 600, 100, 100, NULL, NULL, hInstance, NULL);
    cout << "window hwnd=" << hWnd << endl;
 
 
 
 
    const HANDLE thread_handle = CreateThread(nullptr, 0, thread, &hWnd, 0, nullptr);
 
    int Counter = 0;
    // retrieve messages
    while (GetMessage(&msg, NULL, 0, 0) > 0) {
      ++Counter;
      std::cout << "Counter: " << Counter << "; message: " << msg.message << '\n';
      TranslateMessage(&msg);
      DispatchMessage(&msg);
    }
    // use the return-code from the window
    return (int)msg.wParam;
  }
  return EXIT_FAILURE;
}

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

远程进程执行代码

代码只适用于x86程序,如果你系统是64位系统,测试用的笔记本程序需要使用c:\windows\SysWOW64\notepad.exe

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
#include <algorithm>
#include <format>
#include <iomanip>
#include <windows.h>
#include <iostream>
#include <psapi.h>
#include <string>
#include <asmjit/asmjit.h>
 
using namespace std;
using namespace asmjit;
using namespace x86;
 
struct THREAD_PARAM {
  DWORD ret_value;    // alloc_addr + 0x0
  FARPROC settimer;   // alloc_addr + 0x4
  FARPROC killtimer;  // alloc_addr + 0x8
  HWND remote_hwnd;   // alloc_addr + 0xC
  DWORD timerproc;    // alloc_addr + 0x10
  DWORD timer_id;     // alloc_addr + 0x14
  DWORD custom_call;  // alloc_addr + 0x18
};
 
/**
* \brief 获取指定进程中的模块函数句柄
* \param hRemoteProcess 指定进程句柄
* \param lpModuleName 指定函数名所在的模块名,大小写任意
* \param lpProcName 指定要获取的函数名,大小写必须匹配
* \return 成功则返回指定的函数地址,未找到返回空指针
* \note 可至微软learn网站查询函数所在的模块
*/
FARPROC GetRemoteModule(_In_ const HANDLE hRemoteProcess, _In_ const LPCWSTR lpModuleName, _In_ const LPCSTR lpProcName) {
  // https://learn.microsoft.com/zh-cn/windows/win32/psapi/enumerating-all-modules-for-a-process
 
  // 获取远程模块信息
  HMODULE hModule[MAX_PATH];
  DWORD cbNeeded;
  if (!EnumProcessModules(hRemoteProcess, hModule, MAX_PATH, &cbNeeded))
    return nullptr;
 
  // 遍历枚举到的模块
  for (size_t i = 0; i < cbNeeded / sizeof(HMODULE); i++) {
    TCHAR szModName[MAX_PATH];
 
    // Get the full path to the module's file.
    if (GetModuleFileNameEx(hRemoteProcess, hModule[i], szModName,
                            sizeof(szModName) / sizeof(TCHAR))) {
      // 转为wstring字符串,并全部转换为小写以便比较
      wstring ModName(szModName);
      wstring ModuleName(lpModuleName);
      ranges::transform(ModName, ModName.begin(), ::tolower);
      ranges::transform(ModuleName, ModuleName.begin(), ::tolower);
 
      //wcout << format(L"\t0x{:08X} {}\n", (DWORD)hModule[i], ModName);
 
      // 如果是要找的模块
      if (ModName.find(ModuleName) != wstring::npos)
        // 如果GetProcAddress函数成功,则返回值是导出的函数或变量的地址。如果GetProcAddress函数失败,则返回值为 NULL。 要获得更多的错误信息,请调用 GetLastError。
        return GetProcAddress(hModule[i], lpProcName);
    }
  }
  return nullptr;
}
 
int main() {
  const HWND remote_hwnd =
    FindWindow(L"Notepad", nullptr);
  cout << "remote_hwnd=" << remote_hwnd << endl;
 
  DWORD remote_pid = 0;
  GetWindowThreadProcessId(remote_hwnd, &remote_pid);
  cout << "remote_pid=" << remote_pid << endl;
 
  const HANDLE remote_handle = OpenProcess(PROCESS_ALL_ACCESS, false, remote_pid);
  if (!remote_handle)
    return 0;
 
 
  // 获取远程进程模块函数信息
  auto settimer = GetRemoteModule(remote_handle, TEXT("User32.dll"), "SetTimer");
  auto killtimer = GetRemoteModule(remote_handle, TEXT("User32.dll"), "KillTimer");
  //cout << format("SetTimer addr=0x{:08X}\n", (DWORD)settimer);
  //cout << format("KillTimer addr=0x{:08X}\n", (DWORD)killtimer);
 
 
  // 申请远程空间,写入和执行权限
  DWORD alloc_addr = (DWORD)VirtualAllocEx(remote_handle, nullptr, MAX_PATH, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
  if (!alloc_addr) {
    cout << "GetLastError()=" << GetLastError() << endl;
    return 0;
  }
  cout << setw(8) << setfill('0') << hex << "VirtualAlloc addr=0x" << alloc_addr << endl;
  DWORD addr_param = alloc_addr;  // 参数内存地址
  DWORD addr_call = alloc_addr + 0x21;  // 函数地址
 
 
  // 构造和写入函数
  THREAD_PARAM thread_param{};
  thread_param.remote_hwnd = remote_hwnd;
  thread_param.settimer = settimer;
  thread_param.killtimer = killtimer;
 
  // 生成代码
  JitRuntime rt;
  auto a = x86::Assembler();
  CodeHolder code;
  code.init(rt.environment(), rt.cpuFeatures());
  code.attach(&a);
 
  // 构造thread函数
  a.push(0);
  a.push(0);
  a.push(0);
  a.push(0);
  a.call(dword_ptr(alloc_addr + 0x4));  // settimer
  a.mov(dword_ptr(alloc_addr + 0x14), eax); //timer_id
  a.push(dword_ptr(alloc_addr + 0x10));  // timerproc
  a.push(0);
  a.push(eax);
  a.push(dword_ptr(alloc_addr + 0xC));  // remote_hwnd
  a.call(dword_ptr(alloc_addr + 0x4));  // settimer
  a.ret();
  CodeBuffer& thread = code.textSection()->buffer();  // 获取对应的机器码
  // 打印生成的机器码
  //cout << "assembly=";
  //for (auto& i : thread)
  //  cout << format("{:02X} ", i);
  //cout << endl;
 
  size_t nSize = thread.size();
  cout << format("线程函数写入地址=0x{:08X} 大小=0x{:08X}\n", addr_call, nSize);
  WriteProcessMemory(remote_handle, (LPVOID)addr_call, thread.data(), nSize, nullptr);
  DWORD thread_addr = addr_call; // 记录线程函数地址
  addr_call = addr_call + nSize + 0x8;
 
  // 重置并复用CodeHolder变量code
  code.reset();
  code.init(rt.environment(), rt.cpuFeatures());
  code.attach(&a);
 
  // 构造timerproc
  a.push(dword_ptr(alloc_addr + 0x14)); // idTimer
  a.push(dword_ptr(alloc_addr + 0xC));  // hwnd
  a.call(dword_ptr(alloc_addr + 0x8)); // call KillTimer
  a.call(dword_ptr(alloc_addr + 0x18)); // custom_call
  a.ret();
  CodeBuffer& timerproc = code.textSection()->buffer();
 
  thread_param.timerproc = addr_call; // 记录therad地址
  nSize = timerproc.size();
  cout << format("回调函数写入地址=0x{:08X} 大小=0x{:08X}\n", addr_call, nSize);
  WriteProcessMemory(remote_handle, (LPVOID)addr_call, timerproc.data(), nSize, nullptr);
  addr_call = addr_call + nSize + 0x8;
 
  // 重置并复用CodeHolder变量code
  code.reset();
  code.init(rt.environment(), rt.cpuFeatures());
  code.attach(&a);
 
  // 构造自定函数
  a.xor_(eax, eax);
  a.div(eax); // 异常语句
  a.mov(dword_ptr(alloc_addr), eax);  // 写入返回值到alloc_addr,程序读取alloc_addr地址的数值即可知道返回值
  a.ret();
  CodeBuffer& custom_call = code.textSection()->buffer();
 
  thread_param.custom_call = addr_call; // 记录custom_call地址
  nSize = custom_call.size();
  cout << format("自定函数写入地址=0x{:08X} 大小=0x{:08X}\n", addr_call, nSize);
  WriteProcessMemory(remote_handle, (LPVOID)addr_call, custom_call.data(), nSize, nullptr);
  addr_call = addr_call + nSize + 0x8;
 
  // 写入参数
  cout << format("线程参数写入地址=0x{:08X} 大小=0x{:08X}\n", addr_param, sizeof(THREAD_PARAM));
  WriteProcessMemory(remote_handle, (LPVOID)addr_param, &thread_param, sizeof(THREAD_PARAM), nullptr);
 
  const HANDLE hRemoteThread = CreateRemoteThread(remote_handle, nullptr, 0, (LPTHREAD_START_ROUTINE)thread_addr, (LPVOID)addr_param, 0, nullptr);
 
  //system("pause");
  return 0;
}
本作品采用 知识共享署名-非商业性使用 4.0 国际许可协议 进行许可
标签: C++
最后更新:2024-06-16

wking

不管博客型博主

点赞
< 上一篇

文章评论

razz evil exclaim smile redface biggrin eek confused idea lol mad twisted rolleyes wink cool arrow neutral cry mrgreen drooling persevering
取消回复

目录
  • 验证SetTimer函数自带异常处理
  • 新线程内执行TimerProc函数
    • 控制台程序
    • 窗口程序
  • 将注入函数转为汇编语言
    • 本进程执行代码
    • 远程进程执行代码
标签聚合
大航海时代 wordpress 一支红杏 C++ win10 linux R6300V2 OneNote

COPYRIGHT © 2024 wkings.blog. ALL RIGHTS RESERVED.

Theme Kratos Made By Seaton Jiang