-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathDynamicLibraryInjection.cpp
342 lines (295 loc) · 8.6 KB
/
DynamicLibraryInjection.cpp
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
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
#include <stdio.h>
#include <Windows.h>
#include <tlhelp32.h>
//二次转发,获取实际行数
#define ERR_PRINT(FUNC_NAME) _ERR_PRINT(FUNC_NAME)
#define _ERR_PRINT(FUNC_NAME) printf("[%s]Fail, GetLastError:%d, Line:%d\n", #FUNC_NAME, GetLastError(), __LINE__)
//获取某个权限
BOOL EnbalePrivileges(HANDLE hProcess, PCWCHAR pszPrivilegesName)
{
// 打开进程令牌并获取进程令牌句柄
HANDLE hToken = NULL;
BOOL bRet = OpenProcessToken(hProcess, TOKEN_ADJUST_PRIVILEGES, &hToken);
if (bRet == FALSE)
{
ERR_PRINT(OpenProcessToken);
return FALSE;
}
// 获取本地系统的 pszPrivilegesName 特权的LUID值
LUID luidValue = { 0 };
bRet = LookupPrivilegeValueW(NULL, pszPrivilegesName, &luidValue);
if (bRet == FALSE)
{
ERR_PRINT(LookupPrivilegeValueW);
return FALSE;
}
// 设置提升权限信息
TOKEN_PRIVILEGES tokenPrivileges = { 0 };
tokenPrivileges.PrivilegeCount = 1;
tokenPrivileges.Privileges[0].Luid = luidValue;
tokenPrivileges.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
// 提升进程令牌访问权限
bRet = AdjustTokenPrivileges(hToken, FALSE, &tokenPrivileges, 0, NULL, NULL);
if (bRet == FALSE)
{
ERR_PRINT(AdjustTokenPrivileges);
return FALSE;
}
// 根据错误码判断是否特权都设置成功
DWORD dwRet = GetLastError();
if (dwRet == ERROR_SUCCESS)
{
return TRUE;
}
else if (dwRet == ERROR_NOT_ALL_ASSIGNED)
{
ERR_PRINT(AdjustTokenPrivileges);
return FALSE;
}
return FALSE;
}
//通过进程名(带后缀.exe)获取进程ID
BOOL GetProcessIDByPath(PCWCHAR pName, DWORD *pProcessID)
{
if (pName == NULL || pProcessID == NULL)
{
return FALSE;
}
//做一个进程快照
HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPALL, 0);
if (hSnapshot == INVALID_HANDLE_VALUE)
{
return FALSE;
}
//遍历快照找到名称匹配的第一个进程(有多个同名总是选择第一个)
PROCESSENTRY32W pe = { sizeof(pe) };
for (BOOL ret = Process32FirstW(hSnapshot, &pe); ret != FALSE; ret = Process32NextW(hSnapshot, &pe))
{
if (wcscmp(pe.szExeFile, pName) == 0)
{
*pProcessID = pe.th32ProcessID;//传出
CloseHandle(hSnapshot);
return TRUE;
}
}
CloseHandle(hSnapshot);
return FALSE;
}
BOOL IsDllLoad(PCWCHAR pDllPath, DWORD dwProcessID, HMODULE *pDllModule)
{
if (pDllPath == NULL)
{
return FALSE;
}
//做一个进程内的模块快照
recall:
HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, dwProcessID);
if (hSnapshot == INVALID_HANDLE_VALUE)
{
if (GetLastError() == ERROR_BAD_LENGTH)//MSDN文档说:出现此错误请重复调用直到成功
{
Sleep(0);
goto recall;
}
return FALSE;
}
//遍历快照找到名称匹配的第一个模块(有多个同名总是选择第一个)
MODULEENTRY32W md = { sizeof(md) };
for (BOOL ret = Module32FirstW(hSnapshot, &md); ret != FALSE; ret = Module32NextW(hSnapshot, &md))
{
if (wcscmp(md.szExePath, pDllPath) == 0)
{
if (pDllModule != NULL)
{
*pDllModule = md.hModule;//传出
}
CloseHandle(hSnapshot);
return TRUE;
}
}
CloseHandle(hSnapshot);
return FALSE;
}
int wmain(int argc, wchar_t *argv[])
{
//通过命令行获取信息,第一个是dll路径,第二个是被注入进程的ID
if (argc != 3)//3是因为要扣掉第0个自身路径
{
ERR_PRINT(arg count);
printf("Use:\n\t[This EXE] [Dll Path] [Process ID/Name] To Call\n");
return -1;
}
//获取dll路径
const wchar_t *cpDllPath = argv[1];
if (cpDllPath[0] == L'\0')
{
ERR_PRINT(Dll Path);
return -1;
}
SIZE_T szDllNameSize = (wcslen(cpDllPath) + 1) * sizeof(*cpDllPath);//加1是为了保留末尾0字符
//获取进程id
DWORD dwProcessID;
if (swscanf(argv[2], L"%ld", &dwProcessID) != 1)
{
//sscanf失败代表这个有可能是路径
//通过快照匹配获取进程id
if (GetProcessIDByPath(argv[2], &dwProcessID) == FALSE)
{
ERR_PRINT(Process ID/Name);
return -1;
}
}
//获得调试权限(提权)
if (EnbalePrivileges(GetCurrentProcess(), SE_DEBUG_NAME) == FALSE)
{
ERR_PRINT(EnbalePrivileges);
return -1;
}
//打开目标进程(请求所有权限,因为本进程具有SE_DEBUG_NAME权限所以此操作必定成功)
//MSDN:如果调用方已启用 SeDebugPrivilege 特权,则无论安全描述符的内容如何,都会授予请求的访问权限。
HANDLE hTargetProcess = OpenProcess(PROCESS_ALL_ACCESS, false, dwProcessID);
if (hTargetProcess == NULL)
{
ERR_PRINT(OpenProcess);
return -1;
}
//分配远程进程内存
LPVOID pProcessMemory = VirtualAllocEx(hTargetProcess, 0, szDllNameSize, MEM_COMMIT, PAGE_READWRITE);
if (pProcessMemory == NULL)
{
ERR_PRINT(VirtualAllocEx);
return -1;
}
//写入dll路径
SIZE_T szActualWriteSize;
if (WriteProcessMemory(hTargetProcess, pProcessMemory, (LPVOID)cpDllPath, szDllNameSize, &szActualWriteSize) == FALSE ||
szActualWriteSize != szDllNameSize)
{
ERR_PRINT(WriteProcessMemory);
return -1;
}
//获得ZwCreateThreadEx函数地址
HMODULE hNtDllMd = LoadLibraryW(L"ntdll.dll");//这里是加载模块,所以后面需要closehandle
if (hNtDllMd == NULL)
{
ERR_PRINT(GetModuleHandleW);
return -1;
}
//先定义一下ZwCreateThreadEx函数指针类型
typedef DWORD(WINAPI *def_ZwCreateThreadEx)(//x64
PHANDLE,
ACCESS_MASK,
LPVOID,
HANDLE,
LPTHREAD_START_ROUTINE,
LPVOID,
ULONG,
SIZE_T,
SIZE_T,
SIZE_T,
LPVOID);
#define STATUS_SUCCESS 0x0000
def_ZwCreateThreadEx pZwCreateThreadEx = (def_ZwCreateThreadEx)GetProcAddress(hNtDllMd, "ZwCreateThreadEx");
if (pZwCreateThreadEx == NULL)
{
ERR_PRINT(GetProcAddress);
return -1;
}
//获得LoadLibraryW和FreeLibrary函数地址
HMODULE hKernel32Md = GetModuleHandleW(L"kernel32.dll");//这里是获取已加载dll的模块句柄,无需closehandle
if (hKernel32Md == NULL)
{
ERR_PRINT(GetModuleHandleW);
return -1;
}
LPVOID pLoadLibraryW = GetProcAddress(hKernel32Md, "LoadLibraryW");
if (pLoadLibraryW == NULL)
{
ERR_PRINT(GetProcAddress);
return -1;
}
LPVOID pFreeLibrary = GetProcAddress(hKernel32Md, "FreeLibrary");
if (pFreeLibrary == NULL)
{
ERR_PRINT(GetProcAddress);
return -1;
}
//启动远程线程加载dll
HANDLE hTargetThread = NULL;
DWORD dwStatus = pZwCreateThreadEx(&hTargetThread, PROCESS_ALL_ACCESS, NULL, hTargetProcess, (LPTHREAD_START_ROUTINE)pLoadLibraryW, pProcessMemory, 0, 0, 0, 0, NULL);
if (hTargetThread == NULL || dwStatus != STATUS_SUCCESS)
{
ERR_PRINT(ZwCreateThreadEx);
return -1;
}
//等待函数退出
WaitForSingleObject(hTargetThread, INFINITE);
//查看模块是否载入
HMODULE hTargetDll = NULL;//目标dll在目标进程内的句柄
if (IsDllLoad(cpDllPath, dwProcessID, &hTargetDll))
{
printf("Injection Success.\n");
}
else
{
printf("Injection Unsuccess.\n");
}
//获取线程退出码
DWORD hTargetThreadExitCode = 0;
if (GetExitCodeThread(hTargetThread, &hTargetThreadExitCode) == FALSE)
{
ERR_PRINT(GetExitCodeThread);
return -1;
}
//关闭远程线程句柄
CloseHandle(hTargetThread);
printf("LoadLibrary Thread Exit, Code:%d\n", hTargetThreadExitCode);
putchar('\n');
system("pause");//暂停
putchar('\n');
//让远程进程卸载dll
if (hTargetDll != NULL)
{
//启动远程线程释放dll
HANDLE hTargetThread = NULL;
DWORD dwStatus = pZwCreateThreadEx(&hTargetThread, PROCESS_ALL_ACCESS, NULL, hTargetProcess, (LPTHREAD_START_ROUTINE)pFreeLibrary, (LPVOID)hTargetDll, 0, 0, 0, 0, NULL);
if (hTargetThread == NULL || dwStatus != STATUS_SUCCESS)
{
ERR_PRINT(ZwCreateThreadEx);
return -1;
}
//等待函数退出
WaitForSingleObject(hTargetThread, INFINITE);
//查看模块是否卸载
if (!IsDllLoad(cpDllPath, dwProcessID, NULL))
{
printf("Unload Success.\n");
}
else
{
printf("Unload Unsuccess.\n");
}
//获取线程退出码
DWORD hTargetThreadExitCode = 0;
if (GetExitCodeThread(hTargetThread, &hTargetThreadExitCode) == FALSE)
{
ERR_PRINT(GetExitCodeThread);
return -1;
}
//关闭远程线程句柄
CloseHandle(hTargetThread);
printf("FreeLibrary Thread Exit, Code:%d\n", hTargetThreadExitCode);
}
//释放远程进程内存
if (VirtualFreeEx(hTargetProcess, pProcessMemory, 0, MEM_RELEASE) == FALSE)
{
ERR_PRINT(VirtualFreeEx);
return -1;
}
//关闭远程进程句柄
CloseHandle(hTargetProcess);
//关闭ntdll.dll
CloseHandle(hNtDllMd);
//安全退出
return 0;
}