# 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 ### Non-Credit Practice 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 ``` 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