mirror of
https://github.com/mytechnotalent/Embedded-Hacking.git
synced 2026-06-07 23:03:59 +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
|
||||
@@ -0,0 +1,136 @@
|
||||
# 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 2: Invert the Temperature Reading
|
||||
|
||||
#### Objective
|
||||
Using GDB to locate the IEEE-754 scaling constant `0.1f` at file offset `0x42C`, patch it to `-0.1f` using a hex editor, and verify on hardware that the serial output now displays negative temperature values.
|
||||
|
||||
#### Prerequisites
|
||||
- Completed Week 9 tutorial (GDB, Ghidra, 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 DHT11 driver uses a scaling constant of `0.1f` stored at address `0x1000042C` (file offset `0x42C`) to convert raw sensor data into human-readable values. By changing this constant to `-0.1f`, you will invert the decimal component of the temperature calculation, causing the reported temperature to drop. This exercise teaches IEEE-754 float encoding and how a single 4-byte patch can dramatically change sensor behavior.
|
||||
|
||||
#### 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: Verify the Current Scaling Constant
|
||||
|
||||
Examine the float constant at the known address:
|
||||
|
||||
```gdb
|
||||
(gdb) x/wx 0x1000042c
|
||||
```
|
||||
|
||||
Output:
|
||||
```
|
||||
0x1000042c: 0x3dcccccd
|
||||
```
|
||||
|
||||
This is `0.1f` in IEEE-754 encoding (approximately — the repeating binary fraction makes it `0x3dcccccd`).
|
||||
|
||||
##### Step 3: Understand the IEEE-754 Encoding
|
||||
|
||||
**Current value (0.1f):**
|
||||
|
||||
| Field | Bits | Value |
|
||||
| -------- | ---------- | ----- |
|
||||
| Sign | `0` | Positive |
|
||||
| Exponent | `01111011` | 123 (biased) |
|
||||
| Mantissa | `10011001100110011001101` | ~1.6 |
|
||||
|
||||
**New value (-0.1f):**
|
||||
- Flip only the sign bit (bit 31) from `0` to `1`
|
||||
- `0x3dcccccd` → `0xbdcccccd`
|
||||
|
||||
| Value | Hex | Little-Endian Bytes |
|
||||
| ------ | ------------ | ------------------- |
|
||||
| 0.1f | `0x3dcccccd` | `cd cc cc 3d` |
|
||||
| -0.1f | `0xbdcccccd` | `cd cc cc bd` |
|
||||
|
||||
> 💡 **Key insight:** To negate an IEEE-754 float, you only need to flip the most significant bit. In little-endian, this is the **last** byte — change `3d` to `bd`.
|
||||
|
||||
##### Step 4: 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 offset: `42C`
|
||||
3. You should see: `cd cc cc 3d` (or `cc cc cc 3d`)
|
||||
4. Replace with: `cd cc cc bd` (or `cc cc cc bd`)
|
||||
|
||||
> ⚠️ **Note:** The exact bytes may be `cc cc cc 3d` or `cd cc cc 3d` depending on compiler rounding. Just change the last byte from `3d` to `bd`.
|
||||
|
||||
##### Step 5: 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 6: 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:**
|
||||
- All operator values remain unchanged (50, 5, 0, 0, 12, 11)
|
||||
- Temperature should now display with an inverted decimal component
|
||||
- Humidity will also be affected (same constant is shared)
|
||||
|
||||
#### Expected Output
|
||||
|
||||
After completing this exercise, you should be able to:
|
||||
- Decode and encode IEEE-754 floating-point values
|
||||
- Understand that flipping one bit (sign bit) negates a float
|
||||
- Patch floating-point constants in compiled binaries
|
||||
- Predict how a constant change propagates through calculations
|
||||
|
||||
#### Questions for Reflection
|
||||
|
||||
###### Question 1: Why does changing one byte (`3d` → `bd`) negate the entire float value? What does the sign bit (bit 31) control in IEEE-754?
|
||||
|
||||
###### Question 2: The scaling constant `0.1f` is used by BOTH the humidity and temperature `vfma.f32` instructions. Why does patching this single constant affect both readings?
|
||||
|
||||
###### Question 3: If you wanted to change the constant to `0.5f` (`0x3f000000`, little-endian `00 00 00 3f`) instead of `-0.1f`, how would the temperature reading change? If the raw decimal part is 8, what would the new output be?
|
||||
|
||||
###### Question 4: Could you achieve negative temperature by patching the `vfma.f32` instruction itself instead of the constant? What instruction might you replace it with?
|
||||
|
||||
#### Tips and Hints
|
||||
- IEEE-754 sign bit is the MSB (bit 31) — `0` = positive, `1` = negative
|
||||
- In little-endian, the sign bit is in the **last** (highest address) byte
|
||||
- Use an online IEEE-754 converter to verify your understanding
|
||||
- If the output looks completely wrong (NaN, inf), you may have changed the wrong byte — start over with a fresh copy of the `.bin` file
|
||||
@@ -0,0 +1,152 @@
|
||||
# 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 3: Add a Fixed Temperature Offset
|
||||
|
||||
#### Objective
|
||||
Patch both the `vfma.f32` instruction at file offset `0x414` and the scaling constant at `0x42C` to replace the multiply-add with a simple add of `10.0f`, causing every temperature reading to be increased by exactly 10°C, and verify on hardware.
|
||||
|
||||
#### Prerequisites
|
||||
- Completed Week 9 tutorial and Exercise 2
|
||||
- `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 temperature calculation uses `vfma.f32 s15, s13, s11` which computes `s15 = s15 + (s13 × s11)` where `s11 = 0.1f`. You will make TWO patches: (1) change the `vfma.f32` instruction to `vadd.f32` so it performs addition instead of multiply-add, and (2) change the constant from `0.1f` to `10.0f`. The result: every temperature reading will have 10°C added to it. This exercise teaches ARM floating-point instruction encoding and multi-site patching.
|
||||
|
||||
#### 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: Verify the Current Instructions
|
||||
|
||||
Examine the floating-point instructions near the temperature calculation:
|
||||
|
||||
```gdb
|
||||
(gdb) x/4bx 0x10000414
|
||||
```
|
||||
|
||||
Output:
|
||||
```
|
||||
0x10000414: 0xe6 0xee 0xa5 0x7a
|
||||
```
|
||||
|
||||
This is `vfma.f32 s15, s13, s11` — the temperature fused multiply-add.
|
||||
|
||||
##### Step 3: Verify the Current Constant
|
||||
|
||||
```gdb
|
||||
(gdb) x/wx 0x1000042c
|
||||
```
|
||||
|
||||
Output:
|
||||
```
|
||||
0x1000042c: 0x3dcccccd
|
||||
```
|
||||
|
||||
This is `0.1f`.
|
||||
|
||||
##### Step 4: Understand the Two Patches
|
||||
|
||||
**Patch 1 — Instruction at offset `0x414`:**
|
||||
|
||||
| Original | Bytes (LE) | New | Bytes (LE) |
|
||||
| --------------------------- | --------------- | --------------------------- | --------------- |
|
||||
| `vfma.f32 s15, s13, s11` | `e6 ee a5 7a` | `vadd.f32 s15, s15, s11` | `b4 ee a5 7a` |
|
||||
|
||||
> 🔍 Only the first two bytes change: `e6 ee` → `b4 ee`. The operand bytes `a5 7a` stay the same.
|
||||
|
||||
**Patch 2 — Constant at offset `0x42C`:**
|
||||
|
||||
| Original | Hex | LE Bytes | New | Hex | LE Bytes |
|
||||
| -------- | ------------ | --------------- | ----- | ------------ | --------------- |
|
||||
| 0.1f | `0x3dcccccd` | `cd cc cc 3d` | 10.0f | `0x41200000` | `00 00 20 41` |
|
||||
|
||||
##### Step 5: Patch the Instruction 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 offset: `414`
|
||||
3. You should see: `e6 ee a5 7a`
|
||||
4. Change the first two bytes: `e6 ee` → `b4 ee`
|
||||
5. Result should be: `b4 ee a5 7a`
|
||||
|
||||
##### Step 6: Patch the Constant with HxD
|
||||
|
||||
1. Press **Ctrl+G** and enter offset: `42C`
|
||||
2. You should see: `cd cc cc 3d` (or `cc cc cc 3d`)
|
||||
3. Replace all 4 bytes with: `00 00 20 41`
|
||||
|
||||
##### 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:**
|
||||
- All operator values remain unchanged (50, 5, 0, 0, 12, 11)
|
||||
- Temperature should now read approximately **10°C higher** than the real temperature
|
||||
- Humidity will also be affected (the constant is shared)
|
||||
|
||||
> ⚠️ **Note:** Since the constant at `0x42C` is shared between the humidity `vfma.f32` at `0x410` and the temperature one at `0x414`, changing it to `10.0f` will also affect humidity. The humidity instruction still uses `vfma` (multiply-add), so it will compute `humidity_int + (decimal × 10.0)` — producing very large humidity values.
|
||||
|
||||
#### Expected Output
|
||||
|
||||
After completing this exercise, you should be able to:
|
||||
- Distinguish between `vfma.f32` (multiply-add) and `vadd.f32` (add) encodings
|
||||
- Perform multi-site patches in a single binary
|
||||
- Understand how shared constants affect multiple code paths
|
||||
- Predict the side effects of patching shared data
|
||||
|
||||
#### Questions for Reflection
|
||||
|
||||
###### Question 1: Why did we need to change BOTH the instruction AND the constant? What would happen if you only changed the constant to `10.0f` but left the `vfma.f32` instruction unchanged?
|
||||
|
||||
###### Question 2: The humidity `vfma.f32` at offset `0x410` was NOT changed to `vadd`. With the constant now set to `10.0f`, what formula does the humidity instruction compute? If the raw humidity integer is 51 and decimal is 0, what value would it display?
|
||||
|
||||
###### Question 3: If you wanted to add 10°C to temperature WITHOUT affecting humidity, you would need to change both instructions. What bytes would you write at offset `0x410` to change the humidity `vfma` to `vadd` as well, and what constant would preserve the original humidity calculation?
|
||||
|
||||
###### Question 4: The `vadd.f32 s15, s15, s11` encoding is `b4 ee a5 7a`. In the original `vfma.f32 s15, s13, s11` (`e6 ee a5 7a`), why do only the first two bytes differ? What do those bytes encode?
|
||||
|
||||
#### Tips and Hints
|
||||
- Make BOTH patches before saving — if you only patch one, the results will be wrong
|
||||
- The `vfma` → `vadd` change only affects the first two bytes of the 4-byte instruction
|
||||
- `10.0f` in IEEE-754 is `0x41200000` — memorize this common value
|
||||
- Always start with a fresh copy of the `.bin` file if you need to redo the exercise
|
||||
- Compare the original and hacked serial output side by side to verify only temperature changed as expected
|
||||
@@ -0,0 +1,140 @@
|
||||
# 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 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 <literal_pool_start>
|
||||
```
|
||||
|
||||
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 <address_from_literal_pool>
|
||||
```
|
||||
|
||||
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
|
||||
Binary file not shown.
+1213
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user