| 415 | return dll_base |
| 416 | |
| 417 | def call_dll_entrypoint(self, dll: pefile.PE, dll_base: int, dll_len: int, dll_name: str): |
| 418 | entry_address = dll.OPTIONAL_HEADER.AddressOfEntryPoint |
| 419 | |
| 420 | if dll.get_section_by_rva(entry_address) is None: |
| 421 | return |
| 422 | |
| 423 | if dll_name in ('kernelbase.dll', 'kernel32.dll'): |
| 424 | self.ql.log.debug(f'Ignoring {dll_name} entry point') |
| 425 | return |
| 426 | |
| 427 | # DllMain functions often call many APIs that may crash the program if they |
| 428 | # are not implemented correctly (if at all). here we blacklist the problematic |
| 429 | # DLLs whose DllMain functions are known to be crashing. |
| 430 | # |
| 431 | # the blacklist may be revisited from time to time to see if any of the file |
| 432 | # can be safely unlisted. |
| 433 | blacklist = { |
| 434 | 32 : ('gdi32.dll','user32.dll',), |
| 435 | 64 : ('gdi32.dll','user32.dll',) |
| 436 | }[self.ql.arch.bits] |
| 437 | |
| 438 | if dll_name in blacklist: |
| 439 | self.ql.log.debug(f'Ignoring {dll_name} entry point (blacklisted)') |
| 440 | return |
| 441 | |
| 442 | entry_point = dll_base + entry_address |
| 443 | exit_point = dll_base + dll_len - 16 |
| 444 | |
| 445 | args = ( |
| 446 | (HINSTANCE, dll_base), # hinstDLL = base address of DLL |
| 447 | (DWORD, 1), # fdwReason = DLL_PROCESS_ATTACH |
| 448 | (LPVOID, 0) # lpReserved = 0 |
| 449 | ) |
| 450 | |
| 451 | self.ql.log.info(f'Calling {dll_name} DllMain at {entry_point:#x}') |
| 452 | |
| 453 | regs_state = self.ql.arch.regs.save() |
| 454 | |
| 455 | fcall = self.ql.os.fcall_select(CDECL) |
| 456 | fcall.call_native(entry_point, args, exit_point) |
| 457 | |
| 458 | # Execute the call to the entry point |
| 459 | try: |
| 460 | self.ql.emu_start(entry_point, exit_point) |
| 461 | except UcError: |
| 462 | self.ql.log.error(f'Error encountered while running {dll_name} DllMain, bailing') |
| 463 | |
| 464 | self.ql.arch.regs.restore(regs_state) |
| 465 | else: |
| 466 | fcall.cc.unwind(len(args)) |
| 467 | |
| 468 | self.ql.log.info(f'Returned from {dll_name} DllMain') |
| 469 | |
| 470 | def set_cmdline(self, name: bytes, address: int, memory: bytearray): |
| 471 | cmdln = { |