4.3 KiB
Embedded Systems Reverse Engineering
Week 6
Static Variables in Embedded Systems: Debugging and Hacking Static Variables w/ GPIO Input Basics
Non-Credit Practice Exercise 4 Solution: Invert the Button Logic with XOR
Answers
Patch Details
| Item | Original | Patched |
|---|---|---|
| Instruction | eor.w r3, r3, #1 | eor.w r3, r3, #0 |
| Address | 0x10000286 | 0x10000286 |
| Hex bytes | 83 F0 01 03 | 83 F0 00 03 |
| Patched byte offset | 0x288 (3rd byte) | 01 → 00 |
Logic Table Comparison
Original (EOR #1):
| Button State | GPIO 15 | After UBFX | After EOR #1 | LED (GPIO 16) |
|---|---|---|---|---|
| Released | 1 (HIGH) | 1 | 0 | OFF |
| Pressed | 0 (LOW) | 0 | 1 | ON |
Patched (EOR #0):
| Button State | GPIO 15 | After UBFX | After EOR #0 | LED (GPIO 16) |
|---|---|---|---|---|
| Released | 1 (HIGH) | 1 | 1 | ON |
| Pressed | 0 (LOW) | 0 | 0 | OFF |
Hardware Result
- Button NOT pressed: LED ON (was OFF)
- Button PRESSED: LED OFF (was ON)
- Behavior completely reversed by changing a single byte (01 → 00)
Reflection Answers
-
Why does XOR with 1 act as a NOT for single-bit values? Write out the truth table for
x XOR 1andx XOR 0where x is 0 or 1.x x XOR 1 x XOR 0 0 1 0 1 0 1 x XOR 1always flips the bit (acts as NOT): 0→1, 1→0.x XOR 0always preserves the bit (acts as identity): 0→0, 1→1. This works because XOR returns 1 when inputs differ and 0 when they match. XOR with 1 forces a difference; XOR with 0 forces a match. This property only applies to the single affected bit—for multi-bit values, each bit is XORed independently. -
Instead of changing
eor.w r3, r3, #1toeor.w r3, r3, #0, could you achieve the same result by NOPing (removing) the instruction entirely? What bytes encode a NOP in Thumb? Yes. Removing the EOR instruction entirely would have the same effect as EOR #0—the value passes through unchanged. A Thumb NOP is encoded as00 BF(2 bytes). Sinceeor.wis a 32-bit Thumb-2 instruction (4 bytes), you would need two NOPs to replace it:00 BF 00 BF. In the hex editor, replace bytes at offset 0x286–0x289 from83 F0 01 03to00 BF 00 BF. Both approaches yield identical behavior, but the EOR #0 patch is "cleaner" because it preserves the instruction structure—making the modification more obvious during reverse engineering. -
The pull-up resistor means "pressed = LOW." If you removed the pull-up (changed
gpio_pull_upto no pull), would the button still work? Why or why not? It would be unreliable. Without a pull-up or pull-down resistor, the GPIO input is floating when the button is not pressed—there's no defined voltage on the pin. The input would pick up electrical noise, stray capacitance, and electromagnetic interference, causing random readings (0 or 1 unpredictably). When the button IS pressed, it connects to ground (LOW), which works. But when released, the pin has no path to any voltage, sogpio_get(15)returns garbage. The pull-up provides a defined HIGH state when the button circuit is open. -
The
ubfx r3, r3, #0xf, #0x1instruction extracts bit 15. If you changed#0xfto#0x10(bit 16), what GPIO pin would you be reading? What value would you get if nothing is connected to that pin? You would be reading GPIO 16, which is the LED output pin. Since GPIO 16 is configured as an output (not input), reading its input register returns the current output state—either 0 or 1 depending on whether the LED is currently on or off. This would create a feedback loop: the LED's current state determines its next state (after the XOR), causing unpredictable oscillation or a stuck state. If GPIO 16 had nothing connected and was unconfigured, the floating input would return random values, similar to Q3's scenario.