Reverse engineering: a first look
Approaching reverse engineering as a web and JVM developer – what Ghidra and IDA are for, what a decompiler gives you over a disassembler, and why decompiled output makes you confront what your source compiles down to.
This entry was reading rather than building, and it sits entirely outside the apprenticeship: reverse engineering – how the field is approached, and a first pass at getting familiar with its two flagship tools, Ghidra and IDA.
It’s worth stating where I started from, because it explains what I got out of it. By trade I’m a web and JVM developer, which means my working life is spent behind two thick layers of insulation from the machine. TypeScript goes through a bundler and then an engine’s JIT. Java and Kotlin compile to bytecode that a JVM interprets, profiles and compiles on the fly. I couldn’t tell you what any of that finally emits as machine code, and I’ve never had a reason to care. Reverse engineering starts from exactly the place I’ve spent a career avoiding: a program in its final form, no source available, and a question.
The two tools
Ghidra is a software reverse engineering framework created and maintained by the NSA’s Research Directorate. It was an internal tool for their own analysts – comments in the source suggest parts of it date back to 1999 – until the binaries were released at the RSA Conference in March 2019, with the source following on GitHub a month later under the Apache License 2.0. It’s written in Java, which gave me the odd pleasure of meeting a Java application from the wrong side of the abstraction: installing it means installing a JDK first. The capability list is disassembly, decompilation, graphing and scripting; it supports a wide variety of instruction sets and executable formats, and it runs interactively or in automated modes, scriptable in Java or Python.
IDA, from Hex-Rays, is the proprietary incumbent that Ghidra gets measured against. Its licensing is tiered. IDA Free costs nothing and is non-commercial only: x86 and x86-64, disassembler plus a cloud-based decompiler. IDA Home is also non-commercial, adding other processor families and the development kits. IDA Pro is the commercial tier, with more than 60 processor disassemblers, decompilers chosen per plan, and remote debugging. The shape of it for a beginner: both routes are free to start on, and the money buys breadth – more architectures, local decompilation, commercial use – rather than a different activity.
What a decompiler gives you
A disassembler translates machine code back into assembly. A decompiler goes a step further and reconstructs something high-level from it, and both tools do both. For someone at my level the decompiler is the entire point of entry: I don’t read assembly, and pseudocode in roughly C’s shape is the only view of a binary I can reason about unaided.
The part that took me a while to internalise is what that output is. It’s a reconstruction, not a recovery, and the difference is the whole story.
The misconception I started with: I assumed a decompiler’s job was to get the original source back. It can’t. Compilation is lossy. Names, types and comments are gone the moment the source is compiled, and optimisation rewrites the control flow besides. What a decompiler produces is code with equivalent behaviour, not the author’s code. Ghidra’s defaults make this concrete: a function with no surviving symbol is labelled FUN_ followed by its address, and an unidentified type gets a name based purely on its size.
That lossiness is why the throwaway line in my log turned out to be the real substance: reading decompiled output forces you to think about what your source actually compiles down to. I’d have claimed I understood compilation – I write Kotlin, I know roughly what bytecode looks like, I know the JIT exists – but that knowledge has never been load-bearing. It changes nothing about how I work day to day. Reading a decompiled function, where every helpful name is gone and all that’s left is structure, made the distance between what I write and what runs the subject of the exercise rather than the backdrop.
A week of reading makes me familiar with the vocabulary, not competent. The stated next step was to stop reading and actually drive the tools. I’ve since done that; it went slower than I expected, and that week has its own writeup.