mirror of
https://github.com/mytechnotalent/Embedded-Hacking.git
synced 2026-07-15 08:27:25 +02:00
Added WEEK06 and WEEK07
This commit is contained in:
@@ -0,0 +1,188 @@
|
||||
# Embedded Systems Reverse Engineering
|
||||
[Repository](https://github.com/mytechnotalent/Embedded-Hacking)
|
||||
|
||||
## Week 6
|
||||
Static Variables in Embedded Systems: Debugging and Hacking Static Variables w/ GPIO Input Basics
|
||||
|
||||
### Exercise 4: Invert the Button Logic with XOR
|
||||
|
||||
#### Objective
|
||||
Find the `eor r3, r3, #0x1` instruction that implements the ternary operator's button inversion, patch it to `eor r3, r3, #0x0` using a hex editor to reverse the LED behavior, and verify that the LED is now ON when the button is pressed and OFF when released — the opposite of the original behavior.
|
||||
|
||||
#### Prerequisites
|
||||
- Completed Week 6 tutorial (all GDB and hex editor sections)
|
||||
- `0x0014_static-variables.bin` binary 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 button on GP15 and LED on GP16
|
||||
|
||||
#### Task Description
|
||||
The original program uses `gpio_put(LED_GPIO, !gpio_get(BUTTON_GPIO))` which the compiler implements as an XOR (`eor r3, r3, #0x1`) to invert the button state. With the pull-up resistor, button released = HIGH, so `HIGH XOR 1 = 0` (LED off). You will patch the XOR operand from `#0x1` to `#0x0`, which effectively removes the inversion: `HIGH XOR 0 = 1` (LED on when released). This exercise demonstrates how a single-byte binary patch can completely reverse hardware behavior.
|
||||
|
||||
#### Step-by-Step Instructions
|
||||
|
||||
##### Step 1: Start the Debug Session
|
||||
|
||||
**Terminal 1 - Start OpenOCD:**
|
||||
|
||||
```bash
|
||||
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:**
|
||||
|
||||
```bash
|
||||
arm-none-eabi-gdb build/0x0014_static-variables.elf
|
||||
```
|
||||
|
||||
**Connect to target:**
|
||||
|
||||
```gdb
|
||||
(gdb) target remote :3333
|
||||
(gdb) monitor reset halt
|
||||
```
|
||||
|
||||
##### Step 2: Locate the GPIO Logic
|
||||
|
||||
From the tutorial, the GPIO input/output logic is near address `0x10000274`. Disassemble:
|
||||
|
||||
```gdb
|
||||
(gdb) x/10i 0x10000274
|
||||
```
|
||||
|
||||
Look for this sequence:
|
||||
|
||||
```
|
||||
mov.w r1, #0xd0000000 ; SIO base address
|
||||
ldr r3, [r1, #offset] ; Read GPIO input register
|
||||
ubfx r3, r3, #0xf, #0x1 ; Extract bit 15 (button state)
|
||||
eor r3, r3, #0x1 ; XOR with 1 — INVERT ← OUR TARGET
|
||||
mcrr p0, 0x4, r2, r3, cr0 ; Write to GPIO output
|
||||
```
|
||||
|
||||
Note the exact address of the `eor r3, r3, #0x1` instruction.
|
||||
|
||||
##### Step 3: Understand the Current Logic
|
||||
|
||||
Trace the logic with the pull-up resistor:
|
||||
|
||||
| Button State | GPIO 15 Input | After UBFX | After EOR #1 | LED (GPIO 16) |
|
||||
| ------------ | ------------- | ---------- | ------------ | -------------- |
|
||||
| Released | 1 (HIGH) | 1 | 0 | OFF |
|
||||
| Pressed | 0 (LOW) | 0 | 1 | ON |
|
||||
|
||||
The `eor #0x1` flips the bit, implementing the `!` (NOT) from the C code.
|
||||
|
||||
##### Step 4: Verify with GDB
|
||||
|
||||
Set a breakpoint at the `eor` instruction:
|
||||
|
||||
```gdb
|
||||
(gdb) b *<address_of_eor>
|
||||
(gdb) c
|
||||
```
|
||||
|
||||
When it hits, check what value is about to be XORed:
|
||||
|
||||
```gdb
|
||||
(gdb) info registers r3
|
||||
```
|
||||
|
||||
- If button is **released**: `r3 = 1` → after EOR: `r3 = 0`
|
||||
- If button is **pressed**: `r3 = 0` → after EOR: `r3 = 1`
|
||||
|
||||
##### Step 5: Test the Patch in GDB
|
||||
|
||||
Modify the EOR operand in RAM to see the effect live:
|
||||
|
||||
```gdb
|
||||
(gdb) set $r3 = 0
|
||||
(gdb) si
|
||||
(gdb) info registers r3
|
||||
```
|
||||
|
||||
Or skip the EOR entirely by advancing the PC past it, then observe the LED behavior.
|
||||
|
||||
##### Step 6: Examine the Instruction Encoding
|
||||
|
||||
Look at the raw bytes:
|
||||
|
||||
```gdb
|
||||
(gdb) x/4bx <address_of_eor>
|
||||
```
|
||||
|
||||
The `eor` instruction in Thumb-2 (32-bit encoding) will contain the immediate value `0x01`. Study the bytes carefully — the immediate operand is encoded within the instruction word.
|
||||
|
||||
##### Step 7: Patch with the Hex Editor
|
||||
|
||||
1. Open `0x0014_static-variables.bin` in HxD
|
||||
2. Calculate the file offset: `address - 0x10000000`
|
||||
3. Press **Ctrl+G** and enter the offset
|
||||
4. Locate the byte that encodes the `#0x1` immediate value
|
||||
5. Change `01` to `00`
|
||||
6. Verify the surrounding bytes are unchanged
|
||||
7. Click **File** → **Save As** → `0x0014_static-variables-h.bin`
|
||||
|
||||
> 🔍 **Thumb-2 encoding note:** The `eor` instruction is 4 bytes (32-bit Thumb-2). The immediate value may not be in the most obvious position — it is typically encoded in bit fields spread across the instruction. Look for the `01` byte within the 4-byte sequence.
|
||||
|
||||
##### Step 8: Predict the New Behavior
|
||||
|
||||
After patching, the logic changes:
|
||||
|
||||
| Button State | GPIO 15 Input | After UBFX | After EOR #0 | LED (GPIO 16) |
|
||||
| ------------ | ------------- | ---------- | ------------ | -------------- |
|
||||
| Released | 1 (HIGH) | 1 | 1 | **ON** |
|
||||
| Pressed | 0 (LOW) | 0 | 0 | **OFF** |
|
||||
|
||||
The LED behavior is now **inverted** from the original!
|
||||
|
||||
##### Step 9: Convert to UF2 and Flash
|
||||
|
||||
```bash
|
||||
python ../uf2conv.py build/0x0014_static-variables-h.bin --base 0x10000000 --family 0xe48bff59 --output build/hacked.uf2
|
||||
```
|
||||
|
||||
1. Hold BOOTSEL and plug in your Pico 2
|
||||
2. Drag and drop `hacked.uf2` onto the RPI-RP2 drive
|
||||
|
||||
##### Step 10: Verify the Hack
|
||||
|
||||
Test the button:
|
||||
- **Button NOT pressed**: LED should now be **ON** (was OFF before patching)
|
||||
- **Button PRESSED**: LED should now be **OFF** (was ON before patching)
|
||||
|
||||
The LED behavior is completely reversed by changing a single byte!
|
||||
|
||||
#### Expected Output
|
||||
|
||||
After completing this exercise, you should be able to:
|
||||
- Locate XOR / EOR instructions in disassembled GPIO logic
|
||||
- Understand how XOR implements logical NOT for single-bit values
|
||||
- Patch a Thumb-2 encoded immediate operand
|
||||
- Predict hardware behavior changes from binary patches
|
||||
|
||||
#### Questions for Reflection
|
||||
|
||||
###### Question 1: Why does XOR with 1 act as a NOT for single-bit values? Write out the truth table for `x XOR 1` and `x XOR 0` where x is 0 or 1.
|
||||
|
||||
###### Question 2: Instead of changing `eor r3, r3, #0x1` to `eor r3, r3, #0x0`, could you achieve the same result by NOPing (removing) the instruction entirely? What bytes encode a NOP in Thumb?
|
||||
|
||||
###### Question 3: The pull-up resistor means "pressed = LOW." If you removed the pull-up (changed `gpio_pull_up` to no pull), would the button still work? Why or why not?
|
||||
|
||||
###### Question 4: The `ubfx r3, r3, #0xf, #0x1` instruction extracts bit 15. If you changed `#0xf` to `#0x10` (bit 16), what GPIO pin would you be reading? What value would you get if nothing is connected to that pin?
|
||||
|
||||
#### Tips and Hints
|
||||
- `eor r3, r3, #0x1` is a 32-bit Thumb-2 instruction (4 bytes), not a 16-bit Thumb instruction
|
||||
- A Thumb NOP is `00 bf` (2 bytes) — you would need two NOPs to replace a 4-byte instruction
|
||||
- Use GDB `x/1tw` to view a word in binary format, making bit manipulation easier to see
|
||||
- The SIO base address `0xd0000000` provides single-cycle access to GPIO — it's separate from the IO_BANK0 registers at `0x40028000`
|
||||
|
||||
#### Next Steps
|
||||
- Review all four exercises and verify you can patch any part of the binary: data values, arithmetic operations, and logic operations
|
||||
- Try combining multiple hacks in a single binary: change the initial value, speed up the overflow, AND invert the button logic
|
||||
- Compare your patched binary with the original using `fc /b original.bin patched.bin` in the command prompt to see all changed bytes
|
||||
Reference in New Issue
Block a user