3.3 KiB
Embedded Systems Reverse Engineering
Week 1
Introduction and Overview of Embedded Reverse Engineering: Ethics, Scoping, and Basic Concepts
Non-Credit Practice Exercise 4 Solution: Connect GDB & Basic Exploration
Answers
Step 3: Answer Exactly
- Was GDB able to connect to OpenOCD?
- Yes, via
target extended-remote localhost:3333.
- Yes, via
- Did the program stop at the
mainbreakpoint?- Yes, at
Breakpoint 1, main () at ../0x0001_hello-world.c:4.
- Yes, at
- What is the address of
main's first instruction, and is it Flash or RAM?0x10000234, and it is in Flash (0x100...XIP region).
- What is the
spvalue atmain, and is it Flash or RAM?0x20082000, and it is in RAM (0x200...SRAM region).
- What is the first instruction in
main, and what does it do?push {r3, lr}; it savesr3andlron the stack and keeps 8-byte stack alignment for ABI-compliant calls.
- Does GDB match what Ghidra shows?
- Yes. The disassembly and flow match the Ghidra listing.
Step 4: Capture Register Values (pc, sp, lr, r0-r3)
| Register | Value | Description |
|---|---|---|
| pc | 0x10000234 |
Program Counter - at start of main (Flash) |
| sp | 0x20082000 |
Stack Pointer - top of stack (RAM) |
| lr | 0x1000018f |
Link Register - return address after main |
| r0 | 0x0 |
General Purpose - will hold function arguments |
| r1 | 0x10000235 |
General Purpose |
| r2 | 0x80808080 |
General Purpose |
| r3 | 0xe000ed08 |
General Purpose |
Reference Disassembly (for verification)
0x10000234 <+0>: push {r3, lr} # Save registers to stack
0x10000236 <+2>: bl 0x1000156c <stdio_init_all> # Initialize I/O
0x1000023a <+6>: ldr r0, [pc, #8] # Load string pointer
0x1000023c <+8>: bl 0x100015fc <__wrap_puts> # Print string
0x10000240 <+12>: b.n 0x1000023a <main+6> # Infinite loop
0x10000242 <+14>: nop
0x10000244 <+16>: (data: pointer to string)
GDB Connection Sequence
Terminal 1: openocd -s "..." -f interface/cmsis-dap.cfg -f target/rp2350.cfg
Terminal 2: arm-none-eabi-gdb build/0x0001_hello-world.elf
(gdb) target extended-remote localhost:3333
(gdb) monitor reset halt
(gdb) b main
(gdb) c
(gdb) disas main
(gdb) i r
Step 5: Reflection Answers
-
Why does the stack pointer start at
0x20082000? The initial stack pointer value comes from the first entry in the vector table at0x10000000. The linker script sets__StackTopto0x20082000, which is the top of the SCRATCH_Y region in SRAM. The stack grows downward from this address. -
Why does
push {r3, lr}saver3even though it doesn't seem to be used? ARM requires 8-byte stack alignment. Pushinglralone would only move SP by 4 bytes. Includingr3ensures the stack remains 8-byte aligned, which is required by the ARM Architecture Procedure Call Standard (AAPCS). -
How does the infinite loop work? The instruction at
0x10000240isb.n 0x1000023a- an unconditional branch back tomain+6, which reloads the string pointer and calls__wrap_putsagain. The function never returns.