Introduction

Static analysis is the art of understanding a program without running it. It’s the first step in any reverse engineering workflow and often reveals enough to understand what a binary does.

Essential Tools

Disassemblers

ToolPlatformNotes
GhidraCross-platformFree, decompiler included
IDA ProCross-platformIndustry standard, expensive
Binary NinjaCross-platformModern API, mid-range price
radare2Cross-platformCLI-based, scriptable

File Analysis

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
# Basic file identification
file target_binary

# Check security mitigations
checksec --file=target_binary

# List imported symbols
nm -D target_binary
objdump -T target_binary

# List strings
strings -n 8 target_binary | less

Reading Assembly

The key skill is reading disassembly output. Here’s a simple example:

1
2
3
; if (argc != 2) { usage(); return 1; }
cmp    dword [rbp-0x4], 0x2
jne    0x401150 <usage>

Common Patterns

  • Function prologue: push rbp; mov rbp, rsp — sets up stack frame
  • Conditional jumps: cmp + je/jne/jl/jg — if/else logic
  • Loops: backward jmp with a counter check
  • Syscalls: mov eax, <nr>; syscall — direct kernel calls

Practical Workflow

  1. Identify the binary type (ELF, PE, Mach-O)
  2. Check mitigations (NX, PIE, RELRO, canaries)
  3. Map the structure — find main(), key functions
  4. Trace data flow — follow inputs through the program
  5. Annotate — rename functions, add comments in your disassembler

Next Steps

In the next post, we’ll cover dynamic analysis — using debuggers and tracing tools to observe a binary at runtime.