# 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

### Exercise 4: Speed Profile

#### Objective
Find both `sleep_ms(500)` calls in the `0x0020_dynamic-conditionals` binary using GDB, identify the literal pool values `0x1f4` (500) loaded into `r0` before each `bl sleep_ms`, calculate the file offsets, and patch case '1' to use `0x64` (100ms) for fast movement and case '2' to use `0x3e8` (1000ms) for slow movement, then verify on hardware that the two keys produce visibly different servo speeds.

#### 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
Both case '1' and case '2' call `sleep_ms(500)` between their two `servo_set_angle` calls. The value `500` (`0x1F4`) is loaded from the literal pool into `r0` before each `bl sleep_ms`. You will find both `sleep_ms` literal pool entries — one in case '1' and one in case '2' — and patch them to different values: `100` (`0x64`) for fast snapping and `1000` (`0x3E8`) for slow sweeping, creating distinct speed profiles per key.

#### 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 Both sleep_ms Calls

Disassemble main and locate the `sleep_ms` calls:

```gdb
(gdb) disassemble 0x10000234,+250
```

Look for the pattern repeated in both cases:

```
ldr  r0, [pc, #offset]     ; load delay value
bl   sleep_ms
```

Each case has at least one `sleep_ms` call. Identify which belongs to case '1' and which to case '2' by tracing the branch targets.

##### Step 3: Examine the Literal Pool Entries

For each `sleep_ms` call, examine the referenced literal pool entry:

```gdb
(gdb) x/wx <case1_sleep_literal>
(gdb) x/wx <case2_sleep_literal>
```

Both should show `0x000001f4` (500).

##### Step 4: Calculate the File Offsets

```
file_offset = literal_pool_address - 0x10000000
```

Note the file offsets for both 4-byte sleep values.

##### Step 5: Encode the New Values

| Case   | Original          | New               | Speed    |
| ------ | ----------------- | ----------------- | -------- |
| Case 1 | `F4 01 00 00` (500ms)  | `64 00 00 00` (100ms) | Fast snap |
| Case 2 | `F4 01 00 00` (500ms)  | `E8 03 00 00` (1000ms) | Slow sweep |

###### Question 1: Each case calls `sleep_ms` twice (once between the first and second `servo_set_angle`). Do both share the same literal pool entry, or does each have its own?

##### 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 go to the case '1' sleep value offset
3. Replace `F4 01 00 00` with `64 00 00 00` (100ms)
4. Press **Ctrl+G** and go to the case '2' sleep value offset
5. Replace `F4 01 00 00` with `E8 03 00 00` (1000ms)

##### 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 behavior:**
- Press '1' → servo snaps **fast** (100ms between angles) — almost instant jump
- Press '2' → servo moves **slow** (1000ms between angles) — takes a full second at each position
- The speed difference should be very obvious visually and audibly

#### Expected Output

After completing this exercise, you should be able to:
- Distinguish between multiple literal pool entries for the same value
- Trace which code path references which literal pool entry
- Patch timing constants independently per branch
- Understand how sleep duration affects perceived motor behavior

#### Questions for Reflection

###### Question 1: Why does 100ms make the servo appear to "snap" while 1000ms makes it appear to "sweep"? Is the servo actually moving faster, or is it about the pause between commands?

###### Question 2: If the compiler uses a single shared literal pool entry for all `sleep_ms(500)` calls, what alternative patching strategy would you need to create different speeds per case?

###### Question 3: What is the minimum `sleep_ms` value that would still allow the servo to physically reach its target angle before the next command? How would you determine this experimentally?

###### Question 4: Could you set the sleep to `0` (`00 00 00 00`)? What would happen to the servo behavior?

#### Tips and Hints
- `100` decimal = `0x64`, fits in one byte: `64 00 00 00` in little-endian
- `1000` decimal = `0x3E8`: `E8 03 00 00` in little-endian
- If both `sleep_ms` calls share one literal pool word, you cannot give them different values by patching data alone — you would need to patch one `ldr` instruction to point to a different pool entry or use a `movs` immediate
- The SG90 servo takes about 200-300ms to traverse its full range, so 100ms will cause it to not quite reach the endpoint before the next command fires
