# Embedded Systems Reverse Engineering [Repository](https://github.com/mytechnotalent/Embedded-Hacking) ## Week 3 Embedded System Analysis: Understanding the RP2350 Architecture w/ Comprehensive Firmware Analysis ### Non-Credit Practice Exercise 1: Trace a Reset #### Objective Single-step through the first 10 instructions of the reset handler to understand exactly what happens when the RP2350 powers on or resets. #### Prerequisites - Raspberry Pi Pico 2 with debug probe connected - OpenOCD and `arm-none-eabi-gdb` available in your PATH - `build\0x0001_hello-world.elf` present and flashed to the board - Week 3 environment setup completed (OpenOCD running, GDB connected) #### Task Description You will set a breakpoint at the reset handler (`0x1000015c`), trigger a reset, and step through each instruction one at a time while documenting what each instruction does. #### Step-by-Step Instructions ##### Step 1: Start OpenOCD ```powershell 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" ``` ##### Step 2: Launch GDB ```powershell arm-none-eabi-gdb build\0x0001_hello-world.elf ``` ##### Step 3: Connect to Target ```gdb (gdb) target extended-remote :3333 ``` ##### Step 4: Set Breakpoint at Reset Handler ```gdb (gdb) b *0x1000015c ``` **What this does:** Places a breakpoint at the very first instruction of the reset handler (the entry point after bootrom). ##### Step 5: Reset and Break ```gdb (gdb) monitor reset halt (gdb) c ``` **What this does:** - `monitor reset halt` resets the chip and immediately halts it - `c` continues execution until the breakpoint at the reset handler is hit ##### Step 6: Single-Step Through Instructions Now step through the first 10 instructions, one at a time: ```gdb (gdb) si (gdb) disas $pc,+2 (gdb) info registers r0 ``` Repeat `si` nine more times, examining each instruction. **Example of what you'll see:** **Instruction 1:** ``` 0x1000015c <_reset_handler>: mov.w r0, #3489660928 @ 0xd0000000 ``` **What it does:** Loads the SIO base address (0xd0000000) into r0 **Instruction 2:** ``` 0x10000160 <_reset_handler+4>: ldr r0, [r0, #0] ``` **What it does:** Reads the CPUID register to determine which core is running **Instruction 3:** ``` 0x10000162 <_reset_handler+6>: cbz r0, 0x1000016a ``` **What it does:** If CPUID is 0 (Core 0), branch ahead to continue boot; otherwise handle Core 1 ##### Step 7: Document Your Observations For each of the 10 instructions: 1. Write down the address 2. Write down the assembly instruction 3. Explain what it does 4. Note any register changes using `info registers` #### Expected Output - You should see the reset handler check which core is running - If you're on Core 0, you'll see it jump to the data copy section - Register `r0` will contain CPUID value (should be 0) - PC (program counter) advances with each `si` command #### Questions for Reflection ###### Question 1: Why does the reset handler check the CPUID before doing anything else? ###### Question 2: What would happen if Core 1 tried to run the same initialization code as Core 0? ###### Question 3: Which registers are used in the first 10 instructions, and why those specific ones? #### Tips and Hints - Use `disas $pc,+20` to see upcoming instructions without stepping through them - Use `info registers` to see all register values at any point - If you step past where you wanted to stop, just `monitor reset halt` and start over - Keep notes as you go—this is detective work! #### Next Steps - Try stepping all the way through to the data copy loop - Set a breakpoint at `0x1000016c` (the data copy loop) and continue there directly - Move on to Exercise 2 to calculate the stack size from the vector table #### Additional Challenge Set a breakpoint at `0x10000178` (the BSS clear phase) and continue execution to see how the reset handler transitions from data copying to BSS clearing.