Updated DS refs

This commit is contained in:
Kevin Thomas
2026-04-15 17:23:21 -04:00
parent 6d01ea5f24
commit 38b5b1bcb5
220 changed files with 33267 additions and 0 deletions
+185
View File
@@ -0,0 +1,185 @@
# Week 7 Quiz: Constants, I²C, Structs, and String Patching
## Instructions
Choose the best answer for each question. There is only one correct answer per question.
---
## Questions
### Question 1
What is the key difference between `#define FAV_NUM 42` and `const int OTHER_FAV_NUM = 1337` in terms of how they appear in the compiled binary?
A) `#define` appears as `movs r1, #0x2a` (16-bit Thumb) and `const` appears as `movw r1, #0x539` (32-bit Thumb-2) — both are instruction immediates because the compiler optimized away the const variable
B) `#define` creates a value in the `.data` section; `const` creates a value in the `.rodata` section
C) `#define` is replaced by the preprocessor so the value appears as an immediate in instructions; `const` always creates a real variable loaded from flash via `ldr`
D) `#define` values are stored in SRAM; `const` values are stored in flash
> 📖 **Reference:** Week 7, Part 9, Step 12 "Analyze #define vs const in Assembly" (Both end up as instruction immediates: `movs r1, #0x2a` for FAV_NUM and `movw r1, #0x539` for OTHER_FAV_NUM. The compiler optimized the `const` because `&OTHER_FAV_NUM` is never taken.)
**Correct Answer: A**
---
### Question 2
I²C uses two wires for communication. What are they called and what is each used for?
A) TX (transmit data) and RX (receive data)
B) SDA (serial data) and SCL (serial clock)
C) MOSI (master out) and MISO (master in)
D) VCC (power) and GND (ground)
> 📖 **Reference:** Week 7, Part 2 "The Two I²C Wires" table (SDA = Serial Data, SCL = Serial Clock)
**Correct Answer: B**
---
### Question 3
Why do I²C bus lines require pull-up resistors?
A) To limit current and protect the devices from damage
B) I²C uses open-drain signals — devices can only pull lines LOW, so pull-ups are needed to bring lines back HIGH
C) The pull-ups provide power to the I²C slave devices
D) Pull-ups increase the data transfer speed by reducing line capacitance
> 📖 **Reference:** Week 7, Part 2 "Why Pull-Up Resistors?" (I²C uses open-drain signals; devices can only pull LOW, pull-ups bring lines back to HIGH)
**Correct Answer: B**
---
### Question 4
The `i2c1_inst` struct in SRAM at address `0x2000062c` contains two members. What are they?
A) `sda_pin` = 2 and `scl_pin` = 3 (the GPIO pin numbers)
B) `hw` = `0x40098000` (pointer to hardware registers) and `restart_on_next` = `false`
C) `address` = `0x27` (LCD I²C address) and `baud_rate` = `100000`
D) `tx_buffer` and `rx_buffer` (data transfer buffers)
> 📖 **Reference:** Week 7, Part 8, Step 9 and Part 9, Step 13 examining `i2c1_inst` at `0x2000062c` shows `0x40098000` (hw pointer) and `0x00000000` (restart_on_next = false)
**Correct Answer: B**
---
### Question 5
In the Thumb instruction `movs r1, #0x2a`, the bytes in the binary are `2A 21`. If you want to change FAV_NUM from 42 to 99, what bytes would you write?
A) `63 21` — because 99 in hex is `0x63` and the opcode `21` stays the same
B) `99 21` — because 99 in decimal is written directly
C) `21 63` — because the opcode comes first in big-endian format
D) `63 00` — because the opcode changes when the value changes
> 📖 **Reference:** Week 7, Part 10, Step 17 "How Thumb encoding works" (immediate value is the first byte, opcode `21` is the second; `movs r1, #imm8`)
**Correct Answer: A**
---
### Question 6
The `movw r1, #1337` instruction at `0x10000296` encodes the value 1337 (`0x539`) in a 32-bit Thumb-2 instruction. The raw bytes are `40 F2 39 51`. Where is the lower 8 bits of the immediate value (`0x39`) located?
A) Byte 0 (`0x40`) — the immediate is always in the first byte of the instruction
B) Byte 2 (`0x39`) — the imm8 field is in the third byte (low byte of the second halfword)
C) Byte 3 (`0x51`) — the immediate is stored in the last byte along with the register
D) The value `0x539` is stored as a separate 4-byte word in the literal pool, not in the instruction
> 📖 **Reference:** Week 7, Part 10, Step 18 "Understand the Encoding" (the `movw` encoding diagram shows Byte 2 = `0x39` = imm8 field, which holds the lower 8 bits of the immediate value)
**Correct Answer: B**
---
### Question 7
When patching the LCD string "Reverse" to "Exploit" in the binary, why must the replacement string be the same length?
A) The LCD hardware only accepts strings of exactly 7 characters
B) The replacement must fit within the allocated bytes — a longer string would overwrite adjacent data (like the "Engineering" string stored immediately after)
C) The Thumb instruction set cannot encode string addresses of different lengths
D) The Pico SDK validates string lengths at boot and rejects changes
> 📖 **Reference:** Week 7, Part 10, Step 19 "IMPORTANT: The new string must be the same length as the original!" and Key Takeaway 8
**Correct Answer: B**
---
### Question 8
The LCD string "Reverse" is located at address `0x10003ee8`. What is the correct file offset in the `.bin` file?
A) `0x3EE8` — subtract the base address `0x10000000`
B) `0x10003EE8` — the file offset is the same as the memory address
C) `0x7DD0` — multiply by 2 because the binary uses 16-bit alignment
D) `0x3EE0` — round down to the nearest 16-byte boundary
> 📖 **Reference:** Week 7, Part 10, Step 16 "Calculate the File Offset" (file_offset = address 0x10000000; `0x10003ee8` → `0x3EE8`)
**Correct Answer: A**
---
### Question 9
What does the macro chain `I2C_PORT``i2c1``&i2c1_inst``hw``0x40098000` represent?
A) The sequence of function calls during I²C initialization
B) The path from a high-level macro in your code to the physical I²C1 hardware registers, through preprocessor expansion, pointer dereference, and struct member access
C) The I²C data transmission protocol (start, address, data, stop)
D) The order in which the compiler optimizes I²C-related code
> 📖 **Reference:** Week 7, Part 4 "The Macro Chain" diagram and Part 9, Step 13 tracing the chain from code to `0x40098000`
**Correct Answer: B**
---
### Question 10
The compiler transforms `gpio_pull_up(2)` into a call to `gpio_set_pulls(2, 1, 0)`. What does each argument represent?
A) Pin number, pull-up resistance value in kΩ, pull-down resistance value in kΩ
B) Pin number, enable pull-up (true), enable pull-down (false)
C) SDA pin, SCL pin, I²C bus number
D) Pin number, direction (1 = input), initial value (0 = LOW)
> 📖 **Reference:** Week 7, Key Takeaway 10 "Compiler optimization changes code — `gpio_pull_up` becomes `gpio_set_pulls`" and Week 6 reference (inlined function: pin, up=true, down=false)
**Correct Answer: B**
---
## Answer Key
1. A - Both `#define` and `const` appear as instruction immediates (`movs` and `movw`) because the compiler optimized the `const` — its address is never taken
2. B - SDA (Serial Data) carries data; SCL (Serial Clock) provides timing
3. B - I²C open-drain signals can only pull LOW; pull-ups return lines to HIGH
4. B - `hw` = `0x40098000` (hardware register pointer) and `restart_on_next` = false
5. A - Change `2A` to `63` (99 in hex); opcode `21` (`movs r1, #imm8`) remains unchanged
6. B - The imm8 field (lower 8 bits of the immediate) is in the third byte of the 4-byte `movw` instruction
7. B - A longer string would overwrite adjacent data in the `.rodata` section
8. A - File offset = address base = `0x10003EE8` `0x10000000` = `0x3EE8`
9. B - The chain traces from a C macro through pointer indirection to physical hardware register addresses
10. B - Arguments are: GPIO pin number, pull-up enable (true), pull-down enable (false)
---
## Scoring Guide
- **10 correct**: Excellent! You have a strong grasp of Week 7 concepts
- **8-9 correct**: Very good! Review the topics you missed
- **6-7 correct**: Good start. Go back and review the key concepts
- **5 or fewer**: Review the Week 7 material again and try the practice exercises
---
## Topics Covered
This quiz tests your understanding of:
- `#define` preprocessor macros vs `const` variables: compiler optimization of const to immediates
- I²C communication protocol: SDA/SCL wires and pull-up resistor requirements
- Pico SDK `i2c_inst_t` struct layout and hardware register pointers
- Thumb instruction encoding: `movs rD, #imm8` and `movw rD, #imm16` byte layouts
- 32-bit Thumb-2 `movw` encoding: imm8 field location in the instruction
- String patching constraints: same-length rule and adjacent data corruption risk
- File offset calculation: memory address minus base address `0x10000000`
- SDK macro chain: from `I2C_PORT` to `0x40098000` hardware registers
- Compiler optimization: `gpio_pull_up` inlined as `gpio_set_pulls`
+91
View File
@@ -0,0 +1,91 @@
# Embedded Systems Reverse Engineering
[Repository](https://github.com/mytechnotalent/Embedded-Hacking)
## Week 7
Constants in Embedded Systems: Debugging and Hacking Constants w/ 1602 LCD I2C Basics
### Non-Credit Practice Exercise 1 Solution: Change Both LCD Lines
#### Answers
##### String Locations in Flash
| String | Address | File Offset | Length (bytes) | Hex Encoding |
|---------------|--------------|-------------|----------------|---------------------------------------------------|
| "Reverse" | 0x10003ee8 | 0x3EE8 | 8 (7 + null) | 52 65 76 65 72 73 65 00 |
| "Engineering" | 0x10003ef0 | 0x3EF0 | 12 (11 + null) | 45 6E 67 69 6E 65 65 72 69 6E 67 00 |
##### Line 1 Patch: "Reverse" → "Exploit"
| Character | Hex |
|-----------|--------|
| E | 0x45 |
| x | 0x78 |
| p | 0x70 |
| l | 0x6c |
| o | 0x6f |
| i | 0x69 |
| t | 0x74 |
| \0 | 0x00 |
```
Offset 0x3EE8:
Before: 52 65 76 65 72 73 65 00 ("Reverse")
After: 45 78 70 6C 6F 69 74 00 ("Exploit")
```
##### Line 2 Patch: "Engineering" → "Hacking!!!!"
| Character | Hex |
|-----------|--------|
| H | 0x48 |
| a | 0x61 |
| c | 0x63 |
| k | 0x6b |
| i | 0x69 |
| n | 0x6e |
| g | 0x67 |
| ! | 0x21 |
| ! | 0x21 |
| ! | 0x21 |
| ! | 0x21 |
| \0 | 0x00 |
```
Offset 0x3EF0:
Before: 45 6E 67 69 6E 65 65 72 69 6E 67 00 ("Engineering")
After: 48 61 63 6B 69 6E 67 21 21 21 21 00 ("Hacking!!!!")
```
##### Conversion and Flash
```powershell
cd C:\Users\flare-vm\Desktop\Embedded-Hacking-main\0x0017_constants
python ..\uf2conv.py build\0x0017_constants-h.bin --base 0x10000000 --family 0xe48bff59 --output build\hacked.uf2
```
##### LCD Verification
```
Line 1: Exploit
Line 2: Hacking!!!!
```
#### Reflection Answers
1. **Why must the replacement string be the same length (or shorter) as the original? What specific data would you corrupt if you used a longer string?**
Strings are stored consecutively in the `.rodata` section. "Reverse" occupies 8 bytes starting at `0x10003ee8` and "Engineering" starts immediately at `0x10003ef0`. If the replacement string is longer than 8 bytes, the extra bytes would overwrite the beginning of "Engineering" (or whatever data follows). The `.rodata` section has no gaps—it's a packed sequence of constants, format strings, and other read-only data. Corrupting adjacent data could break LCD line 2, crash `printf` format strings, or cause undefined behavior.
2. **The two strings are stored only 8 bytes apart (0x3EE8 to 0x3EF0). "Reverse" is 7 characters + null = 8 bytes. What would happen if you patched "Reverse" with "Reversal" (8 characters + null = 9 bytes)?**
"Reversal" needs 9 bytes (8 chars + null terminator). The 9th byte (the `0x00` null terminator) would be written to address `0x10003ef0`, which is the first byte of "Engineering" — the letter 'E' (`0x45`). This would overwrite 'E' with `0x00`, turning "Engineering" into an empty string. The LCD would display "Reversal" on line 1 and nothing on line 2, because `lcd_puts` would see a null terminator immediately at the start of the second string.
3. **If you wanted the LCD to display "Hello" on line 1 (5 characters instead of 7), what would you put in the remaining 2 bytes plus null? Write out the full 8-byte hex sequence.**
"Hello" = 5 characters, followed by the null terminator and 2 padding null bytes:
```
48 65 6C 6C 6F 00 00 00
H e l l o \0 \0 \0
```
The first `0x00` at position 5 terminates the string. The remaining two `0x00` bytes are padding that fills the original 8-byte allocation. These padding bytes are never read by `lcd_puts` because it stops at the first null terminator.
4. **Could you change the LCD to display nothing on line 1 by patching just one byte? Which byte and what value?**
Yes. Change the first byte at offset `0x3EE8` from `0x52` ('R') to `0x00` (null). This makes the string start with a null terminator, so `lcd_puts` sees an empty string and displays nothing. Only one byte needs to change: the byte at file offset `0x3EE8`, from `0x52` to `0x00`.
+205
View File
@@ -0,0 +1,205 @@
# Embedded Systems Reverse Engineering
[Repository](https://github.com/mytechnotalent/Embedded-Hacking)
## Week 7
Constants in Embedded Systems: Debugging and Hacking Constants w/ 1602 LCD I2C Basics
### Non-Credit Practice Exercise 1: Change Both LCD Lines
#### Objective
Patch the LCD display strings in the `.bin` file to change "Reverse" to "Exploit" on line 1 and "Engineering" to "Hacking!!!!" on line 2, using GDB to locate the string addresses, a hex editor to perform the patches, and the Pico 2 hardware to verify the changes on the physical LCD.
#### Prerequisites
- Completed Week 7 tutorial (GDB and hex editor sections)
- `0x0017_constants.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 1602 LCD connected via I²C
#### Task Description
The LCD currently displays "Reverse" on line 1 and "Engineering" on line 2. You will find both string literals in flash memory using GDB, calculate their file offsets, and patch them to display custom text. The critical constraint is that replacement strings must be the **same length** as the originals (or shorter, padded with null bytes) — otherwise you'll corrupt adjacent data.
#### 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\0x0017_constants.elf
```
**Connect to target:**
```gdb
(gdb) target remote :3333
(gdb) monitor reset halt
```
##### Step 2: Locate the String Literals in Memory
From the tutorial, we know the strings are in the `.rodata` section:
```gdb
(gdb) x/s 0x10003ee8
```
Output:
```
0x10003ee8: "Reverse"
```
```gdb
(gdb) x/s 0x10003ef0
```
Output:
```
0x10003ef0: "Engineering"
```
##### Step 3: Examine the Raw Bytes
Look at the hex encoding of both strings:
```gdb
(gdb) x/8xb 0x10003ee8
```
Output:
```
0x10003ee8: 0x52 0x65 0x76 0x65 0x72 0x73 0x65 0x00
R e v e r s e \0
```
```gdb
(gdb) x/12xb 0x10003ef0
```
Output:
```
0x10003ef0: 0x45 0x6e 0x67 0x69 0x6e 0x65 0x65 0x72
E n g i n e e r
0x10003ef8: 0x69 0x6e 0x67 0x00
i n g \0
```
##### Step 4: Plan Your Replacement Strings
**Original strings and their lengths:**
- "Reverse" = 7 characters + null terminator = 8 bytes
- "Engineering" = 11 characters + null terminator = 12 bytes
**Replacement strings (MUST be same length or shorter):**
- "Exploit" = 7 characters ? (same as "Reverse")
- "Hacking!!!!" = 11 characters ? (same as "Engineering")
Build the ASCII hex for "Exploit":
| Character | Hex |
| --------- | ------ |
| E | `0x45` |
| x | `0x78` |
| p | `0x70` |
| l | `0x6c` |
| o | `0x6f` |
| i | `0x69` |
| t | `0x74` |
| \0 | `0x00` |
Build the ASCII hex for "Hacking!!!!":
| Character | Hex |
| --------- | ------ |
| H | `0x48` |
| a | `0x61` |
| c | `0x63` |
| k | `0x6b` |
| i | `0x69` |
| n | `0x6e` |
| g | `0x67` |
| ! | `0x21` |
| ! | `0x21` |
| ! | `0x21` |
| ! | `0x21` |
| \0 | `0x00` |
##### Step 5: Calculate File Offsets
```
file_offset = address - 0x10000000
```
- "Reverse" at `0x10003ee8` ? file offset `0x3EE8`
- "Engineering" at `0x10003ef0` ? file offset `0x3EF0`
##### Step 6: Patch String 1 — "Reverse" ? "Exploit"
1. In HxD, open `C:\Users\flare-vm\Desktop\Embedded-Hacking-main\0x0017_constants\build\0x0017_constants.bin`
2. Press **Ctrl+G** and enter offset: `3EE8`
3. You should see: `52 65 76 65 72 73 65 00` ("Reverse\0")
4. Replace with: `45 78 70 6C 6F 69 74 00` ("Exploit\0")
##### Step 7: Patch String 2 — "Engineering" ? "Hacking!!!!"
1. Press **Ctrl+G** and enter offset: `3EF0`
2. You should see: `45 6E 67 69 6E 65 65 72 69 6E 67 00` ("Engineering\0")
3. Replace with: `48 61 63 6B 69 6E 67 21 21 21 21 00` ("Hacking!!!!\0")
##### Step 8: Save and Convert
1. Click **File** ? **Save As** ? `0x0017_constants-h.bin`
```powershell
cd C:\Users\flare-vm\Desktop\Embedded-Hacking-main\0x0017_constants
python ..\uf2conv.py build\0x0017_constants-h.bin --base 0x10000000 --family 0xe48bff59 --output build\hacked.uf2
```
##### Step 9: 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 LCD:**
- Line 1 should now show: `Exploit`
- Line 2 should now show: `Hacking!!!!`
#### Expected Output
After completing this exercise, you should be able to:
- Locate string literals in flash memory using GDB
- Convert ASCII characters to hex bytes for patching
- Patch multiple strings in a single binary
- Understand the same-length constraint for string patching
#### Questions for Reflection
###### Question 1: Why must the replacement string be the same length (or shorter) as the original? What specific data would you corrupt if you used a longer string?
###### Question 2: The two strings "Reverse" and "Engineering" are stored only 8 bytes apart (`0x3EE8` to `0x3EF0`). "Reverse" is 7 characters + null = 8 bytes — it perfectly fills the gap. What would happen if you patched "Reverse" with "Reversal" (8 characters + null = 9 bytes)?
###### Question 3: If you wanted the LCD to display "Hello" on line 1 (5 characters instead of 7), what would you put in the remaining 2 bytes plus null? Write out the full 8-byte hex sequence.
###### Question 4: Could you change the LCD to display nothing on line 1 by patching just one byte? Which byte and what value?
#### Tips and Hints
- Use an ASCII table to convert characters: uppercase A-Z = `0x41`-`0x5A`, lowercase a-z = `0x61`-`0x7A`
- The null terminator `0x00` marks the end of the string — anything after it is ignored by `lcd_puts`
- If your replacement is shorter, pad with `0x00` bytes to fill the original length
- The 1602 LCD has 16 characters per line — you cannot display more than 16 characters per line regardless of string length
#### Next Steps
- Proceed to Exercise 2 to explore finding all string literals in the binary
- Try displaying reversed text: can you make it show "gninnignE" and "esreveR"?
- Use GDB to verify your patches before flashing: `set {char[8]} 0x10003ee8 = "Exploit"` to test in RAM first
+68
View File
@@ -0,0 +1,68 @@
# Embedded Systems Reverse Engineering
[Repository](https://github.com/mytechnotalent/Embedded-Hacking)
## Week 7
Constants in Embedded Systems: Debugging and Hacking Constants w/ 1602 LCD I2C Basics
### Non-Credit Practice Exercise 2 Solution: Find All String Literals in the Binary
#### Answers
##### String Catalog
| Address | File Offset | String Content | Length | Purpose |
|---------------|-------------|--------------------------|--------|-----------------------------|
| `0x10003ee8` | `0x3EE8` | "Reverse" | 8 | LCD line 1 text |
| `0x10003ef0` | `0x3EF0` | "Engineering" | 12 | LCD line 2 text |
| `0x10003efc` | `0x3EFC` | "FAV_NUM: %d\r\n" | 16 | printf format string |
| `0x10003f0c` | `0x3F0C` | "OTHER_FAV_NUM: %d\r\n" | 22 | printf format string |
| Various | Various | SDK panic/assert strings | Varies | Pico SDK internal messages |
| Various | Various | Source file paths | Varies | SDK debug/assert references |
##### GDB String Search Commands
```gdb
(gdb) x/s 0x10003ee8
0x10003ee8: "Reverse"
(gdb) x/s 0x10003ef0
0x10003ef0: "Engineering"
(gdb) x/s 0x10003efc
0x10003efc: "FAV_NUM: %d\r\n"
(gdb) x/s 0x10003f0c
0x10003f0c: "OTHER_FAV_NUM: %d\r\n"
```
##### Scanning for Strings
```gdb
(gdb) x/20s 0x10003e00
(gdb) x/50s 0x10003d00
```
##### Literal Pool Reference
From the literal pool at `0x100002a4`:
| Pool Address | Value | String It Points To |
|----------------|---------------|---------------------------|
| `0x100002ac` | `0x10003EE8` | "Reverse" |
| `0x100002b0` | `0x10003EF0` | "Engineering" |
| `0x100002b4` | `0x10003EFC` | "FAV_NUM: %d\r\n" |
| `0x100002b8` | `0x10003F0C` | "OTHER_FAV_NUM: %d\r\n" |
#### Reflection Answers
1. **How many distinct strings did you find? Were any of them surprising or unexpected?**
At minimum 4 application-level strings: "Reverse", "Engineering", "FAV_NUM: %d\r\n", and "OTHER_FAV_NUM: %d\r\n". Beyond these, the Pico SDK embeds additional strings — panic handler messages, assert failure messages, and source file path strings used for debug output. The SDK strings are surprising because they reveal internal implementation details: file paths expose the build environment directory structure, and error messages reveal which SDK functions have built-in error checking. A reverse engineer can learn the SDK version and build configuration just from these strings.
2. **Why are strings so valuable to a reverse engineer? What can an attacker learn about a program just from its strings?**
Strings are high-entropy human-readable data that reveals program behavior without reading assembly. An attacker can learn: what the program displays or communicates (LCD messages, serial output), what libraries it uses (SDK error messages), how it handles errors (panic/assert strings), what data formats it processes (`printf` format strings with `%d`, `%s`, `%f`), network endpoints or credentials (URLs, passwords, API keys), the build environment (file paths), and the overall purpose of the firmware. Strings are often the first thing a reverse engineer examines in an unknown binary.
3. **What technique could a developer use to make strings harder to find in a binary? (Think about what the strings look like in memory.)**
String encryption/obfuscation: encrypt all string literals at compile time using XOR, AES, or a custom cipher, and decrypt them into a RAM buffer only when needed at runtime. This way, scanning the binary with `strings` or a hex editor reveals only ciphertext — random-looking bytes instead of readable text. Other techniques include: splitting strings across multiple locations and assembling them at runtime, using character arrays initialized by code rather than string literals, replacing strings with numeric lookup indices into an encrypted table, or using compile-time obfuscation tools that automatically transform string constants.
4. **The printf format strings contain \r\n. In the binary, these appear as two bytes: 0x0D 0x0A. Why two bytes instead of the four characters \, r, \, n?**
The C compiler processes escape sequences during compilation. In source code, `\r` is written as two characters (backslash + r), but the compiler converts it to a single byte: `0x0D` (carriage return, ASCII 13). Similarly, `\n` becomes `0x0A` (line feed, ASCII 10). These are **control characters** — non-printable ASCII codes that control terminal behavior. The backslash notation is just a human-readable way to represent these bytes in source code. By the time the string reaches the binary, all escape sequences have been resolved to their single-byte equivalents.
+157
View File
@@ -0,0 +1,157 @@
# Embedded Systems Reverse Engineering
[Repository](https://github.com/mytechnotalent/Embedded-Hacking)
## Week 7
Constants in Embedded Systems: Debugging and Hacking Constants w/ 1602 LCD I2C Basics
### Non-Credit Practice Exercise 2: Find All String Literals in the Binary
#### Objective
Systematically search through the `0x0017_constants` binary using GDB and a hex editor to locate every human-readable string literal, catalog their addresses, contents, and purposes, and gain experience identifying data structures in compiled binaries.
#### Prerequisites
- Completed Week 7 tutorial (GDB section)
- `0x0017_constants.elf` and `0x0017_constants.bin` available in your build directory
- GDB (`arm-none-eabi-gdb`) and OpenOCD installed
- A hex editor (HxD, ImHex, or similar)
#### Task Description
Compiled binaries contain string literals in the `.rodata` section — format strings for `printf`, LCD messages, library strings, and more. You will use two techniques to find them: (1) searching with GDB's `x/s` command to examine suspected string regions, and (2) visually scanning the binary in a hex editor for ASCII sequences. You will document every string you find, its address, and its likely purpose.
#### 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\0x0017_constants.elf
```
**Connect to target:**
```gdb
(gdb) target remote :3333
(gdb) monitor reset halt
```
##### Step 2: Locate the Known Strings
We already know about these strings from the tutorial:
```gdb
(gdb) x/s 0x10003ee8
0x10003ee8: "Reverse"
(gdb) x/s 0x10003ef0
0x10003ef0: "Engineering"
```
These are the LCD display strings. Now let's find more.
##### Step 3: Find printf Format Strings
The program uses `printf("FAV_NUM: %d\r\n", ...)` and `printf("OTHER_FAV_NUM: %d\r\n", ...)`. These format strings must be somewhere in flash. Look in the `.rodata` section near the LCD strings:
```gdb
(gdb) x/10s 0x10003ec0
```
This displays 10 consecutive strings starting from that address. Examine the output — you should find the `printf` format strings. Try different starting addresses if needed:
```gdb
(gdb) x/20s 0x10003e00
```
##### Step 4: Search the Binary Systematically
Use GDB to scan through flash memory in large chunks, looking for readable strings:
```gdb
(gdb) x/50s 0x10003d00
```
Many results will be garbage (non-ASCII data interpreted as text), but real strings will stand out. Look for:
- Format strings containing `%d`, `%s`, `%f`, `\r\n`
- Error messages from the Pico SDK
- Function names or debug info
##### Step 5: Open the Binary in a Hex Editor
1. Open `C:\Users\flare-vm\Desktop\Embedded-Hacking-main\0x0017_constants\build\0x0017_constants.bin` in HxD
2. Switch to the "Text" pane (right side) to see ASCII representation
3. Scroll through the binary and look for readable text sequences
In HxD, printable ASCII characters (0x200x7E) are displayed as text; non-printable bytes appear as dots.
##### Step 6: Use Hex Editor Search
Most hex editors can search for ASCII text:
1. Press **Ctrl+F** (Find)
2. Switch to "Text" or "String" search mode
3. Search for known strings like `Reverse`, `FAV_NUM`, `Engineering`
4. For each hit, note the file offset
##### Step 7: Catalog Your Findings
Create a table of all strings you find:
| Address | File Offset | String Content | Purpose |
| -------------- | ----------- | ----------------------- | --------------------------- |
| `0x10003ee8` | `0x3EE8` | "Reverse" | LCD line 1 text |
| `0x10003ef0` | `0x3EF0` | "Engineering" | LCD line 2 text |
| `0x10003eXX` | `0x3EXX` | "FAV_NUM: %d\r\n" | printf format string |
| `0x10003eXX` | `0x3EXX` | "OTHER_FAV_NUM: %d\r\n" | printf format string |
| ... | ... | ... | ... |
Fill in the actual addresses you discover.
##### Step 8: Identify SDK and Library Strings
The Pico SDK may include additional strings (error messages, assert messages, etc.). Look for text patterns like:
- "panic" or "assert"
- File paths (e.g., paths from the SDK source)
- Function names
These strings reveal internal SDK behavior that isn't visible in the source code.
#### Expected Output
After completing this exercise, you should be able to:
- Systematically enumerate string literals in a compiled binary
- Use both GDB (`x/s`) and hex editor text view to find strings
- Distinguish between application strings, format strings, and SDK/library strings
- Understand that string literals reveal program functionality to a reverse engineer
#### Questions for Reflection
###### Question 1: How many distinct strings did you find? Were any of them surprising or unexpected?
###### Question 2: Why are strings so valuable to a reverse engineer? What can an attacker learn about a program just from its strings?
###### Question 3: What technique could a developer use to make strings harder to find in a binary? (Think about what the strings look like in memory.)
###### Question 4: The `printf` format strings contain `\r\n`. In the binary, these appear as two bytes: `0x0D 0x0A`. Why two bytes instead of the four characters `\`, `r`, `\`, `n`?
#### Tips and Hints
- In GDB, `x/s` treats any address as the start of a null-terminated string — it will print garbage if the address isn't really a string
- Use `x/Ns address` where N is a number to print N consecutive strings (useful for scanning regions)
- In HxD, use **Edit** ? **Select Block** to highlight a region and examine the text pane
- Real strings are typically 4+ printable ASCII characters followed by a null byte (`0x00`)
- The `.rodata` section is usually located after the `.text` (code) section in the binary
#### Next Steps
- Proceed to Exercise 3 to trace the I²C struct pointer chain
- Try the `strings` command if available: `strings 0x0017_constants.bin` will extract all printable character sequences
- Consider: if you found a password string in an embedded device binary, what security implications would that have?
+91
View File
@@ -0,0 +1,91 @@
# Embedded Systems Reverse Engineering
[Repository](https://github.com/mytechnotalent/Embedded-Hacking)
## Week 7
Constants in Embedded Systems: Debugging and Hacking Constants w/ 1602 LCD I2C Basics
### Non-Credit Practice Exercise 3 Solution: Trace the I²C Struct Pointer Chain
#### Answers
##### Complete Pointer Chain
```
I2C_PORT (source macro: #define I2C_PORT i2c1)
i2c1 (SDK macro: #define i2c1 (&i2c1_inst))
&i2c1_inst = 0x2000062c (SRAM address of i2c_inst_t struct)
i2c1_inst.hw = 0x40098000 (pointer to I²C1 hardware register base)
I²C1 Hardware Registers (memory-mapped I/O silicon)
+-- IC_CON at 0x40098000
+-- IC_TAR at 0x40098004
+-- IC_SAR at 0x40098008
+-- IC_DATA_CMD at 0x40098010
```
##### Literal Pool Load
```gdb
(gdb) x/6wx 0x100002a4
0x100002a4: 0x000186a0 0x2000062c 0x10003ee8 0x10003ef0
0x100002b4: 0x10003efc 0x10003f0c
```
The value `0x2000062c` at pool address `0x100002a8` is loaded into `r0` by a `ldr r0, [pc, #offset]` instruction before the `bl i2c_init` call.
##### i2c1_inst Struct in SRAM
```gdb
(gdb) x/2wx 0x2000062c
0x2000062c <i2c1_inst>: 0x40098000 0x00000000
```
| Offset | Field | Value | Size | Meaning |
|--------|-------------------|-------------|---------|-------------------------------|
| +0x00 | hw | 0x40098000 | 4 bytes | Pointer to I²C1 hardware regs |
| +0x04 | restart_on_next | 0x00000000 | 4 bytes | false (no pending restart) |
Total struct size: 8 bytes (4-byte pointer + 4-byte bool padded to word alignment).
##### Hardware Registers at 0x40098000
```gdb
(gdb) x/8wx 0x40098000
```
| Offset | Register | Address | Description |
|--------|-------------|-------------|---------------------------|
| +0x00 | IC_CON | 0x40098000 | I²C control register |
| +0x04 | IC_TAR | 0x40098004 | Target address register |
| +0x08 | IC_SAR | 0x40098008 | Slave address register |
| +0x10 | IC_DATA_CMD | 0x40098010 | Data command register |
##### I²C0 Comparison
```gdb
(gdb) x/2wx 0x20000628
```
| Controller | Struct Address | hw Pointer | Separation |
|------------|---------------|-------------|-------------|
| I²C0 | 0x20000628 | 0x40090000 | Base |
| I²C1 | 0x2000062c | 0x40098000 | +0x8000 |
Same struct layout, different hardware pointer — demonstrating the SDK's abstraction.
#### Reflection Answers
1. **Why does the SDK use a struct with a pointer to hardware registers instead of accessing 0x40098000 directly? What advantage does this abstraction provide?**
The struct abstraction allows the same code to work for both I²C controllers — I²C0 at `0x40090000` and I²C1 at `0x40098000` — by simply passing a different struct pointer. Functions like `i2c_init(i2c_inst_t *i2c, uint baudrate)` accept a pointer parameter, so one implementation serves both controllers. Without the struct, every I²C function would need either hardcoded addresses (duplicating code for each controller) or `if/else` branches. The abstraction also enables portability: if a future chip moves the hardware registers, only the struct initialization changes — not every function that accesses I²C.
2. **The hw pointer stores 0x40098000. In the binary, this appears as bytes 00 80 09 40. Why is the byte order reversed from how we write the address?**
ARM Cortex-M33 uses **little-endian** byte ordering: the least significant byte (LSB) is stored at the lowest memory address. For the 32-bit value `0x40098000`: byte 0 (lowest address) = `0x00` (LSB), byte 1 = `0x80`, byte 2 = `0x09`, byte 3 = `0x40` (MSB). We write numbers with the MSB first (big-endian notation), but the processor stores them LSB-first. This is a fundamental property of the ARM architecture that affects how you read multi-byte values in hex editors and GDB `x/bx` output.
3. **If you changed the hw pointer at 0x2000062c from 0x40098000 to 0x40090000 using GDB, what I²C controller would the program use? What would happen to the LCD?**
The program would use **I²C0** instead of I²C1, because all subsequent hardware register accesses (via `i2c1_inst.hw->...`) would read/write the I²C0 registers at `0x40090000`. However, the LCD is physically wired to the I²C1 pins (GPIO 14 for SDA, GPIO 15 for SCL), and those GPIOs are configured for the I²C1 peripheral. The I²C0 controller drives different default pins (GPIO 0/1). So the program would send I²C commands through the wrong controller on the wrong pins — the LCD would receive no signals and would stop updating, displaying whatever was last written before the pointer change.
4. **The macro chain has 4 levels of indirection (I2C_PORT → i2c1 → &i2c1_inst → hw → registers). Is this typical for embedded SDKs? What are the trade-offs of this approach?**
Yes, this is typical. STM32 HAL, Nordic nRF5 SDK, ESP-IDF, and most professional embedded SDKs use similar multi-level abstractions. **Benefits:** code reuse across multiple peripheral instances, clean type-safe APIs, portability across chip revisions, and testability (you can mock the struct for unit tests). **Costs:** complexity for reverse engineers (harder to trace from API call to hardware), potential code bloat if not optimized, and a steeper learning curve for SDK users. In practice, modern compilers (with `-O2` or higher) optimize away most indirection — the final binary often inlines the pointer dereferences into direct register accesses, so the runtime overhead is negligible.
+206
View File
@@ -0,0 +1,206 @@
# Embedded Systems Reverse Engineering
[Repository](https://github.com/mytechnotalent/Embedded-Hacking)
## Week 7
Constants in Embedded Systems: Debugging and Hacking Constants w/ 1602 LCD I2C Basics
### Non-Credit Practice Exercise 3: Trace the I²C Struct Pointer Chain
#### Objective
Use GDB to follow the `i2c1_inst` struct pointer chain from the code instruction that loads it, through the struct in SRAM, to the hardware registers at `0x40098000`. Document every step of the chain: `I2C_PORT` ? `i2c1` ? `&i2c1_inst` ? `hw` ? `0x40098000`, and verify each pointer and value in memory.
#### Prerequisites
- Completed Week 7 tutorial (Parts 3-4 on structs and the macro chain)
- `0x0017_constants.elf` binary available in your build directory
- GDB (`arm-none-eabi-gdb`) and OpenOCD installed
- Understanding of C pointers and structs
#### Task Description
The Pico SDK uses a chain of macros and structs to abstract hardware access. When you write `I2C_PORT` in C, it expands through multiple macro definitions to ultimately become a pointer to an `i2c_inst_t` struct in SRAM, which in turn contains a pointer to the I²C hardware registers. You will trace this entire chain in GDB, examining each link to understand how the SDK connects your code to silicon.
#### 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\0x0017_constants.elf
```
**Connect to target:**
```gdb
(gdb) target remote :3333
(gdb) monitor reset halt
```
##### Step 2: Find the i2c_init Call
Run the program to allow initialization to complete, then halt:
```gdb
(gdb) b *0x10000234
(gdb) c
```
Now step through to just before the `i2c_init` call:
```gdb
(gdb) x/10i 0x1000023c
```
Look for the instruction that loads the `i2c1_inst` pointer into `r0`:
```
0x1000023c: ldr r0, [pc, #offset] ; Load &i2c1_inst into r0
0x1000023e: ldr r1, =0x186A0 ; 100000 (baud rate)
0x10000240: bl i2c_init ; Call i2c_init(i2c1, 100000)
```
##### Step 3: Follow the PC-Relative Load
The `ldr r0, [pc, #offset]` instruction loads a value from a **literal pool** — a data area near the code. Examine what's at the literal pool:
```gdb
(gdb) x/4wx 0x100002a8
```
Look for a value in the `0x2000xxxx` range — this is the SRAM address of `i2c1_inst`. It should be `0x2000062c`.
##### Step 4: Examine the i2c1_inst Struct in SRAM
Now examine the struct at that SRAM address:
```gdb
(gdb) x/2wx 0x2000062c
```
Expected output:
```
0x2000062c: 0x40098000 0x00000000
```
This maps to the `i2c_inst_t` struct:
| Offset | Field | Value | Meaning |
| ------ | ----------------- | ------------ | -------------------------------- |
| `+0x00` | `hw` | `0x40098000` | Pointer to I²C1 hardware regs |
| `+0x04` | `restart_on_next` | `0x00000000` | `false` (no pending restart) |
##### Step 5: Follow the hw Pointer to Hardware Registers
The first member of the struct (`hw`) points to `0x40098000` — the I²C1 hardware register block. Examine it:
```gdb
(gdb) x/8wx 0x40098000
```
You should see the I²C1 control and status registers:
| Offset | Register | Description |
| ------ | -------------- | ------------------------------ |
| `+0x00` | IC_CON | I²C control register |
| `+0x04` | IC_TAR | Target address register |
| `+0x08` | IC_SAR | Slave address register |
| `+0x0C` | (reserved) | — |
| `+0x10` | IC_DATA_CMD | Data command register |
##### Step 6: Verify the I²C Target Address
After `i2c_init` and `lcd_i2c_init` have run, check the target address register:
Let the program run past initialization:
```gdb
(gdb) delete
(gdb) b *<address_after_lcd_init>
(gdb) c
```
Then examine IC_TAR:
```gdb
(gdb) x/1wx 0x40098004
```
You should see `0x27` (or a value containing 0x27) — this is the LCD's I²C address!
##### Step 7: Document the Complete Chain
Create a diagram of the complete pointer chain:
```
Your Code: I2C_PORT
¦
? (preprocessor macro)
i2c1
¦
? (macro: #define i2c1 (&i2c1_inst))
&i2c1_inst = 0x2000062c (SRAM address)
¦
? (struct member access)
i2c1_inst.hw = 0x40098000 (hardware register base)
¦
? (memory-mapped I/O)
I²C1 Hardware Registers (silicon)
¦
+-- IC_CON at 0x40098000
+-- IC_TAR at 0x40098004
+-- IC_DATA_CMD at 0x40098010
+-- ...
```
##### Step 8: Compare with I²C0
The Pico 2 has two I²C controllers. Find the `i2c0_inst` struct and compare:
```gdb
(gdb) x/2wx 0x20000628
```
If I²C0's struct is at a nearby address, you should see:
- `hw` pointing to `0x40090000` (I²C0 base, different from I²C1's `0x40098000`)
- `restart_on_next` = 0
This demonstrates how the SDK uses the same struct layout for both I²C controllers, with only the hardware pointer changing.
#### Expected Output
After completing this exercise, you should be able to:
- Trace pointer chains from high-level code to hardware registers
- Understand how the Pico SDK uses structs to abstract hardware
- Read struct members from raw memory using GDB
- Navigate from SRAM data structures to memory-mapped I/O registers
#### Questions for Reflection
###### Question 1: Why does the SDK use a struct with a pointer to hardware registers instead of accessing `0x40098000` directly? What advantage does this abstraction provide?
###### Question 2: The `hw` pointer stores `0x40098000`. In the binary, this appears as bytes `00 80 09 40`. Why is the byte order reversed from how we write the address?
###### Question 3: If you changed the `hw` pointer at `0x2000062c` from `0x40098000` to `0x40090000` using GDB (`set {int}0x2000062c = 0x40090000`), what I²C controller would the program use? What would happen to the LCD?
###### Question 4: The macro chain has 4 levels of indirection (I2C_PORT ? i2c1 ? &i2c1_inst ? hw ? registers). Is this typical for embedded SDKs? What are the trade-offs of this approach?
#### Tips and Hints
- Use `x/wx` to examine 32-bit words (pointers are 32 bits on ARM Cortex-M33)
- SRAM addresses start with `0x20xxxxxx`; hardware register addresses start with `0x40xxxxxx`
- The literal pool (where PC-relative loads get their data) is usually right after the function's code
- `i2c_inst_t` is only 8 bytes: 4-byte pointer + 4-byte bool (padded to 4 bytes for alignment)
- I²C0 base = `0x40090000`, I²C1 base = `0x40098000` — they are `0x8000` bytes apart
#### Next Steps
- Proceed to Exercise 4 to patch the LCD to display your own custom message
- Try modifying the `restart_on_next` field in GDB and observe if it changes I²C behavior
- Explore the I²C hardware registers at `0x40098000` — can you read the IC_STATUS register to see if the bus is active?
+96
View File
@@ -0,0 +1,96 @@
# Embedded Systems Reverse Engineering
[Repository](https://github.com/mytechnotalent/Embedded-Hacking)
## Week 7
Constants in Embedded Systems: Debugging and Hacking Constants w/ 1602 LCD I2C Basics
### Non-Credit Practice Exercise 4 Solution: Display Your Own Custom Message on the LCD
#### Answers
##### String Constraints
| Line | Original | Address | File Offset | Max Chars | Allocated Bytes |
|------|--------------|-------------|-------------|-----------|-----------------|
| 1 | "Reverse" | 0x10003ee8 | 0x3EE8 | 7 | 8 |
| 2 | "Engineering" | 0x10003ef0 | 0x3EF0 | 11 | 12 |
##### Example Patch: "Hello!!" and "World!!"
**Line 1: "Hello!!" (7 characters — exact fit)**
| Character | Hex |
|-----------|--------|
| H | 0x48 |
| e | 0x65 |
| l | 0x6C |
| l | 0x6C |
| o | 0x6F |
| ! | 0x21 |
| ! | 0x21 |
| \0 | 0x00 |
```
Offset 0x3EE8:
Before: 52 65 76 65 72 73 65 00 ("Reverse")
After: 48 65 6C 6C 6F 21 21 00 ("Hello!!")
```
**Line 2: "World!!" (7 characters — needs 5 bytes of null padding)**
| Character | Hex |
|-----------|--------|
| W | 0x57 |
| o | 0x6F |
| r | 0x72 |
| l | 0x6C |
| d | 0x64 |
| ! | 0x21 |
| ! | 0x21 |
| \0 | 0x00 |
| \0 (pad) | 0x00 |
| \0 (pad) | 0x00 |
| \0 (pad) | 0x00 |
| \0 (pad) | 0x00 |
```
Offset 0x3EF0:
Before: 45 6E 67 69 6E 65 65 72 69 6E 67 00 ("Engineering")
After: 57 6F 72 6C 64 21 21 00 00 00 00 00 ("World!!")
```
##### Example Patch: Short String "Hi"
**Line 1: "Hi" (2 characters — needs 5 bytes of null padding)**
```
Offset 0x3EE8:
Before: 52 65 76 65 72 73 65 00 ("Reverse")
After: 48 69 00 00 00 00 00 00 ("Hi")
```
##### Conversion and Flash
```powershell
cd C:\Users\flare-vm\Desktop\Embedded-Hacking-main\0x0017_constants
python ..\uf2conv.py build\0x0017_constants-h.bin --base 0x10000000 --family 0xe48bff59 --output build\hacked.uf2
```
#### Reflection Answers
1. **You padded short strings with 0x00 null bytes. Would it also work to pad with 0x20 (space characters)? What would be the difference on the LCD display?**
Both approaches produce valid strings, but the display differs. With `0x00` padding, the string terminates at the first null byte — `lcd_puts` stops reading there, and the remaining bytes are ignored. The LCD shows only your text. With `0x20` (space) padding, the spaces become part of the string — `lcd_puts` sends them to the LCD as visible blank characters. The LCD would show your text followed by trailing spaces. Functionally both work, but `0x00` padding is cleaner because the string length matches your intended text, and the LCD positions after your text remain in whatever state the LCD controller initialized them to (typically blank anyway).
2. **The LCD is a 1602 (16 columns × 2 rows). What would happen if you could somehow put a 20-character string in memory? Would the LCD display all 20, or only the first 16?**
The LCD would display only the first 16 characters in the visible area. The HD44780 controller (used in 1602 LCD modules) has 40 bytes of DDRAM per line, so characters 17-20 would be written to DDRAM but are beyond the visible 16-column window. They would only become visible if you issued a display shift command to scroll the view. The `lcd_puts` function writes all characters to the controller regardless of line length — it has no built-in truncation. The 16-character limit is a physical display constraint, not a software one.
3. **If you wanted to combine the string hacks from Exercise 1 (changing both LCD lines) AND a hypothetical numeric hack (e.g., changing the movs r1, #42 encoding at offset 0x28E), could you do all patches in a single .bin file? What offsets would you need to modify?**
Yes, all patches can be applied to the same `.bin` file since they are at non-overlapping offsets. The three patch locations are:
- **Offset 0x28E**: FAV_NUM — change `movs r1, #42` immediate byte from `0x2A` to desired value (1 byte)
- **Offset 0x3EE8**: LCD line 1 — replace the 8-byte "Reverse" string
- **Offset 0x3EF0**: LCD line 2 — replace the 12-byte "Engineering" string
Each patch modifies a different region of the binary, so they are completely independent. You could also patch the `movw r1, #1337` instruction at offset `0x298` (the imm8 byte of the OTHER_FAV_NUM encoding) for a fourth independent patch.
4. **Besides LCD text, what other strings could you patch in a real-world embedded device to change its behavior? Think about Wi-Fi SSIDs, Bluetooth device names, HTTP headers, etc.**
Real-world embedded devices contain many patchable strings: **Wi-Fi SSIDs** and **passwords** (change what network the device connects to), **Bluetooth device names** (change how it appears during pairing), **HTTP/HTTPS URLs** (redirect API calls to a different server), **MQTT broker addresses** (redirect IoT telemetry), **DNS hostnames**, **firmware version strings** (spoof version for update bypass), **serial number formats**, **command-line interface prompts**, **error and debug messages** (hide forensic evidence), **TLS/SSL certificate fields**, **NTP server addresses** (manipulate time synchronization), and **authentication tokens or API keys**. String patching is one of the most practical firmware modification techniques because it's simple to execute and can dramatically change device behavior.
+148
View File
@@ -0,0 +1,148 @@
# Embedded Systems Reverse Engineering
[Repository](https://github.com/mytechnotalent/Embedded-Hacking)
## Week 7
Constants in Embedded Systems: Debugging and Hacking Constants w/ 1602 LCD I2C Basics
### Non-Credit Practice Exercise 4: Display Your Own Custom Message on the LCD
#### Objective
Patch both LCD string literals in the binary to display your name (or any custom message) on the 1602 LCD, respecting the character length constraints, converting your text to hex bytes, and verifying the result on hardware.
#### Prerequisites
- Completed Week 7 tutorial (hex editor section) and Exercise 1
- `0x0017_constants.bin` binary available in your build directory
- A hex editor (HxD, ImHex, or similar)
- Python installed (for UF2 conversion)
- Raspberry Pi Pico 2 with 1602 LCD connected via I²C
#### Task Description
You will choose two custom messages to display on the LCD — one for each line. Line 1 replaces "Reverse" (7 characters max) and line 2 replaces "Engineering" (11 characters max). You must convert your chosen text to ASCII hex, handle the case where your text is shorter than the original (pad with null bytes), patch the binary, and flash it to see your custom message on the physical LCD.
#### Step-by-Step Instructions
##### Step 1: Choose Your Messages
Plan two messages that fit the constraints:
| Line | Original | Max Length | Your Message | Length | Valid? |
| ---- | ------------- | ---------- | ------------ | ------ | ------ |
| 1 | "Reverse" | 7 chars | | | |
| 2 | "Engineering" | 11 chars | | | |
**Examples that work:**
- Line 1: "Hello!!" (7 chars) ✅
- Line 2: "World!!" (7 chars, pad with 4 null bytes) ✅
- Line 1: "Hi" (2 chars, pad with 5 null bytes) ✅
- Line 2: "My Name Here" — ❌ (12 chars, too long!)
> ⚠️ **Remember:** The 1602 LCD can display up to 16 characters per line, but the binary only allocates 8 bytes for "Reverse" and 12 bytes for "Engineering". You cannot exceed these byte allocations.
##### Step 2: Convert Your Messages to Hex
Use an ASCII table to convert each character:
**Common ASCII values:**
| Character | Hex | Character | Hex | Character | Hex |
| --------- | ------ | --------- | ------ | --------- | ------ |
| Space | `0x20` | 0-9 | `0x30`-`0x39` | A-Z | `0x41`-`0x5A` |
| ! | `0x21` | : | `0x3A` | a-z | `0x61`-`0x7A` |
| " | `0x22` | ? | `0x3F` | \0 (null) | `0x00` |
Write out the hex bytes for each message, including the null terminator and any padding:
**Line 1 (8 bytes total):**
```
[char1] [char2] [char3] [char4] [char5] [char6] [char7] [0x00]
```
If your message is shorter than 7 characters, fill the remaining bytes with `0x00`.
**Line 2 (12 bytes total):**
```
[char1] [char2] [char3] [char4] [char5] [char6] [char7] [char8] [char9] [char10] [char11] [0x00]
```
If your message is shorter than 11 characters, fill the remaining bytes with `0x00`.
##### Step 3: Open the Binary and Navigate
1. In HxD, open `C:\Users\flare-vm\Desktop\Embedded-Hacking-main\0x0017_constants\build\0x0017_constants.bin`
2. Press **Ctrl+G** and enter offset: `3EE8` (Line 1: "Reverse")
3. Verify you see: `52 65 76 65 72 73 65 00` ("Reverse\0")
##### Step 4: Patch Line 1
Replace the 8 bytes starting at offset `0x3EE8` with your prepared hex sequence.
For example, to write "Hello!!" (7 chars + null):
```
Before: 52 65 76 65 72 73 65 00 (Reverse)
After: 48 65 6C 6C 6F 21 21 00 (Hello!!)
```
For a shorter message like "Hi" (2 chars + null + padding):
```
Before: 52 65 76 65 72 73 65 00 (Reverse)
After: 48 69 00 00 00 00 00 00 (Hi\0\0\0\0\0\0)
```
##### Step 5: Patch Line 2
1. Press **Ctrl+G** and enter offset: `3EF0` (Line 2: "Engineering")
2. Verify you see: `45 6E 67 69 6E 65 65 72 69 6E 67 00`
3. Replace the 12 bytes with your prepared hex sequence
##### Step 6: Save the Patched Binary
1. Click **File****Save As**`0x0017_constants-h.bin`
##### Step 7: Convert to UF2 and Flash
```powershell
cd C:\Users\flare-vm\Desktop\Embedded-Hacking-main\0x0017_constants
python ..\uf2conv.py build\0x0017_constants-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 8: Verify on the LCD
Check the physical LCD display. Your custom messages should appear on lines 1 and 2.
If the LCD shows garbled text or nothing at all:
- Verify your hex conversion was correct
- Ensure you included the null terminator (`0x00`)
- Confirm you didn't accidentally modify bytes outside the string regions
- Re-open the binary and double-check offsets `0x3EE8` and `0x3EF0`
#### Expected Output
After completing this exercise, you should be able to:
- Convert any ASCII text to hex bytes for binary patching
- Handle strings shorter than the allocated space using null padding
- Patch string literals in any compiled binary
- Verify patches work on real hardware
#### Questions for Reflection
###### Question 1: You padded short strings with `0x00` null bytes. Would it also work to pad with `0x20` (space characters)? What would be the difference on the LCD display?
###### Question 2: The LCD is a 1602 (16 columns × 2 rows). What would happen if you could somehow put a 20-character string in memory? Would the LCD display all 20, or only the first 16?
###### Question 3: If you wanted to combine the string hacks from Exercise 1 (changing both LCD lines) AND a hypothetical numeric hack (e.g., changing the `movs r1, #42` encoding at offset `0x28E`), could you do all patches in a single `.bin` file? What offsets would you need to modify?
###### Question 4: Besides LCD text, what other strings could you patch in a real-world embedded device to change its behavior? Think about Wi-Fi SSIDs, Bluetooth device names, HTTP headers, etc.
#### Tips and Hints
- HxD shows the ASCII representation of bytes in the right panel — use this to verify your patches look correct
- A quick way to compute ASCII: lowercase letter hex = uppercase letter hex + `0x20`
- If you make a mistake, close the file WITHOUT saving and start over with the original `.bin`
- Take a photo of your custom LCD display for your portfolio!
#### Next Steps
- Review all four WEEK07 exercises and verify you understand string patching, data analysis, struct tracing, and custom message creation
- Try patching the `printf` format strings to display different labels in the serial output
- Challenge: can you make the LCD display emoji-like characters using the LCD's custom character feature (if supported by the backpack)?
Binary file not shown.
File diff suppressed because it is too large Load Diff
+79
View File
@@ -0,0 +1,79 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1200 800">
<style>
.bg{fill:#0a0a0f}.pnl{fill:#12121a;stroke:#1a1a2e}.hdr{fill:#12121a}
.title{font:bold 42px 'Courier New',monospace;fill:#00ff41}
.sub{font:bold 28px 'Courier New',monospace;fill:#00d4ff}
.txt{font:24px 'Courier New',monospace;fill:#c0c0c0}
.dim{font:20px 'Courier New',monospace;fill:#888}
.grn{font:bold 24px 'Courier New',monospace;fill:#00ff41}
.red{font:bold 24px 'Courier New',monospace;fill:#ff0040}
.cyn{font:bold 24px 'Courier New',monospace;fill:#00d4ff}
.amb{font:bold 24px 'Courier New',monospace;fill:#ffaa00}
.badge{stroke:#00ff41;rx:14}
</style>
<rect class="bg" width="1200" height="800"/>
<!-- Background grid decoration -->
<g opacity="0.06">
<line x1="0" y1="100" x2="1200" y2="100" stroke="#00ff41" stroke-width="1"/>
<line x1="0" y1="200" x2="1200" y2="200" stroke="#00ff41" stroke-width="1"/>
<line x1="0" y1="300" x2="1200" y2="300" stroke="#00ff41" stroke-width="1"/>
<line x1="0" y1="400" x2="1200" y2="400" stroke="#00ff41" stroke-width="1"/>
<line x1="0" y1="500" x2="1200" y2="500" stroke="#00ff41" stroke-width="1"/>
<line x1="0" y1="600" x2="1200" y2="600" stroke="#00ff41" stroke-width="1"/>
<line x1="0" y1="700" x2="1200" y2="700" stroke="#00ff41" stroke-width="1"/>
<line x1="200" y1="0" x2="200" y2="800" stroke="#00ff41" stroke-width="1"/>
<line x1="400" y1="0" x2="400" y2="800" stroke="#00ff41" stroke-width="1"/>
<line x1="600" y1="0" x2="600" y2="800" stroke="#00ff41" stroke-width="1"/>
<line x1="800" y1="0" x2="800" y2="800" stroke="#00ff41" stroke-width="1"/>
<line x1="1000" y1="0" x2="1000" y2="800" stroke="#00ff41" stroke-width="1"/>
</g>
<!-- Hex rain decoration -->
<g opacity="0.04" font-family="'Courier New',monospace" font-size="14" fill="#00ff41">
<text x="50" y="80">4F 70 65 6E 4F 43 44</text>
<text x="900" y="120">10 00 02 34 08 B5 01</text>
<text x="150" y="180">47 44 42 20 52 45 56</text>
<text x="800" y="240">20 08 20 00 FF AA 00</text>
<text x="80" y="350">52 50 32 33 35 30 00</text>
<text x="950" y="380">0A 0A 0F 12 12 1A 1A</text>
<text x="100" y="520">41 52 4D 76 38 2D 4D</text>
<text x="870" y="560">00 FF 41 00 D4 FF 88</text>
<text x="60" y="680">47 48 49 44 52 41 00</text>
<text x="920" y="720">FF 00 40 C0 C0 C0 00</text>
</g>
<!-- Corner accents -->
<polyline points="30,30 30,80 80,80" fill="none" stroke="#00ff41" stroke-width="2" opacity="0.3"/>
<polyline points="1170,30 1170,80 1120,80" fill="none" stroke="#00ff41" stroke-width="2" opacity="0.3"/>
<polyline points="30,770 30,720 80,720" fill="none" stroke="#00ff41" stroke-width="2" opacity="0.3"/>
<polyline points="1170,770 1170,720 1120,720" fill="none" stroke="#00ff41" stroke-width="2" opacity="0.3"/>
<!-- Top accent line -->
<rect x="100" y="140" width="1000" height="2" fill="#00ff41" opacity="0.4"/>
<!-- Course Title -->
<text x="600" y="210" text-anchor="middle" font-family="'Courier New',monospace" font-size="56" font-weight="bold" fill="#00ff41">Embedded Systems</text>
<text x="600" y="278" text-anchor="middle" font-family="'Courier New',monospace" font-size="56" font-weight="bold" fill="#00ff41">Reverse Engineering</text>
<!-- Divider -->
<rect x="300" y="310" width="600" height="2" fill="#00d4ff" opacity="0.6"/>
<!-- Week Number -->
<text x="600" y="380" text-anchor="middle" font-family="'Courier New',monospace" font-size="42" font-weight="bold" fill="#00d4ff">// WEEK 07</text>
<!-- Week Topic -->
<text x="600" y="440" text-anchor="middle" font-family="'Courier New',monospace" font-size="28" fill="#c0c0c0">Constants in Embedded Systems:</text>
<text x="600" y="478" text-anchor="middle" font-family="'Courier New',monospace" font-size="28" fill="#c0c0c0">Debugging and Hacking Constants</text>
<text x="600" y="516" text-anchor="middle" font-family="'Courier New',monospace" font-size="28" fill="#c0c0c0">w/ 1602 LCD I2C Basics</text>
<!-- Bottom accent line -->
<rect x="100" y="570" width="1000" height="2" fill="#00ff41" opacity="0.4"/>
<!-- University -->
<text x="600" y="635" text-anchor="middle" font-family="'Courier New',monospace" font-size="36" font-weight="bold" fill="#ffaa00">George Mason University</text>
<!-- Bottom badge -->
<rect x="400" y="670" width="400" height="40" rx="20" fill="none" stroke="#00ff41" stroke-width="1.5" opacity="0.5"/>
<text x="600" y="697" text-anchor="middle" font-family="'Courier New',monospace" font-size="20" fill="#00ff41" opacity="0.7">RP2350 // ARM Cortex-M33</text>
</svg>

After

Width:  |  Height:  |  Size: 4.4 KiB

+63
View File
@@ -0,0 +1,63 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1200 800">
<style>
.bg{fill:#0a0a0f}.pnl{fill:#12121a;stroke:#1a1a2e}.hdr{fill:#12121a}
.title{font:bold 42px 'Courier New',monospace;fill:#00ff41}
.sub{font:bold 28px 'Courier New',monospace;fill:#00d4ff}
.txt{font:24px 'Courier New',monospace;fill:#c0c0c0}
.dim{font:20px 'Courier New',monospace;fill:#888}
.grn{font:bold 24px 'Courier New',monospace;fill:#00ff41}
.red{font:bold 24px 'Courier New',monospace;fill:#ff0040}
.cyn{font:bold 24px 'Courier New',monospace;fill:#00d4ff}
.amb{font:bold 24px 'Courier New',monospace;fill:#ffaa00}
.badge{stroke:#00ff41;rx:14}
</style>
<rect class="bg" width="1200" height="800"/>
<rect class="hdr" x="0" y="0" width="1200" height="100" rx="0"/>
<text class="title" x="600" y="52" text-anchor="middle">#define vs const</text>
<text class="dim" x="600" y="88" text-anchor="middle">Preprocessor Macros vs Constant Variables</text>
<!-- Left Panel: #define -->
<rect class="pnl" x="30" y="110" width="555" height="370" rx="8"/>
<text class="amb" x="50" y="145">#define FAV_NUM 42</text>
<rect x="50" y="160" width="515" height="140" rx="6" fill="#1a1a2e" stroke="#ffaa00" stroke-width="1"/>
<text class="txt" x="70" y="190">Preprocessor text replacement</text>
<text class="txt" x="70" y="220">Happens BEFORE compilation</text>
<text class="txt" x="70" y="250">No memory allocated</text>
<text class="txt" x="70" y="280">Cannot take address (&amp;)</text>
<text class="dim" x="50" y="325">In Binary:</text>
<rect x="50" y="335" width="515" height="55" rx="6" fill="#0a0a0f" stroke="#ffaa00" stroke-width="1"/>
<text class="grn" x="70" y="368">movs r1, #42 @ 0x2a</text>
<text class="dim" x="50" y="415">16-bit Thumb instruction</text>
<text class="dim" x="50" y="440">Value embedded as immediate</text>
<text class="dim" x="50" y="465">Compiler sees only "42"</text>
<!-- Right Panel: const -->
<rect class="pnl" x="615" y="110" width="555" height="370" rx="8"/>
<text class="cyn" x="635" y="145">const int OTHER_FAV_NUM=1337</text>
<rect x="635" y="160" width="515" height="140" rx="6" fill="#1a1a2e" stroke="#00d4ff" stroke-width="1"/>
<text class="txt" x="655" y="190">Creates real variable</text>
<text class="txt" x="655" y="220">Theoretically in .rodata</text>
<text class="txt" x="655" y="250">Has an address (if needed)</text>
<text class="txt" x="655" y="280">Type-checked by compiler</text>
<text class="dim" x="635" y="325">In Binary:</text>
<rect x="635" y="335" width="515" height="55" rx="6" fill="#0a0a0f" stroke="#00d4ff" stroke-width="1"/>
<text class="grn" x="655" y="368">movw r1, #1337 @ 0x539</text>
<text class="dim" x="635" y="415">32-bit Thumb-2 instruction</text>
<text class="dim" x="635" y="440">Also embedded as immediate!</text>
<text class="dim" x="635" y="465">Compiler optimized it away</text>
<!-- Bottom Panel: Key Insight -->
<rect class="pnl" x="30" y="500" width="1140" height="140" rx="8"/>
<text class="red" x="50" y="535">KEY INSIGHT:</text>
<text class="txt" x="265" y="535">Both ended up as instruction immediates!</text>
<text class="dim" x="50" y="570">The compiler saw &amp;OTHER_FAV_NUM is never used, so it</text>
<text class="dim" x="50" y="595">optimized const the same way as #define -- no memory load needed.</text>
<text class="amb" x="50" y="625">Lesson: const is a source-level concept -- not guaranteed in binary</text>
<!-- Footer -->
</svg>

After

Width:  |  Height:  |  Size: 3.3 KiB

+85
View File
@@ -0,0 +1,85 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1200 800">
<style>
.bg{fill:#0a0a0f}.pnl{fill:#12121a;stroke:#1a1a2e}.hdr{fill:#12121a}
.title{font:bold 42px 'Courier New',monospace;fill:#00ff41}
.sub{font:bold 28px 'Courier New',monospace;fill:#00d4ff}
.txt{font:24px 'Courier New',monospace;fill:#c0c0c0}
.dim{font:20px 'Courier New',monospace;fill:#888}
.grn{font:bold 24px 'Courier New',monospace;fill:#00ff41}
.red{font:bold 24px 'Courier New',monospace;fill:#ff0040}
.cyn{font:bold 24px 'Courier New',monospace;fill:#00d4ff}
.amb{font:bold 24px 'Courier New',monospace;fill:#ffaa00}
.badge{stroke:#00ff41;rx:14}
</style>
<rect class="bg" width="1200" height="800"/>
<rect class="hdr" x="0" y="0" width="1200" height="100" rx="0"/>
<text class="title" x="600" y="52" text-anchor="middle">I2C Protocol</text>
<text class="dim" x="600" y="88" text-anchor="middle">Two-Wire Serial Communication</text>
<!-- Top Left: What is I2C -->
<rect class="pnl" x="30" y="110" width="555" height="190" rx="8"/>
<text class="sub" x="50" y="145">What is I2C?</text>
<text class="txt" x="50" y="180">Two-wire serial protocol</text>
<text class="cyn" x="50" y="210">SDA</text>
<text class="txt" x="120" y="210">= Serial Data</text>
<text class="cyn" x="50" y="240">SCL</text>
<text class="txt" x="120" y="240">= Serial Clock</text>
<text class="dim" x="50" y="270">Open-drain with pull-up resistors</text>
<!-- Top Right: Bus Diagram -->
<rect class="pnl" x="615" y="110" width="555" height="190" rx="8"/>
<text class="sub" x="635" y="145">I2C Bus</text>
<rect x="655" y="165" width="100" height="40" rx="4" fill="#0a0a0f" stroke="#00ff41" stroke-width="1"/>
<text class="grn" x="680" y="192">Pico</text>
<line x1="755" y1="175" x2="850" y2="175" stroke="#00d4ff" stroke-width="2"/>
<line x1="755" y1="195" x2="850" y2="195" stroke="#ffaa00" stroke-width="2"/>
<text class="dim" x="770" y="170">SDA</text>
<text class="dim" x="770" y="215">SCL</text>
<rect x="850" y="165" width="100" height="40" rx="4" fill="#0a0a0f" stroke="#ff0040" stroke-width="1"/>
<text class="red" x="878" y="192">LCD</text>
<text class="dim" x="655" y="245">GPIO 2 = SDA, GPIO 3 = SCL</text>
<text class="dim" x="655" y="270">Pull-ups hold lines HIGH</text>
<!-- Middle: Device Addresses -->
<rect class="pnl" x="30" y="315" width="1140" height="135" rx="8"/>
<text class="sub" x="50" y="350">Common I2C Addresses (7-bit)</text>
<rect x="50" y="365" width="250" height="60" rx="4" fill="#0a0a0f" stroke="#1a1a2e"/>
<text class="amb" x="70" y="392">0x27</text>
<text class="dim" x="160" y="392">LCD</text>
<rect x="320" y="365" width="250" height="60" rx="4" fill="#0a0a0f" stroke="#1a1a2e"/>
<text class="amb" x="340" y="392">0x3F</text>
<text class="dim" x="430" y="392">LCD Alt</text>
<rect x="590" y="365" width="265" height="60" rx="4" fill="#0a0a0f" stroke="#1a1a2e"/>
<text class="amb" x="610" y="392">0x48</text>
<text class="dim" x="700" y="392">Sensor</text>
<rect x="875" y="365" width="275" height="60" rx="4" fill="#0a0a0f" stroke="#1a1a2e"/>
<text class="amb" x="895" y="392">0x50</text>
<text class="dim" x="985" y="392">EEPROM</text>
<!-- Bottom: Transaction Flow -->
<rect class="pnl" x="30" y="465" width="1140" height="185" rx="8"/>
<text class="sub" x="50" y="500">I2C Transaction Flow</text>
<rect x="50" y="520" width="95" height="40" rx="4" fill="#00ff41" fill-opacity="0.15" stroke="#00ff41"/>
<text class="grn" x="65" y="546">START</text>
<text class="txt" x="155" y="546">--></text>
<rect x="200" y="520" width="140" height="40" rx="4" fill="#00d4ff" fill-opacity="0.15" stroke="#00d4ff"/>
<text class="cyn" x="215" y="546">Address</text>
<text class="txt" x="350" y="546">--></text>
<rect x="395" y="520" width="80" height="40" rx="4" fill="#ffaa00" fill-opacity="0.15" stroke="#ffaa00"/>
<text class="amb" x="413" y="546">ACK</text>
<text class="txt" x="485" y="546">--></text>
<rect x="530" y="520" width="95" height="40" rx="4" fill="#00d4ff" fill-opacity="0.15" stroke="#00d4ff"/>
<text class="cyn" x="548" y="546">Data</text>
<text class="txt" x="635" y="546">--></text>
<rect x="680" y="520" width="80" height="40" rx="4" fill="#ffaa00" fill-opacity="0.15" stroke="#ffaa00"/>
<text class="amb" x="698" y="546">ACK</text>
<text class="txt" x="770" y="546">--></text>
<rect x="815" y="520" width="90" height="40" rx="4" fill="#ff0040" fill-opacity="0.15" stroke="#ff0040"/>
<text class="red" x="833" y="546">STOP</text>
<text class="dim" x="50" y="595">Master sends START, then 7-bit address + R/W bit</text>
<text class="dim" x="50" y="620">Slave responds with ACK, then data bytes follow</text>
<!-- Footer -->
</svg>

After

Width:  |  Height:  |  Size: 4.5 KiB

+66
View File
@@ -0,0 +1,66 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1200 800">
<style>
.bg{fill:#0a0a0f}.pnl{fill:#12121a;stroke:#1a1a2e}.hdr{fill:#12121a}
.title{font:bold 42px 'Courier New',monospace;fill:#00ff41}
.sub{font:bold 28px 'Courier New',monospace;fill:#00d4ff}
.txt{font:24px 'Courier New',monospace;fill:#c0c0c0}
.dim{font:20px 'Courier New',monospace;fill:#888}
.grn{font:bold 24px 'Courier New',monospace;fill:#00ff41}
.red{font:bold 24px 'Courier New',monospace;fill:#ff0040}
.cyn{font:bold 24px 'Courier New',monospace;fill:#00d4ff}
.amb{font:bold 24px 'Courier New',monospace;fill:#ffaa00}
.badge{stroke:#00ff41;rx:14}
</style>
<rect class="bg" width="1200" height="800"/>
<rect class="hdr" x="0" y="0" width="1200" height="100" rx="0"/>
<text class="title" x="600" y="52" text-anchor="middle">C Structs &amp; typedef</text>
<text class="dim" x="600" y="88" text-anchor="middle">Grouping Related Data in C</text>
<!-- Left Panel: Struct Definition -->
<rect class="pnl" x="30" y="110" width="555" height="320" rx="8"/>
<text class="sub" x="50" y="145">Struct Definition</text>
<rect x="50" y="160" width="515" height="245" rx="6" fill="#0a0a0f" stroke="#1a1a2e"/>
<text class="cyn" x="70" y="192">typedef struct {</text>
<text class="txt" x="100" y="222">i2c_hw_t *hw;</text>
<text class="txt" x="100" y="252">bool restart_on_next;</text>
<text class="cyn" x="70" y="282">} i2c_inst_t;</text>
<text class="dim" x="70" y="320">typedef creates an alias</text>
<text class="dim" x="70" y="345">so we can write: i2c_inst_t var;</text>
<text class="dim" x="70" y="370">instead of: struct { ... } var;</text>
<!-- Right Panel: Struct in Memory -->
<rect class="pnl" x="615" y="110" width="555" height="320" rx="8"/>
<text class="sub" x="635" y="145">Memory Layout</text>
<text class="dim" x="635" y="175">i2c_inst_t at 0x2000062C</text>
<rect x="635" y="190" width="515" height="70" rx="4" fill="#0a0a0f" stroke="#00ff41" stroke-width="1"/>
<text class="dim" x="655" y="215">Offset 0x00</text>
<text class="grn" x="820" y="215">hw</text>
<text class="amb" x="890" y="215">= 0x40098000</text>
<text class="dim" x="655" y="245">i2c_hw_t* (4 bytes)</text>
<rect x="635" y="270" width="515" height="70" rx="4" fill="#0a0a0f" stroke="#00d4ff" stroke-width="1"/>
<text class="dim" x="655" y="295">Offset 0x04</text>
<text class="cyn" x="820" y="295">restart_on_next</text>
<text class="amb" x="655" y="325">= 0x00 (false)</text>
<text class="dim" x="870" y="325">bool (1 byte)</text>
<text class="dim" x="635" y="370">Total struct size: 8 bytes</text>
<text class="dim" x="635" y="400">hw points to I2C1 registers</text>
<!-- Bottom: Forward Declaration -->
<rect class="pnl" x="30" y="445" width="1140" height="120" rx="8"/>
<text class="sub" x="50" y="480">Forward Declaration</text>
<rect x="50" y="495" width="1100" height="45" rx="4" fill="#0a0a0f" stroke="#1a1a2e"/>
<text class="cyn" x="70" y="524">struct i2c_inst;</text>
<text class="dim" x="310" y="524">// tells compiler: this type exists, define later</text>
<!-- Bottom: Why structs -->
<rect class="pnl" x="30" y="580" width="1140" height="100" rx="8"/>
<text class="sub" x="50" y="615">Why Structs Matter in RE</text>
<text class="txt" x="50" y="650">GDB shows raw memory -- you must recognize struct layouts</text>
<text class="dim" x="50" y="670">x/2wx 0x2000062c shows: 0x40098000 0x00000000</text>
<!-- Footer -->
</svg>

After

Width:  |  Height:  |  Size: 3.3 KiB

+80
View File
@@ -0,0 +1,80 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1200 800">
<style>
.bg{fill:#0a0a0f}.pnl{fill:#12121a;stroke:#1a1a2e}.hdr{fill:#12121a}
.title{font:bold 42px 'Courier New',monospace;fill:#00ff41}
.sub{font:bold 28px 'Courier New',monospace;fill:#00d4ff}
.txt{font:24px 'Courier New',monospace;fill:#c0c0c0}
.dim{font:20px 'Courier New',monospace;fill:#888}
.grn{font:bold 24px 'Courier New',monospace;fill:#00ff41}
.red{font:bold 24px 'Courier New',monospace;fill:#ff0040}
.cyn{font:bold 24px 'Courier New',monospace;fill:#00d4ff}
.amb{font:bold 24px 'Courier New',monospace;fill:#ffaa00}
.badge{stroke:#00ff41;rx:14}
</style>
<rect class="bg" width="1200" height="800"/>
<rect class="hdr" x="0" y="0" width="1200" height="100" rx="0"/>
<text class="title" x="600" y="52" text-anchor="middle">Pico SDK Macro Chain</text>
<text class="dim" x="600" y="88" text-anchor="middle">From I2C_PORT to Hardware Registers</text>
<!-- Chain visualization -->
<rect class="pnl" x="30" y="110" width="1140" height="480" rx="8"/>
<text class="sub" x="50" y="145">Macro Expansion Chain</text>
<!-- Step 1 -->
<rect x="50" y="165" width="280" height="55" rx="6" fill="#00ff41" fill-opacity="0.1" stroke="#00ff41"/>
<text class="grn" x="70" y="200">I2C_PORT</text>
<text class="dim" x="50" y="240">#define I2C_PORT i2c1</text>
<!-- Arrow 1 -->
<text class="txt" x="350" y="200">--></text>
<!-- Step 2 -->
<rect x="400" y="165" width="280" height="55" rx="6" fill="#00d4ff" fill-opacity="0.1" stroke="#00d4ff"/>
<text class="cyn" x="420" y="200">i2c1</text>
<text class="dim" x="400" y="240">#define i2c1 (&amp;i2c1_inst)</text>
<!-- Arrow 2 -->
<text class="txt" x="700" y="200">--></text>
<!-- Step 3 -->
<rect x="750" y="165" width="380" height="55" rx="6" fill="#ffaa00" fill-opacity="0.1" stroke="#ffaa00"/>
<text class="amb" x="770" y="200">&amp;i2c1_inst</text>
<text class="dim" x="750" y="240">Address of global struct</text>
<!-- Step 4: struct contents -->
<text class="sub" x="50" y="285">Struct Contents at 0x2000062C</text>
<rect x="50" y="300" width="1080" height="130" rx="6" fill="#0a0a0f" stroke="#1a1a2e"/>
<text class="txt" x="70" y="335">i2c_inst_t i2c1_inst = {</text>
<text class="txt" x="100" y="365">.hw = (i2c_hw_t *)0x40098000,</text>
<text class="txt" x="100" y="395">.restart_on_next = false</text>
<text class="txt" x="70" y="420">};</text>
<!-- Arrow to hardware -->
<text class="sub" x="50" y="445">Hardware Register Access</text>
<rect x="50" y="460" width="1080" height="110" rx="6" fill="#0a0a0f" stroke="#ff0040" stroke-width="1"/>
<text class="txt" x="70" y="490">i2c1_inst.hw</text>
<text class="txt" x="290" y="490">--></text>
<text class="amb" x="340" y="490">i2c1_hw</text>
<text class="txt" x="460" y="490">--></text>
<text class="red" x="510" y="490">(i2c_hw_t*)0x40098000</text>
<text class="dim" x="70" y="525">I2C1_BASE = 0x40098000</text>
<text class="dim" x="500" y="525">I2C0_BASE = 0x40090000</text>
<text class="dim" x="70" y="555">Direct memory-mapped I/O to RP2350 peripheral</text>
<!-- Bottom: Summary Box -->
<rect class="pnl" x="30" y="605" width="1140" height="85" rx="8"/>
<text class="red" x="50" y="640">FULL CHAIN:</text>
<text class="grn" x="240" y="640">I2C_PORT</text>
<text class="txt" x="390" y="640">--></text>
<text class="cyn" x="435" y="640">i2c1</text>
<text class="txt" x="510" y="640">--></text>
<text class="amb" x="555" y="640">&amp;i2c1_inst</text>
<text class="txt" x="720" y="640">--></text>
<text class="red" x="770" y="640">0x40098000</text>
<text class="dim" x="50" y="670">Macro --> Macro --> Struct pointer --> HW register base</text>
<!-- Footer -->
</svg>

After

Width:  |  Height:  |  Size: 3.6 KiB

+53
View File
@@ -0,0 +1,53 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1200 800">
<style>
.bg{fill:#0a0a0f}.pnl{fill:#12121a;stroke:#1a1a2e}.hdr{fill:#12121a}
.title{font:bold 42px 'Courier New',monospace;fill:#00ff41}
.sub{font:bold 28px 'Courier New',monospace;fill:#00d4ff}
.txt{font:24px 'Courier New',monospace;fill:#c0c0c0}
.dim{font:20px 'Courier New',monospace;fill:#888}
.grn{font:bold 24px 'Courier New',monospace;fill:#00ff41}
.red{font:bold 24px 'Courier New',monospace;fill:#ff0040}
.cyn{font:bold 24px 'Courier New',monospace;fill:#00d4ff}
.amb{font:bold 24px 'Courier New',monospace;fill:#ffaa00}
.badge{stroke:#00ff41;rx:14}
</style>
<rect class="bg" width="1200" height="800"/>
<rect class="hdr" x="0" y="0" width="1200" height="100" rx="0"/>
<text class="title" x="600" y="52" text-anchor="middle">Source Code</text>
<text class="dim" x="600" y="88" text-anchor="middle">0x0017_constants.c</text>
<!-- Code Panel -->
<rect class="pnl" x="30" y="110" width="1140" height="470" rx="8"/>
<rect x="50" y="125" width="1100" height="440" rx="6" fill="#0a0a0f" stroke="#1a1a2e"/>
<text class="dim" x="70" y="155">//--- Defines and Constants ---</text>
<text class="cyn" x="70" y="185">#define FAV_NUM 42</text>
<text class="cyn" x="70" y="215">#define I2C_PORT i2c1</text>
<text class="cyn" x="70" y="245">#define I2C_SDA_PIN 2</text>
<text class="cyn" x="70" y="275">#define I2C_SCL_PIN 3</text>
<text class="amb" x="70" y="305">const int OTHER_FAV_NUM = 1337;</text>
<text class="dim" x="70" y="345">//--- Main Loop ---</text>
<text class="txt" x="70" y="375">lcd_set_cursor(0, 0);</text>
<text class="txt" x="70" y="405">lcd_puts("Reverse");</text>
<text class="txt" x="70" y="435">lcd_set_cursor(1, 0);</text>
<text class="txt" x="70" y="465">lcd_puts("Engineering");</text>
<text class="dim" x="70" y="505">//--- Serial Output Loop ---</text>
<text class="txt" x="70" y="535">printf("FAV_NUM: %d\r\n", FAV_NUM);</text>
<text class="txt" x="70" y="558">printf("OTHER_FAV_NUM: %d\r\n", OTHER_FAV_NUM);</text>
<!-- Right side: Output -->
<rect class="pnl" x="30" y="595" width="555" height="100" rx="8"/>
<text class="sub" x="50" y="628">LCD Output</text>
<text class="grn" x="50" y="660">Line 0: "Reverse"</text>
<text class="grn" x="50" y="685">Line 1: "Engineering"</text>
<rect class="pnl" x="615" y="595" width="555" height="100" rx="8"/>
<text class="sub" x="635" y="628">Serial Output</text>
<text class="txt" x="635" y="660">FAV_NUM: 42</text>
<text class="txt" x="635" y="685">OTHER_FAV_NUM: 1337</text>
<!-- Footer -->
</svg>

After

Width:  |  Height:  |  Size: 2.5 KiB

+65
View File
@@ -0,0 +1,65 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1200 800">
<style>
.bg{fill:#0a0a0f}.pnl{fill:#12121a;stroke:#1a1a2e}.hdr{fill:#12121a}
.title{font:bold 42px 'Courier New',monospace;fill:#00ff41}
.sub{font:bold 28px 'Courier New',monospace;fill:#00d4ff}
.txt{font:24px 'Courier New',monospace;fill:#c0c0c0}
.dim{font:20px 'Courier New',monospace;fill:#888}
.grn{font:bold 24px 'Courier New',monospace;fill:#00ff41}
.red{font:bold 24px 'Courier New',monospace;fill:#ff0040}
.cyn{font:bold 24px 'Courier New',monospace;fill:#00d4ff}
.amb{font:bold 24px 'Courier New',monospace;fill:#ffaa00}
.badge{stroke:#00ff41;rx:14}
</style>
<rect class="bg" width="1200" height="800"/>
<rect class="hdr" x="0" y="0" width="1200" height="100" rx="0"/>
<text class="title" x="600" y="52" text-anchor="middle">GDB Analysis</text>
<text class="dim" x="600" y="88" text-anchor="middle">Disassembly of main() at 0x10000234</text>
<!-- Main disassembly panel -->
<rect class="pnl" x="30" y="110" width="1140" height="420" rx="8"/>
<text class="sub" x="50" y="145">Key Instructions from x/54i 0x10000234</text>
<rect x="50" y="160" width="1100" height="355" rx="6" fill="#0a0a0f" stroke="#1a1a2e"/>
<text class="grn" x="70" y="190">push {r3, lr}</text>
<text class="dim" x="540" y="190">// save return addr</text>
<text class="txt" x="70" y="220">bl stdio_init_all</text>
<text class="dim" x="540" y="220">// init serial</text>
<text class="txt" x="70" y="250">ldr r1, [pc, #104]</text>
<text class="dim" x="540" y="250">// r1 = 100000 (baud)</text>
<text class="txt" x="70" y="280">ldr r0, [pc, #104]</text>
<text class="dim" x="540" y="280">// r0 = &amp;i2c1_inst</text>
<text class="txt" x="70" y="310">bl i2c_init</text>
<text class="dim" x="540" y="310">// init I2C at 100kHz</text>
<text class="txt" x="70" y="340">movs r0, #2</text>
<text class="dim" x="540" y="340">// GPIO 2 (SDA)</text>
<text class="txt" x="70" y="370">bl gpio_set_function</text>
<text class="dim" x="540" y="370">// set pin to I2C</text>
<text class="txt" x="70" y="400">movs r1, #39</text>
<text class="dim" x="540" y="400">// 0x27 = LCD addr</text>
<text class="txt" x="70" y="430">bl lcd_i2c_init</text>
<text class="dim" x="540" y="430">// init LCD device</text>
<text class="red" x="70" y="460">b.n 0x1000028e</text>
<text class="dim" x="540" y="460">// infinite loop start</text>
<text class="dim" x="70" y="490">...</text>
<text class="dim" x="120" y="490">AAPCS: r0-r3 = first 4 args, r0 = return value</text>
<!-- Bottom: Literal Pool -->
<rect class="pnl" x="30" y="545" width="1140" height="230" rx="8"/>
<text class="sub" x="50" y="580">Literal Pool at 0x100002A4</text>
<rect x="50" y="595" width="1100" height="160" rx="6" fill="#0a0a0f" stroke="#1a1a2e"/>
<text class="amb" x="70" y="625">0x000186A0</text>
<text class="dim" x="300" y="625">I2C baudrate (100000)</text>
<text class="amb" x="70" y="655">0x2000062C</text>
<text class="dim" x="300" y="655">&amp;i2c1_inst struct in RAM</text>
<text class="amb" x="70" y="685">0x10003EE8</text>
<text class="dim" x="300" y="685">"Reverse" string in flash</text>
<text class="amb" x="70" y="715">0x10003EF0</text>
<text class="dim" x="300" y="715">"Engineering" string in flash</text>
<text class="amb" x="640" y="625">0x10003EFC</text>
<text class="dim" x="870" y="625">"FAV_NUM: %d\r\n"</text>
<text class="amb" x="640" y="655">0x10003F0C</text>
<text class="dim" x="870" y="655">"OTHER_FAV_NUM: %d\r\n"</text>
</svg>

After

Width:  |  Height:  |  Size: 3.4 KiB

+71
View File
@@ -0,0 +1,71 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1200 800">
<style>
.bg{fill:#0a0a0f}.pnl{fill:#12121a;stroke:#1a1a2e}.hdr{fill:#12121a}
.title{font:bold 42px 'Courier New',monospace;fill:#00ff41}
.sub{font:bold 28px 'Courier New',monospace;fill:#00d4ff}
.txt{font:24px 'Courier New',monospace;fill:#c0c0c0}
.dim{font:20px 'Courier New',monospace;fill:#888}
.grn{font:bold 24px 'Courier New',monospace;fill:#00ff41}
.red{font:bold 24px 'Courier New',monospace;fill:#ff0040}
.cyn{font:bold 24px 'Courier New',monospace;fill:#00d4ff}
.amb{font:bold 24px 'Courier New',monospace;fill:#ffaa00}
.badge{stroke:#00ff41;rx:14}
</style>
<rect class="bg" width="1200" height="800"/>
<rect class="hdr" x="0" y="0" width="1200" height="100" rx="0"/>
<text class="title" x="600" y="52" text-anchor="middle">Instruction Encoding</text>
<text class="dim" x="600" y="88" text-anchor="middle">movs (16-bit Thumb) vs movw (32-bit Thumb-2)</text>
<!-- Top Left: movs encoding -->
<rect class="pnl" x="30" y="110" width="555" height="310" rx="8"/>
<text class="sub" x="50" y="145">movs r1, #42 (FAV_NUM)</text>
<text class="dim" x="50" y="175">At address 0x1000028E</text>
<rect x="50" y="195" width="515" height="55" rx="6" fill="#0a0a0f" stroke="#00ff41" stroke-width="1"/>
<text class="grn" x="70" y="228">Bytes: 2A 21</text>
<text class="dim" x="50" y="270">2A = immediate value (42)</text>
<text class="dim" x="50" y="295">21 = opcode (movs r1)</text>
<text class="amb" x="50" y="325">16-bit Thumb instruction</text>
<text class="dim" x="50" y="355">Fits values 0-255 in 8 bits</text>
<text class="dim" x="50" y="380">File offset: 0x28E</text>
<!-- Top Right: movw encoding -->
<rect class="pnl" x="615" y="110" width="555" height="310" rx="8"/>
<text class="sub" x="635" y="145">movw r1, #1337 (OTHER_FAV)</text>
<text class="dim" x="635" y="175">At address 0x10000296</text>
<rect x="635" y="195" width="515" height="55" rx="6" fill="#0a0a0f" stroke="#00d4ff" stroke-width="1"/>
<text class="cyn" x="655" y="228">Bytes: 40 F2 39 51</text>
<text class="dim" x="635" y="270">40 F2 = opcode (first halfword)</text>
<text class="dim" x="635" y="295">39 = imm8 (lower 8 bits)</text>
<text class="dim" x="635" y="320">51 = dest reg + upper imm</text>
<text class="amb" x="635" y="350">32-bit Thumb-2 instruction</text>
<text class="dim" x="635" y="380">File offset: 0x296</text>
<!-- Bottom: Byte Layout Diagram -->
<rect class="pnl" x="30" y="435" width="1140" height="170" rx="8"/>
<text class="sub" x="50" y="470">movw Byte Layout (40 F2 39 51)</text>
<rect x="50" y="485" width="260" height="50" rx="4" fill="#12121a" stroke="#ffaa00"/>
<text class="amb" x="90" y="516">40 F2</text>
<text class="dim" x="50" y="555">Opcode + upper imm</text>
<rect x="330" y="485" width="260" height="50" rx="4" fill="#12121a" stroke="#00ff41"/>
<text class="grn" x="400" y="516">39</text>
<text class="dim" x="330" y="555">imm8 (lower 8 bits)</text>
<rect x="610" y="485" width="260" height="50" rx="4" fill="#12121a" stroke="#00d4ff"/>
<text class="cyn" x="690" y="516">51</text>
<text class="dim" x="610" y="555">Dest reg (r1) + bits</text>
<text class="dim" x="900" y="516">imm16 = 0x539</text>
<text class="dim" x="900" y="555">= 1337 decimal</text>
<!-- Bottom: Why movw -->
<rect class="pnl" x="30" y="620" width="1140" height="100" rx="8"/>
<text class="red" x="50" y="655">Why movw instead of movs?</text>
<text class="txt" x="50" y="690">1337 &gt; 255 -- does not fit in 8-bit movs immediate</text>
<text class="dim" x="640" y="690">movw encodes 0-65535 in 32-bit instruction</text>
</svg>

After

Width:  |  Height:  |  Size: 3.5 KiB

+68
View File
@@ -0,0 +1,68 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1200 800">
<style>
.bg{fill:#0a0a0f}.pnl{fill:#12121a;stroke:#1a1a2e}.hdr{fill:#12121a}
.title{font:bold 42px 'Courier New',monospace;fill:#00ff41}
.sub{font:bold 28px 'Courier New',monospace;fill:#00d4ff}
.txt{font:24px 'Courier New',monospace;fill:#c0c0c0}
.dim{font:20px 'Courier New',monospace;fill:#888}
.grn{font:bold 24px 'Courier New',monospace;fill:#00ff41}
.red{font:bold 24px 'Courier New',monospace;fill:#ff0040}
.cyn{font:bold 24px 'Courier New',monospace;fill:#00d4ff}
.amb{font:bold 24px 'Courier New',monospace;fill:#ffaa00}
.badge{stroke:#00ff41;rx:14}
</style>
<rect class="bg" width="1200" height="800"/>
<rect class="hdr" x="0" y="0" width="1200" height="100" rx="0"/>
<text class="title" x="600" y="52" text-anchor="middle">I2C Struct in Memory</text>
<text class="dim" x="600" y="88" text-anchor="middle">Examining i2c1_inst at 0x2000062C</text>
<!-- GDB output -->
<rect class="pnl" x="30" y="110" width="1140" height="120" rx="8"/>
<text class="sub" x="50" y="145">GDB Memory Dump</text>
<rect x="50" y="160" width="1100" height="50" rx="6" fill="#0a0a0f" stroke="#1a1a2e"/>
<text class="grn" x="70" y="192">x/2wx 0x2000062c:</text>
<text class="amb" x="420" y="192">0x40098000</text>
<text class="amb" x="670" y="192">0x00000000</text>
<!-- Struct layout diagram -->
<rect class="pnl" x="30" y="245" width="1140" height="280" rx="8"/>
<text class="sub" x="50" y="280">i2c_inst_t Struct Layout</text>
<!-- Member 1: hw pointer -->
<rect x="50" y="300" width="540" height="70" rx="6" fill="#0a0a0f" stroke="#00ff41" stroke-width="1"/>
<text class="dim" x="70" y="328">Offset 0x00 | 4 bytes</text>
<text class="cyn" x="70" y="358">i2c_hw_t *hw</text>
<text class="amb" x="310" y="358">= 0x40098000</text>
<!-- Arrow to HW -->
<text class="txt" x="605" y="345">--></text>
<!-- HW register block -->
<rect x="650" y="300" width="490" height="70" rx="6" fill="#0a0a0f" stroke="#ff0040" stroke-width="1"/>
<text class="red" x="670" y="328">I2C1 HW Registers</text>
<text class="dim" x="670" y="358">Base: 0x40098000 (MMIO)</text>
<!-- Member 2: restart_on_next -->
<rect x="50" y="400" width="540" height="70" rx="6" fill="#0a0a0f" stroke="#00d4ff" stroke-width="1"/>
<text class="dim" x="70" y="425">Offset 0x04 | 1 byte</text>
<text class="cyn" x="70" y="455">bool restart_on_next</text>
<text class="amb" x="410" y="455">= false</text>
<text class="dim" x="650" y="430">I2C0 base = 0x40090000</text>
<text class="dim" x="650" y="460">I2C1 base = 0x40098000</text>
<!-- String Literals -->
<rect class="pnl" x="30" y="540" width="1140" height="170" rx="8"/>
<text class="sub" x="50" y="575">String Literals in Flash (.rodata)</text>
<rect x="50" y="590" width="535" height="55" rx="6" fill="#0a0a0f" stroke="#1a1a2e"/>
<text class="grn" x="70" y="622">x/s 0x10003ee8:</text>
<text class="txt" x="340" y="622">"Reverse"</text>
<rect x="615" y="590" width="535" height="55" rx="6" fill="#0a0a0f" stroke="#1a1a2e"/>
<text class="grn" x="635" y="622">x/s 0x10003ef0:</text>
<text class="txt" x="900" y="622">"Engineering"</text>
<text class="dim" x="50" y="665">Stored consecutively in .rodata (flash)</text>
<text class="dim" x="50" y="685">These addresses are targets for patching</text>
</svg>

After

Width:  |  Height:  |  Size: 3.2 KiB

+63
View File
@@ -0,0 +1,63 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1200 800">
<style>
.bg{fill:#0a0a0f}.pnl{fill:#12121a;stroke:#1a1a2e}.hdr{fill:#12121a}
.title{font:bold 42px 'Courier New',monospace;fill:#00ff41}
.sub{font:bold 28px 'Courier New',monospace;fill:#00d4ff}
.txt{font:24px 'Courier New',monospace;fill:#c0c0c0}
.dim{font:20px 'Courier New',monospace;fill:#888}
.grn{font:bold 24px 'Courier New',monospace;fill:#00ff41}
.red{font:bold 24px 'Courier New',monospace;fill:#ff0040}
.cyn{font:bold 24px 'Courier New',monospace;fill:#00d4ff}
.amb{font:bold 24px 'Courier New',monospace;fill:#ffaa00}
.badge{stroke:#00ff41;rx:14}
</style>
<rect class="bg" width="1200" height="800"/>
<rect class="hdr" x="0" y="0" width="1200" height="100" rx="0"/>
<text class="title" x="600" y="52" text-anchor="middle">Hacking the Binary</text>
<text class="dim" x="600" y="88" text-anchor="middle">Patching LCD Text: "Reverse" --> "Exploit"</text>
<!-- Offset calculation -->
<rect class="pnl" x="30" y="110" width="1140" height="100" rx="8"/>
<text class="sub" x="50" y="145">File Offset Formula</text>
<text class="grn" x="50" y="180">file_offset = address - 0x10000000</text>
<text class="dim" x="620" y="180">Binary loaded at 0x10000000</text>
<!-- Hack 1: String patch -->
<rect class="pnl" x="30" y="225" width="1140" height="280" rx="8"/>
<text class="sub" x="50" y="260">Hack: Change LCD String</text>
<text class="dim" x="50" y="290">Address 0x10003EE8 --> File offset 0x3EE8</text>
<text class="txt" x="50" y="325">Original:</text>
<rect x="210" y="335" width="400" height="42" rx="4" fill="#0a0a0f" stroke="#ff0040" stroke-width="1"/>
<text class="red" x="230" y="362">52 65 76 65 72 73 65 00</text>
<text class="dim" x="630" y="362">"Reverse"</text>
<text class="txt" x="50" y="400">Patched:</text>
<rect x="210" y="410" width="400" height="42" rx="4" fill="#0a0a0f" stroke="#00ff41" stroke-width="1"/>
<text class="grn" x="230" y="437">45 78 70 6C 6F 69 74 00</text>
<text class="dim" x="630" y="437">"Exploit"</text>
<text class="dim" x="50" y="480">Same length (7 chars) -- null terminator stays</text>
<!-- Flash Steps -->
<rect class="pnl" x="30" y="530" width="1140" height="155" rx="8"/>
<text class="sub" x="50" y="562">Flash the Hacked Binary</text>
<rect x="50" y="575" width="1100" height="40" rx="4" fill="#0a0a0f" stroke="#1a1a2e"/>
<text class="cyn" x="70" y="601">python uf2conv.py build\patched.bin</text>
<text class="txt" x="70" y="635">1.</text>
<text class="dim" x="100" y="635">Save patched .bin file</text>
<text class="txt" x="70" y="660">2.</text>
<text class="dim" x="100" y="660">Convert to .uf2 format</text>
<text class="txt" x="530" y="635">3.</text>
<text class="dim" x="560" y="635">Hold BOOTSEL, plug in Pico</text>
<text class="txt" x="530" y="660">4.</text>
<text class="dim" x="560" y="660">Drag hacked.uf2 to drive</text>
<!-- Result -->
<rect class="pnl" x="30" y="700" width="1140" height="70" rx="8"/>
<text class="grn" x="50" y="738">LCD now shows: "Exploit"</text>
<text class="dim" x="460" y="738">instead of "Reverse"</text>
<text class="red" x="750" y="738">No source code needed!</text>
</svg>

After

Width:  |  Height:  |  Size: 3.1 KiB

+88
View File
@@ -0,0 +1,88 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1200 800">
<style>
.bg{fill:#0a0a0f}.pnl{fill:#12121a;stroke:#1a1a2e}.hdr{fill:#12121a}
.title{font:bold 42px 'Courier New',monospace;fill:#00ff41}
.sub{font:bold 28px 'Courier New',monospace;fill:#00d4ff}
.txt{font:24px 'Courier New',monospace;fill:#c0c0c0}
.dim{font:20px 'Courier New',monospace;fill:#888}
.grn{font:bold 24px 'Courier New',monospace;fill:#00ff41}
.red{font:bold 24px 'Courier New',monospace;fill:#ff0040}
.cyn{font:bold 24px 'Courier New',monospace;fill:#00d4ff}
.amb{font:bold 24px 'Courier New',monospace;fill:#ffaa00}
.badge{stroke:#00ff41;rx:14}
</style>
<rect class="bg" width="1200" height="800"/>
<rect class="hdr" x="0" y="0" width="1200" height="100" rx="0"/>
<text class="title" x="600" y="52" text-anchor="middle">I2C &amp; Macro Exploitation</text>
<text class="dim" x="600" y="88" text-anchor="middle">Constants, I2C, Structs, and Hacking</text>
<!-- Left Column -->
<rect class="pnl" x="30" y="110" width="555" height="340" rx="8"/>
<text class="sub" x="50" y="145">Key Concepts</text>
<text class="grn" x="50" y="180">#define</text>
<text class="dim" x="230" y="180">Text replacement, no memory</text>
<text class="grn" x="50" y="210">const</text>
<text class="dim" x="230" y="210">Variable in .rodata (maybe)</text>
<text class="grn" x="50" y="240">I2C</text>
<text class="dim" x="230" y="240">Two-wire: SDA + SCL</text>
<text class="grn" x="50" y="270">struct</text>
<text class="dim" x="230" y="270">Groups related data fields</text>
<text class="grn" x="50" y="300">typedef</text>
<text class="dim" x="230" y="300">Creates type alias</text>
<text class="grn" x="50" y="330">AAPCS</text>
<text class="dim" x="230" y="330">r0-r3 args, r0 return</text>
<text class="grn" x="50" y="360">movs</text>
<text class="dim" x="230" y="360">16-bit, imm 0-255</text>
<text class="grn" x="50" y="390">movw</text>
<text class="dim" x="230" y="390">32-bit, imm 0-65535</text>
<text class="grn" x="50" y="420">Literal Pool</text>
<text class="dim" x="230" y="420">Large consts after code</text>
<!-- Right Column: Key Addresses -->
<rect class="pnl" x="615" y="110" width="555" height="340" rx="8"/>
<text class="sub" x="635" y="145">Key Addresses</text>
<text class="amb" x="635" y="180">0x10000234</text>
<text class="dim" x="850" y="180">main() entry</text>
<text class="amb" x="635" y="210">0x1000028E</text>
<text class="dim" x="850" y="210">FAV_NUM (movs)</text>
<text class="amb" x="635" y="240">0x10000296</text>
<text class="dim" x="850" y="240">OTHER_FAV_NUM (movw)</text>
<text class="amb" x="635" y="270">0x10003EE8</text>
<text class="dim" x="850" y="270">"Reverse" string</text>
<text class="amb" x="635" y="300">0x10003EF0</text>
<text class="dim" x="850" y="300">"Engineering" string</text>
<text class="amb" x="635" y="330">0x40098000</text>
<text class="dim" x="850" y="330">I2C1 HW base</text>
<text class="amb" x="635" y="360">0x2000062C</text>
<text class="dim" x="850" y="360">i2c1_inst struct</text>
<text class="dim" x="635" y="400">file_offset = addr - 0x10000000</text>
<text class="dim" x="635" y="425">String patches must be same length</text>
<!-- Bottom: Macro Chain and Hack Summary -->
<rect class="pnl" x="30" y="465" width="1140" height="100" rx="8"/>
<text class="sub" x="50" y="500">Macro Chain</text>
<text class="grn" x="50" y="535">I2C_PORT</text>
<text class="txt" x="210" y="535">--></text>
<text class="cyn" x="260" y="535">i2c1</text>
<text class="txt" x="340" y="535">--></text>
<text class="amb" x="390" y="535">&amp;i2c1_inst</text>
<text class="txt" x="560" y="535">--></text>
<text class="red" x="610" y="535">0x40098000</text>
<!-- Bottom: Hack result -->
<rect class="pnl" x="30" y="580" width="1140" height="115" rx="8"/>
<text class="sub" x="50" y="615">Binary Hack Result</text>
<text class="txt" x="50" y="650">LCD: "Reverse" --></text>
<text class="grn" x="370" y="650">"Exploit"</text>
<text class="dim" x="520" y="650">Patched at 0x3EE8</text>
<text class="dim" x="50" y="675">Compiler may optimize const same as #define</text>
<!-- Key Takeaway -->
<rect class="pnl" x="30" y="710" width="1140" height="70" rx="8"/>
<text class="red" x="50" y="748">TAKEAWAY:</text>
<text class="txt" x="230" y="748">const is a source-level concept.</text>
<text class="dim" x="680" y="748">In binary, everything can change!</text>
</svg>

After

Width:  |  Height:  |  Size: 4.3 KiB