@@ -455,8 +455,34 @@ def _setup_memory(self):
455455
456456 def _setup_pebteb (self , thread ):
457457 self .teb = thread .Teb & 0xFFFFFFFFFFFFF000
458- self .wow64 = self .modules ["ntdll.dll" ].find_export ("Wow64Transition" ) is not None
459458
459+ # Handle WoW64 support
460+ def patch_wow64 (patch_addr ):
461+ # See: https://opcode0x90.wordpress.com/2007/05/18/kifastsystemcall-hook/
462+ # mov edx, esp; sysenter; ret
463+ KiFastSystemCall = b"\x8B \xD4 \x0F \x34 \x90 \x90 \xC3 "
464+ self .write (patch_addr , KiFastSystemCall )
465+ self .wow64 = True
466+
467+ ntdll = self .modules ["ntdll.dll" ]
468+ Wow64Transition = ntdll .find_export ("Wow64Transition" )
469+ ZwWow64ReadVirtualMemory64 = ntdll .find_export ("ZwWow64ReadVirtualMemory64" )
470+ if Wow64Transition :
471+ # This exists from Windows 10 1607 (Build: 14393)
472+ patch_addr = self .read_ptr (Wow64Transition .address )
473+ self .info (f"Patching Wow64Transition: [{ hex (Wow64Transition .address )} ] -> { hex (patch_addr )} " )
474+ patch_wow64 (patch_addr )
475+ elif ZwWow64ReadVirtualMemory64 :
476+ # This function exists since Windows XP
477+ # TODO: Implement by finding EA ???????? 3300 in wow64cpu.dll instead
478+ # Reference: https://github.com/x64dbg/ScyllaHide/blob/a727ac39/InjectorCLI/RemoteHook.cpp#L354-L434
479+ patch_addr = self .read_ptr (self .teb + 0xC0 )
480+ self .error (f"Unsupported WoW64 OS version detected, trampoline: { hex (patch_addr )} " )
481+ patch_wow64 (patch_addr )
482+ else :
483+ self .wow64 = False
484+
485+ # Get thread information
460486 for i in range (0 , len (self ._minidump .threads .threads )):
461487 thread = self ._minidump .threads .threads [i ]
462488 teb = thread .Teb & 0xFFFFFFFFFFFFF000
@@ -800,21 +826,13 @@ def _setup_modules(self):
800826 def _setup_syscalls (self ):
801827 # Load the ntdll module from memory
802828 ntdll = self .modules ["ntdll.dll" ]
829+ self .KiUserExceptionDispatcher = ntdll .find_export ("KiUserExceptionDispatcher" ).address
830+ self .LdrLoadDll = ntdll .find_export ("LdrLoadDll" ).address
831+
803832 nt_syscalls = []
804833 for export in ntdll .exports :
805834 if export .name and export .name .startswith ("Zw" ):
806835 nt_syscalls .append ((export .address , export .name ))
807- elif export .name == "Wow64Transition" :
808- patch_addr = self .read_ptr (export .address )
809- self .info (f"Patching Wow64Transition: { hex (export .address )} -> { hex (patch_addr )} " )
810- # See: https://opcode0x90.wordpress.com/2007/05/18/kifastsystemcall-hook/
811- # mov edx, esp; sysenter; ret
812- KiFastSystemCall = b"\x8B \xD4 \x0F \x34 \x90 \x90 \xC3 "
813- self .write (patch_addr , KiFastSystemCall )
814- elif export .name == "KiUserExceptionDispatcher" :
815- self .KiUserExceptionDispatcher = export .address
816- elif export .name == "LdrLoadDll" :
817- self .LdrLoadDll = export .address
818836
819837 def add_syscalls (syscalls , table ):
820838 # The index when sorting by RVA is the syscall index
@@ -1493,6 +1511,8 @@ def _arg_type_string(arg):
14931511 return type (arg ).__name__
14941512
14951513def _hook_interrupt (uc : Uc , number , dp : Dumpulator ):
1514+ if dp .trace :
1515+ dp .trace .flush ()
14961516 try :
14971517 # Extract exception information
14981518 exception = UnicornExceptionInfo ()
@@ -1643,6 +1663,8 @@ def _emulate_unsupported_instruction(dp: Dumpulator, instr: CsInsn):
16431663
16441664def _hook_invalid (uc : Uc , dp : Dumpulator ):
16451665 address = dp .regs .cip
1666+ if dp .trace :
1667+ dp .trace .flush ()
16461668 # HACK: unicorn cannot gracefully exit in all contexts
16471669 if dp .kill_me :
16481670 dp .error (f"terminating emulation..." )
0 commit comments