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

156 lines
5.7 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 1: Change Servo Angle Range
#### Objective
Find the IEEE-754 floating-point value `0x43340000` (180.0f) in the `0x0020_dynamic-conditionals` binary using GDB, calculate the file offset, patch it to `0x43070000` (135.0f) using a hex editor, then find and patch the `0x00000000` (0.0f) value to `0x42340000` (45.0f), and verify on hardware that the servo now sweeps from 45° to 135° instead of 0° to 180°.
#### 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 uses `servo_set_angle(0.0f)` and `servo_set_angle(180.0f)` to sweep the servo across its full range. The float values `0.0` (`0x00000000`) and `180.0` (`0x43340000`) are loaded from the literal pool into registers before the `bl servo_set_angle` calls. You will locate these values in the disassembly, find the corresponding bytes in the `.bin` file, and patch them to `45.0` (`0x42340000`) and `135.0` (`0x43070000`) so the servo sweeps a narrower 90° range centered at 90°.
#### 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 servo_set_angle Calls
Disassemble main and look for the `servo_set_angle` calls:
```gdb
(gdb) disassemble 0x10000234,+250
```
Look for instruction patterns like:
```
ldr r0, [pc, #offset] ; load float from literal pool
bl servo_set_angle
```
There will be multiple pairs — one loading `0x00000000` (0.0f) and another loading `0x43340000` (180.0f).
##### Step 3: Examine the Literal Pool Values
Once you find the `ldr r0, [pc, #offset]` instructions, examine the literal pool entries they reference:
```gdb
(gdb) x/wx <literal_pool_address_for_180>
```
You should see `0x43340000` (180.0f in IEEE-754).
```gdb
(gdb) x/wx <literal_pool_address_for_0>
```
You should see `0x00000000` (0.0f in IEEE-754).
##### Step 4: Calculate the File Offsets
```
file_offset = literal_pool_address - 0x10000000
```
Note the file offsets for both 4-byte words.
##### Step 5: Encode the New Values
**IEEE-754 Encoding:**
| Angle | IEEE-754 Hex | Little-Endian Bytes |
| ----- | -------------- | ------------------- |
| 0.0f | `0x00000000` | `00 00 00 00` |
| 45.0f | `0x42340000` | `00 00 34 42` |
| 135.0f| `0x43070000` | `00 00 07 43` |
| 180.0f| `0x43340000` | `00 00 34 43` |
##### Step 6: 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 enter the file offset for the 180.0f value
3. You should see: `00 00 34 43`
4. Replace with: `00 00 07 43` (135.0f)
5. Press **Ctrl+G** and enter the file offset for the 0.0f value
6. You should see: `00 00 00 00`
7. Replace with: `00 00 34 42` (45.0f)
###### Question 1: How many literal pool entries reference `0x43340000`? Do you need to patch all of them?
##### Step 7: 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 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 servo behavior:**
- Press '1' → servo sweeps from **45°** to **135°** (was 0° to 180°)
- Press '2' → servo sweeps from **135°** to **45°** (was 180° to 0°)
- The total sweep range should be noticeably smaller
#### Expected Output
After completing this exercise, you should be able to:
- Locate IEEE-754 floating-point values in the literal pool
- Understand the IEEE-754 single-precision encoding format
- Patch floating-point angle constants in embedded firmware
- Calculate file offsets from memory addresses
#### Questions for Reflection
###### Question 1: The value `180.0f` is encoded as `0x43340000` in IEEE-754. Break this down: what are the sign bit, exponent, and mantissa fields?
###### Question 2: Why is `0.0f` stored as `0x00000000` and not some other pattern? What makes zero special in IEEE-754?
###### Question 3: If you wanted to set the servo to exactly 90° (center), what IEEE-754 hex value would you use? Show the calculation.
###### Question 4: Could the compiler optimize `0.0f` differently — for example, using `movs r0, #0` instead of a literal pool load? How would that affect your patching strategy?
#### Tips and Hints
- IEEE-754 for 90.0f: sign=0, exponent=127+6=133=0x85, mantissa=0x340000 → `0x42b40000`
- There may be multiple references to `0x43340000` in the literal pool — the case '1' and case '2' branches each load both angles
- Be careful with `0x00000000` — make sure you are patching a float literal pool entry and not zeroed data
- Use `x/4wx <address>` in GDB to view several literal pool words at once