4 ms·
It has been 2-3 decades since I’ve worked on this, so this may be outdated advice. In fact, I just learned of Ghidra when I read the article. In general there
by aparsons 6y ago
It has been 2-3 decades since I’ve worked on this, so this may be outdated advice. In fact, I just learned of Ghidra when I read the article.
In general there are three cases:
- Developer forgot to strip/obfuscate symbols, in which case you’re golden
- Symbol you seek is in a shared library: patch the DLL. Often what we did was do investigations in a VM, where the n most common shared library calls were patched to send stack and symbol data to a local DB. Very similar play to RR, but only in the patched code.
- If the (missing) symbol you seek is pre linked (static), things get interesting. We built a pattern matcher that was incredible. Idea is, if you have the disassembly and a loop, like:
int fun(char* str) { call processChar on each uppercase character }
It pattern matched a name like rax_foreach_iflte_cx_call_obfuscatedSymbolForProcessChar
90+% of code either:
- enters the same dynamic library trampoline
- displays very very common programming patterns.
From what I know, we never released this outside early MS DN members because the 10% is often very useful code and developer tools weren’t given away for free yet.
But once the DLL is patched, you propagate names up graph. Any remaining symbols were hand annotated (and we run the propagator again).
Brian Parks went on to extend this system to work with C++ templates. C++ mangling is very predictable, so his program could scavenge for symbols (obfuscators only worked on the root symbol name) and build out the class at compile time for us to reference.