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

160 lines
5.9 KiB
Markdown

# Embedded Systems Reverse Engineering
[Repository](https://github.com/mytechnotalent/Embedded-Hacking)
## Week 10
Conditionals in Embedded Systems: Debugging and Hacking Static & Dynamic Conditionals w/ SG90 Servo Motor PWM Basics
### Non-Credit Practice Exercise 2: Add a Third Command
#### Objective
Find the comparison instruction `cmp r4, #0x32` ('2') in the `0x0020_dynamic-conditionals` binary using GDB, locate the branch target for case '2', and modify existing code so that pressing '3' (0x33) moves the servo to the center position (90°) by patching one of the existing comparisons and its corresponding angle value to `0x42b40000` (90.0f).
#### Prerequisites
- Completed Week 10 tutorial (GDB and hex editor sections)
- `0x0020_dynamic-conditionals.elf` and `0x0020_dynamic-conditionals.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 SG90 servo motor connected on GPIO 6
#### Task Description
The program has two active commands: '1' (0x31) moves the servo 0°→180° and '2' (0x32) moves it 180°→0°. Adding a completely new code path would require rewriting branch offsets throughout the binary. Instead, you will repurpose the '2' command by changing its comparison value from `0x32` ('2') to `0x33` ('3') and patching both of its angle values to `0x42b40000` (90.0f), so pressing '3' moves the servo to center and holds it there.
#### Step-by-Step Instructions
##### Step 1: Start the Debug Session
**Terminal 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"
```
**Terminal 2 - Start GDB:**
```powershell
arm-none-eabi-gdb build\0x0020_dynamic-conditionals.elf
```
**Connect to target:**
```gdb
(gdb) target remote :3333
(gdb) monitor reset halt
```
##### Step 2: Find the Comparison Instructions
Disassemble main and locate both `cmp` instructions:
```gdb
(gdb) disassemble 0x10000234,+250
```
Look for:
```
cmp r4, #0x31 ; compare with '1'
beq <target1>
cmp r4, #0x32 ; compare with '2'
beq <target2>
```
Note the address of the `cmp r4, #0x32` instruction.
##### Step 3: Examine the Comparison Byte
The `cmp r4, #0x32` instruction encodes `0x32` as an immediate. Examine the instruction bytes:
```gdb
(gdb) x/2bx <address_of_cmp_0x32>
```
You should see a byte containing `0x32`.
##### Step 4: Find the Angle Values for Case '2'
Follow the `beq` target for case '2' and look for the literal pool loads:
```gdb
(gdb) x/wx <literal_pool_for_case2_angle1>
(gdb) x/wx <literal_pool_for_case2_angle2>
```
Case '2' loads `0x43340000` (180.0f) first, then `0x00000000` (0.0f).
##### Step 5: Calculate the File Offsets
```
file_offset = address - 0x10000000
```
Note offsets for:
1. The `0x32` byte in the `cmp` instruction
2. Both angle literal pool entries for case '2'
##### Step 6: Encode the New Values
| Patch Target | Original | New | Purpose |
| ---------------- | ---------------- | ---------------- | ------------------------- |
| Compare byte | `32` | `33` | Match '3' instead of '2' |
| Angle 1 (180.0f) | `00 00 34 43` | `00 00 b4 42` | 90.0f center position |
| Angle 2 (0.0f) | `00 00 00 00` | `00 00 b4 42` | 90.0f center position |
##### Step 7: Patch with HxD
1. In HxD, open `C:\Users\flare-vm\Desktop\Embedded-Hacking-main\0x0020_dynamic-conditionals\build\0x0020_dynamic-conditionals.bin`
2. Press **Ctrl+G** and go to the compare byte offset
3. Change `32` to `33`
4. Go to the first angle offset for case '2' and replace `00 00 34 43` with `00 00 b4 42`
5. Go to the second angle offset for case '2' and replace `00 00 00 00` with `00 00 b4 42`
###### Question 1: Why do we set both angle values to 90.0f instead of just one?
##### Step 8: Save and Convert
1. Click **File****Save As**`0x0020_dynamic-conditionals-h.bin`
```powershell
cd C:\Users\flare-vm\Desktop\Embedded-Hacking-main\0x0020_dynamic-conditionals
python ..\uf2conv.py build\0x0020_dynamic-conditionals-h.bin --base 0x10000000 --family 0xe48bff59 --output build\hacked.uf2
```
##### Step 9: 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 '1' → servo sweeps 0° to 180° (unchanged)
- Press '3' → servo moves to **90° center** and stays
- Press '2' → now falls through to default "??" (no longer mapped)
#### Expected Output
After completing this exercise, you should be able to:
- Locate and patch comparison immediate values in ARM Thumb instructions
- Repurpose existing code paths instead of adding new ones
- Understand how `cmp` immediates are encoded in the instruction stream
- Combine multiple patches (comparison + data) for a single behavior change
#### Questions for Reflection
###### Question 1: Why is it easier to repurpose an existing command than to add a truly new third code path in the binary?
###### Question 2: The `cmp` instruction uses an 8-bit immediate field. What range of ASCII characters could you use as command keys?
###### Question 3: After your patch, pressing '2' now triggers the default "??" branch. Could you keep both '2' AND '3' working? What would that require?
###### Question 4: What would happen if you changed the comparison to `0x00`? Could a user ever trigger that command via `getchar()`?
#### Tips and Hints
- The `cmp rN, #imm8` instruction in Thumb has the immediate in the lower byte of the instruction word
- IEEE-754 for 90.0f: `0x42b40000` → little-endian `00 00 b4 42`
- Be careful not to confuse literal pool entries between case '1' and case '2' — trace the branch targets carefully
- The `getchar()` function reads one byte from UART, so any byte value 0x00-0xFF is theoretically possible