dll注入与代码注入

学习《逆向工程核心原理》,在x64下dll注入与代码注入。

dll注入主要用到CreateRemoteThread,

HANDLE WINAPI CreateRemoteThread(
__in HANDLE hProcess,
__in LPSECURITY_ATTRIBUTES lpThreadAttributes,
__in SIZE_T dwStackSize,
__in LPTHREAD_START_ROUTINE lpStartAddress,
__in LPVOID lpParameter,
__in DWORD dwCreationFlags,
__out LPDWORD lpThreadId
);
利用获取到的LoadLibraryW地址作为lpStartAddress,需注入进程中分配保存的dll名称作为lpParameter,实现动态加载dll

代码注入类似,主要用到VirtualAllocEx,WriteProcessMemory,在需注入的进程中开辟空间,写入代码,变量。

  1 #include "pch.h"
  2 #include <windows.h>
  3 #include <tchar.h>
  4 #include <tlhelp32.h>
  5 #include <stdio.h>
  6 #include <shlobj.h>
  7 extern void checkAdmin();
  8 
  9 //遍历输出进程pid
 10 int TraversalProcess() {
 11     HANDLE hProceessnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
 12     if (hProceessnap == INVALID_HANDLE_VALUE)
 13     {
 14         printf_s("创建进行快照失败\n");
 15         return -1;
 16     }
 17     else
 18     {
 19         PROCESSENTRY32 pe32;
 20         pe32.dwSize = sizeof(pe32);
 21         BOOL hProcess = Process32First(hProceessnap, &pe32);
 22         while (hProcess)
 23         {
 24             /*WCHAR * ProcessName =(WCHAR *)L"ProcessID.exe";
 25             if (!wcscmp(pe32.szExeFile, ProcessName))
 26             {*/
 27                 printf("进程名:%-10ls ----------------进程ID:%6d\n", pe32.szExeFile, pe32.th32ProcessID);
 28             /*    break;
 29             }*/
 30             hProcess = Process32Next(hProceessnap, &pe32);
 31         }
 32     }
 33     CloseHandle(hProceessnap);
 34 }
 35 
 36 //设置权限
 37 BOOL SetPrivilege(LPCTSTR lpszPrivilege, BOOL bEnablePrivilege)
 38 {
 39     TOKEN_PRIVILEGES tp;
 40     HANDLE hToken;
 41     LUID luid;
 42 
 43     if (!OpenProcessToken(GetCurrentProcess(),
 44         TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
 45         &hToken))
 46     {
 47         _tprintf(L"OpenProcessToken error: %u\n", GetLastError());
 48         return FALSE;
 49     }
 50 
 51     if (!LookupPrivilegeValue(NULL,           // lookup privilege on local system
 52         lpszPrivilege,  // privilege to lookup 
 53         &luid))        // receives LUID of privilege
 54     {
 55         _tprintf(L"LookupPrivilegeValue error: %u\n", GetLastError());
 56         return FALSE;
 57     }
 58 
 59     tp.PrivilegeCount = 1;
 60     tp.Privileges[0].Luid = luid;
 61     if (bEnablePrivilege)
 62         tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
 63     else
 64         tp.Privileges[0].Attributes = 0;
 65 
 66     // Enable the privilege or disable all privileges.
 67     if (!AdjustTokenPrivileges(hToken,
 68         FALSE,
 69         &tp,
 70         sizeof(TOKEN_PRIVILEGES),
 71         (PTOKEN_PRIVILEGES)NULL,
 72         (PDWORD)NULL))
 73     {
 74         _tprintf(L"AdjustTokenPrivileges error: %u\n", GetLastError());
 75         return FALSE;
 76     }
 77 
 78     if (GetLastError() == ERROR_NOT_ALL_ASSIGNED)
 79     {
 80         _tprintf(L"The token does not have the specified privilege. \n");
 81         return FALSE;
 82     }
 83 
 84     return TRUE;
 85 }
 86 
 87 //dll注入
 88 BOOL InjectDll(DWORD dwPID, LPCTSTR szDllPath)
 89 {
 90     HANDLE hProcess = NULL, hThread = NULL;
 91     HMODULE hMod = NULL;
 92     LPVOID pRemoteBuf = NULL;
 93     DWORD dwBufSize = (DWORD)(_tcslen(szDllPath) + 1) * sizeof(TCHAR);
 94     LPTHREAD_START_ROUTINE pThreadProc;
 95 
 96     // #1. 使用dwPID请求对象进程(notepad.exe)的HANDLE。
 97     if (!(hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwPID)))
 98     {
 99         _tprintf(L"OpenProcess(%d) failed!!! [%d]\n", dwPID, GetLastError());
100         return FALSE;
101     }
102 
103     // #2. 在目标进程(notepad.exe)内存中分配与szDllName大小相同的内存。
104     pRemoteBuf = VirtualAllocEx(hProcess, NULL, dwBufSize, MEM_COMMIT, PAGE_READWRITE);
105 
106     // #3. 在分配的内存中使用dll路径
107     WriteProcessMemory(hProcess, pRemoteBuf, (LPVOID)szDllPath, dwBufSize, NULL);
108 
109     // #4. 请求到LoadLibraryA() API地址。
110     hMod = GetModuleHandle(L"kernel32.dll");
111     pThreadProc = (LPTHREAD_START_ROUTINE)GetProcAddress(hMod, "LoadLibraryW");
112 
113     // #5. 在notepad.exe进程中运行线程
114     hThread = CreateRemoteThread(hProcess, NULL, 0, pThreadProc, pRemoteBuf, 0, NULL);
115     //通过CreateRemoteThread,调用pThreadProc,即LoadLibraryW,参数为在需注入进程中开辟的内存(存储了dll路径)
116 
117     WaitForSingleObject(hThread, INFINITE);
118 
119     CloseHandle(hThread);
120     CloseHandle(hProcess);
121 
122     return TRUE;
123 }
124 //卸载dll
125 BOOL EjectDll(DWORD dwPID, LPCTSTR szDllName)
126 {
127     BOOL bMore = FALSE, bFound = FALSE;
128     HANDLE hSnapshot, hProcess, hThread;
129     HMODULE hModule = NULL;
130     MODULEENTRY32 me = { sizeof(me) };
131     LPTHREAD_START_ROUTINE pThreadProc;
132     // dwPID = notepad 进程 ID
133     // 使用TH32CS_SNAPMODULE参数获得载入notepad程序的DLL名称
134     hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, dwPID);
135 
136     bMore = Module32First(hSnapshot, &me);
137     for (; bMore; bMore = Module32Next(hSnapshot, &me))
138     {
139         if (!_tcsicmp((LPCTSTR)me.szModule, szDllName) ||
140             !_tcsicmp((LPCTSTR)me.szExePath, szDllName))
141         {
142             bFound = TRUE;
143             break;
144         }
145     }
146 
147     if (!bFound)
148     {
149         CloseHandle(hSnapshot);
150         return FALSE;
151     }
152 
153     if (!(hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwPID)))
154     {
155         _tprintf(L"OpenProcess(%d) failed!!! [%d]\n", dwPID, GetLastError());
156         return FALSE;
157     }
158 
159     hModule = GetModuleHandle(L"kernel32.dll");
160     pThreadProc = (LPTHREAD_START_ROUTINE)GetProcAddress(hModule, "FreeLibrary");
161     hThread = CreateRemoteThread(hProcess, NULL, 0,
162         pThreadProc, me.modBaseAddr,
163         0, NULL);
164     WaitForSingleObject(hThread, INFINITE);
165 
166     CloseHandle(hThread);
167     CloseHandle(hProcess);
168     CloseHandle(hSnapshot);
169 
170     return TRUE;
171 }
172 
173 
174 //代码注入所需结构体
175 typedef struct _THREAD_PARAM
176 {
177     FARPROC pFunc[2];               // LoadLibraryA(), GetProcAddress()
178     char    szBuf[4][128];          // "user32.dll", "MessageBoxA", "www.reversecore.com", "ReverseCore"
179 } THREAD_PARAM, *PTHREAD_PARAM;
180 
181 typedef HMODULE(WINAPI *PFLOADLIBRARYA)
182 (
183     LPCSTR lpLibFileName
184     );
185 
186 typedef FARPROC(WINAPI *PFGETPROCADDRESS)
187 (
188     HMODULE hModule,
189     LPCSTR lpProcName
190     );
191 
192 typedef int (WINAPI *PFMESSAGEBOXA)
193 (
194     HWND hWnd,
195     LPCSTR lpText,
196     LPCSTR lpCaption,
197     UINT uType
198     );
199 
200 //需注入的代码
201 DWORD WINAPI ThreadProc(LPVOID lParam)
202 {
203     PTHREAD_PARAM   pParam = (PTHREAD_PARAM)lParam;
204     HMODULE         hMod = NULL;
205     FARPROC         pFunc = NULL;
206     //调用 LoadLibrary()  加载 "user32.dll"
207     hMod = ((PFLOADLIBRARYA)pParam->pFunc[0])(pParam->szBuf[0]);    // "user32.dll"
208     if (!hMod)
209         return 1;
210 
211     //调用 GetProcAddress() 获取"MessageBoxA"
212     pFunc = (FARPROC)((PFGETPROCADDRESS)pParam->pFunc[1])(hMod, pParam->szBuf[1]);  // "MessageBoxA"
213     if (!pFunc)
214         return 1;
215 
216     // 调用MessageBoxA()
217     ((PFMESSAGEBOXA)pFunc)(NULL, pParam->szBuf[2], pParam->szBuf[3], MB_OK);
218     return 0;
219 }
220 
221 //实现代码注入
222 BOOL InjectCode(DWORD dwPID)
223 {
224     HMODULE         hMod = NULL;
225     THREAD_PARAM    param = { 0, };
226     HANDLE          hProcess = NULL;
227     HANDLE          hThread = NULL;
228     LPVOID          pRemoteBuf[2] = { 0, };
229     DWORD           dwSize = 0;
230 
231     hMod = GetModuleHandleA("kernel32.dll");
232 
233     // set THREAD_PARAM   
234     param.pFunc[0] = GetProcAddress(hMod, "LoadLibraryA");
235     param.pFunc[1] = GetProcAddress(hMod, "GetProcAddress");
236     strcpy_s(param.szBuf[0], "user32.dll");
237     strcpy_s(param.szBuf[1], "MessageBoxA");
238     strcpy_s(param.szBuf[2], "这是code inject");
239     strcpy_s(param.szBuf[3], "好开心!");
240 
241     // Open Process
242     if (!(hProcess = OpenProcess(PROCESS_ALL_ACCESS,   // dwDesiredAccess
243         FALSE,                // bInheritHandle
244         dwPID)))             // dwProcessId
245     {
246         printf("OpenProcess() fail : err_code = %d\n", GetLastError());
247         return FALSE;
248     }
249 
250     // Allocation for THREAD_PARAM       写入代码注入所需的data
251     dwSize = sizeof(THREAD_PARAM);
252     if (!(pRemoteBuf[0] = VirtualAllocEx(hProcess,          // hProcess
253         NULL,                 // lpAddress
254         dwSize,               // dwSize
255         MEM_COMMIT,           // flAllocationType
256         PAGE_READWRITE)))    // flProtect
257     {
258         printf("VirtualAllocEx() fail : err_code = %d\n", GetLastError());
259         return FALSE;
260     }
261     SIZE_T sz = 0;
262     if (!WriteProcessMemory(hProcess,                       // hProcess
263         pRemoteBuf[0],                  // lpBaseAddress
264         (LPVOID)&param,                 // lpBuffer
265         dwSize,                         // nSize
266         &sz))                         // [out] lpNumberOfBytesWritten
267     {
268         printf("写入大小:%d\n", sz);
269         printf("THREAD_PARAM  WriteProcessMemory() fail : err_code = %d\n", GetLastError());
270         return FALSE;
271     }
272 
273     // Allocation for ThreadProc()     写入代码
274     dwSize = abs((int)((DWORD)InjectCode - (DWORD)ThreadProc));
275     
276     printf("dwSize:%d\n", dwSize);
277     //dwSize = 1024;
278     if (!(pRemoteBuf[1] = VirtualAllocEx(hProcess,          // hProcess
279         NULL,                 // lpAddress
280         dwSize,               // dwSize
281         MEM_COMMIT,           // flAllocationType
282         PAGE_EXECUTE_READWRITE)))    // flProtect
283     {
284         printf("VirtualAllocEx() fail : err_code = %d\n", GetLastError());
285         return FALSE;
286     }
287     sz = 0;
288     if (!WriteProcessMemory(hProcess,                       // hProcess
289         pRemoteBuf[1],                  // lpBaseAddress
290         (LPVOID)ThreadProc,             // lpBuffer
291         dwSize,                         // nSize
292         &sz))                         // [out] lpNumberOfBytesWritten
293     {
294         printf("写入大小:%d\n", sz);
295         printf("ThreadProc() WriteProcessMemory() fail : err_code = %d\n", GetLastError());
296         return FALSE;
297     }
298     printf("ThreadProc()写入大小:%d\n", sz);
299     if (!(hThread = CreateRemoteThread(hProcess,            // hProcess
300         NULL,                // lpThreadAttributes
301         0,                   // dwStackSize
302         (LPTHREAD_START_ROUTINE)pRemoteBuf[1],     // dwStackSize
303         pRemoteBuf[0],       // lpParameter
304         0,                   // dwCreationFlags
305         NULL)))             // lpThreadId
306     {
307         printf("CreateRemoteThread() fail : err_code = %d\n", GetLastError());
308         return FALSE;
309     }
310 
311     WaitForSingleObject(hThread, INFINITE);
312     CloseHandle(hThread);
313     CloseHandle(hProcess);
314     printf("code inject end\n");
315     return TRUE;
316 }
317 
318 
319 int _tmain(int argc, TCHAR *argv[])
320 {
321     /*if (argc != 3)
322     {
323         _tprintf(L"USAGE : %s <pid> <dll_path>\n", argv[0]);
324         return 1;
325     }*/
326     // change privilege
327       // 判断当前进程是否以管理员身份运行
328     checkAdmin();
329     /*if (!SetPrivilege(SE_DEBUG_NAME, TRUE))
330         return 1;*/
331     //TraversalProcess();
332     TCHAR pid[10];
333     TCHAR path[MAX_PATH];
334     system("tasklist");
335     printf("ok\n");
336     printf("输入要注入的进程pid:\n");
337     scanf_s("%ls", pid, 10);
338     printf("请选择功能:1.dll注入 2.代码注入\n");
339     int flag = 0;
340     scanf_s("%d", &flag, 1);
341     if (flag == 1) {
342     printf("输入要注入的dll路径:");
343     scanf_s("%ls", path,MAX_PATH);
344     // inject dll
345     if (InjectDll((DWORD)_tstol(pid), path))
346         _tprintf(L"InjectDll(\"%s\") success!!!\n", path);
347     else
348         _tprintf(L"InjectDll(\"%s\") failed!!!\n", path);
349     printf("输入q 卸载dll\n");
350     while (getchar() != 'q');
351     TCHAR *p = _tcsrchr(path, '\\');
352     if(EjectDll((DWORD)_tstol(pid), p+1))
353         printf("卸载dll成功!\n");
354     else 
355     {
356         printf("卸载失败!\n");
357     }
358 
359     system("pause");
360     return 0;
361     }
362     else if (flag == 2)
363     {
364         InjectCode((DWORD)_tstol(pid));
365         system("pause");
366         return 0;
367     }
368     else
369     {
370         system("pause");
371         return 0;
372     }
373 }

判断当前运行时的权限,以管理员身份运行。

 1 BOOL    IsAdmin(HANDLE hProcess)
 2 {
 3     HANDLE hToken = NULL;
 4     OpenProcessToken(hProcess, TOKEN_QUERY, &hToken);
 5 
 6     TOKEN_ELEVATION_TYPE tokenType = TokenElevationTypeDefault; // 用于接收令牌类型
 7 
 8     DWORD dwRetSize = 0; // 用于接收函数输出信息的字节数
 9 
10     // 2. 查询进程令牌中的权限提升值.( 这个值会记录当前的令牌是何种类型( 细节在17_权限管理_令牌的获取.cpp ) )
11     GetTokenInformation(hToken,
12         TokenElevationType,// 获取令牌的当前提升等级
13         &tokenType,
14         sizeof(tokenType),
15         &dwRetSize // 所需缓冲区的字节数
16     );
17 
18 
19     // 根据令牌的类型来输出相应的信息
20     if (TokenElevationTypeFull == tokenType) {
21         // 3. 如果令牌是TokenElevationTypeFull , 则拥有至高无上的能力,可以给令牌添加任何特权
22         printf("管理员账户,并拥有全部的权限,可以给令牌添加任何特权\n");
23         return TRUE;
24     }
25     // 4. 如果是其他的, 则需要以管理员身份重新运行本进程. 这样就能以第三步的方法解决剩下的问题.
26     else if (TokenElevationTypeDefault == tokenType) {
27         printf("默认用户, 可能是一个普通用户, 可能是关闭UAC时登录的管理员用户\n");
28 
29         // 调用系统函数IsUserAnAdmin, 进一步确定是普通用户还是管理员用户
30         return IsUserAnAdmin();
31     }
32     else if (TokenElevationTypeLimited == tokenType) {
33 
34         // 判断受限制的用户是管理员
35         // 如果是管理员, 则这个令牌中会保存有管理员的SID
36 
37         // 1. 获取系统内键管理员用户的SID
38         SID adminSid;
39         DWORD dwSize = sizeof(adminSid);
40         CreateWellKnownSid(WinBuiltinAdministratorsSid, // 获取SID的类型,这里是系统内键管理员
41             NULL, // 传NULL,获取本地计算机的管理员
42             &adminSid,// 函数输出的管理员SID
43             &dwSize // 输入结构的大小,也作为输出
44         );
45 
46         // 获取本令牌的连接令牌(受限制的令牌都会有一个连接的令牌,受限制的令牌正式由主令牌所创建的. )
47         TOKEN_LINKED_TOKEN linkToken;
48         GetTokenInformation(hToken,
49             TokenLinkedToken, // 获取连接的令牌句柄
50             &linkToken,
51             sizeof(linkToken),
52             &dwSize
53         );
54 
55         // 在连接的令牌中查找是否具有管理员的SID
56         BOOL    bIsContain = FALSE; // 用于保存是否包含.
57         CheckTokenMembership(linkToken.LinkedToken, // 在这个令牌中检查
58             &adminSid,             // 检查令牌中是否包含此SID
59             &bIsContain);           // 输出TRUE则包含,反之不包含
60 
61 
62 
63         if (bIsContain) {
64             printf("权限被阉割的受限制管理员账户, 部分权限被移处理\n");
65         }
66 
67 
68         return bIsContain; // 不是以管理员权限运行
69     }
70 
71     return FALSE;
72 }
73 
74 void checkAdmin() {
75     if (!IsAdmin(GetCurrentProcess())) {
76 
77         // 以管理员身份运行本进程
78         //  1 获取本进程的文件路径.
79         TCHAR path[MAX_PATH] = { 0 }; // 需要初始化
80         DWORD dwPathSize = MAX_PATH;
81         QueryFullProcessImageName(GetCurrentProcess(), 0,
82             path,
83             &dwPathSize);
84 
85         // 2 调用创建进程的API运行本进程.
86         ShellExecute(NULL,            // 窗口句柄,没有则填NULL
87             _T("runas"),   // 以管理员身份运行的重要参数
88             path,            // 所有运行的程序的路径(这里是本进程)
89             NULL,            // 命令行参数
90             NULL,            // 新进程的工作目录的路径
91             SW_SHOW           // 创建后的显示标志(最小化,最大化, 显示,隐藏等)
92         );
93 
94         // 退出本进程
95         ExitProcess(0);
96     }
97 }

猜你喜欢

转载自www.cnblogs.com/DirWang/p/11861880.html
今日推荐