Fixed WEEK06

This commit is contained in:
Kevin Thomas
2026-03-01 20:54:11 -05:00
parent f36217539e
commit d2685b03f2
5 changed files with 299 additions and 146 deletions
+30 -25
View File
@@ -7,7 +7,7 @@ Static Variables in Embedded Systems: Debugging and Hacking Static Variables w/
### 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.
Find the `eor.w r3, r3, #1` instruction that implements the ternary operator's button inversion, patch it to `eor.w r3, r3, #0` 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)
@@ -18,7 +18,7 @@ Find the `eor r3, r3, #0x1` instruction that implements the ternary operator's b
- 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.
The original program uses `gpio_put(LED_GPIO, !gpio_get(BUTTON_GPIO))` which the compiler implements as an XOR (`eor.w r3, r3, #1`) 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 `#1` to `#0`, 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
@@ -58,14 +58,14 @@ From the tutorial, the GPIO input/output logic is near address `0x10000274`. Dis
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
0x10000274: mov.w r1, #0xd0000000 ; SIO base address
0x10000280: ldr r3, [r1, #4] ; Read GPIO input register
0x10000282: ubfx r3, r3, #15, #1 ; Extract bit 15 (button state)
0x10000286: eor.w r3, r3, #1 ; XOR with 1 — INVERT ← OUR TARGET
0x1000028a: mcrr 0, 4, r2, r3, cr0 ; Write to GPIO output
```
Note the exact address of the `eor r3, r3, #0x1` instruction.
The `eor.w r3, r3, #1` instruction is at address `0x10000286`.
##### Step 3: Understand the Current Logic
@@ -76,14 +76,14 @@ Trace the logic with the pull-up resistor:
| 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.
The `eor.w #1` flips the bit, implementing the `!` (NOT) from the C code.
##### Step 4: Verify with GDB
Set a breakpoint at the `eor` instruction:
Set a breakpoint at the `eor.w` instruction:
```gdb
(gdb) b *<address_of_eor>
(gdb) b *0x10000286
(gdb) c
```
@@ -113,22 +113,26 @@ Or skip the EOR entirely by advancing the PC past it, then observe the LED behav
Look at the raw bytes:
```gdb
(gdb) x/4bx <address_of_eor>
(gdb) x/4bx 0x10000286
0x10000286 <main+82>: 0x83 0xf0 0x01 0x03
```
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.
The `eor.w` instruction is a 32-bit Thumb-2 encoding. The 4 bytes break down as:
- `0x83 0xF0` — opcode + source register (r3)
- `0x01`**the immediate value (`#1`)** ← this is what we change
- `0x03` — destination register (r3)
##### 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`
1. In HxD, open `C:\Users\flare-vm\Desktop\Embedded-Hacking-main\0x0014_static-variables\build\0x0014_static-variables.bin`
2. The instruction starts at file offset: `0x10000286 - 0x10000000 = 0x286`
3. The immediate byte is the 3rd byte: offset `0x286 + 2 = 0x288`
4. Press **Ctrl+G** and enter offset: `288`
5. You should see `01` — change it to `00`
6. Verify the surrounding bytes (`83 F0` before and `03` after) are unchanged
7. Click **File****Save As**`0x0014_static-variables-h.bin` (in the same `build` directory)
> 🔍 **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.
> 🔍 **Why offset `0x288`?** The 4-byte instruction starts at `0x286`, but the immediate value `#1` is in the **third byte** (index 2), so it's at `0x286 + 2 = 0x288`.
##### Step 8: Predict the New Behavior
@@ -143,8 +147,9 @@ 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
```powershell
cd C:\Users\flare-vm\Desktop\Embedded-Hacking-main\0x0014_static-variables
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
@@ -170,14 +175,14 @@ After completing this exercise, you should be able to:
###### 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 2: Instead of changing `eor.w r3, r3, #1` to `eor.w r3, r3, #0`, 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
- `eor.w r3, r3, #1` 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`