矛与盾----注入到目标进程
假设我们有如下代码:
而且我们知道函数add 的地址是 0x00401630. 这篇文章的目的就是写一个程序,注入到目标进程,然后调用这个进程的add()函数。
要注入到目标进程有很多种方法, 这里我选择用CreateRemoreThread 来示例。
HANDLE CreateRemoteThread(
HANDLE hProcess, //目标进程的句柄
LPSECURITY_ATTRIBUTES lpThreadAttributes,//指向线程的安全描述结构体的指针,一般设置为NULL,表示使用默认的安全级别
SIZE_T dwStackSize,//线程堆栈大小,一般设置为0,表示使用默认的大小,一般为1M
LPTHREAD_START_ROUTINE lpStartAddress,//线程函数的地址
LPVOID lpParameter,//线程参数
DWORD dwCreationFlags,//线程的创建方式
LPDWORD lpThreadId//输出参数,记录创建的远程线程的ID
);
使用CreateRemoteThread 来完成代码注入非常简单, 只需要进行如下 步骤:
- 打开目标进程
- 分配空间, 把我们要注入的函数写入这个空间
- 创建远程线程
我们可以看下如下代码:
1 void __stdcall addHP()
2 {
3 __asm
4 {
5 mov eax, 0x00401630
6 call eax
7 }
8 }
9 bool remoteCall(LPCWSTR windowsName)
10 {
11 //1. 打开进程
12 HWND tergetHwnd = ::FindWindow(NULL,windowsName);
13 DWORD processId;
14 ::GetWindowThreadProcessId(tergetHwnd,&processId);
15 HANDLE processHandle = ::OpenProcess(PROCESS_ALL_ACCESS,
16 FALSE, processId);
17 if (NULL == processHandle)
18 {
19 AfxMessageBox(_T("Create process failed"));
20 return false;
21 }
22 //2. 分配空间, 把我们要注入的函数写入这个空间
23 LPVOID remotefunc = VirtualAllocEx(processHandle, NULL,MAX_REMOTE_DATA,
24 MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
25 if (NULL == remotefunc)
26 {
27 AfxMessageBox(_T("remotefunc alloc failed"));
28 return false;
29 }
30 if (!WriteProcessMemory(processHandle,remotefunc,&addHP,
31 MAX_REMOTE_DATA, 0))
32 {
33 AfxMessageBox(_T("write process memory failed"));
34 return false;
35 }
36 //创建远程线程
37 DWORD threadId;
38 HANDLE remoteHandle = CreateRemoteThread(processHandle,
39 NULL, 0, (LPTHREAD_START_ROUTINEremotefunc), NULL, 0, &threadId);
40 if (!remoteHandle)
41 {
42 AfxMessageBox(_T("CreateRemoteThread failed"));
43 return false;
44 }
45 VirtualFreeEx(processHandle, remotefunc, MAX_REMOTE_DATA, MEM_RELEASE);
46 CloseHandle(remoteHandle);
47 return true;
48 }
测试一下是OK 的。 但是这样执行却有一个问题, 就是我们不能给addHP()传递参数, 因为所有关于这些参数的值都是在当前进程的, 所以我们要修改为如下程序:
1 // 这里我们做的就是用函数指针封装 add HP 函数
2 int const MAX_REMOTE_DATA = 1024 * 4;
3 void __stdcall addHP(int num)
4 {
5 __asm
6 {
7 push num
8 mov eax, 0x00401630
9 call eax
10 }
11 }
12 typedef struct tagRpcData
13 {
14 int num;
15 void* pfunCall;
16 }stRpcData, *LPRPCDATA;
17 int const MAX_REMOTE_DATA = 1024 * 4;
18 typedef void(__stdcall* FUNCADD)(int);
19 void __stdcall remoteFun(LPRPCDATA pData)
20 {
21 FUNCADD fun = (FUNCADD)pData->pfunCall;
22 fun(pData->num);
23 return 0;
24 }
25 bool remoteCall(LPCWSTR windowsName)
26 {
27 //1. 打开进程
28 HWND tergetHwnd = ::FindWindow(NULL,windowsName);
29 DWORD processId;
30 ::GetWindowThreadProcessId(tergetHwnd,&processId);
31 HANDLE processHandle = ::OpenProcess(PROCESS_ALL_ACCESS,
32 FALSE, processId);
33 if (NULL == processHandle)
34 {
35 AfxMessageBox(_T("Create process failed"));
36 return false;
37 }
38 //2. 分配空间, 把我们要注入的函数写入这个空间
39 LPVOID remotefunc = VirtualAllocEx(processHandle, NULL,MAX_REMOTE_DATA,
40 MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
41 if (NULL == remotefunc)
42 {
43 AfxMessageBox(_T("remotefunc alloc failed"));
44 return false;
45 }
46 if (!WriteProcessMemory(processHandle,remotefunc,&addHP,
47 MAX_REMOTE_DATA, 0))
48 {
49 AfxMessageBox(_T("write process memory failed"));
50 return false;
51 }
52 //3. 分配空间, 把我们要注入的函数写入这个空间
53 LPVOID remoteParam = VirtualAllocEx(processHandle, NULL,MAX_REMOTE_DATA,
54 MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
55 if (NULL == remoteParam)
56 {
57 AfxMessageBox(_T("remoteParam alloc failed"));
58 return false;
59 }
60 if (!WriteProcessMemory(processHandle,remoteParam,&addHP,
61 MAX_REMOTE_DATA, 0))
62 {
63 AfxMessageBox(_T("write process memory failed"));
64 return false;
65 }
66 //创建远程线程
67 DWORD threadId;
68 HANDLE remoteHandle = CreateRemoteThread(processHandle,
69 NULL, 0, (LPTHREAD_START_ROUTINE)(remotefunc), remoteParam, 0, &threadId);
70 if (!remoteHandle)
71 {
72 AfxMessageBox(_T("CreateRemoteThread failed"));
73 return false;
74 }
75 VirtualFreeEx(processHandle, remotefunc, MAX_REMOTE_DATA, MEM_RELEASE);
76 VirtualFreeEx(processHandle, remoteParam, MAX_REMOTE_DATA, MEM_RELEASE);
77 CloseHandle(remoteHandle);
78 return true;
79 }
这样就OK了。
这里再记录两个函数:
1 //提升进程访问权限
2 bool enableDebugPriv()
3 {
4 HANDLE hToken;
5 LUID sedebugnameValue;
6 TOKEN_PRIVILEGES tkp;
7 if (!OpenProcessToken(GetCurrentProcess(),
8 TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken)) {
9 return false;
10 }
11 if (!LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &sedebugnameValue)) {
12 CloseHandle(hToken);
13 return false;
14 }
15 tkp.PrivilegeCount = 1;
16 tkp.Privileges[0].Luid = sedebugnameValue;
17 tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
18 if (!AdjustTokenPrivileges(hToken, FALSE, &tkp, sizeof(tkp), NULL, NULL)) {
19 CloseHandle(hToken);
20 return false;
21 }
22 return true;
23 }
24 //根据进程名称得到进程ID,如果有多个运行实例的话,返回第一个枚举到的进程的ID
25 DWORD processNameToId(LPCTSTR lpszProcessName)
26 {
27 HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
28 PROCESSENTRY32 pe;
29 pe.dwSize = sizeof(PROCESSENTRY32);
30 if (!Process32First(hSnapshot, &pe)) {
31 MessageBox(NULL,
32 _T("The frist entry of the process list has not been copyied to the buffer"),
33 _T("Notice"), MB_ICONINFORMATION | MB_OK);
34 return 0;
35 }
36 while (Process32Next(hSnapshot, &pe)) {
37 if (!strcmp(lpszProcessName, pe.szExeFile)) {
38 return pe.th32ProcessID;
39 }
40 }
41 return 0;
42 }