Added WEEK06 and WEEK07

This commit is contained in:
Kevin Thomas
2026-03-01 12:45:26 -05:00
parent a751314efd
commit 7c3017c942
11 changed files with 3423 additions and 0 deletions
+204
View File
@@ -0,0 +1,204 @@
# 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
### 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:**
```bash
openocd ^
-s "C:\Users\flare-vm\.pico-sdk\openocd\0.12.0+dev\scripts" ^
-f interface/cmsis-dap.cfg ^
-f target/rp2350.cfg ^
-c "adapter speed 5000"
```
**Terminal 2 - Start GDB:**
```bash
arm-none-eabi-gdb build/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. Open `0x0017_constants.bin` in HxD
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`
```bash
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
+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
### 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:**
```bash
openocd ^
-s "C:\Users\flare-vm\.pico-sdk\openocd\0.12.0+dev\scripts" ^
-f interface/cmsis-dap.cfg ^
-f target/rp2350.cfg ^
-c "adapter speed 5000"
```
**Terminal 2 - Start GDB:**
```bash
arm-none-eabi-gdb build/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 `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?
+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
### 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:**
```bash
openocd ^
-s "C:\Users\flare-vm\.pico-sdk\openocd\0.12.0+dev\scripts" ^
-f interface/cmsis-dap.cfg ^
-f target/rp2350.cfg ^
-c "adapter speed 5000"
```
**Terminal 2 - Start GDB:**
```bash
arm-none-eabi-gdb build/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?
+147
View File
@@ -0,0 +1,147 @@
# 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
### 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. Open `0x0017_constants.bin` in HxD
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
```bash
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 both hacks from Exercise 1 (changing strings) AND the Week 7 tutorial hacks (changing FAV_NUM and OTHER_FAV_NUM), 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)?
+1022
View File
File diff suppressed because it is too large Load Diff