Skip to content

Commit cfd166a

Browse files
authored
Merge pull request #68 from mrexodia/old-wow64
Support WOW64 for older Windows builds
2 parents 99fe0bb + 6cf51ec commit cfd166a

File tree

2 files changed

+38
-13
lines changed

2 files changed

+38
-13
lines changed

.gitignore

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
build/
22
dist/
33
*.egg-info/
4-
venv/
4+
venv*/
55
.idea/
66
__pycache__/
77
*.pyc
@@ -10,3 +10,6 @@ __pycache__/
1010
/tests/*.trace64
1111
/tests/*.txt
1212
/tests/*.dmp
13+
.DS_Store
14+
.vscode/
15+
*.austin

src/dumpulator/dumpulator.py

Lines changed: 34 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -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

14951513
def _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

16441664
def _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

Comments
 (0)