mirror of
https://github.com/NaC-L/Mergen.git
synced 2026-06-11 09:44:31 +00:00
Adds scripts/dev/trace_external_calls.py: loads a PE into Unicorn, patches every IAT slot with a unique unmapped-address sentinel, then emulates from the chosen entry. When any call/jmp/ret resolves its target to a sentinel, logs the call-site address, the mnemonic, and the addressing form. One-shot diagnostic for answering 'what x86 instruction issues this external call at runtime.' Using it on example2-virt.bin shows the Themida transform precisely: - guest imports (GetStdHandle etc) remain in the IAT - every guest call site is rewritten from 'call [rip+IAT]' to a VM-staged 'push target; ret' where target was loaded from the IAT upstream - for example2, the first external call happens at VA 0x14017fa77 via 'ret 0', popping the GetStdHandle IAT value off the stack - Themida strips its own SDK markers (VirtualizerSDK64.dll#103/#503) from the IAT; our ignore_imports filter already accounts for this The lifter's current recognition handles direct call-through-IAT and register-indirect IAT calls (the non-virt binary resolves 5 imports cleanly). It does not recognize the ret-pops-IAT-loaded- pointer pattern, which is why the virt lift surfaces zero imports. Also annotates themida_samples.json with these properties inline so the transform semantics live next to the test that exercises them.
32 lines
1.2 KiB
JSON
32 lines
1.2 KiB
JSON
{
|
|
"_comment": [
|
|
"Themida preserves the guest binary's own imports (Win32 APIs) in the IAT,",
|
|
"but rewrites each call site from `call [rip+IAT]` to a VM-staged",
|
|
"`push target; ret` where `target` was loaded from the IAT by an upstream",
|
|
"VM handler. The lifter currently does not recognize this transfer pattern",
|
|
"as an import call, so the guest's externals do not surface in the IR.",
|
|
"See scripts/dev/trace_external_calls.py for a Unicorn-based tracer that",
|
|
"shows the real call mechanism at runtime.",
|
|
"",
|
|
"Themida strips its own SDK markers (VirtualizerSDK64.dll#103/#503,",
|
|
"VirtualizerStart/End) from the protected binary's IAT, so those",
|
|
"appear in the non-virt reference but not in the virt binary. The",
|
|
"ignore_imports pattern filters them out before update / compare."
|
|
],
|
|
"samples": [
|
|
{
|
|
"name": "example2",
|
|
"reference_binary": "../testthemida/example2.bin",
|
|
"virt_binary": "../testthemida/example2-virt.bin",
|
|
"entry": "0x140001000",
|
|
"ignore_imports": ["^VirtualizerSDK64\\.dll#"],
|
|
"required_imports": [
|
|
"CharUpperA",
|
|
"GetStdHandle",
|
|
"ReadConsoleA",
|
|
"WriteConsoleA"
|
|
]
|
|
}
|
|
]
|
|
}
|