# 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 4: Find All printf Format Strings #### Objective Systematically search through the `0x001a_operators` binary using GDB and a hex editor to locate every `printf` format string, catalog their addresses, file offsets, contents, and purposes, and gain experience identifying data structures in compiled binaries. #### Prerequisites - Completed Week 9 tutorial (GDB section) - `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) #### Task Description The `0x001a_operators` program contains multiple `printf` calls, each with a format string like `"arithmetic_operator: %d\r\n"`. These strings are stored in the `.rodata` section of flash memory. You will use GDB to trace each `printf` call to its format string argument, then verify the strings in HxD. You will also search for strings that are NOT directly referenced by `printf` (like the `"DHT11 read failed"` error message). This exercise builds your ability to map out all human-readable data in a binary. #### 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: Disassemble Main to Find printf Calls ```gdb (gdb) x/60i 0x10000234 ``` Look for repeated patterns of: ``` ldr r0, [pc, #offset] ; Load format string address movs r1, #value ; Load the value to print bl printf ; Call printf ``` Each `ldr r0` before a `bl printf` loads the format string address from the literal pool. ##### Step 3: Examine the Literal Pool Find the literal pool after the loop branch (typically after the `b.n` instruction). Examine the word values: ```gdb (gdb) x/10wx ``` Each word that falls in the `0x10003xxx` range is likely a pointer to a string in `.rodata`. ##### Step 4: Read Each Format String For each address found in the literal pool, use `x/s` to read the string: ```gdb (gdb) x/s ``` Document each one. You should find at least these format strings: - `"arithmetic_operator: %d\r\n"` - `"increment_operator: %d\r\n"` - `"relational_operator: %d\r\n"` - `"logical_operator: %d\r\n"` - `"bitwise_operator: %d\r\n"` - `"assignment_operator: %d\r\n"` - `"Humidity: %.1f%%, Temperature: %.1f°C\r\n"` - `"DHT11 read failed"` ##### Step 5: Build a String Catalog Fill in a table like this (addresses will vary — use the ones you find): | Address | File Offset | String Content | Used By | | -------------- | ----------- | --------------------------------------- | ----------- | | `0x10003xxx` | `0x3xxx` | `"arithmetic_operator: %d\r\n"` | printf #1 | | `0x10003xxx` | `0x3xxx` | `"increment_operator: %d\r\n"` | printf #2 | | `0x10003xxx` | `0x3xxx` | `"relational_operator: %d\r\n"` | printf #3 | | `0x10003xxx` | `0x3xxx` | `"logical_operator: %d\r\n"` | printf #4 | | `0x10003xxx` | `0x3xxx` | `"bitwise_operator: %d\r\n"` | printf #5 | | `0x10003xxx` | `0x3xxx` | `"assignment_operator: %d\r\n"` | printf #6 | | `0x10003xxx` | `0x3xxx` | `"Humidity: %.1f%%, Temperature: %.1f°C\r\n"` | printf #7 | | `0x10003xxx` | `0x3xxx` | `"DHT11 read failed"` | puts | ##### Step 6: Verify in HxD 1. In HxD, open `C:\Users\flare-vm\Desktop\Embedded-Hacking-main\0x001a_operators\build\0x001a_operators.bin` 2. For each string, press **Ctrl+G** and enter the file offset 3. Verify you can read the ASCII text in the right panel 4. Note how the strings are stored consecutively in memory, each terminated by `0x00` ##### Step 7: Search for Hidden Strings Scroll through the `.rodata` region in HxD (typically starting around offset `0x3000`+) and look for any ASCII text in the right panel that you didn't find via `printf` calls. Library functions may have their own strings. #### Expected Output After completing this exercise, you should be able to: - Trace `printf` calls to their format string arguments using GDB - Read string addresses from literal pools - Build a complete catalog of strings in a binary - Navigate to specific offsets in a hex editor to verify string data #### Questions for Reflection ###### Question 1: The format string `"Humidity: %.1f%%, Temperature: %.1f°C\r\n"` uses `%%` to print a literal percent sign. What would happen if you patched one of the `%` characters to a space (`0x20`)? ###### Question 2: If you patched the string `"arithmetic_operator: %d\r\n"` to `"HACKED_OPERATOR!: %d\r\n"` (same length, 27 characters + null), what would the serial output show? Would the actual computed value change? ###### Question 3: The strings are stored consecutively in `.rodata`. If you made `"arithmetic_operator: %d\r\n"` one byte longer, which string would be corrupted and how? ###### Question 4: Why does the compiler use `puts` instead of `printf` for `"DHT11 read failed"`? What's the difference between the two functions for strings with no format specifiers? #### Tips and Hints - Format strings always start with a printable ASCII character — look for bytes in the `0x20`-`0x7E` range - The `\r\n` at the end of format strings shows up as bytes `0x0D 0x0A` - Use HxD's **Search** → **Find** (Ctrl+F) with "Text string" mode to search for known text like "arithmetic" - Strings in `.rodata` are typically 4-byte aligned, so there may be padding bytes (`0x00`) between them - The `°` character in "°C" is a multi-byte UTF-8 sequence (`0xC2 0xB0`), not a single byte