Navigating Disassembly & the Decompiler

25 minIn Progress

Navigating Disassembly & the Decompiler

The CodeBrowser: Your Analysis Workspace

The Ghidra CodeBrowser is where all reverse engineering happens. It presents multiple synchronized views of the binary, letting you examine the same code from different perspectives simultaneously. Understanding how to navigate these views efficiently is the difference between productive analysis and frustration.


The Listing View (Disassembly)

The Listing window occupies the center of the CodeBrowser and displays the raw disassembled instructions. This is the ground truth of what the binary does.

Anatomy of a Listing Line

Address    Bytes          Mnemonic   Operands           Comment
---------- -------------- ---------- ------------------ ------------------
004010a0   55             PUSH       EBP                ; save frame pointer
004010a1   8b ec          MOV        EBP,ESP            ; set up stack frame
004010a3   83 ec 20       SUB        ESP,0x20           ; allocate 32 bytes
004010a6   6a 00          PUSH       0x0                ; uType = MB_OK
004010a8   68 00 30 40 00 PUSH       0x403000           ; "Hello"
004010ad   e8 4e ff ff ff CALL       MessageBoxA
ColumnMeaning
AddressVirtual memory address of the instruction
BytesRaw machine-code opcodes (toggle with Edit > Tool Options > Listing Fields)
MnemonicThe instruction name (PUSH, MOV, CALL, SUB, etc.)
OperandsThe instruction's parameters -- registers, immediates, memory references
CommentAnalyst-added or auto-generated annotations

Reading x86 Instruction Format

x86 assembly uses the format: MNEMONIC DESTINATION, SOURCE

This means data flows right to left:

  • MOV EAX, 5 -- move the value 5 into EAX
  • ADD ECX, EAX -- add EAX to ECX, storing the result in ECX
  • CMP EAX, 0 -- compare EAX with 0 (sets processor flags)

Essential Instruction Categories

CategoryInstructionsWhat They Do
Data MovementMOV, LEA, PUSH, POP, XCHGMove data between registers, memory, and the stack
ArithmeticADD, SUB, MUL, DIV, INC, DECMathematical operations
LogicAND, OR, XOR, NOT, SHL, SHRBitwise operations (XOR reg, reg is a common zeroing idiom)
ComparisonCMP, TESTCompare values and set flags (do not store a result)
Control FlowJMP, Jcc, CALL, RETChange execution flow -- branches, function calls, returns
String/RepREP MOVSB, REP STOSBMemory copy/fill operations

Key Insight: XOR EAX, EAX does not mean "encrypt." It is the standard compiler idiom for setting a register to zero, equivalent to EAX = 0. You will see this pattern constantly.


The Decompiler View

The Decompile window (right side) reconstructs C-like pseudocode from the assembly. It is your primary tool for understanding what a function does at a high level.

Decompiler Output Naming Conventions

Name PatternMeaningWhat to Do
FUN_004010a0Auto-named function at address 0x004010a0Rename after you understand its purpose
DAT_00403000Auto-named global data at address 0x00403000Rename to describe the data (e.g., g_c2_url)
local_XXLocal variable (stack-allocated, offset XX from frame)Rename to describe usage
param_XFunction parameter (X = ordinal position)Rename to match API documentation
iVar1, uVar2Typed local variables (i = int, u = unsigned)Rename for clarity

Example: Before and After Annotation

Before:

void FUN_00401080(void) {
    undefined4 local_10c;
    undefined4 local_8;
    FUN_00401000(DAT_00403100, 0x50);
    local_10c = FUN_00401130(0, DAT_00403100, 0x1bb, 0, 0, 3, 0, 0);
    // ...
}

After analyst annotation:

void establish_c2_connection(void) {
    HINTERNET hConnect;
    HINTERNET hInternet;
    xor_decrypt(g_encrypted_c2_url, 0x50);
    hConnect = InternetConnectA(0, g_encrypted_c2_url, 443, 0, 0, INTERNET_SERVICE_HTTP, 0, 0);
    // ...
}

Decompiler Limitations

  • Auto-generated names are meaningless -- you must rename as you analyze
  • Type inference can be wrong -- an int might actually be a HANDLE or DWORD flag
  • Optimized code may decompile into confusing expressions
  • Obfuscated or anti-analysis code produces unreliable output
  • Struct access may appear as pointer arithmetic until you define the struct type

Synchronized Navigation

The Listing and Decompiler views are synchronized: clicking a line in one view highlights the corresponding code in the other. This dual-view approach is the core of effective Ghidra analysis.

The Recommended Workflow

  1. Start in the Decompiler -- read pseudocode to understand the high-level logic and control flow
  2. Switch to the Listing when something looks wrong, unclear, or when the decompiler oversimplifies
  3. Click a variable in the Decompiler to highlight all locations where it is used
  4. Click an address in the Listing to see the corresponding pseudocode line
  5. Double-click a CALL target to navigate into the called function

Navigation Keyboard Shortcuts

ActionShortcutDescription
Go to addressGJump to a specific memory address
Go backAlt+LeftReturn to previous location (like browser back)
Go forwardAlt+RightMove forward in navigation history
Search strings in memoryS then searchFind string patterns in the binary
Find referencesCtrl+Shift+FSearch for references to a value
Next functionCtrl+DownJump to the start of the next function
Previous functionCtrl+UpJump to the start of the previous function

Analyst Tip: Use Alt+Left and Alt+Right constantly. Ghidra maintains a navigation history like a web browser. When you dive into a function and want to return, Alt+Left takes you back instantly.


The Program Trees and Symbol Tree

Program Trees (Section Layout)

The Program Trees panel shows the PE section layout of the loaded binary:

SectionTypical Contents
.textExecutable code -- this is where the disassembly lives
.dataInitialized global variables (read/write)
.rdataRead-only data: strings, constants, import tables
.rsrcResources: icons, version info, embedded files
.relocRelocation table (for ASLR support)

Symbol Tree (Organized Navigation)

The Symbol Tree is your primary navigation panel:

CategoryContentsAnalysis Value
ImportsDLLs and their imported functionsReveals what external APIs the binary uses
ExportsFunctions the binary exposesCritical for DLL analysis
FunctionsAll discovered functionsBrowse and search all code
LabelsNamed addressesIncludes data labels, string references
NamespacesGrouped symbols (DLL names, classes)Organized hierarchy of symbols

Filtering Imports for Malware Analysis

The Imports section is one of the first places to check. Look for DLLs that reveal malware capabilities:

DLLCapability Indicator
WININET.DLLHTTP/FTP network communication
WS2_32.DLLRaw socket networking
ADVAPI32.DLLRegistry, services, crypto, security
CRYPT32.DLLEncryption and certificate operations
URLMON.DLLURL download operations
SHELL32.DLLShell execution, file operations

The Graph View

For complex functions with many branches, the Graph View provides a visual representation of control flow:

  • Open via Window > Function Graph or the graph icon in the toolbar
  • Each block represents a sequence of instructions ending in a branch
  • Green arrows indicate the "true" branch of a conditional jump
  • Red arrows indicate the "false" branch
  • Blue arrows indicate unconditional jumps

The Graph View is especially useful for understanding switch statements, nested if-else chains, and loop structures at a glance.


Practical Exercise

  1. Open an imported binary in Ghidra's CodeBrowser
  2. Navigate to the entry point via the Symbol Tree
  3. In the Listing view, identify the function prologue (PUSH EBP / MOV EBP,ESP)
  4. Switch to the Decompiler view and read the pseudocode for the entry function
  5. Double-click a CALL instruction to follow it into a subroutine
  6. Use Alt+Left to navigate back
  7. Open the Imports in the Symbol Tree and browse the imported DLLs
  8. Select any imported function and press X to see where it is referenced
Try it in the shell
Practise this lesson's tooling on its sample in an emulated analyst shell. Output is pre-recorded — nothing executes.

Suggested triage steps

  1. 1

    Establish the file

    A DLL has exports rather than a single entry point, which changes where you start reading.

  2. 2

    Find your landmarks

    Imports are the fastest way into unfamiliar disassembly — each one is a named function you can navigate to.

  3. 3

    Find the strings to pivot from

    In Ghidra you would double-click one of these to jump to the code that uses it.

analyst@lab:~emulated · nothing executes

MAA analyst shell — emulated. Nothing executes.

Type 'help', or click a step on the left.

$
Navigating Disassembly & the Decompiler | Malware Analysis Academy