forked from
lass.pds.lassul.us/superconfig
This repository has no description
6.6 kB
name: reverse-engineering description: Reverse engineer and debug binaries using Ghidra (static analysis, decompilation) and GDB (live debugging of running processes). Use when the user wants to analyze binaries, decompile functions, debug running processes, set breakpoints, or inspect memory.#
Reverse Engineering & Debugging Skill#
Use Ghidra for static analysis/decompilation and GDB for live debugging of running processes.
All commands use nix shell to get the tools without installing them globally.
Ghidra Headless Analysis#
Use ghidra-analyzeHeadless for static analysis without the GUI.
Import and analyze a binary#
nix shell nixpkgs#ghidra -c ghidra-analyzeHeadless /tmp/ghidra_projects MyProject \
-import /path/to/binary -overwrite
# With specific processor (e.g., ARM, MIPS)
nix shell nixpkgs#ghidra -c ghidra-analyzeHeadless /tmp/ghidra_projects MyProject \
-import /path/to/binary -processor x86:LE:64:default -overwrite
Run analysis scripts#
Ghidra ships with many built-in scripts. Use -postScript to run them after analysis.
# Decompile all functions
nix shell nixpkgs#ghidra -c ghidra-analyzeHeadless /tmp/ghidra_projects MyProject \
-process binary_name -postScript DecompileAllFunctions.java \
-noanalysis -readOnly -scriptlog /dev/stdout 2>/dev/null
# List all functions
nix shell nixpkgs#ghidra -c ghidra-analyzeHeadless /tmp/ghidra_projects MyProject \
-process binary_name -postScript ListFunctions.java \
-noanalysis -readOnly -scriptlog /dev/stdout 2>/dev/null
Custom Ghidra scripts (Java)#
Write a custom script to extract specific information. Save as .java and pass with -postScript:
// SaveTo: /tmp/ghidra_scripts/DecompileFunction.java
import ghidra.app.script.GhidraScript;
import ghidra.app.decompiler.*;
import ghidra.program.model.listing.*;
public class DecompileFunction extends GhidraScript {
@Override
public void run() throws Exception {
String targetName = getScriptArgs()[0];
DecompInterface decomp = new DecompInterface();
decomp.openProgram(currentProgram);
FunctionManager fm = currentProgram.getFunctionManager();
for (Function f : fm.getFunctions(true)) {
if (f.getName().contains(targetName)) {
DecompileResults res = decomp.decompileFunction(f, 30, monitor);
if (res.decompileCompleted()) {
println("=== " + f.getName() + " at " + f.getEntryPoint() + " ===");
println(res.getDecompiledFunction().getC());
}
}
}
decomp.dispose();
}
}
nix shell nixpkgs#ghidra -c ghidra-analyzeHeadless /tmp/ghidra_projects MyProject \
-process binary_name \
-postScript /tmp/ghidra_scripts/DecompileFunction.java "main" \
-scriptPath /tmp/ghidra_scripts -noanalysis -readOnly \
-scriptlog /dev/stdout 2>/dev/null
Workflow: Analyze an unknown binary#
- Import:
nix shell nixpkgs#ghidra -c ghidra-analyzeHeadless /tmp/ghidra_projects Proj -import /path/to/binary -overwrite - List functions to find interesting targets
- Decompile specific functions of interest
- Look for strings, cross-references, and data structures
GDB Live Debugging#
Use GDB to attach to running processes, set breakpoints, and inspect state.
Attach to a running process#
# By PID
sudo nix shell nixpkgs#gdb -c gdb -batch -p <PID> -ex "bt"
# By name (find PID first)
nix shell nixpkgs#gdb -c gdb -batch -p $(pidof process_name) -ex "bt"
Non-interactive GDB commands#
Use -batch and -ex for scripted debugging:
# Get backtrace of a running process
sudo nix shell nixpkgs#gdb -c gdb -batch -p <PID> -ex "thread apply all bt"
# Print a variable
sudo nix shell nixpkgs#gdb -c gdb -batch -p <PID> -ex "print some_global_var"
# Dump memory region
sudo nix shell nixpkgs#gdb -c gdb -batch -p <PID> -ex "x/100x 0x7fff12345678"
# List all threads
sudo nix shell nixpkgs#gdb -c gdb -batch -p <PID> -ex "info threads"
# Show loaded shared libraries
sudo nix shell nixpkgs#gdb -c gdb -batch -p <PID> -ex "info sharedlibrary"
# Get register state
sudo nix shell nixpkgs#gdb -c gdb -batch -p <PID> -ex "info registers"
# Set breakpoint and continue until hit
sudo nix shell nixpkgs#gdb -c gdb -batch -p <PID> \
-ex "break function_name" \
-ex "continue" \
-ex "bt" \
-ex "info locals"
# Multiple commands
sudo nix shell nixpkgs#gdb -c gdb -batch -p <PID> \
-ex "info threads" \
-ex "thread apply all bt" \
-ex "info registers"
GDB with binary (not attached)#
# Run with arguments
nix shell nixpkgs#gdb -c gdb -batch -ex "run" -ex "bt" --args ./binary arg1 arg2
# Run until crash, get backtrace
nix shell nixpkgs#gdb -c gdb -batch -ex "run" -ex "bt full" -ex "info registers" --args ./binary
# Set breakpoint before running
nix shell nixpkgs#gdb -c gdb -batch \
-ex "break main" \
-ex "run" \
-ex "step 10" \
-ex "info locals" \
-ex "bt" \
--args ./binary
GDB Python scripting#
For complex analysis, use GDB's Python API:
sudo nix shell nixpkgs#gdb -c gdb -batch -p <PID> -ex "python
import gdb
for thread in gdb.inferiors()[0].threads():
thread.switch()
frame = gdb.newest_frame()
print(f'Thread {thread.num}: {frame.name()} at {frame.pc():#x}')
"
Workflow: Debug a running process#
- Find the process:
ps aux | grep process_nameorpidof process_name - Get overview:
sudo nix shell nixpkgs#gdb -c gdb -batch -p <PID> -ex "info threads" -ex "thread apply all bt" - Check specific state: inspect variables, registers, memory
- Set breakpoints if needed for dynamic analysis
- Combine with Ghidra: decompile the binary to understand what functions do, then use GDB to observe runtime behavior
Combining Ghidra + GDB#
- Find the binary path:
readlink -f /proc/<PID>/exe - Import into Ghidra for static analysis: understand the code structure
- Use GDB to observe runtime behavior: set breakpoints at interesting functions found in Ghidra
- Cross-reference: Ghidra gives you function names and decompiled code, GDB shows you actual runtime values
Tips#
- Ghidra headless output goes to scriptlog; use
-scriptlog /dev/stdoutto capture it - Use
-noanalysis -readOnlywhen running scripts on already-analyzed projects - GDB
-batchmode is essential for non-interactive use — it runs commands and exits sudois typically needed for GDB to attach to processes you don't own- Check
/proc/sys/kernel/yama/ptrace_scopeif attach fails (set to 0 for debugging)