Changeset 4826
- Timestamp:
- 07/10/12 12:18:31 (11 months ago)
- Location:
- zzuf/trunk/src
- Files:
-
- 3 edited
-
libzzuf/lib-win32.c (modified) (3 diffs)
-
libzzuf/sys.c (modified) (1 diff)
-
myfork.c (modified) (6 diffs)
Legend:
- Unmodified
- Added
- Removed
-
zzuf/trunk/src/libzzuf/lib-win32.c
r4813 r4826 41 41 /* Kernel functions that we divert */ 42 42 #if defined HAVE_CREATEFILEA 43 static HANDLE (__stdcall *ORIG(CreateFileA))(LPC TSTR, DWORD, DWORD,43 static HANDLE (__stdcall *ORIG(CreateFileA))(LPCSTR, DWORD, DWORD, 44 44 LPSECURITY_ATTRIBUTES, 45 45 DWORD, DWORD, HANDLE); … … 67 67 68 68 #if defined HAVE_CREATEFILEA 69 HANDLE __stdcall NEW(CreateFileA)(LPC TSTR lpFileName, DWORD dwDesiredAccess,69 HANDLE __stdcall NEW(CreateFileA)(LPCSTR lpFileName, DWORD dwDesiredAccess, 70 70 DWORD dwShareMode, LPSECURITY_ATTRIBUTES lpSecurityAttributes, 71 71 DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes, … … 73 73 { 74 74 HANDLE ret; 75 75 76 ret = ORIG(CreateFileA)(lpFileName, dwDesiredAccess, dwShareMode, 76 77 lpSecurityAttributes, dwCreationDisposition, -
zzuf/trunk/src/libzzuf/sys.c
r4813 r4826 155 155 continue; 156 156 157 thunk = (thunk_t)((char *)module + import ->FirstThunk);157 thunk = (thunk_t)((char *)module + import[j].FirstThunk); 158 158 for(i = 0; thunk[i].u1.Function; i++) 159 159 { -
zzuf/trunk/src/myfork.c
r4813 r4826 78 78 static void rep32(uint8_t *buf, void *addr); 79 79 static int dll_inject(PROCESS_INFORMATION *, char const *); 80 static intptr_tget_proc_address(void *, DWORD, char const *);80 static void *get_proc_address(void *, DWORD, char const *); 81 81 #endif 82 82 … … 305 305 DWORD err = GetLastError(); 306 306 FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | 307 FORMAT_MESSAGE_FROM_SYSTEM |307 FORMAT_MESSAGE_FROM_SYSTEM | 308 308 FORMAT_MESSAGE_IGNORE_INSERTS, 309 309 NULL, err, 0, (LPTSTR)&buf, 0, NULL); … … 333 333 334 334 #if defined HAVE_WINDOWS_H 335 static void rep32(uint8_t *buf, void *addr)336 {337 while(buf++)338 if (memcmp(buf, "____", 4) == 0)339 {340 memcpy(buf, &addr, 4);341 return;342 }343 }344 335 345 336 static int dll_inject(PROCESS_INFORMATION *pinfo, char const *lib) 346 337 { 347 static uint8_t const loader[] = 348 /* Load the injected DLL into memory */ 349 "\xb8____" /* mov %eax, <library_name_address> */ 350 "\x50" /* push %eax */ 351 "\xb8____" /* mov %eax, <LoadLibraryA> */ 352 "\xff\xd0" /* call %eax */ 353 /* Restore the clobbered entry point code using our backup */ 354 "\xb8\0\0\0\0" /* mov %eax,0 */ 355 "\x50" /* push %eax */ 356 "\xb8____" /* mov %eax, <jumper_length> */ 357 "\x50" /* push %eax */ 358 "\xb8____" /* mov %eax, <backuped_entry_point_address> */ 359 "\x50" /* push %eax */ 360 "\xb8____" /* mov %eax, <original_entry_point_address> */ 361 "\x50" /* push %eax */ 362 "\xb8____" /* mov %eax, <GetCurrentProcess> */ 363 "\xff\xd0" /* call %eax */ 364 "\x50" /* push %eax */ 365 "\xb8____" /* mov %eax, <WriteProcessMemory> */ 366 "\xff\xd0" /* call %eax */ 367 /* Jump to the original entry point */ 368 "\xb8____" /* mov %eax, <original_entry_point_address> */ 369 "\xff\xe0"; /* jmp %eax */ 370 371 static uint8_t const waiter[] = 372 "\xeb\xfe"; /* jmp <current> */ 373 374 static uint8_t const jumper[] = 375 /* Jump to the injected loader */ 376 "\xb8____" /* mov eax, <loader_address> */ 377 "\xff\xe0"; /* jmp eax */ 378 379 CONTEXT ctx; 380 void *process = pinfo->hProcess; 381 void *thread = pinfo->hThread; 382 void *epaddr; 383 DWORD pid = pinfo->dwProcessId; 384 385 /* code: 386 * +---------------+--------------------+--------------+-------------+ 387 * | loader | entry point backup | library name | jumper | 388 * | len(loader) | len(jumper) | len(lib) | len(jumper) | 389 * +---------------+--------------------+--------------+-------------+ */ 390 uint8_t code[1024]; 391 392 uint8_t *loaderaddr; 393 size_t liblen, loaderlen, waiterlen, jumperlen; 394 DWORD tmp; 395 396 liblen = strlen(lib) + 1; 397 loaderlen = sizeof(loader) - 1; 398 waiterlen = sizeof(waiter) - 1; 399 jumperlen = sizeof(jumper) - 1; 400 if (loaderlen + jumperlen + liblen > 1024) 401 return -1; 402 403 /* Allocate memory in the child for our injected code */ 404 loaderaddr = VirtualAllocEx(process, NULL, loaderlen + jumperlen + liblen, 405 MEM_COMMIT, PAGE_EXECUTE_READWRITE); 406 if(!loaderaddr) 407 return -1; 408 409 /* Create the first shellcode (jumper). 410 * 411 * The jumper's job is simply to jump at the second shellcode's location. 412 * It is written at the original entry point's location, which will in 413 * turn be restored by the second shellcode. 414 */ 415 memcpy(code + loaderlen + jumperlen + liblen, jumper, jumperlen); 416 rep32(code + loaderlen + jumperlen + liblen, loaderaddr); 417 418 /* Create the second shellcode (loader, backuped entry point, and library 419 * name). 420 * 421 * The loader's job is to load the library by calling LoadLibraryA(), 422 * restore the original entry point using the backup copy, and jump 423 * back to the original entry point as if the process had just started. 424 * 425 * The second shellcode is written at a freshly allocated memory location. 426 */ 427 memcpy(code, loader, loaderlen); 428 memcpy(code + loaderlen + jumperlen, lib, liblen); 429 430 /* Find the entry point address. It's simply in EAX. */ 431 ctx.ContextFlags = CONTEXT_FULL; 432 GetThreadContext(thread, &ctx); 433 epaddr = (void *)(uintptr_t)ctx.Eax; 434 435 /* Backup the old entry point code */ 436 ReadProcessMemory(process, epaddr, code + loaderlen, jumperlen, &tmp); 437 if(tmp != jumperlen) 438 return -1; 439 440 /* Replace the entry point code with a short jump to self, then resume 441 * the thread. This is necessary for CreateToolhelp32Snapshot() to 442 * work. */ 443 WriteProcessMemory(process, epaddr, waiter, waiterlen, &tmp); 444 if(tmp != waiterlen) 445 return -1; 446 FlushInstructionCache(process, epaddr, waiterlen); 447 ResumeThread(thread); 448 449 /* Wait until the entry point is reached */ 450 for (tmp = 0; tmp < 100; tmp++) 451 { 452 CONTEXT ctx; 453 ctx.ContextFlags = CONTEXT_FULL; 454 GetThreadContext(thread, &ctx); 455 if ((uintptr_t)ctx.Eip == (uintptr_t)epaddr) 456 break; 338 int res = -1; 339 340 /* This payload allows us to load arbitrary module located at the end of this buffer */ 341 static uint8_t const ldr[] = 342 { 343 "\x60" /* pushad */ 344 "\xEB\x0E" /* jmp short 0x11 */ 345 "\xB8____" /* mov eax,LoadLibraryA */ 346 "\xFF\xD0" /* call eax */ 347 "\x85\xC0" /* test eax,eax */ 348 "\x75\x01" /* jnz 0xf */ 349 "\xCC" /* int3 */ 350 "\x61" /* popad */ 351 "\xC3" /* ret */ 352 "\xE8\xED\xFF\xFF\xFF" /* call dword 0x3 */ 353 }; 354 355 /* We use this code to make the targeted process waits for us */ 356 static uint8_t const wait[] = "\xeb\xfe"; /* jmp $-1 */ 357 size_t wait_len = sizeof(wait) - 1; 358 uint8_t orig_data[2]; 359 360 void *process = pinfo->hProcess; 361 void *thread = pinfo->hThread; 362 DWORD pid = pinfo->dwProcessId; 363 void *rldlib = NULL; 364 DWORD written = 0; 365 DWORD old_prot = 0; 366 367 /* Payload */ 368 void *rpl = NULL; 369 uint8_t *pl = NULL; 370 size_t pl_len = sizeof(ldr) - 1 + strlen(lib) + 1; 371 372 CONTEXT ctxt; 373 DWORD oep; /* Original Entry Point */ 374 375 /* Use the main thread to inject our library */ 376 ctxt.ContextFlags = CONTEXT_FULL; 377 if (!GetThreadContext(thread, &ctxt)) goto _return; 378 379 /* Make the target program waits when it reachs the original entry point, because we can't do many thing from the windows loader */ 380 oep = ctxt.Eax; 381 if (!ReadProcessMemory(process, (LPVOID)oep, orig_data, sizeof(orig_data), &written) || written != sizeof(orig_data)) goto _return; /* save original opcode */ 382 if (!WriteProcessMemory(process, (LPVOID)oep, wait, wait_len , &written) || written != wait_len) goto _return; /* write jmp short $-1 */ 383 if (!FlushInstructionCache(process, (LPVOID)oep, wait_len)) goto _return; 384 if (ResumeThread(thread) == (DWORD)-1) goto _return; 385 386 /* Stop when the program reachs the oep */ 387 while (oep != ctxt.Eip) 388 { 389 if (!GetThreadContext(thread, &ctxt)) goto _return; 457 390 Sleep(10); 458 391 } 459 SuspendThread(thread); 460 if (tmp == 100) 461 return -1; 462 463 /* Remotely parse the target process's module list to get the addresses 464 * of the functions we need. This can only be done because we advanced 465 * the target's execution to the entry point. */ 466 rep32(code, loaderaddr + loaderlen + jumperlen); 467 rep32(code, (void *)get_proc_address(process, pid, "LoadLibraryA")); 468 rep32(code, (void *)(uintptr_t)jumperlen); 469 rep32(code, loaderaddr + loaderlen); 470 rep32(code, epaddr); 471 rep32(code, (void *)get_proc_address(process, pid, "GetCurrentProcess")); 472 rep32(code, (void *)get_proc_address(process, pid, "WriteProcessMemory")); 473 rep32(code, epaddr); 474 475 /* Write our shellcodes into the target process */ 476 WriteProcessMemory(process, epaddr, code + loaderlen + jumperlen + liblen, 477 jumperlen, &tmp); 478 if(tmp != jumperlen) 479 return -1; 480 FlushInstructionCache(process, epaddr, waiterlen); 481 482 WriteProcessMemory(process, loaderaddr, code, 483 loaderlen + jumperlen + liblen, &tmp); 484 if(tmp != loaderlen + jumperlen + liblen) 485 return -1; 486 487 return 0; 392 393 if (SuspendThread(thread) == (DWORD)-1) goto _return; 394 395 /* Resolve LoadLibraryA from the target process memory context */ 396 rldlib = get_proc_address(process, pid, "LoadLibraryA"); 397 398 if ((rpl = VirtualAllocEx(process, NULL, pl_len, MEM_COMMIT, PAGE_EXECUTE_READWRITE)) == NULL) goto _return; 399 400 /* Emulate a call to the ldr code, thus the ret instruction from ldr will get eip back to the original entry point */ 401 ctxt.Esp -= 4; 402 if (!WriteProcessMemory(process, (LPVOID)ctxt.Esp, &oep, sizeof(oep), &written) || written != sizeof(oep)) goto _return; 403 ctxt.Eip = (DWORD)rpl; 404 if (!SetThreadContext(thread, &ctxt)) goto _return; 405 406 /* Forge the payload */ 407 if ((pl = (uint8_t *)malloc(pl_len)) == NULL) goto _return; 408 memcpy(pl, ldr, sizeof(ldr) - 1); 409 memcpy(pl + 4, &rldlib, sizeof(rldlib)); /* Write the address of LoadLibraryA */ 410 strcpy((char *)(pl + sizeof(ldr) - 1), lib); /* Write the first parameter of LoadLibraryA */ 411 412 if (!WriteProcessMemory(process, rpl, pl, pl_len, &written) || written != pl_len) goto _return; 413 414 /* Restore original opcode */ 415 if (!WriteProcessMemory(process, (LPVOID)oep, orig_data, sizeof(orig_data), &written) || written != sizeof(orig_data)) goto _return; 416 417 if (!FlushInstructionCache(process, rpl, pl_len)) goto _return; 418 if (!FlushInstructionCache(process, (LPVOID)oep, sizeof(orig_data))) goto _return; 419 420 res = 0; 421 _return: 422 if (pl != NULL) free(pl); 423 424 /* We must not free remote allocated memory since they will be used after the process will be resumed */ 425 return res; 488 426 } 489 427 490 static intptr_tget_proc_address(void *process, DWORD pid, const char *func)428 static void *get_proc_address(void *process, DWORD pid, const char *func) 491 429 { 492 430 char buf[1024]; … … 494 432 495 433 MODULEENTRY32 entry; 496 intptr_tret = 0;434 void *ret = 0; 497 435 DWORD tmp; 498 436 void *list; … … 508 446 509 447 uint32_t exportaddr; 510 uint8_t const*base = entry.modBaseAddr;448 uint8_t *base = entry.modBaseAddr; 511 449 512 450 if (strcmp("kernel32.dll", entry.szModule)) … … 539 477 ReadProcessMemory(process, base + expdir.AddressOfNameOrdinals 540 478 + i * sizeof(WORD), 541 &j, sizeof(j), &tmp);479 &j, sizeof(j), &tmp); 542 480 ReadProcessMemory(process, base + expdir.AddressOfFunctions 543 481 + j * sizeof(DWORD), 544 &funcaddr, sizeof(funcaddr), &tmp);545 546 ret = (intptr_t)base + funcaddr;482 &funcaddr, sizeof(funcaddr), &tmp); 483 484 ret = base + funcaddr; 547 485 goto _finished; 548 486 }
Note: See TracChangeset
for help on using the changeset viewer.
