5.4 KiB
Embedded Systems Reverse Engineering
Week 11
Structures and Functions in Embedded Systems: Debugging and Hacking w/ IR Remote Control and NEC Protocol Basics
Non-Credit Practice Exercise 4: Change Blink Speed
Objective
Find the blink_led(pin, 3, 50) call in the 0x0026_functions binary using GDB, identify the immediate value 0x32 (50) being loaded into r2 (the delay parameter), calculate the file offset, and patch it to 0x19 (25) so that each LED blinks at double speed when activated by the IR remote.
Prerequisites
- Completed Week 11 tutorial (GDB and hex editor sections)
0x0026_functions.elfand0x0026_functions.binavailable 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 takes a delay parameter of 50ms (0x32) in register r2. This value controls how long each LED stays on and off during the blink cycle. By patching this to 25ms (0x19), the LEDs will blink twice as fast, creating a noticeably quicker flashing pattern when any IR remote button is pressed.
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
Step 2: Find the blink_led Call
Disassemble main and look for the parameter setup before bl blink_led:
(gdb) disassemble 0x10000234,+300
Look for:
movs r0, <pin> ; GPIO pin number
movs r1, #3 ; blink count
movs r2, #0x32 ; delay = 50ms
bl blink_led
Note the address of the movs r2, #0x32 instruction.
Step 3: Examine the Instruction Encoding
Look at the raw bytes:
(gdb) x/2bx <address_of_movs_r2_0x32>
The movs r2, #0x32 instruction has 0x32 (50) as the immediate byte.
Step 4: Calculate the File Offset
file_offset = address - 0x10000000
Note the file offset of the byte containing 32.
Step 5: Encode the New Value
| Parameter | Original | New | Effect |
|---|---|---|---|
| Delay | 32 (50ms) |
19 (25ms) |
2x faster blink |
Be careful: 0x32 is also the ASCII code for '2'. Make sure you are patching the movs r2 instruction and not a comparison value like cmp r4, #0x32.
Step 6: Patch with HxD
- In HxD, open
C:\Users\flare-vm\Desktop\Embedded-Hacking-main\0x0026_functions\build\0x0026_functions.bin - Press Ctrl+G and enter the file offset
- You should see:
32 - Replace with:
19
Question 1: How can you confirm you are patching the delay parameter and not some other 0x32 byte in the binary?
Step 7: Save and Convert
- Click File → Save As →
0x0026_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
- Hold BOOTSEL and plug in your Pico 2
- Drag and drop
hacked.uf2onto the RPI-RP2 drive
Check the behavior:
- Press button 1 → Red LED blinks 3 times but noticeably faster (25ms on/off vs 50ms)
- Press button 2 → Green LED blinks 3 times at double speed
- Press button 3 → Yellow LED blinks 3 times at double speed
- The total blink sequence should complete in roughly half the original time
Expected Output
After completing this exercise, you should be able to:
- Locate function parameters in ARM Thumb
movsinstructions - Distinguish between identical byte values used in different contexts
- Patch timing parameters to change observable hardware behavior
- Understand the relationship between delay values and perceived blink speed
Questions for Reflection
Question 1: The blink_led function calls sleep_ms internally with the delay value. If you set the delay to 1ms (0x01), would you still see the LED blink, or would it appear constantly on?
Question 2: The value 0x32 appears in this binary as both a delay parameter (50ms) and potentially as an ASCII comparison ('2'). How would you systematically find ALL occurrences of 0x32 and determine which one to patch?
Question 3: If you wanted a delay of 500ms (0x1F4), the value would not fit in a movs immediate. How would the compiler handle this larger delay value?
Question 4: The blink function uses the delay for both the on-time and the off-time. Could you make the LED stay on longer than it stays off? What kind of patch would that require?
Tips and Hints
25decimal =0x19hex — fits in one byte, so themovsencoding works directly- Verify location by checking the surrounding instructions:
movs r1, #3should be right before andbl blink_ledright after - The total blink time for 3 blinks at 50ms = 3 × (50 + 50) = 300ms; at 25ms = 3 × (25 + 25) = 150ms
- If there are multiple call sites for
blink_led, each may have its ownmovs r2, #0x32that needs patching