跳至主要内容

28.进程通信

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
#include <stdio.h>
#include "Windows.h"


void Attack() {
printf("Attack\n");
}
void Help() {
printf("Help\n");
}
void Injection() {
printf("Inject!\n");
}

int main() {
printf("Game Start!\n");
while (1) {
int opCode;
int over = 0;
scanf_s("%d", &opCode);

if (over)
{
break;
}
switch (opCode) {
case 1:
Attack();
break;
case 2:
Help();
break;
case 777:
Injection();
break;
case 3:
over = 1;
break;
}
}
return 0;
}
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
// dllmain.cpp : 定义 DLL 应用程序的入口点。
#include "pch.h"
#include <windows.h>

// 目标函数地址(x64 下直接函数指针调用)
#define _Attack_ 0x07FF6304A13FCULL
#define _Help_ 0x07FF6304A140BULL
#define _Injection_ 0x07FF7CAC113F7ULL

// 必须和注入器完全一致
#define __Map__ "Share"
#define MAP_SIZE 0x1000

HMODULE g_hModule;
HANDLE g_hMapFile = NULL;
LPVOID lpBuff = NULL;
DWORD dwType = 0;

// 如果目标函数带参数,改成对应签名,例如 typedef void (__cdecl *FN)(int, int);
typedef void(__cdecl* FN_GameFunc)();

DWORD WINAPI ThreadProc(LPVOID lpParameter) {
dwType = 0;

g_hMapFile = OpenFileMappingA(FILE_MAP_ALL_ACCESS, FALSE, __Map__);
if (g_hMapFile == NULL) {
OutputDebugStringA("[DLL] OpenFileMapping Error!\n");
return 0;
}

lpBuff = MapViewOfFile(g_hMapFile, FILE_MAP_ALL_ACCESS, 0, 0, MAP_SIZE);
if (lpBuff == NULL) {
OutputDebugStringA("[DLL] MapViewOfFile Error!\n");
CloseHandle(g_hMapFile);
return 0;
}
OutputDebugStringA("[DLL] Shared memory OK, waiting for commands...\n");

while (1) {
if (lpBuff != NULL) {
CopyMemory(&dwType, lpBuff, sizeof(dwType));
}

if (dwType == 1) {
OutputDebugStringA("[DLL] Call Attack\n");
((FN_GameFunc)_Attack_)(); // 原来的 __asm { mov eax,_Attack_; call eax }
dwType = 0;
CopyMemory(lpBuff, &dwType, sizeof(dwType));
}
else if (dwType == 2) {
OutputDebugStringA("[DLL] Call Help\n");
((FN_GameFunc)_Help_)(); // 原来的 __asm { mov eax,_Help_; call eax }
dwType = 0;
CopyMemory(lpBuff, &dwType, sizeof(dwType));
}
else if (dwType == 3) {
OutputDebugStringA("[DLL] Call Injection\n");
((FN_GameFunc)_Injection_)(); // 原来的 __asm { mov eax,_Injection_; call eax }
dwType = 0;
CopyMemory(lpBuff, &dwType, sizeof(dwType));
}
else if (dwType == 4) {
OutputDebugStringA("[DLL] Unloading...\n");
UnmapViewOfFile(lpBuff);
CloseHandle(g_hMapFile);
FreeLibraryAndExitThread(g_hModule, 4); // 卸载 DLL 并结束线程
}
Sleep(500);
}
return 0;
}

BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) {
g_hModule = hModule;
switch (ul_reason_for_call) {
case DLL_PROCESS_ATTACH:
// 注入后开线程(DllMain 里 CreateThread 是注入的常规做法)
CreateThread(NULL, 0, ThreadProc, NULL, 0, NULL);
break;
case DLL_PROCESS_DETACH:
OutputDebugStringA("[DLL] DLL_PROCESS_DETACH\n");
break;
}
return TRUE;
}

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
#include <debugapi.h>
#include <errhandlingapi.h>
#include <handleapi.h>
#include <libloaderapi.h>
#include <memoryapi.h>
#include <minwinbase.h>
#include <minwindef.h>
#include <processthreadsapi.h>
#include <string.h>
#include <synchapi.h>
#include <windows.h>
#include <stdio.h>
#include <winnt.h>

#define __MAP__ "Share"

HANDLE g_hMapFile;
LPTSTR lpBuff;

BOOL Init()
{
//创建共享内存
g_hMapFile = CreateFileMappingA(INVALID_HANDLE_VALUE, NULL,PAGE_READWRITE,0,0x1000,__MAP__);
if (g_hMapFile == NULL) {
printf("CreateFileMappingA Error\n");
return FALSE;
}
//映射内存(大小和 CreateFileMapping 保持一致)
lpBuff = MapViewOfFile(g_hMapFile,FILE_MAP_ALL_ACCESS,0,0,0x1000);
if (lpBuff == NULL) {
printf("MapViewOfFile Error\n");
return FALSE;
}
return TRUE;
}

BOOL LoadDll(DWORD dwProcessID,char *szDllPathName){
BOOL bRet;
HANDLE hProcess;
HANDLE hThread;
DWORD dwLength;
FARPROC dwLoadAddr;
LPVOID lpAllocAddr;
HMODULE hModule;

bRet = FALSE;
dwLoadAddr = 0;
hProcess = 0;

//获取进程句柄
hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE,dwProcessID);
if (hProcess == NULL) {
OutputDebugStringA("OpenProcess Error! \n");
return FALSE;
}
//计算DLL路径名字长度,并且要加上0结尾的长度
dwLength = strlen(szDllPathName) + 1;

//在目标进程分配内存
lpAllocAddr = VirtualAllocEx(hProcess, NULL, dwLength, MEM_COMMIT,PAGE_READWRITE);

if (lpAllocAddr == NULL) {
OutputDebugStringA("VirtualAllocEx Error! \n");
CloseHandle(hProcess);
return FALSE;
}
//拷贝DLL路径名字到目标进程的内存
bRet = WriteProcessMemory(hProcess, lpAllocAddr, szDllPathName,dwLength,NULL);
if (!bRet) {
OutputDebugStringA("WriteProcessMemory Error! \n");
CloseHandle(hProcess);
return FALSE;
}

//获取模块地址
hModule = GetModuleHandleA("Kernel32.dll");
if (hModule == NULL) {
OutputDebugStringA("GetModuleHandleA Error! \n");
CloseHandle(hProcess);
return FALSE;
}
//获取LoadLibraryA函数地址
dwLoadAddr = GetProcAddress(hModule, "LoadLibraryA");
if (dwLoadAddr == NULL) {
OutputDebugStringA("GetProcAddress Error! \n");
CloseHandle(hProcess);
CloseHandle(hModule);
return FALSE;
}
//创建远程线程,加载DLL
hThread = CreateRemoteThread(hProcess, NULL, 0,(LPTHREAD_START_ROUTINE)dwLoadAddr,lpAllocAddr,0,NULL);
if (hThread == NULL) {
OutputDebugStringA("CreateRemoteThread Error! \n");
CloseHandle(hProcess);
CloseHandle(hModule);
return FALSE;
}

CloseHandle(hProcess);
CloseHandle(hThread);

return TRUE;
}


int main(int argc, char *argv[]) {
DWORD dwCtrlCode;
DWORD dwOrderList[3];

dwCtrlCode = 0;
if (Init()) {
LoadDll(111, "Dll1.dll");
}else {
return 0;
}

dwOrderList[0] = 3;
dwOrderList[1] = 3;
dwOrderList[2] = 4;
for (int i = 0; i < 3; i++) {
dwCtrlCode = dwOrderList[i];
CopyMemory(lpBuff,&dwCtrlCode,4);
Sleep(2000);
}
return 0;
}

关于本文

由 GuQing 撰写,采用 CC BY-NC 4.0 许可协议。