0x01: The Philosophy of Disassembly
Disassembly is the process of reversing the final stage of compilation. While the CPU sees a stream of high-speed electrical pulses (represented as Hex/Binary), the analyst needs to see intent.
In the world of the 0x10 Operator, disassembly is the only way to verify what a program actually does, regardless of what the documentation claims.
Critical Use Cases:
- Malware Analysis: Determining if a binary is exfiltrating data or encrypting your disk.
- Vulnerability Research: Identifying “Buffer Overflows” or “Use-After-Free” bugs by seeing exactly how the compiler allocated memory.
- Exploit Development: Moving from a simple “crash” to a working “exploit” requires knowing the exact state of the registers and the stack at the moment of failure.
0x02: The Anatomy of an Instruction
When we disassemble a binary, we are looking for three pieces of information that make up an instruction:
- The Address (Offset): Where the instruction lives in memory.
- The Opcode (Machine Code): The raw bytes the CPU interprets.
- The Mnemonic (Assembly): The human-readable name for the action (e.g.,
MOV,PUSH,BL).
0x03: Tactical Tooling: objdump
While advanced analysts eventually move to heavy-duty GUIs like Ghidra or IDA Pro, the “First Response” tool is always objdump. It is fast, lightweight, and pre-installed on almost every Linux system.
By using the -c flag in GCC, we create an Object File (.o). This is vital because it strips away the noise of the C-Runtime and allows us to focus strictly on the code we wrote.
0x04: Analyzing the hello.o Trace
Look at the following trace generated from a simple write() function. This is your first look at the “Matrix”:
00000000 <main>:
0: b580 push {r7, lr} // Save the return address
2: af00 add r7, sp, #0 // Set up the local stack frame
4: 2207 movs r2, #7 // Argument 3: String length (7)
c: 2001 movs r0, #1 // Argument 1: File Descriptor (1 = stdout)
e: f7ff fffe bl 0 <write> // Branch with Link: Call the write functionIntelligence Note: Notice how the arguments are loaded into registers (r0, r1, r2) before the bl (Branch with Link) instruction is called. In Reverse Engineering, seeing a bl or call instruction is your signal to look at the registers immediately preceding it to find the function’s parameters.
0x05: Interactive Lab (Disassembly Reconstruction)
In this lab, you must act as the “Human Disassembler.” Look at the raw machine code and identify the operation.
MISSION: Using the objdump logic from the briefing, identify the Mnemonic (the assembly command) represented by the hex code b580.
DATA: B5 80
MNEMONIC: [LOCKED]
0x06: Mission Task
Current Objective: Compile the
hello.cprogram usinggcc -c hello.c. Runobjdump -d hello.oand look at themovsinstructions.The Challenge: Why does the compiler use
movsinstead of justmov? Search for the difference in the ARM instruction set documentation. This tiny detail (the “s” suffix) affects how the CPU’s Flags (Zero, Negative, Carry) are set, which is crucial for understanding conditional branches likejump if equal.
0x07: Advanced Disassembly & Logic Flow
When you run objdump -d, you are performing Static Analysis. You are looking at the instructions while they are “frozen.” To make this information useful, you need to reconstruct the logic that the programmer originally wrote in C.
1. The Function Prologue (The Handshake)
Every function starts with a sequence called the Prologue. Look at our hello.o output again: 0: b580 push {r7, lr}
r7: This is the Frame Pointer. It holds a reference to the start of the current function’s workspace.lr(Link Register): This is the “Return Ticket.” It holds the address the CPU should jump back to once this function finishes. If a hacker overwrites this value on the stack, they can redirect the program to their own code. This is the foundation of Buffer Overflow Exploits.
2. PC-Relative Addressing (Finding Data)
Notice this line in the disassembly: 6: 4b04 ldr r3, [pc, #16]
In ARM architecture, the PC (Program Counter) points to the instruction currently being executed. The code is saying: “Go 16 bytes forward from where we are right now and grab the data there.” This is how the program finds the “Hello!” string. The string isn’t “in” the code; it’s tucked away in a data section, and the code uses the PC as a GPS to find it.
3. The Branch with Link (bl)
e: f7ff fffe bl 0 <write>
The bl instruction is a “Call.” It does two things:
- It jumps to the
writefunction. - It saves the current address into the Link Register (lr) so the program knows how to come back.
0x08: Tactical Intelligence Extraction
In high-level C, you write: write(1, "Hello!", 7);. In Disassembly, you must track where those three arguments (1, address, and 7) go.
| C Argument | ARM Register | Disassembly Line |
1 (File Descriptor) | r0 | c: 2001 movs r0, #1 |
"Hello!" (Buffer) | r1 | a: 4619 mov r1, r3 (r3 held the address) |
7 (Count) | r2 | 4: 2207 movs r2, #7 |
0x09: Interactive Lab (Logic Reconstruction)
You have intercepted a mystery binary. Your mission is to determine what value is being passed as the Length of the string by analyzing the raw hex.
MISSION: Calculate the final value stored in register R2 after execution.
0x10: The “Pro” Disassembler Overview
While objdump is our primary scout, for complex missions, we use tools that can graph the logic flow:
- Ghidra (NSA): Excellent for “Decompilation” (turning assembly back into C-like code).
- IDA Pro: The gold standard for commercial malware analysis.
- Binary Ninja: Known for its clean UI and powerful “Intermediate Language” (IL) which simplifies complex assembly.
As we move into the next lectures, we will begin using these tools to map out large, “stripped” binaries where we don’t even have function names to guide us.
Mission Task
Current Objective: Re-run
objdump -d hello.o. Look for the18: 0000000c .word 0x0000000cat the end.Challenge: This is a Literal Pool. The instruction at offset
6used the Program Counter to find this value. Can you calculate why the offset is#16? (Hint: In ARM, the PC is often 2 instructions ahead of the one being executed).
This is p5.1_disasm.summary // The Operator’s Synthesis.
To achieve the rank of 0x11 (Master Analyst), you must be able to look at a wall of hexadecimal noise and instantly see the high-level logic. This lecture serves as a “Combat Review” of everything we have covered regarding disassembly, from raw opcodes to register tracking.
0x11: The Disassembly Masterclass
Disassembly is the bridge between the Physical Layer (machine code) and the Logical Layer (source code). By now, you should recognize that every binary follows a predictable pattern dictated by the compiler and the CPU architecture.
I. The Physical Signature (The Bytes)
Every instruction starts as a specific hex value. When you see B5 80, your brain should immediately translate that to PUSH {R7, LR}.
- Pro Tip: In ARM Thumb mode (32-bit), instructions are often 2 bytes. In A64 (64-bit), they are strictly 4 bytes. Knowing the “width” of your instructions prevents you from getting lost in the offsets.
II. The Structural Blueprint (The Sections)
We don’t just find code anywhere. A well-formed ELF binary organizes its intel into compartments:
.text: The armory where the actual instructions (MOV,ADD,BL) are stored..rodata: The archive where static strings (“Hello World”) live..data: The workbench for variables that change during execution.
III. The Data Flow (The Calling Convention)
This is where most analysts fail. You must remember the Standard Handshake:
- R0-R3 / X0-X7: These are the “Input Slots.” Before a function is called, the arguments are placed here.
- BL (Branch with Link): The jump happens.
- R0 / X0: After the function returns, the “Result” is placed back in the first register.
0x12: Tactical Error Resolution (The “Why” Behind the Error)
In your last mission, many of you encountered “Logic Divergence.” Let’s analyze why those errors happen and how to resolve them.
Scenario: ADDS R2, R0, R1 where R0=5 and R1=1.
- Error: “I thought the answer was 1.”
- Reason: You focused on the last register loaded (
R1) and forgot thatADDSis an arithmetic operation, not a move. - Resolution: Always look for the Mnemonic. If it’s
ADD,SUB, orMUL, you are performing math, not just storage.
- Reason: You focused on the last register loaded (
- Error: “I thought the answer was 5.”
- Reason: You identified the source register (
R0) but ignored the secondary operand. - Resolution: ARM instructions often use Three-Operand Syntax:
DESTINATION, OPERAND1, OPERAND2. The first register is where the result goes; the next two are the ingredients.
- Reason: You identified the source register (
- Error: “The Hex says 0xA, so I wrote 10.”
- Reason: This is correct, but if the lab asks for Hex and you give Decimal (or vice versa), the system will flag a mismatch.
- Resolution: Radix Literacy. Always check your prefixes.
10â‰0x10(which is 16).
0x13: Interactive Lab (Final Synthesis Check)
This is the final gate. You must analyze this three-line trace and provide the final state of the registers.
0x14: The Road Ahead
You have mastered the Static deconstruction of a binary. You can read the code while it sleeps. In the next phase, we wake it up. We will move into Dynamic Analysis, where we use debuggers to watch these registers change in real-time.
Mission Task:
Use
objdump -Son a binary you compiled with debugging symbols (gcc -g). This flag interweaves your C source code with the Disassembly. This is the “God View” of reverse engineering. Study how a single line of C (likex = a * b) often results in 3 or 4 lines of Assembly.
