Files
Embedded-Hacking/WEEK11/WEEK11-02.md
2026-03-19 15:01:07 -04:00

5.3 KiB

Embedded Systems Reverse Engineering

Repository

Week 11

Structures and Functions in Embedded Systems: Debugging and Hacking w/ IR Remote Control and NEC Protocol Basics

Objective

Find the blink_led(pin, 3, 50) call in the 0x0026_functions binary using GDB, identify the immediate value #3 being loaded into r1 (the blink count parameter), calculate the file offset, and patch it to #5 so that each LED blinks 5 times instead of 3 when activated by the IR remote.

Prerequisites

  • Completed Week 11 tutorial (GDB and hex editor sections)
  • 0x0026_functions.elf and 0x0026_functions.bin available in your build directory
  • GDB (arm-none-eabi-gdb) and OpenOCD installed
  • A hex editor (HxD, ImHex, or similar)
  • Python installed (for UF2 conversion)
  • Raspberry Pi Pico 2 with IR remote and LEDs on GPIO 16, 17, 18

Task Description

The blink_led function is called with three parameters: the GPIO pin number, a blink count of 3, and a delay of 50ms. The blink count is loaded as a small immediate value (movs r1, #3) directly in the instruction before the bl blink_led call. You will locate this instruction, find the byte encoding the #3 immediate, and patch it to #5 so the LEDs blink 5 times per button press.

Step-by-Step Instructions

Step 1: Start the Debug Session

Terminal 1 - Start OpenOCD:

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"

Terminal 2 - Start GDB:

arm-none-eabi-gdb build\0x0026_functions.elf

Connect to target:

(gdb) target remote :3333
(gdb) monitor reset halt

Disassemble main and look for the function call sequence:

(gdb) disassemble 0x10000234,+300

Look for the parameter setup before bl blink_led:

movs r0, <pin>       ; GPIO pin number (from get_led_pin)
movs r1, #3          ; blink count = 3
movs r2, #0x32       ; delay = 50ms
bl   blink_led

Note the address of the movs r1, #3 instruction.

Step 3: Examine the Instruction Encoding

Look at the raw bytes of the movs r1, #3 instruction:

(gdb) x/2bx <address_of_movs_r1_3>

In Thumb encoding, movs r1, #imm8 has the immediate in the lower byte. You should see a byte containing 03.

Step 4: Calculate the File Offset
file_offset = address - 0x10000000

Note the file offset of the byte containing 03.

Step 5: Encode the New Value
Parameter Original New Encoding
Blink count 03 05 movs r1, #5
Step 6: Patch with HxD
  1. In HxD, open C:\Users\flare-vm\Desktop\Embedded-Hacking-main\0x0026_functions\build\0x0026_functions.bin
  2. Press Ctrl+G and enter the file offset
  3. You should see: 03
  4. Replace with: 05
Question 1: The movs r1, #3 is a 2-byte Thumb instruction. Which byte contains the immediate — the first or the second?
Step 7: Save and Convert
  1. Click FileSave As0x0026_functions-h.bin
cd C:\Users\flare-vm\Desktop\Embedded-Hacking-main\0x0026_functions
python ..\uf2conv.py build\0x0026_functions-h.bin --base 0x10000000 --family 0xe48bff59 --output build\hacked.uf2
Step 8: Flash and Verify
  1. Hold BOOTSEL and plug in your Pico 2
  2. Drag and drop hacked.uf2 onto the RPI-RP2 drive

Check the behavior:

  • Press button 1 → Red LED blinks 5 times (was 3), then stays on
  • Press button 2 → Green LED blinks 5 times (was 3), then stays on
  • Press button 3 → Yellow LED blinks 5 times (was 3), then stays on
  • Count carefully — you should see exactly 5 on/off cycles

Expected Output

After completing this exercise, you should be able to:

  • Locate small immediate values in Thumb movs instructions
  • Understand Thumb instruction encoding for immediate operands
  • Patch function parameters by modifying instruction immediates
  • Verify behavioral changes by counting observable events

Questions for Reflection

Tips and Hints

  • Small immediates (0-255) are encoded directly in the movs instruction — no literal pool needed
  • The ARM calling convention uses r0, r1, r2, r3 for the first four function parameters in order
  • Look for movs r1, #3 right before bl blink_led — there may be one shared call site or multiple per button
  • If there are multiple movs r1, #3 instructions (one per case), you need to patch all of them for consistent behavior