1 // PE注入.cpp : 定义控制台应用程序的入口点。 2 // 3 4 #include "stdafx.h" 5 6 #include7 8 #include 9 10 #include 11 12 #include 13 14 15 16 #pragma comment (lib, "winmm.lib") 17 18 19 #pragma comment (lib, "kernel32.lib") 20 21 /*获取进程ID号*/ 22 23 DWORD GetProcessIdByName(LPWSTR name) 24 25 { 26 27 PROCESSENTRY32 pe32; 28 29 HANDLE snapshot = NULL; 30 31 DWORD pid = 0; 32 33 34 35 snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); 36 37 if (snapshot != INVALID_HANDLE_VALUE) 38 39 { 40 41 pe32.dwSize = sizeof(PROCESSENTRY32); 42 43 if (Process32First(snapshot, &pe32)) 44 45 { 46 47 do 48 49 { 50 51 if (!lstrcmp(pe32.szExeFile, name)) 52 53 { 54 55 pid = pe32.th32ProcessID; 56 57 break; 58 59 } 60 61 } while (Process32Next(snapshot, &pe32)); 62 63 } 64 65 CloseHandle(snapshot); 66 67 } 68 69 return pid; 70 71 } 72 73 extern "C" void mainCRTStartup(); 74 DWORD main(); 75 76 /** 77 78 * 远程进程内存中注入PE 79 80 */ 81 82 HMODULE injectModule(HANDLE proc, LPVOID module) 83 84 85 86 { 87 88 89 DWORD i = 0; 90 91 DWORD_PTR delta = NULL; 92 93 DWORD_PTR olddelta = NULL; 94 95 /* 获取模块PE头 */ 96 97 PIMAGE_NT_HEADERS headers = (PIMAGE_NT_HEADERS)((LPBYTE)module + ((PIMAGE_DOS_HEADER)module)->e_lfanew); 98 99 PIMAGE_DATA_DIRECTORY datadir; 100 101 102 103 /* 计算注入代码长度 */ 104 105 DWORD moduleSize = headers->OptionalHeader.SizeOfImage; 106 107 LPVOID distantModuleMemorySpace = NULL; 108 109 LPBYTE tmpBuffer = NULL; 110 111 BOOL ok = FALSE; 112 113 if (headers->Signature != IMAGE_NT_SIGNATURE) 114 115 return NULL; 116 117 if (IsBadReadPtr(module, moduleSize)) 118 119 return NULL; 120 121 distantModuleMemorySpace = VirtualAllocEx(proc, NULL, moduleSize, MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE); 122 123 if (distantModuleMemorySpace != NULL) 124 125 { 126 127 tmpBuffer = (LPBYTE)VirtualAlloc(NULL, moduleSize, MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE); 128 129 if (tmpBuffer != NULL) 130 131 { 132 133 RtlCopyMemory(tmpBuffer, module, moduleSize); 134 135 datadir = &headers->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC]; 136 137 if (datadir->Size > 0 && datadir->VirtualAddress > 0) 138 139 { 140 141 delta = (DWORD_PTR)((LPBYTE)distantModuleMemorySpace - headers->OptionalHeader.ImageBase); 142 143 144 145 olddelta = (DWORD_PTR)((LPBYTE)module - headers->OptionalHeader.ImageBase); 146 147 148 149 150 151 PIMAGE_BASE_RELOCATION reloc = (PIMAGE_BASE_RELOCATION)(tmpBuffer + datadir->VirtualAddress); 152 153 154 155 while (reloc->VirtualAddress != 0) 156 157 { 158 159 if (reloc->SizeOfBlock >= sizeof(IMAGE_BASE_RELOCATION)) 160 161 { 162 163 DWORD relocDescNb = (reloc->SizeOfBlock - sizeof(IMAGE_BASE_RELOCATION)) / sizeof(WORD); 164 165 166 167 LPWORD relocDescList = (LPWORD)((LPBYTE)reloc + sizeof(IMAGE_BASE_RELOCATION)); 168 169 170 171 for (i = 0; i ) 172 173 { 174 175 if (relocDescList[i] > 0) 176 177 { 178 179 DWORD_PTR *p = (DWORD_PTR *)(tmpBuffer + (reloc->VirtualAddress + (0x0FFF & (relocDescList[i])))); 180 181 182 183 *p -= olddelta; 184 185 *p += delta; 186 187 } 188 189 } 190 191 } 192 193 reloc = (PIMAGE_BASE_RELOCATION)((LPBYTE)reloc + reloc->SizeOfBlock); 194 195 } 196 197 198 199 tmpBuffer[(DWORD)main - (DWORD)module] = 0x55; 200 201 202 203 ok = WriteProcessMemory(proc, distantModuleMemorySpace, tmpBuffer, moduleSize, NULL); 204 205 } 206 207 VirtualFree(tmpBuffer, 0, MEM_RELEASE); 208 209 } 210 211 212 213 if (!ok) 214 215 216 217 { 218 219 220 VirtualFreeEx(proc, distantModuleMemorySpace, 0, MEM_RELEASE); 221 222 distantModuleMemorySpace = NULL; 223 224 } 225 226 } 227 228 return (HMODULE)distantModuleMemorySpace; 229 230 } 231 232 233 /** 234 235 * 获取DEBUG权限 236 237 */ 238 239 BOOL EnableDebugPrivileges(void) 240 241 { 242 243 HANDLE token; 244 245 TOKEN_PRIVILEGES priv; 246 247 BOOL ret = FALSE; 248 249 250 251 if (OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &token)) 252 253 { 254 255 priv.PrivilegeCount = 1; 256 257 priv.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; 258 259 260 261 if (LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &priv.Privileges[0].Luid) != FALSE && 262 263 AdjustTokenPrivileges(token, FALSE, &priv, 0, NULL, NULL) != FALSE) 264 265 { 266 267 ret = TRUE; 268 269 } 270 271 CloseHandle(token); 272 273 } 274 275 return ret; 276 277 } 278 279 BOOL peInjection(DWORD pid, LPTHREAD_START_ROUTINE callRoutine) 280 281 { 282 283 HANDLE proc, thread; 284 285 HMODULE module, injectedModule; 286 287 288 289 BOOL result = FALSE; 290 291 292 293 294 proc = OpenProcess(PROCESS_CREATE_THREAD | 295 296 PROCESS_QUERY_INFORMATION | 297 298 PROCESS_VM_OPERATION | 299 300 PROCESS_VM_WRITE | 301 302 PROCESS_VM_READ, 303 304 FALSE, 305 306 pid); 307 308 309 310 if (proc != NULL) 311 312 { 313 314 module = GetModuleHandle(NULL); 315 316 injectedModule = (HMODULE)injectModule(proc, module); 317 318 if (injectedModule != NULL) 319 320 { 321 322 LPTHREAD_START_ROUTINE remoteThread = (LPTHREAD_START_ROUTINE)((LPBYTE)injectedModule + (DWORD_PTR)((LPBYTE)callRoutine - (LPBYTE)module)); 323 324 thread = CreateRemoteThread(proc, NULL, 0, remoteThread, NULL, 0, NULL); 325 326 if (thread != NULL) 327 328 { 329 330 CloseHandle(thread); 331 332 result = TRUE; 333 334 } 335 336 else 337 338 { 339 340 VirtualFreeEx(proc, module, 0, MEM_RELEASE); 341 342 } 343 344 } 345 346 CloseHandle(proc); 347 348 } 349 350 return result; 351 352 } 353 354 DWORD WINAPI entryThread(LPVOID param) 355 356 { 357 358 359 360 DWORD newModuleD = (DWORD)param; 361 362 363 MessageBox(NULL, L"Injection success.Now initializing runtime library.", NULL, 0); 364 365 //mainCRTStartup(); 366 367 MessageBox(NULL, L"This will never be called.", NULL, 0); 368 369 return 0; 370 371 } 372 373 void entryPoint() 374 375 { 376 377 MessageBox(NULL, L"entryPoint", NULL, 0); 378 379 EnableDebugPrivileges(); 380 381 382 383 //peInjection(GetProcessIdByName(L"explorer.exe"), entryThread); 384 peInjection( 6384, entryThread); 385 386 } 387 DWORD main() 388 389 { 390 391 //MessageBox(NULL, L"In Main ", NULL, 0); 392 393 printf("This printf can work because runtime library is now initialized.\n"); 394 entryPoint(); 395 396 397 398 399 //(NULL, L"In main end", NULL, 0); 400 401 ExitThread(0); 402 403 return 0; 404 405 } 406 407
通过此方法可将一个进程的完整镜像完全注入到另外一个进程的内存空间中,从而在一个进程空间中包含了两套不同的代码。与DLL注入相比,PE注入的主要优势是不需要很多文件,只需要MAIN.EXE注入到其他进程并唤起自身代码即可。
PE注入