# Embedded Systems Reverse Engineering [Repository](https://github.com/mytechnotalent/Embedded-Hacking) ## Week 1 Introduction and Overview of Embedded Reverse Engineering: Ethics, Scoping, and Basic Concepts ### Non-Credit Practice Exercise 4: Connect GDB & Basic Exploration #### Objective Set up GDB (GNU Debugger) to dynamically analyze the "hello, world" program running on your Pico 2, verifying that your debugging setup works correctly. #### Prerequisites - Raspberry Pi Pico 2 with "hello-world" binary already flashed - OpenOCD installed and working - GDB (arm-none-eabi-gdb) installed - Your Pico 2 connected to your computer via USB CMSIS-DAP interface - CMake build artifacts available (`.elf` file from compilation) #### Task Description In this exercise, you'll: 1. Start OpenOCD to provide a debug server 2. Connect GDB to the Pico 2 via OpenOCD 3. Set a breakpoint at the main function 4. Examine registers and memory while the program is running 5. Verify that your dynamic debugging setup works #### Important Setup Notes Before you start, make sure: - Your Pico 2 is **powered on** and connected to your computer - You have **OpenOCD** installed for ARM debugging - You have **GDB** (specifically `arm-none-eabi-gdb`) installed - Your binary file (`0x0001_hello-world.elf`) is available in the `build/` directory #### Step-by-Step Instructions ##### Step 1: Start OpenOCD in Terminal 1 Open a **new terminal window** (PowerShell, Command Prompt, or WSL): **On Windows (PowerShell/Command Prompt):** ``` openocd ^ -s "C:\Users\flare-vm\.pico-sdk\openocd\0.12.0+dev\scripts" ^ -f interface/cmsis-dap.cfg ^ -f target/rp2350.cfg ^ -c "adapter speed 5000" ``` **Expected Output:** ``` Open On-Chip Debugger 0.12.0+dev ... Info : CMSIS-DAP: SWD detected Info : RP2350 (dual core) detected Info : Using JTAG interface ... Info : accepting 'gdb' connection on tcp/3333 ``` ##### Step 2: Start GDB in Terminal 2 Open a **second terminal window** and navigate to your project directory: ``` arm-none-eabi-gdb build\0x0001_hello-world.elf ``` **Expected Output:** ``` Reading symbols from build\0x0001_hello-world.elf... (gdb) ``` ##### Step 3: Connect GDB to OpenOCD At the GDB prompt `(gdb)`, type: ```gdb target extended-remote localhost:3333 ``` **Expected Output:** ``` Remote debugging using localhost:3333 (gdb) ``` (The warning is normal - you already loaded the .elf file, so it doesn't matter) ##### Step 4: Reset and Halt the Target To reset the Pico 2 and prepare for debugging, type: ```gdb monitor reset halt ``` **Expected Output:** ``` (gdb) ``` (This resets the processor and halts it, preventing execution until you tell it to run) ##### Step 5: Set a Breakpoint at main To stop execution at the beginning of the `main` function: ```gdb b main ``` **Expected Output:** ``` Breakpoint 1 at 0x10000234: file ../0x0001_hello-world.c, line 4. (gdb) ``` **What this means:** - Breakpoint 1 is set at address `0x10000234` - That's in the file `../0x0001_hello-world.c` at line 4 - The breakpoint is at the `main` function ##### Step 6: Continue Execution to the Breakpoint Now let the program run until it hits your breakpoint: ```gdb c ``` **Expected Output:** ``` Continuing. Breakpoint 1, main () at ../0x0001_hello-world.c:4 4 stdio_init_all(); (gdb) ``` **Great!** Your program is now halted at the beginning of `main()`. ##### Step 7: Examine the Assembly with `disas` To see the assembly language of the current function: ```gdb disas ``` **Expected Output:** ``` Dump of assembler code for function main: => 0x10000234 <+0>: push {r3, lr} 0x10000236 <+2>: bl 0x1000156c 0x1000023a <+6>: ldr r0, [pc, #8] @ (0x10000244 ) 0x1000023c <+8>: bl 0x100015fc <__wrap_puts> 0x10000240 <+12>: b.n 0x1000023a 0x10000242 <+14>: nop 0x10000244 <+16>: adds r4, r1, r7 0x10000246 <+18>: asrs r0, r0, #32 End of assembler dump. (gdb) ``` **Interpretation:** - The `=>` arrow shows where we're currently stopped (at `0x10000234`) - We can see the `push`, `bl` (branch and link), `ldr`, and `b.n` (branch) instructions - This is the exact code you analyzed in the Ghidra exercises! ##### Step 8: View All Registers with `i r` To see the current state of all CPU registers: ```gdb i r ``` **Expected Output:** ``` r0 0x0 0 r1 0x10000235 268436021 r2 0x80808080 -2139062144 r3 0xe000ed08 -536810232 r4 0x100001d0 268435920 r5 0x88526891 -2007865199 r6 0x4f54710 83183376 r7 0x400e0014 1074659348 r8 0x43280035 1126694965 r9 0x0 0 r10 0x10000000 268435456 r11 0x62707361 1651536737 r12 0xed07f600 -318245376 sp 0x20082000 0x20082000 lr 0x1000018f 268435855 pc 0x10000234 0x10000234
xpsr 0x69000000 1761607680 ``` **Key Registers to Understand:** | Register | Value | Meaning | | -------- | ------------ | ------------------------------------------------- | | `pc` | `0x10000234` | Program Counter - we're at the start of `main` | | `sp` | `0x20082000` | Stack Pointer - top of our stack in RAM | | `lr` | `0x1000018f` | Link Register - where we return from `main` | | `r0-r3` | Various | Will hold function arguments and return values | ##### Step 9: Step Into the First Instruction To execute one assembly instruction: ```gdb si ``` **Expected Output:** ``` 0x10000236 in main () at ../0x0001_hello-world.c:5 5 stdio_init_all(); (gdb) ``` The `pc` should now be at `0x10000236`, which is the next instruction. ##### Step 10: Answer These Questions Based on what you've observed: ###### Question 1: GDB Connection - Was GDB able to connect to OpenOCD? (Yes/No) - Did the program stop at your breakpoint? (Yes/No) - __________ ###### Question 2: Breakpoint Address - What is the memory address of the `main` function's first instruction? - __________ - Is this in Flash memory (0x100...) or RAM (0x200...)? - __________ ###### Question 3: Stack Pointer - What is the value of the Stack Pointer (sp) when you're at `main`? - __________ - Is this in Flash or RAM? - __________ ###### Question 4: First Instruction - What is the first instruction in `main`? - __________ - What does it do? (Hint: `push` = save to stack) - __________ ###### Question 5: Disassembly Comparison - Look at the disassembly from GDB (Step 7) - Compare it to the disassembly from Ghidra (Exercise 1) - Are they the same? - __________ #### Deeper Exploration (Optional Challenge) ##### Challenge 1: Step Through stdio_init_all 1. Continue stepping: `si` (step into) or `ni` (next instruction) 2. Eventually, you'll reach `bl 0x1000156c ` 3. Use `si` to step **into** that function 4. What instructions do you see? 5. What registers are being modified? ##### Challenge 2: View Specific Registers Instead of viewing all registers, you can view just a few: ```gdb i r pc sp lr r0 r1 r2 ``` This shows only the registers you care about. ##### Challenge 3: Examine Memory To examine memory at a specific address (e.g., where the string is): ```gdb x/16b 0x100019cc ``` This displays 16 bytes (`b` = byte) starting at address `0x100019cc`. Can you see the "hello, world" string? ##### Challenge 4: Set a Conditional Breakpoint Set a breakpoint that only triggers after a certain condition: ```gdb b *0x1000023a if $r0 != 0 ``` This is useful when you want to break on a condition rather than every time. #### Questions for Reflection 1. **Why does GDB show both the C source line AND the assembly?** - This is because the .elf file contains debug symbols - What would happen if we used a stripped binary? 2. **How does GDB know the assembly for each instruction?** - It disassembles the binary on-the-fly based on the architecture 3. **Why is the Stack Pointer so high (0x20082000)?** - It's at the top of RAM and grows downward - Can you calculate how much RAM this Pico 2 has? 4. **What's the difference between `si` (step into) and `ni` (next instruction)?** - `si` steps into function calls - `ni` executes entire functions without stopping inside them #### Important GDB Commands Reference | Command | Short Form | What It Does | | ---------------------- | ---------- | ------------------------------------ | | `target extended-remote localhost:3333` | | Connect to OpenOCD | | `monitor reset halt` | | Reset and halt the processor | | `break main` | `b main` | Set a breakpoint at main function | | `continue` | `c` | Continue until breakpoint | | `step instruction` | `si` | Step one instruction (into calls) | | `next instruction` | `ni` | Step one instruction (over calls) | | `disassemble` | `disas` | Show assembly for current function | | `info registers` | `i r` | Show all register values | | `x/Nxy ADDRESS` | `x` | Examine memory (N=count, x=format, y=size) | | `quit` | `q` | Exit GDB | **Examples for `x` command:** - `x/10i $pc` - examine 10 instructions at program counter - `x/16b 0x20000000` - examine 16 bytes starting at RAM address - `x/4w 0x10000000` - examine 4 words (4-byte values) starting at Flash address #### Troubleshooting ##### Problem: "OpenOCD not found" **Solution:** Make sure OpenOCD is in your PATH or use the full path to the executable ##### Problem: "Target not responding" **Solution:** - Check that your Pico 2 is properly connected - Make sure OpenOCD is running and shows "accepting 'gdb' connection" - Restart both OpenOCD and GDB ##### Problem: "Cannot find breakpoint at main" **Solution:** - Make sure you compiled with debug symbols - The .elf file must include symbol information - Try breaking at an address instead: `b *0x10000234` ##### Problem: GDB shows "No source available" **Solution:** - This happens with stripped binaries - You can still see assembly with `disas` - You can still examine memory and registers #### Summary By completing this exercise, you've: 1. ? Set up OpenOCD as a debug server 2. ? Connected GDB to a Pico 2 board 3. ? Set a breakpoint and halted execution 4. ? Examined assembly language in a live debugger 5. ? Viewed CPU registers and their values 6. ? Verified your dynamic debugging setup works You're now ready for Week 2, where you'll: - Step through code line by line - Watch variables and memory change - Understand program flow in detail - Use this knowledge to modify running code #### Next Steps 1. **Close GDB**: Type `quit` or `q` to exit 2. **Close OpenOCD**: Type `Ctrl+C` in the OpenOCD terminal 3. **Review**: Go back to the Ghidra exercises and compare static vs. dynamic analysis 4. **Prepare**: Read through Week 2 materials to understand what's coming next