skip to content
HexPharoah Hexpharoah
Table of Contents

How I Analyze Decompiled Code

When I started reversing binaries, I tried reading raw assembly for everything. That got old fast. Decompilers changed the game for me - they turn machine code into something closer to C, and suddenly a 200-line function becomes 20 lines of readable pseudocode.

I have spent time with all three major tools: IDA Pro, Ghidra, and Binary Ninja. Here is how I use each one and what I have learned.


Why I Rely on Decompiled Output

Reading assembly is important, but for understanding program logic quickly, I always start with the decompiler view. It helps me:

  • Spot control flow (loops, conditions) without mentally tracing jumps
  • Recognize API calls and their arguments immediately
  • Find vulnerabilities like buffer overflows or format strings
  • Map out data structures from how memory gets accessed

The trick I learned early: decompiled output is never perfect. Compilers optimize things in ways decompilers cannot fully reverse. I always cross-check suspicious output against the actual disassembly.


My Experience with IDA Pro

IDA was the first serious tool I used. The Hex-Rays decompiler produces the cleanest output I have seen.

What I Like

  • Type propagation is excellent - set one struct and it cascades everywhere
  • FLIRT signatures identify library functions automatically, saves me hours
  • Cross-references (pressing X) let me trace any value through the entire binary
  • The plugin ecosystem is massive

My Workflow

1. Load binary, wait for auto-analysis to finish
2. Start from strings or imports to find interesting functions
3. Press F5 to decompile
4. Immediately rename variables - v4 means nothing, recv_buf tells me everything
5. Set struct types on pointer arguments
6. Use xrefs to follow data flow upstream and downstream

Things That Tripped Me Up

IDA sometimes shows _DWORD * casts everywhere when it cannot determine the actual type. I learned that manually defining structs early cleans up the entire decompilation. Also, IDA occasionally misidentifies function boundaries in heavily obfuscated code - I have to fix those manually with Edit > Functions.


My Experience with Ghidra

I moved to Ghidra when I wanted a free alternative I could use anywhere. Honestly, it surprised me how good it is.

What I Like

  • Completely free - I can install it on any machine without license headaches
  • The side-by-side decompiler + listing view is great for cross-checking
  • Scripting in Python through the Ghidra API saved me on repetitive tasks
  • Collaborative reversing with Ghidra Server when working with my team

My Workflow

1. Create project, import binary
2. Run all analyzers (I check everything)
3. Start from Symbol Tree or string search
4. Read decompiler output on the right panel
5. Right-click to retype variables and fix function signatures

Ghidra’s Quirks

Ghidra names things like local_28, param_1. The naming follows stack offsets:

void vulnerable_function(char *param_1) {
char local_28[32];
strcpy(local_28, param_1); // I spotted this overflow immediately
return;
}

Where Ghidra struggles for me:

  • Switch statements sometimes show as computed jumps - I have to manually create the switch table
  • C++ virtual calls get flattened into pointer math that looks confusing
  • Optimized loops can look weird until I annotate the types

My Experience with Binary Ninja

I picked up Binary Ninja for quick triage work. It sits between IDA and Ghidra in terms of features and price.

What I Like

  • The tiered IL system (LLIL, MLIL, HLIL) gives me different views of the same function
  • HLIL for understanding logic, MLIL when I need to track data flow precisely
  • The Python API is clean and fast - I wrote several automation scripts with it
  • Analysis is fast, great for triaging multiple samples quickly

The IL Levels

This is what sets Binary Ninja apart for me:

Disassembly -> Lifted IL -> Low Level IL -> Medium Level IL -> High Level IL

When HLIL looks wrong, I drop down to MLIL to see what is actually happening. This saved me multiple times when dealing with optimized code.


Comparing Their Output

I loaded the same vulnerable function in all three to see how they present it. The original source (which I figured out after analysis):

int check_password(char *input) {
char buffer[16];
strcpy(buffer, input);
if (strcmp(buffer, "s3cr3t") == 0)
return 1;
return 0;
}

IDA Gave Me

int __cdecl check_password(const char *a1) {
char v2[16];
strcpy(v2, a1);
return strcmp(v2, "s3cr3t") == 0;
}

Clean. Spotted the strcpy overflow instantly.

Ghidra Gave Me

undefined4 check_password(char *param_1) {
char local_18[16];
strcpy(local_18, param_1);
int iVar1 = strcmp(local_18, "s3cr3t");
if (iVar1 == 0) {
return 1;
}
return 0;
}

More verbose but equally clear. The undefined4 return type needed manual fixing.

Binary Ninja Gave Me

int32_t check_password(char* arg1) {
char buf[16];
strcpy(&buf, arg1);
if (strcmp(&buf, "s3cr3t") == 0)
return 1;
return 0;
}

All three showed me the vulnerability. The differences are mostly cosmetic.


Lessons I Learned

  1. Rename everything immediately - Future me always thanks present me for this
  2. Define structs early - One struct definition cleans up dozens of functions
  3. Start from strings - Error messages, URLs, hardcoded keys lead to the important code
  4. Check disassembly when pseudocode looks off - The decompiler lies sometimes
  5. Use multiple tools on hard targets - When I am stuck in IDA, Ghidra sometimes shows it differently and I get unstuck
  6. Script repetitive work - All three have Python APIs, and I use them constantly

Which Tool I Pick

SituationMy Choice
CTF challenge, quick analysisGhidra
Deep malware investigationIDA Pro
Triage multiple samples fastBinary Ninja
Team collaborationGhidra Server
Scripting heavy automationBinary Ninja
Budget is zeroGhidra

At the end of the day, the tool matters less than the skill. I got comfortable with one first (Ghidra), then expanded. The ability to read decompiled output, spot what is wrong, and annotate it properly - that transfers across all tools.


Until Next -- Tata Bye Bye!!
jaswanth

Related Posts