mirror of
https://github.com/mytechnotalent/Embedded-Hacking.git
synced 2026-08-31 07:10:55 +02:00
Overhall w/ slides
This commit is contained in:
@@ -0,0 +1,141 @@
|
||||
# Embedded Systems Reverse Engineering
|
||||
[Repository](https://github.com/mytechnotalent/Embedded-Hacking)
|
||||
|
||||
## Week 9
|
||||
Operators in Embedded Systems: Debugging and Hacking Operators w/ DHT11 Temperature & Humidity Sensor Single-Wire Protocol Basics
|
||||
|
||||
### Exercise 1: Change the Sleep Duration
|
||||
|
||||
#### Objective
|
||||
Find the `sleep_ms(2000)` call in the `0x001a_operators` binary using GDB, identify the immediate value `0x7d0` (2000) being loaded into `r0`, calculate the file offset, patch it to `0x1388` (5000) using a hex editor, and verify on hardware that the serial output now prints every 5 seconds instead of every 2 seconds.
|
||||
|
||||
#### Prerequisites
|
||||
- Completed Week 9 tutorial (GDB and hex editor sections)
|
||||
- `0x001a_operators.elf` and `0x001a_operators.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 DHT11 sensor connected
|
||||
|
||||
#### Task Description
|
||||
The program calls `sleep_ms(2000)` at the end of its main loop, causing a 2-second delay between each set of serial output. The value `2000` (`0x7D0`) is loaded into register `r0` before the `bl sleep_ms` call. You will locate this value in the disassembly, find the corresponding bytes in the `.bin` file, and patch them to `5000` (`0x1388`) so the loop runs every 5 seconds instead.
|
||||
|
||||
#### 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\0x001a_operators.elf
|
||||
```
|
||||
|
||||
**Connect to target:**
|
||||
|
||||
```gdb
|
||||
(gdb) target remote :3333
|
||||
(gdb) monitor reset halt
|
||||
```
|
||||
|
||||
##### Step 2: Find the sleep_ms Call
|
||||
|
||||
Disassemble main and look for the `sleep_ms` call:
|
||||
|
||||
```gdb
|
||||
(gdb) x/60i 0x10000234
|
||||
```
|
||||
|
||||
Look for an instruction pattern like:
|
||||
|
||||
```
|
||||
ldr r0, =0x7d0 ; 2000 milliseconds
|
||||
bl sleep_ms
|
||||
```
|
||||
|
||||
The value `0x7d0` will be loaded from the literal pool.
|
||||
|
||||
##### Step 3: Examine the Literal Pool Value
|
||||
|
||||
Once you find the `ldr r0, [pc, #offset]` instruction, examine the literal pool entry it references:
|
||||
|
||||
```gdb
|
||||
(gdb) x/wx <literal_pool_address>
|
||||
```
|
||||
|
||||
You should see `0x000007d0` (2000 in hex).
|
||||
|
||||
##### Step 4: Calculate the File Offset
|
||||
|
||||
```
|
||||
file_offset = literal_pool_address - 0x10000000
|
||||
```
|
||||
|
||||
Note the file offset of the 4-byte word containing `0x7d0`.
|
||||
|
||||
##### Step 5: Encode the New Value
|
||||
|
||||
The new value `5000` in hex is `0x1388`. In little-endian byte order:
|
||||
|
||||
| Value | Hex | Little-Endian Bytes |
|
||||
| ----- | ---------- | ------------------- |
|
||||
| 2000 | `0x000007D0` | `D0 07 00 00` |
|
||||
| 5000 | `0x00001388` | `88 13 00 00` |
|
||||
|
||||
##### Step 6: Patch with HxD
|
||||
|
||||
1. In HxD, open `C:\Users\flare-vm\Desktop\Embedded-Hacking-main\0x001a_operators\build\0x001a_operators.bin`
|
||||
2. Press **Ctrl+G** and enter the file offset you calculated
|
||||
3. You should see: `D0 07 00 00`
|
||||
4. Replace with: `88 13 00 00`
|
||||
|
||||
##### Step 7: Save and Convert
|
||||
|
||||
1. Click **File** → **Save As** → `0x001a_operators-h.bin`
|
||||
|
||||
```powershell
|
||||
cd C:\Users\flare-vm\Desktop\Embedded-Hacking-main\0x001a_operators
|
||||
python ..\uf2conv.py build\0x001a_operators-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 serial monitor:**
|
||||
- Output should now appear every **5 seconds** instead of every 2 seconds
|
||||
- All operator values should remain unchanged (50, 5, 0, 0, 12, 11)
|
||||
|
||||
#### Expected Output
|
||||
|
||||
After completing this exercise, you should be able to:
|
||||
- Locate literal pool values referenced by `ldr` instructions
|
||||
- Understand little-endian byte ordering for 32-bit values
|
||||
- Patch timing constants in embedded firmware
|
||||
- Calculate file offsets from memory addresses
|
||||
|
||||
#### Questions for Reflection
|
||||
|
||||
###### Question 1: The value `2000` is stored in the literal pool as a 32-bit word, not as an immediate in the instruction. Why can't `2000` be encoded as an immediate in a single `movs` instruction?
|
||||
|
||||
###### Question 2: If you wanted to change the delay to exactly 1 second (1000ms = `0x3E8`), what bytes would you write in little-endian order?
|
||||
|
||||
###### Question 3: The literal pool value is shared — could other code in the binary also reference this same `0x7D0` value? How would you check?
|
||||
|
||||
###### Question 4: What would happen if you changed the sleep value to `0` (`00 00 00 00`)? Would the program crash or just run extremely fast?
|
||||
|
||||
#### Tips and Hints
|
||||
- `movs` can only encode immediates 0-255; values larger than 255 must be loaded from the literal pool via `ldr`
|
||||
- Always verify the bytes BEFORE patching — make sure you see `D0 07 00 00` at your calculated offset
|
||||
- The literal pool is typically right after the function's `b.n` (loop branch) instruction
|
||||
- Use a stopwatch or count "one-one-thousand" to verify the timing change
|
||||
Reference in New Issue
Block a user