- Timestamp:
- Sep 20, 2010, 3:16:36 AM (10 years ago)
- Location:
- zzuf/trunk
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
zzuf/trunk/src/libzzuf/sys.c
r4645 r4648 39 39 40 40 /* TODO: get rid of this later */ 41 HINSTANCE ( __stdcall*LoadLibraryA_orig)(LPCSTR);42 HINSTANCE __stdcallLoadLibraryA_new(LPCSTR path)41 HINSTANCE (WINAPI *LoadLibraryA_orig)(LPCSTR); 42 HINSTANCE WINAPI LoadLibraryA_new(LPCSTR path) 43 43 { 44 44 void *ret; -
zzuf/trunk/src/myfork.c
r4645 r4648 74 74 #if defined HAVE_WINDOWS_H 75 75 static void rep32(uint8_t *buf, void *addr); 76 static int dll_inject( void*, void *, char const *);76 static int dll_inject(PROCESS_INFORMATION *, void *, char const *); 77 77 static intptr_t get_base_address(DWORD); 78 static intptr_t get_entry_point_offset(char const *); 78 static intptr_t get_entry_point(char const *name, DWORD pid); 79 static intptr_t get_proc_address(void *, DWORD, char const *); 79 80 #endif 80 81 … … 261 262 memset(&sinfo, 0, sizeof(sinfo)); 262 263 sinfo.cb = sizeof(sinfo); 264 #if 0 263 265 DuplicateHandle(pid, (HANDLE)_get_osfhandle(pipes[0][1]), pid, 264 266 /* FIXME */ &sinfo.hStdInput, 0, TRUE, DUPLICATE_SAME_ACCESS); … … 268 270 &sinfo.hStdOutput, 0, TRUE, DUPLICATE_SAME_ACCESS); 269 271 sinfo.dwFlags = STARTF_USESTDHANDLES; 272 #endif 270 273 ret = CreateProcess(NULL, child->newargv[0], NULL, NULL, FALSE, 271 274 CREATE_SUSPENDED, NULL, NULL, &sinfo, &pinfo); … … 280 283 281 284 /* Insert the replacement code */ 282 ret = dll_inject( pinfo.hProcess, epaddr, SONAME);285 ret = dll_inject(&pinfo, epaddr, SONAME); 283 286 if(ret < 0) 284 287 { … … 294 297 } 295 298 299 Sleep(5000); 296 300 return (long int)pinfo.hProcess; 297 301 #endif … … 309 313 } 310 314 311 static int dll_inject(void *process, void *epaddr, char const *lib) 315 static int dll_inject(PROCESS_INFORMATION *pinfo, 316 void *epaddr, char const *lib) 312 317 { 313 318 static uint8_t const loader[] = … … 335 340 "\xff\xe0"; /* jmp %eax */ 336 341 342 static uint8_t const waiter[] = 343 "\xeb\xfe"; /* jmp <current> */ 344 337 345 static uint8_t const jumper[] = 338 346 /* Jump to the injected loader */ 339 347 "\xb8____" /* mov eax, <loader_address> */ 340 348 "\xff\xe0"; /* jmp eax */ 349 350 void *process = pinfo->hProcess; 351 void *thread = pinfo->hThread; 352 DWORD pid = pinfo->dwProcessId; 341 353 342 354 /* code: … … 347 359 uint8_t code[1024]; 348 360 349 void *kernel32;350 361 uint8_t *loaderaddr; 351 size_t liblen, loaderlen, jumperlen;362 size_t liblen, loaderlen, waiterlen, jumperlen; 352 363 DWORD tmp; 353 364 354 365 liblen = strlen(lib) + 1; 355 366 loaderlen = sizeof(loader) - 1; 367 waiterlen = sizeof(waiter) - 1; 356 368 jumperlen = sizeof(jumper) - 1; 357 369 if (loaderlen + jumperlen + liblen > 1024) … … 390 402 return -1; 391 403 392 /* XXX: at this point, the StarCraft 2 hack replaces the entry point 393 * contents with a jump to self, then waits until the program counter 394 * actually reaches the entry point. Not sure whether it is needed. */ 395 396 /* FIXME: the GetProcAddress calls assume the library was loaded at 397 * the same address in the child process. This is wrong since Vista 398 * and its address space randomisation. The StarCraft 2 hack remotely 399 * parses the target process's module list in order to find the 400 * kernel32.dll address. Have a look at _RemoteGetProcAddress(). */ 401 kernel32 = LoadLibrary("kernel32.dll"); 402 if(!kernel32) 403 return -1; 404 404 /* Replace the entry point code with a short jump to self, then resume 405 * the thread. This is necessary for CreateToolhelp32Snapshot() to 406 * work. */ 407 WriteProcessMemory(process, epaddr, waiter, waiterlen, &tmp); 408 if(tmp != waiterlen) 409 return -1; 410 FlushInstructionCache(process, epaddr, waiterlen); 411 ResumeThread(thread); 412 413 /* Wait until the entry point is reached */ 414 for (tmp = 0; tmp < 100; tmp++) 415 { 416 CONTEXT ctx; 417 ctx.ContextFlags = CONTEXT_FULL; 418 GetThreadContext(thread, &ctx); 419 if ((uintptr_t)ctx.Eip == (uintptr_t)epaddr) 420 break; 421 Sleep(10); 422 } 423 SuspendThread(thread); 424 if (tmp == 100) 425 return -1; 426 427 /* Remotely parse the target process's module list to get the addresses 428 * of the functions we need. This can only be done because we advanced 429 * the target's execution to the entry point. */ 405 430 rep32(code, loaderaddr + loaderlen + jumperlen); 406 rep32(code, GetProcAddress(kernel32, "LoadLibraryA"));431 rep32(code, (uintptr_t)get_proc_address(process, pid, "LoadLibraryA")); 407 432 rep32(code, (void *)(uintptr_t)jumperlen); 408 433 rep32(code, loaderaddr + loaderlen); 409 434 rep32(code, epaddr); 410 rep32(code, GetProcAddress(kernel32, "GetCurrentProcess"));411 rep32(code, GetProcAddress(kernel32, "WriteProcessMemory"));435 rep32(code, (uintptr_t)get_proc_address(process, pid, "GetCurrentProcess")); 436 rep32(code, (uintptr_t)get_proc_address(process, pid, "WriteProcessMemory")); 412 437 rep32(code, epaddr); 413 FreeLibrary(kernel32);414 438 415 439 /* Write our shellcodes into the target process */ … … 418 442 if(tmp != jumperlen) 419 443 return -1; 444 FlushInstructionCache(process, epaddr, waiterlen); 420 445 421 446 WriteProcessMemory(process, loaderaddr, code, … … 469 494 * Vista's address space randomisation. */ 470 495 if (!ret) 471 ret = (intptr_t)nt->OptionalHeader. BaseOfCode;496 ret = (intptr_t)nt->OptionalHeader.ImageBase; 472 497 473 498 ret += (intptr_t)nt->OptionalHeader.AddressOfEntryPoint; … … 481 506 } 482 507 483 /* Find the process's base address once it is loaded in memory (the header 484 * information is unreliable because of Vista's ASLR). */ 485 static intptr_t get_base_address(DWORD pid) 486 { 508 /* FIXME: this could probably be merged with get_entry_point */ 509 static intptr_t get_proc_address(void *process, DWORD pid, const char *func) 510 { 511 char buf[1024]; 512 size_t buflen = strlen(func) + 1; 513 487 514 MODULEENTRY32 entry; 488 515 intptr_t ret = 0; 516 DWORD tmp; 489 517 void *list; 490 int k;518 int i, k; 491 519 492 520 list = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, pid); … … 494 522 for(k = Module32First(list, &entry); k; k = Module32Next(list, &entry)) 495 523 { 524 IMAGE_DOS_HEADER dos; 525 IMAGE_NT_HEADERS nt; 526 IMAGE_EXPORT_DIRECTORY expdir; 527 528 uint32_t exportaddr; 529 uint8_t const *base = entry.modBaseAddr; 530 531 if (strcmp("kernel32.dll", entry.szModule)) 532 continue; 533 534 ReadProcessMemory(process, base, &dos, sizeof(dos), &tmp); 535 ReadProcessMemory(process, base + dos.e_lfanew, &nt, sizeof(nt), &tmp); 536 537 exportaddr = nt.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress; 538 if (!exportaddr) 539 continue; 540 541 ReadProcessMemory(process, base + exportaddr, &expdir, sizeof(expdir), &tmp); 542 543 for (i = 0; i < (int)expdir.NumberOfNames; i++) 544 { 545 uint32_t nameaddr, funcaddr; 546 uint16_t j; 547 548 /* Look for our function name in the list of names */ 549 ReadProcessMemory(process, base + expdir.AddressOfNames 550 + i * sizeof(DWORD), 551 &nameaddr, sizeof(nameaddr), &tmp); 552 ReadProcessMemory(process, base + nameaddr, buf, buflen, &tmp); 553 554 if (strcmp(buf, func)) 555 continue; 556 557 /* If we found a function with this name, return its address */ 558 ReadProcessMemory(process, base + expdir.AddressOfNameOrdinals 559 + i * sizeof(WORD), 560 &j, sizeof(j), &tmp); 561 ReadProcessMemory(process, base + expdir.AddressOfFunctions 562 + j * sizeof(DWORD), 563 &funcaddr, sizeof(funcaddr), &tmp); 564 565 ret = (intptr_t)base + funcaddr; 566 goto _finished; 567 } 568 } 569 570 _finished: 571 CloseHandle(list); 572 return ret; 573 } 574 575 /* Find the process's base address once it is loaded in memory (the header 576 * information is unreliable because of Vista's ASLR). 577 * FIXME: this does not work properly because CreateToolhelp32Snapshot() 578 * requires a certain level of initialisation. */ 579 static intptr_t get_base_address(DWORD pid) 580 { 581 MODULEENTRY32 entry; 582 intptr_t ret = 0; 583 584 void *list; 585 int k; 586 587 list = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, pid); 588 entry.dwSize = sizeof(entry); 589 for(k = Module32First(list, &entry); k; k = Module32Next(list, &entry)) 590 { 496 591 /* FIXME: how do we select the correct module? */ 497 592 ret = (intptr_t)entry.modBaseAddr; -
zzuf/trunk/test/zznop.c
r4253 r4648 26 26 27 27 fprintf(stderr, "About to call LoadLibraryA()\n"); 28 //LoadLibraryA("whatever");28 LoadLibraryA("whatever"); 29 29 fprintf(stderr, "Finished calling LoadLibraryA()\n"); 30 30
Note: See TracChangeset
for help on using the changeset viewer.