mirror of
https://github.com/mytechnotalent/Embedded-Hacking.git
synced 2026-05-18 22:08:08 +02:00
156 lines
5.7 KiB
Markdown
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
|