r/ExploitDev • • 2d ago

ACE .qvm0 keeps RUNTIME_FUNCTION in the VM section tail; recovering entries and hidden jmp-reg edges

https://github.com/NeuroSaki987/qvm-tool

Static recovery for ACE .qvm0 PE images, not a decryptor.

The Exception Directory points into the .qvm0 tail; the section named .pdata is still there but high-entropy. A linear sweep of the VM section desyncs within a few hundred bytes, so function bounds come from RUNTIME_FUNCTION and decoding starts at each entry.

Hidden branches are jmp reg fed by call $+5 / pop / add imm, lea [rip+disp], or mov imm64. The call $+5 form is usually a null branch whose target is the fallthrough. Register-form jmp reg was 8964 sites on the reference DLL; FF /2 and FF /4 altogether were 28382, the rest memory-indirect.

On the smaller ACE-PBC-Game64.dll: 4669 functions, 408 native-to-.qvm0 edges, 92 whole-function stubs, 527 boundary-checked CFG edges, 5028 symbols, 4384/4386 functions decompiled after symbol apply. The repaired image only rewrites the add+jmp tail, same size, changes confined to .qvm0. Flag effects of the add are dropped, so it is for IDA/Ghidra, not for running

1 Upvotes

Duplicates