Updated WEEK02

This commit is contained in:
Kevin Thomas
2026-05-03 15:08:34 -04:00
parent d990412a44
commit 7c956ee514
39 changed files with 1307 additions and 587 deletions
+9 -16
View File
@@ -9,40 +9,33 @@ Introduction and Overview of Embedded Reverse Engineering: Ethics, Scoping, and
#### Answers
##### Question 1: What does the function return?
`stdio_init_all()` returns `_Bool`. The function signature shows `_Bool stdio_init_all(void)`.
`stdio_init_all()` returns `_Bool`. The function signature is `_Bool stdio_init_all(void)`.
##### Question 2: What parameters does it take?
**None** - the function signature shows `(void)` in parentheses, meaning zero parameters.
None. The signature uses `(void)`, which means zero parameters.
##### Question 3: What functions does it call?
`stdio_init_all()` calls initialization functions for:
- **UART** initialization (serial pin communication) `stdio_uart_init()`
These set up the standard I/O subsystem so that `printf()` can output data.
In this build, it calls `stdio_uart_init()` to initialize serial output.
##### Question 4: What's the purpose?
`stdio_init_all()` initializes **Standard Input/Output** for the Pico 2:
- **std** = Standard
- **io** = Input/Output
It sets up UART communication channels, which allows `printf()` to send output through the serial connection.
Its purpose is to initialize standard I/O so `printf()`/`puts()` output can be transmitted over UART.
##### Expected Output
```
stdio_init_all() returns: void (_Bool)
stdio_init_all() returns: _Bool
It takes 0 parameters
It calls the following functions: UART init
Based on these calls, I believe it initializes: Standard I/O for USB and UART serial communication
Based on these calls, I believe it initializes: Standard I/O for UART serial communication
```
#### Reflection Answers
1. **Why would we need to initialize standard I/O before using `printf()`?**
Without initialization, there is no communication channel configured. `printf()` needs a destination (USB, in other cases, or UART) to send its output. Without `stdio_init_all()`, output has nowhere to go.
Without initialization, there is no configured output path. `printf()` needs a destination (UART in this exercise) to transmit characters.
2. **Can you find other functions in the Symbol Tree that might be related to I/O?**
Yes - functions like `stdio_usb_init`, in other cases, and `stdio_uart_init`, `__wrap_puts`, and other I/O-related functions appear in the Symbol Tree.
Yes - `stdio_uart_init`, `__wrap_puts`, and related low-level serial/output helpers are I/O-related.
3. **How does this function support the `printf("hello, world\r\n")` call in main?**
It configures the USB, in other cases, and UART hardware so that when `printf()` (optimized to `__wrap_puts`) executes, the characters are transmitted over the serial connection to the host computer.
It configures the UART output path so when `printf()` (optimized to `__wrap_puts`) runs, the string is sent over serial.
+1 -1
View File
@@ -61,7 +61,7 @@ Once you've navigated to `stdio_init_all`:
Based on what you see in the decompiled code, answer the following:
###### Question 1: What does the function return?
Look at the return type at the top of the function. Is it `void`, `int`, `bool`, or something else?
Look at the return type at the top of the function. Is it `void`, `int`, `_Bool`, or something else?
###### Question 2: What parameters does it take?
Look at the function signature. Does it take any parameters? (Hint: Look for anything inside the parentheses)
+1 -1
View File
@@ -25,7 +25,7 @@ The string `"hello, world\r\n"` is located at address **`0x100019CC`** in **Flas
- 12 printable characters: `h`, `e`, `l`, `l`, `o`, `,`, ` `, `w`, `o`, `r`, `l`, `d`
- 2 special characters: `\r` (carriage return, 0x0D) and `\n` (newline, 0x0A)
##### Question 3: How many times and which functions reference it?
##### Question 3: How many times is it referenced, and by which function(s)?
The string is referenced **1 time**, only in the **`main()`** function. The `ldr` instruction at `0x1000023a` loads the string address into register `r0`, which is then passed to `__wrap_puts`.
##### Question 4: How is the string encoded?
+7 -8
View File
@@ -82,19 +82,19 @@ To see where this string is **used**:
Based on what you found:
###### Question 1: Memory Location
###### Question 1: What is the address, and is it Flash or RAM?
- What is the address of the "hello, world" string? __________
- Is it in Flash memory (starts with `0x100...`) or RAM (starts with `0x200...`)? __________
###### Question 2: String Storage
###### Question 2: How many bytes does the string take?
- How many bytes does the string take in memory? __________
- Can you count the characters? (h-e-l-l-o-,-space-w-o-r-l-d-\r-\n)
###### Question 3: References
###### Question 3: How many times is it referenced, and by which function(s)?
- How many times is this string referenced in the code? __________
- Which function(s) reference it? (Hint: Look at the cross-references)
###### Question 4: ASCII Encoding
###### Question 4: How is the string encoded?
- How is the string encoded in memory?
- Is each character one byte or more? __________
- What does `\r` and `\n` represent? (Hint: `\r` = carriage return, `\n` = newline)
@@ -133,10 +133,9 @@ Used in: [How the program uses it]
#### Questions for Reflection
1. **Why is the string stored in Flash memory?** Why not in RAM?
2. **How does `printf()` know where to find the string?** (Hint: The address is loaded into `r0`)
3. **What would happen if we didn't have the `\r\n` at the end?** How would the output look?
4. **Could we modify this string at runtime?** Why or why not?
1. **Why is the string stored in Flash instead of RAM?**
2. **What would happen if you tried to modify this string at runtime?**
3. **How does the Listing view help you understand string storage?**
#### Tips and Hints
+1 -1
View File
@@ -30,7 +30,7 @@ It is a **READ** operation. The `ldr` (Load Register) instruction reads the poin
##### Question 4: What happens next after the `ldr`?
After the `ldr r0, [DAT_10000244]` instruction loads the string address into `r0`, the next instruction is **`bl 0x100015fc <__wrap_puts>`** which calls the `puts` function with `r0` as its argument (the string pointer).
##### Question 5: Complete Data Flow Chain
##### Complete the Data Flow Chain
```
String "hello, world\r\n" stored at 0x100019CC (Flash)
+8 -22
View File
@@ -90,30 +90,30 @@ This means:
##### Step 7: Answer These Questions
###### Question 1: Data Address
###### Question 1: What is the address of the data reference?
- What is the address of the data reference you found? (e.g., `DAT_10000244`)
- __________
###### Question 2: Referenced By
###### Question 2: How many places reference this data?
- How many places reference this data?
- __________
- Which function(s) use it?
- __________
###### Question 3: Reference Type
###### Question 3: Is it a read or write operation? Why?
- Is it a read or write operation?
- __________
- Why? (What's the program doing with this data?)
- __________
###### Question 4: The Chain
###### Question 4: What happens next after the `ldr`?
- The `ldr` instruction loads an address into `r0`
- What happens next? (Hint: Look at the next instruction after the `ldr`)
- __________
- Is there a function call? If so, which one?
- __________
###### Question 5: Understanding the Flow
###### Complete the Data Flow Chain
- **`DAT_10000244`** contains the address of the "hello, world" string
- The `ldr` loads that address into `r0`
- Then a function (probably `printf` or `puts`) is called with `r0` as the argument
@@ -146,23 +146,9 @@ Read backwards: `10 00 19 CC` = `0x100019CC`
#### Questions for Reflection
1. **Why does the code need to load an address from memory?**
- Why can't it just use the address directly?
- Hint: Position-independent code and memory protection
2. **What's the relationship between `DAT_10000244` and the "hello, world" string?**
- They're at different addresses - why?
- Which is in Flash and which points to where it's stored?
3. **If we wanted to change what gets printed, where would we modify the code?**
- Could we just change the string at address `0x100019CC`?
- Or would we need to change `DAT_10000244`?
- Or both?
4. **How does this relate to memory layout?**
- Code section (Flash memory starting at `0x10000000`)
- Data section (constants/strings)
- Is everything at different addresses for a reason?
1. **Why does the compiler use an indirect pointer reference here?**
2. **What is a literal pool?**
3. **How does cross-referencing help in reverse engineering?**
#### Tips and Hints
+6 -7
View File
@@ -8,23 +8,22 @@ Introduction and Overview of Embedded Reverse Engineering: Ethics, Scoping, and
#### Answers
##### Step 1-2 Verification
- **Was GDB able to connect to OpenOCD?** Yes, via `target extended-remote localhost:3333`.
- **Did the program stop at the `main` breakpoint?** Yes, at `Breakpoint 1, main () at ../0x0001_hello-world.c:4`.
##### Step 3: Answer Exactly
- **Was GDB able to connect to OpenOCD?**
- Yes, via `target extended-remote localhost:3333`.
- **Did the program stop at the `main` breakpoint?**
- Yes, at `Breakpoint 1, main () at ../0x0001_hello-world.c:4`.
- **What is the address of `main`'s first instruction, and is it Flash or RAM?**
- `0x10000234`, and it is in **Flash** (`0x100...` XIP region).
- **What is the `sp` value at `main`, and is it Flash or RAM?**
- `x/s $sp`, the value is, `0x20082000`, and it is in **RAM** (`0x200...` SRAM region).
- `0x20082000`, and it is in **RAM** (`0x200...` SRAM region).
- **What is the first instruction in `main`, and what does it do?**
- `push {r3, lr}`; it saves `r3` and `lr` on the stack and keeps 8-byte stack alignment for ABI-compliant calls.
- **Does GDB match what Ghidra shows?**
- Yes. The disassembly and flow match the Ghidra listing.
##### Step 4: Capture Register Values (`pc`, `sp`, `lr`, `r0-r3`, by using `x/x $XX`)
##### Step 4: Capture Register Values (`pc`, `sp`, `lr`, `r0-r3`)
| Register | Value | Description |
|----------|-------|-------------|
+8 -19
View File
@@ -228,30 +228,30 @@ The `pc` should now be at `0x10000236`, which is the next instruction.
Based on what you've observed:
###### Question 1: GDB Connection
###### Question 1: Was GDB able to connect to OpenOCD?
- Was GDB able to connect to OpenOCD? (Yes/No)
- Did the program stop at your breakpoint? (Yes/No)
- __________
###### Question 2: Breakpoint Address
###### Question 2: What is the address of `main`'s first instruction, and is it Flash or RAM?
- What is the memory address of the `main` function's first instruction?
- __________
- Is this in Flash memory (0x100...) or RAM (0x200...)?
- __________
###### Question 3: Stack Pointer
###### Question 3: What is the `sp` value at `main`, and is it Flash or RAM?
- What is the value of the Stack Pointer (sp) when you're at `main`?
- __________
- Is this in Flash or RAM?
- __________
###### Question 4: First Instruction
###### Question 4: What is the first instruction in `main`, and what does it do?
- What is the first instruction in `main`?
- __________
- What does it do? (Hint: `push` = save to stack)
- __________
###### Question 5: Disassembly Comparison
###### Question 5: Does GDB match what Ghidra shows?
- Look at the disassembly from GDB (Step 7)
- Compare it to the disassembly from Ghidra (Exercise 1)
- Are they the same?
@@ -289,20 +289,9 @@ This is useful when you want to break on a condition rather than every time.
#### Questions for Reflection
1. **Why does GDB show both the C source line AND the assembly?**
- This is because the .elf file contains debug symbols
- What would happen if we used a stripped binary?
2. **How does GDB know the assembly for each instruction?**
- It disassembles the binary on-the-fly based on the architecture
3. **Why is the Stack Pointer so high (0x20082000)?**
- It's at the top of RAM and grows downward
- Can you calculate how much RAM this Pico 2 has?
4. **What's the difference between `si` (step into) and `ni` (next instruction)?**
- `si` steps into function calls
- `ni` executes entire functions without stopping inside them
1. **Why does the stack pointer start where it does?**
2. **Why does `push {r3, lr}` include `r3`?**
3. **How does the infinite loop work in assembly?**
#### Important GDB Commands Reference
+7 -5
View File
@@ -616,11 +616,13 @@ Ghidra shows you two views of the code:
**Decompile View (Right Panel)** - The reconstructed C code:
```c
int main(void) {
stdio_init_all();
do {
__wrap_puts("hello, world");
} while (true);
int main(void)
{
stdio_init_all();
do {
__wrap_puts("hello, world\r");
} while( true );
}
```
+8 -8
View File
@@ -9,7 +9,7 @@ Hello, World - Debugging and Hacking Basics: Debugging and Hacking a Basic Progr
#### Answers
##### Attack Summary
The goal is to write a custom message into SRAM at `0x20000000` and redirect `r0` to print it instead of the original `"hello, world"` string, without changing the source code.
The goal is to write a custom message into SRAM at `0x20040000` and redirect `r0` to print it instead of the original `"hello, world"` string, without changing the source code.
##### GDB Commands
@@ -17,25 +17,25 @@ The goal is to write a custom message into SRAM at `0x20000000` and redirect `r0
(gdb) target extended-remote :3333
(gdb) monitor reset halt
(gdb) b *0x1000023c # Breakpoint before __wrap_puts
(gdb) c # Continue to breakpoint
(gdb) set {char[20]} 0x20000000 = {'Y','o','u','r',' ','N','a','m','e','!','\r','\0'}
(gdb) set $r0 = 0x20000000 # Redirect r0 to injected message
(gdb) c # Resume - serial shows custom message
(gdb) c # Continue to breakpoint
(gdb) set {char[12]} 0x20040000 = {'Y','o','u','r',' ','N','a','m','e','!','\r','\0'}
(gdb) set $r0 = 0x20040000 # Redirect r0 to injected message
(gdb) c # Resume - serial shows custom message
```
##### Verification
```gdb
(gdb) x/s 0x20000000 # Should show your injected message
(gdb) x/s 0x20040000 # Should show your injected message
(gdb) x/s 0x100019cc # Original string still in Flash
```
#### Reflection Answers
1. **Why does the string have to live in SRAM instead of flash during runtime?**
Flash memory is read-only at runtime. The original string at `0x100019cc` cannot be modified. SRAM starting at `0x20000000` is read-write, so that is where we must place our replacement string.
Flash memory is read-only at runtime. The original string at `0x100019cc` cannot be modified. SRAM is read-write, so we place our replacement string at the safe runtime address `0x20040000`.
2. **What would happen if you forgot the null terminator in your injected string?**
`puts()` reads characters until it encounters `\0`. Without it, `puts()` would continue reading past the intended string, printing garbage characters from adjacent memory until a null byte happens to appear. This could crash the program or leak sensitive data.
3. **How does changing `r0` alter the behavior of `puts()` without touching source code?**
In the ARM calling convention, the first function argument is passed in `r0`. When `bl __wrap_puts` executes at `0x1000023c`, it reads the string address from `r0`. By changing `r0` from `0x100019cc` (original Flash string) to `0x20000000` (our SRAM string), we redirect what `puts()` prints.
In the ARM calling convention, the first function argument is passed in `r0`. When `bl __wrap_puts` executes at `0x1000023c`, it reads the string address from `r0`. By changing `r0` from `0x100019cc` (original Flash string) to `0x20040000` (our SRAM string), we redirect what `puts()` prints.
+6 -6
View File
@@ -14,10 +14,10 @@ Write your own message into SRAM and redirect `r0` so the running program prints
- OpenOCD and `arm-none-eabi-gdb` available in your PATH
- Serial monitor (PuTTY/minicom/screen) set to 115200 baud
- `build\0x0001_hello-world.elf` present and flashed to the board
- Week 2 setup steps (0a0e) completed: OpenOCD, serial monitor, and GDB ready
- Week 2 setup steps (0a0e) completed: OpenOCD, serial monitor, and GDB ready
#### Task Description
You will create a custom string in SRAM at `0x20000000`, point `r0` at it just before `puts()` runs, and watch the live output change to your message.
You will create a custom string in SRAM at `0x20040000`, point `r0` at it just before `puts()` runs, and watch the live output change to your message.
#### Step-by-Step Instructions
@@ -63,13 +63,13 @@ arm-none-eabi-gdb build\0x0001_hello-world.elf
Replace the characters with your name as needed.
```gdb
(gdb) set {char[20]} 0x20000000 = {'Y','o','u','r',' ','N','a','m','e','!','\r','\0'}
(gdb) set {char[12]} 0x20040000 = {'Y','o','u','r',' ','N','a','m','e','!','\r','\0'}
```
##### Step 8: Point `r0` to Your Message
```gdb
(gdb) set $r0 = 0x20000000
(gdb) set $r0 = 0x20040000
```
##### Step 9: Resume and Observe
@@ -82,7 +82,7 @@ Check PuTTY for your custom string replacing "hello, world".
#### Expected Output
- GDB stops at `0x1000023c` before `__wrap_puts`.
- `x/s 0x20000000` shows your injected message.
- `x/s 0x20040000` shows your injected message.
- PuTTY displays your custom message after you continue execution.
#### Questions for Reflection
@@ -94,7 +94,7 @@ Check PuTTY for your custom string replacing "hello, world".
###### Question 3: How does changing `r0` alter the behavior of `puts()` without touching source code?
#### Tips and Hints
- Keep your string length within the allocated array (`char[20]`).
- Match the array length to your payload exactly (characters + `\0`). The example uses `char[12]`.
- If you miss the breakpoint, confirm OpenOCD is running and the address matches `Week 2` disassembly.
- Use `x/s $r0` to confirm the register points to the intended address before continuing.
+7 -7
View File
@@ -9,30 +9,30 @@ Hello, World - Debugging and Hacking Basics: Debugging and Hacking a Basic Progr
#### Answers
##### Attack Summary
Write the payload to `0x20001000` instead of `0x20000000` to demonstrate that multiple safe SRAM locations can be used for injection.
Write the payload to `0x20041000` instead of `0x20040000` to demonstrate that multiple safe SRAM locations can be used for injection.
##### GDB Commands
```gdb
(gdb) b *0x1000023c
(gdb) c
(gdb) set {char[14]} 0x20001000 = {'h','a','c','k','e','d','!','!','!','\r','\0'}
(gdb) set $r0 = 0x20001000
(gdb) set {char[14]} 0x20041000 = {'h','a','c','k','e','d','!','!','!','\r','\0'}
(gdb) set $r0 = 0x20041000
(gdb) c
```
##### Verification
```gdb
(gdb) x/s 0x20001000 # Shows "hacked!!!\r"
(gdb) x/s 0x20041000 # Shows "hacked!!!\r"
```
#### Reflection Answers
1. **How can you ensure `0x20001000` does not collide with stack usage?**
The stack pointer was observed at `0x20082000` (top of stack) and grows downward. Since `0x20001000` is far below the stack region, there is substantial separation. Use `info registers sp` in GDB to verify the current stack pointer is well above your injection address.
1. **How can you ensure `0x20041000` does not collide with stack usage?**
The stack pointer was observed at `0x20082000` (top of stack) and grows downward. Since `0x20041000` is well below the stack region, there is substantial separation. Use `info registers sp` in GDB to verify the current stack pointer is above your injection address.
2. **What symptoms would indicate you overwrote an active stack frame?**
The program would crash when attempting to return from a function. Symptoms include: unexpected address exceptions, invalid memory access faults, or the program jumping to random addresses. The Link Register return path gets corrupted.
3. **How would you pick a safe SRAM offset in a larger program with dynamic allocations?**
Start from the bottom of SRAM (`0x20000000`) for small static payloads, working upward. Check the linker script to understand memory regions. In this simple program with no heap allocations, both `0x20000000` and `0x20001000` are safe. In larger programs, examine the `.bss` and `.data` section boundaries.
Choose a region with clear separation from vectors, stack growth, and active data. In this simple program, `0x20040000` and `0x20041000` are practical safe offsets. In larger programs, inspect linker sections (`.data`, `.bss`, heap) and validate with runtime `sp` checks.
+8 -8
View File
@@ -7,16 +7,16 @@ Hello, World - Debugging and Hacking Basics: Debugging and Hacking a Basic Progr
### Non-Credit Practice Exercise 2: Use a Different SRAM Address
#### Objective
Practice writing to an alternate SRAM location and redirecting `r0` so your message prints from `0x20001000` instead of `0x20000000`.
Practice writing to an alternate SRAM location and redirecting `r0` so your message prints from `0x20041000` instead of `0x20040000`.
#### Prerequisites
- Raspberry Pi Pico 2 with debug probe connected
- OpenOCD, `arm-none-eabi-gdb`, and a serial monitor ready (Week 2 steps 0a0e complete)
- OpenOCD, `arm-none-eabi-gdb`, and a serial monitor ready (Week 2 steps 0a0e complete)
- `build\0x0001_hello-world.elf` flashed and running
- Comfortable setting breakpoints at `0x1000023c`
#### Task Description
You will inject a short string into `0x20001000`, point `r0` there, and verify the live output changes, demonstrating that any safe SRAM slot can host your payload.
You will inject a short string into `0x20041000`, point `r0` there, and verify the live output changes, demonstrating that any safe SRAM slot can host your payload.
#### Step-by-Step Instructions
@@ -47,16 +47,16 @@ openocd ^
(gdb) c
```
##### Step 5: Write a Payload at `0x20001000`
##### Step 5: Write a Payload at `0x20041000`
```gdb
(gdb) set {char[14]} 0x20001000 = {'h','a','c','k','e','d','!','!','!','\r','\0'}
(gdb) set {char[14]} 0x20041000 = {'h','a','c','k','e','d','!','!','!','\r','\0'}
```
##### Step 6: Redirect `r0`
```gdb
(gdb) set $r0 = 0x20001000
(gdb) set $r0 = 0x20041000
```
##### Step 7: Continue and Verify
@@ -68,13 +68,13 @@ openocd ^
Check PuTTY for the new output sourced from the alternate address.
#### Expected Output
- `x/s 0x20001000` shows `"hacked!!!\r"` (or your variant).
- `x/s 0x20041000` shows `"hacked!!!\r"` (or your variant).
- PuTTY prints the injected message instead of the original string.
- The program continues looping with your modified output.
#### Questions for Reflection
###### Question 1: How can you ensure `0x20001000` does not collide with stack usage?
###### Question 1: How can you ensure `0x20041000` does not collide with stack usage?
###### Question 2: What symptoms would indicate you overwrote an active stack frame?
+5 -5
View File
@@ -11,16 +11,16 @@ Hello, World - Debugging and Hacking Basics: Debugging and Hacking a Basic Progr
##### GDB Commands
```gdb
(gdb) set {char[14]} 0x20000000 = {'h','a','c','k','y',',',' ','w','o','r','l','d','\r','\0'}
(gdb) x/20b 0x20000000
(gdb) set {char[14]} 0x20040000 = {'h','a','c','k','y',',',' ','w','o','r','l','d','\r','\0'}
(gdb) x/20b 0x20040000
```
##### Byte Dump Output
```
0x20000000: 0x68 0x61 0x63 0x6b 0x79 0x2c 0x20 0x77
0x20000008: 0x6f 0x72 0x6c 0x64 0x0d 0x00 0x00 0x00
0x20000010: 0x00 0x00 0x00 0x00
0x20040000: 0x68 0x61 0x63 0x6b 0x79 0x2c 0x20 0x77
0x20040008: 0x6f 0x72 0x6c 0x64 0x0d 0x00 0x00 0x00
0x20040010: 0x00 0x00 0x00 0x00
```
##### ASCII Mapping
+5 -5
View File
@@ -13,7 +13,7 @@ Inspect the byte-level layout of your injected string in SRAM and correlate byte
- Pico 2 connected with OpenOCD, GDB, and a serial monitor ready
- `build\0x0001_hello-world.elf` flashed and running
- Ability to break before `__wrap_puts` at `0x1000023c`
- A payload already written to SRAM (e.g., at `0x20000000` from Exercise 1)
- A payload already written to SRAM (e.g., at `0x20040000` from Exercise 1)
#### Task Description
You will use `x/20b` to view the bytes surrounding your injected string, decode the characters, and confirm the presence of control characters and the null terminator.
@@ -38,14 +38,14 @@ You will use `x/20b` to view the bytes surrounding your injected string, decode
If needed, re-inject a payload:
```gdb
(gdb) set {char[14]} 0x20000000 = {'h','a','c','k','y',',',' ','w','o','r','l','d','\r','\0'}
(gdb) set $r0 = 0x20000000
(gdb) set {char[14]} 0x20040000 = {'h','a','c','k','y',',',' ','w','o','r','l','d','\r','\0'}
(gdb) set $r0 = 0x20040000
```
##### Step 4: Examine Bytes Around the String
```gdb
(gdb) x/20b 0x20000000
(gdb) x/20b 0x20040000
```
##### Step 5: Decode the Output
@@ -77,6 +77,6 @@ If needed, re-inject a payload:
- If the bytes look incorrect, re-run the injection command to reset the buffer.
#### Next Steps
- Try viewing a different address (e.g., `0x20001000`) to compare layouts.
- Try viewing a different address (e.g., `0x20041000`) to compare layouts.
- Experiment with longer strings and observe how the byte dump grows.
- Move on to Exercise 4 to automate the hack workflow.
+6 -6
View File
@@ -12,8 +12,8 @@ Hello, World - Debugging and Hacking Basics: Debugging and Hacking a Basic Progr
```gdb
(gdb) define hack
> set {char[14]} 0x20000000 = {'h','a','c','k','y',',',' ','w','o','r','l','d','\r','\0'}
> set $r0 = 0x20000000
> set {char[13]} 0x20040000 = "hacky, world"
> set $r0 = 0x20040000
> c
> end
```
@@ -39,7 +39,7 @@ hacky, world
#### Reflection Answers
1. **How could you parameterize the command to accept different strings or addresses?**
Standard GDB `define` blocks do not support function parameters directly. However, you can use GDB convenience variables (`set $myaddr = 0x20000000`) and reference them in the macro, or create multiple specific commands like `hack_addr1`, `hack_addr2`. For advanced parameterization, use GDB Python scripting.
Standard GDB `define` blocks do not support function parameters directly. However, you can use GDB convenience variables (`set $myaddr = 0x20040000`) and reference them in the macro, or create multiple specific commands like `hack_addr1`, `hack_addr2`. For advanced parameterization, use GDB Python scripting.
2. **What happens if you define `hack` before setting the breakpoint - will it still work as expected?**
The `define` command only creates a macro; it does not execute immediately. The breakpoint must be set and hit before invoking `hack`. The sequence matters: set breakpoint -> run/continue to hit breakpoint -> then call `hack`. Defining the macro before or after the breakpoint does not matter as long as you invoke it at the right time.
@@ -48,9 +48,9 @@ hacky, world
Extend the `define` block with additional commands:
```gdb
(gdb) define hack_verbose
> set {char[14]} 0x20000000 = {'h','a','c','k','y',',',' ','w','o','r','l','d','\r','\0'}
> x/20b 0x20000000
> set $r0 = 0x20000000
> set {char[13]} 0x20040000 = "hacky, world"
> x/20b 0x20040000
> set $r0 = 0x20040000
> info registers r0
> c
> end
+4 -4
View File
@@ -15,7 +15,7 @@ Create a reusable GDB command that injects a string into SRAM, repoints `r0`, an
- Familiarity with breaking at `0x1000023c` and injecting strings from prior exercises
#### Task Description
You will define a custom GDB command `hack` that writes a payload to `0x20000000`, repoints `r0`, and continues execution automatically.
You will define a custom GDB command `hack` that writes a payload to `0x20040000`, repoints `r0`, and continues execution automatically.
#### Step-by-Step Instructions
@@ -32,8 +32,8 @@ You will define a custom GDB command `hack` that writes a payload to `0x20000000
```gdb
(gdb) define hack
> set {char[14]} 0x20000000 = {'h','a','c','k','y',',',' ','w','o','r','l','d','\r','\0'}
> set $r0 = 0x20000000
> set {char[13]} 0x20040000 = "hacky, world"
> set $r0 = 0x20040000
> c
> end
```
@@ -56,7 +56,7 @@ You will define a custom GDB command `hack` that writes a payload to `0x20000000
###### Question 1: How could you parameterize the command to accept different strings or addresses?
###### Question 2: What happens if you define `hack` before setting the breakpointwill it still work as expected?
###### Question 2: What happens if you define `hack` before setting the breakpointwill it still work as expected?
###### Question 3: How would you adapt this pattern for multi-step routines (e.g., patch, dump, continue)?
Binary file not shown.
+121 -201
View File
@@ -97,7 +97,7 @@ Our goal: **Make it print something else WITHOUT changing the source code!**
└─────────────────────────────────────────────────────┘
```
> 🔄 **REVIEW:** In Week 1, we saw the stack pointer (SP) was around `0x20081fc8` - that's in the SRAM region! The stack "grows downward" from the top of SRAM.
> 🔄 **REVIEW:** In Week 1, we saw SP values in the `0x20081xxx` range (for example `0x20081fc8`) - that's in the SRAM region. In this run you may see values like `0x20081ff8` depending on where execution is paused. The stack "grows downward" from the top of SRAM.
#### Why This Matters for Our Hack
@@ -147,8 +147,8 @@ Before we start, make sure you have:
You will need **THREE** terminal windows:
1. **Terminal 1**: Running OpenOCD (the debug server)
2. **Terminal 2**: Running your serial monitor (to see output)
3. **Terminal 3**: Running GDB (where we do the hacking)
2. **Terminal 2**: Running GDB (where we do the hacking)
3. **PuTTY**: Running your serial monitor (to see output)
---
@@ -256,7 +256,8 @@ Now we need to connect GDB to OpenOCD. OpenOCD is listening on port `3333`.
```
Remote debugging using :3333
main () at 0x0001_hello-world/0x0001_hello-world.c:5.
main ()
at C:/Users/flare-vm/Desktop/Embedded-Hacking-main/0x0001_hello-world/0x0001_hello-world.c:5
5 stdio_init_all();
```
@@ -452,6 +453,24 @@ Before we execute the `push` instruction, let's see what's on the stack:
- The stack is empty (all zeros)
- This is the "top" of our stack in RAM
**Verify where this value came from (the Vector Table):**
Now let's trace back where this initial `0x20082000` value came from. It comes from the first entry in the vector table at `0x10000000`:
```gdb
(gdb) x/x $sp
0x20082000: 0x00000000
(gdb) x/x 0x10000000
0x10000000 <__vectors>: 0x20082000
```
**What this shows:**
- The first command `x/x $sp` reads one word at the stack pointer (currently `0x00000000`)
- The second command `x/x 0x10000000` reads the **first entry in the vector table** at address `0x10000000`
- That vector table entry contains `0x20082000` - this is the **initial stack pointer value**!
- The Boot ROM reads this value and puts it into the SP register when the chip starts
- This is why our SP register already has `0x20082000` before `main()` runs
##### Step 7: Execute One Instruction (Step Into)
Now let's execute just ONE assembly instruction:
@@ -740,143 +759,26 @@ There's our string! The `\r` is a carriage return character (part of `\r\n`).
---
## 🔬 Part 6: Starting the Debug Session for the Hack
## 🔬 Part 6: Continuing the Debug Session for the Hack
##### Step 1: Start OpenOCD (Debug Server)
You're right where you need to be from Part 5, so we **do not restart** OpenOCD or GDB here.
OpenOCD is the bridge between your computer and the Pico 2's debug interface. It creates a server that GDB can connect to.
Use this as a quick checkpoint before the hack:
**Open Terminal 1 and type:**
- OpenOCD is still running and listening on `:3333`
- GDB is still connected (`target extended-remote :3333` already done)
- The target is halted at a known point (or easy to re-halt)
```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"
```
If your session is still live, continue directly to Part 7.
**What this command means:**
- `openocd` = the OpenOCD program
- `-f interface/cmsis-dap.cfg` = use the CMSIS-DAP debug probe configuration
- `-f target/rp2350.cfg` = configure for the RP2350 chip
- `-c "adapter speed 5000"` = set the debug speed to 5000 kHz
**You should see output like:**
```
Open On-Chip Debugger 0.12.0
Licensed under GNU GPL v2
Info : Listening on port 3333 for gdb connections
Info : CMSIS-DAP: SWD supported
Info : CMSIS-DAP: Interface ready
```
**Important:** Leave this terminal running! Don't close it.
##### Step 2: Start Your Serial Monitor
**Open PuTTY** and start your serial monitor to watch the Pico 2's output.
**Example using screen (macOS/Linux):**
```bash
screen /dev/tty.usbmodem* 115200
```
**Example using minicom:**
```bash
minicom -D /dev/ttyACM0 -b 115200
```
**You should see:**
```
hello, world
hello, world
hello, world
hello, world
...
```
The program is running and printing `"hello, world"` in an infinite loop!
**Important:** Leave this terminal running! We'll watch it change when we hack the system.
##### Step 3: Start GDB and Load the Binary
**Open Terminal 3** and start GDB with your binary:
```powershell
arm-none-eabi-gdb build\0x0001_hello-world.elf
```
**What this command means:**
- `arm-none-eabi-gdb` = the ARM version of GDB
- `build\0x0001_hello-world.elf` = our compiled program with debug symbols
**You should see:**
```
GNU gdb (Arm GNU Toolchain 13.2) 13.2
Reading symbols from build\0x0001_hello-world.elf...
(gdb)
```
The `(gdb)` prompt means GDB is ready for commands!
##### Step 4: Connect to the Remote Debug Server
Now we need to connect GDB to OpenOCD. OpenOCD is listening on port `3333`.
**Type this command:**
If you got disconnected, run only this minimal recovery in GDB:
```gdb
(gdb) target extended-remote :3333
```
**What this command means:**
- `target remote` = connect to a remote debug server
- `:3333` = on localhost, port 3333 (where OpenOCD is listening)
**You should see:**
```
Remote debugging using :3333
warning: multi-threaded target stopped without sending a thread-id, using first non-exited thread
0x1000023c in main () at 0x0001_hello-world.c:8
8 printf("hello, world\r\n");
```
We're connected! GDB shows us the program is currently in the `main` function.
##### Step 5: Halt the Running Program
The program is still running (you can see "hello, world" still printing in your serial monitor). Let's stop it:
**Type this command:**
```gdb
(gdb) monitor reset halt
```
**What this command means:**
- `monitor` = send a command to OpenOCD (not GDB)
- `reset` = reset the processor
- `halt` = stop execution immediately
**You should see:**
```gdb
(gdb) monitor reset halt
[rp2350.cm0] halted due to debug-request, current mode: Thread
xPSR: 0xf9000000 pc: 0x00000088 msp: 0xf0000000
[rp2350.cm1] halted due to debug-request, current mode: Thread
xPSR: 0xf9000000 pc: 0x00000088 msp: 0xf0000000
```
**Check your serial monitor (Terminal 2):** The "hello, world" messages should have stopped! The processor is now frozen, waiting for our commands.
After that, continue to the analysis steps below.
---
@@ -906,7 +808,7 @@ Let's look at the main function to understand what we're dealing with:
0x10000234 <main>: push {r3, lr}
0x10000236 <main+2>: bl 0x1000156c <stdio_init_all>
0x1000023a <main+6>: ldr r0, [pc, #8] @ (0x10000244 <main+16>)
0x1000023c <main+8>: bl 0x100015fc <__wrap_puts>
=> 0x1000023c <main+8>: bl 0x100015fc <__wrap_puts>
0x10000240 <main+12>: b.n 0x1000023a <main+6>
```
@@ -966,8 +868,7 @@ We want to stop the program RIGHT BEFORE it calls `puts()`. That's at address `0
**You should see:**
```
Breakpoint 1 at 0x1000023c: file 0x0001_hello-world.c, line 8.
Note: automatically using hardware breakpoints for read-only addresses.
Breakpoint 2 at 0x1000023c: file C:/Users/flare-vm/Desktop/Embedded-Hacking-main/0x0001_hello-world/0x0001_hello-world.c, line 8
```
**What does "hardware breakpoints" mean?**
@@ -992,9 +893,9 @@ Now let's run the program until it hits our breakpoint:
```gdb
Continuing.
Thread 1 "rp2350.cm0" hit Breakpoint 1, 0x1000023c in main ()
at 0x0001_hello-world.c:8
8 printf("hello, world\r\n");
Thread 1 "rp2350.cm0" hit Breakpoint 2, 0x1000023c in main ()
at C:/Users/flare-vm/Desktop/Embedded-Hacking-main/0x0001_hello-world/0x0001_hello-world.c:8
8 printf("hello, world\r\n");
```
The program has stopped RIGHT BEFORE calling `puts()`! The string address is loaded into `r0`, but the function hasn't been called yet.
@@ -1053,7 +954,7 @@ Let's see what string `r0` is currently pointing to:
**You should see:**
```gdb
0x100019cc: "hello, world\r"
0x100019cc: "hello, world\r"
```
There it is! The register `r0` contains `0x100019cc`, which is the address of our `"hello, world"` string in flash memory.
@@ -1088,11 +989,13 @@ This is a very important lesson! Here's what happened:
1. When you type `"hacky, world\r"` in GDB, GDB interprets this as: "Create a new string and give me its address"
2. To create a new string at runtime, GDB would need to allocate memory using `malloc()`
2. To create a new string at runtime, GDB tries to allocate target memory using `malloc()`.
3. But our embedded system has **no operating system** and **no C runtime library loaded**! There's no `malloc()` function available.
3. If the target program exposed a working `malloc()` that GDB could call, this style of assignment can work.
4. GDB can't create the string because there's nowhere to put it!
4. In our case, this is a bare-metal firmware image and there is no usable `malloc()` path for GDB expression evaluation, so GDB cannot create temporary storage for that string literal.
5. That is why this command fails here, and why we switch to writing bytes directly into SRAM ourselves.
**Let's verify nothing changed:**
@@ -1103,7 +1006,7 @@ This is a very important lesson! Here's what happened:
**You should see:**
```
0x100019cc: "hello, world\r"
0x100019cc: "hello, world\r"
```
The original string is still there. Our hack attempt failed... but we're not giving up!
@@ -1119,13 +1022,13 @@ Since we can't use `malloc()`, we need to manually create our string somewhere i
- Flash (`0x10000000`): **Read-only** - can't write here
- SRAM (`0x20000000`): **Read-write** - we CAN write here!
> 🔄 **REVIEW:** In Week 1, we saw the stack pointer was at `0x20081fc8`. The stack lives at the TOP of SRAM and grows downward. We'll write our string at the BOTTOM of SRAM (`0x20000000`) to avoid conflicts!
> 🔄 **REVIEW:** In Week 1 we observed SP in the `0x20081xxx` range (for example `0x20081fc8`). In this run, after `push {r3, lr}`, you are seeing `0x20081ff8`, which is also correct and still near the top of SRAM. We'll write our string at a safer SRAM address (`0x20040000`) to avoid vector-table and stack conflicts.
We'll write our malicious string directly to SRAM, then point `r0` to it.
##### Step 13: Create Our Malicious String in SRAM
We need to write 14 bytes (13 characters + null terminator) to SRAM:
We need to write 13 bytes (12 characters + null terminator) to SRAM:
| Character | ASCII Hex |
| --------- | --------- |
@@ -1147,14 +1050,14 @@ We need to write 14 bytes (13 characters + null terminator) to SRAM:
**Type this command:**
```gdb
(gdb) set {char[14]} 0x20000000 = {'h','a','c','k','y',',',' ','w','o','r','l','d','\r','\0'}
(gdb) set {char[13]} 0x20040000 = "hacky, world"
```
**What this command means:**
- `set` = modify memory
- `{char[14]}` = treat the target as an array of 14 characters
- `0x20000000` = the address where we're writing (start of SRAM)
- `= {...}` = the characters to write
- `{char[13]}` = treat the target as an array of 13 characters
- `0x20040000` = the address where we're writing (safe SRAM offset)
- `= "hacky, world"` = the string bytes to write
**No output means success!**
@@ -1165,18 +1068,18 @@ Let's confirm our malicious string is in SRAM:
**Type this command:**
```gdb
(gdb) x/s 0x20000000
(gdb) x/s 0x20040000
```
**You should see:**
```gdb
0x20000000 <ram_vector_table>: "hacky, world\r"
0x20040000: "hacky, world"
```
**OUR STRING IS IN MEMORY!**
GDB shows it's at the `ram_vector_table` location - that's just a label from the linker script. The important thing is our string is there and ready to use.
The important thing is our string is in writable SRAM at a safe offset and ready to use.
---
@@ -1191,13 +1094,13 @@ Now for the magic moment! We'll change `r0` from pointing to the original string
**Type this command:**
```gdb
(gdb) set $r0 = 0x20000000
(gdb) set $r0 = 0x20040000
```
**What this command means:**
- `set` = modify a value
- `$r0` = the `r0` register
- `= 0x20000000` = change it to this address (where our string is)
- `= 0x20040000` = change it to this address (where our string is)
**No output means success!**
@@ -1205,19 +1108,33 @@ Now for the magic moment! We'll change `r0` from pointing to the original string
Let's confirm `r0` now points to our malicious string:
**First, check the raw value:**
**First, check one byte (explicit byte view):**
```gdb
(gdb) x/x $r0
(gdb) x/bx $r0
```
**You should see:**
```
0x20000000 <ram_vector_table>: 0x68
0x20040000: 0x68
```
The value `0x68` is the ASCII code for 'h' - the first character of "hacky"!
The value `0x68` is ASCII `'h'`, the first byte of `"hacky, world"`.
**Now check one 32-bit word (explicit word view):**
```gdb
(gdb) x/wx $r0
```
**You should see:**
```
0x20040000: 0x6b636168
```
This is the first 4 bytes (`h a c k`) packed into one 32-bit little-endian word.
**Now check it as a string:**
@@ -1228,7 +1145,7 @@ The value `0x68` is the ASCII code for 'h' - the first character of "hacky"!
**You should see:**
```
0x20000000 <ram_vector_table>: "hacky, world\r"
0x20040000: "hacky, world"
```
**THE HIJACK IS COMPLETE!** When `puts()` runs, it will read the string address from `r0` - which now points to our malicious string!
@@ -1252,9 +1169,9 @@ This is the moment of truth! Let's continue the program and watch our hack take
```gdb
Continuing.
Thread 1 "rp2350.cm0" hit Breakpoint 1, 0x1000023c in main ()
at 0x0001_hello-world.c:8
8 printf("hello, world\r\n");
Thread 1 "rp2350.cm0" hit Breakpoint 2, 0x1000023c in main ()
at C:/Users/flare-vm/Desktop/Embedded-Hacking-main/0x0001_hello-world/0x0001_hello-world.c:8
8 printf("hello, world\r\n");
```
The program ran through one loop iteration and hit our breakpoint again.
@@ -1305,40 +1222,41 @@ If you haven't already set up the Ghidra project from Week 1:
* FUNCTION
*************************************************************
int main (void )
assume LRset = 0x0
assume TMode = 0x1
int r0:4 <RETURN>
assume LRset = 0x0
assume TMode = 0x1
int r0:4 <RETURN>
main XREF[3]: Entry Point (*) ,
_reset_handler:1000018c (c) ,
.debug_frame::00000018 (*)
0x0001_hello-world.c:4 (2)
0x0001_hello-world.c:5 (2)
10000234 08 b5 push {r3,lr}
10000234 08 b5 push {r3,lr}
0x0001_hello-world.c:5 (4)
10000236 01 f0 99 f9 bl stdio_init_all _Bool stdio_init_all(void)
10000236 01 f0 99 f9 bl stdio_init_all _Bool stdio_init_all(void)
LAB_1000023a XREF[1]: 10000240 (j)
0x0001_hello-world.c:7 (6)
0x0001_hello-world.c:8 (6)
1000023a 02 48 ldr r0=>__EH_FRAME_BEGIN__ ,[DAT_10000244 ] = "hello, world\r"
1000023a 02 48 ldr r0=>__EH_FRAME_BEGIN__ ,[DAT_10000244 ] = "hello, world\r"
= 100019CCh
1000023c 01 f0 de f9 bl __wrap_puts int __wrap_puts(char * s)
1000023c 01 f0 de f9 bl __wrap_puts int __wrap_puts(char * s)
0x0001_hello-world.c:7 (8)
10000240 fb e7 b LAB_1000023a
10000240 fb e7 b LAB_1000023a
10000242 00 ?? 00h
10000243 bf ?? BFh
DAT_10000244 XREF[1]: main:1000023a (R)
10000244 cc 19 00 10 undefine 100019CCh ? -> 100019cc
10000244 cc 19 00 10 undefine 100019CCh ? -> 100019cc
```
**What you'll see in the Decompile View:**
```c
int main(void) {
stdio_init_all();
do {
__wrap_puts("hello, world");
} while (true);
int main(void)
{
stdio_init_all();
do {
__wrap_puts("hello, world\r");
} while( true );
}
```
@@ -1364,9 +1282,8 @@ Let's trace where the string actually lives:
LAB_1000023a XREF[1]: 10000240 (j)
0x0001_hello-world.c:7 (6)
0x0001_hello-world.c:8 (6)
1000023a 02 48 ldr r0=>__EH_FRAME_BEGIN__ ,[DAT_10000244 ] = "hello, world\r"
1000023a 02 48 ldr r0=>__EH_FRAME_BEGIN__ ,[DAT_10000244 ] = "hello, world\r"
= 100019CCh
```
2. **Double-click on `DAT_10000244`** to go to the data reference
@@ -1374,8 +1291,7 @@ Let's trace where the string actually lives:
3. You'll see:
```
DAT_10000244 XREF[1]: main:1000023a (R)
10000244 cc 19 00 10 undefine 100019CCh ? -> 100019cc
10000244 cc 19 00 10 undefine 100019CCh ? -> 100019cc
```
4. **Double-click on `100019CCh`** to navigate to the actual string
@@ -1393,10 +1309,9 @@ Let's trace where the string actually lives:
__boot2_end__ main:1000023a (*) ,
__EH_FRAME_BEGIN__ runtime_init:1000138a (R) ,
_elfSectionHeaders::0000005c (*)
100019cc 68 65 6c ds "hello, world\r"
100019cc 68 65 6c ds "hello, world\r"
6c 6f 2c
20 77 6f
```
##### Step 4: Understand Why We Needed SRAM
@@ -1410,7 +1325,7 @@ This starts with `0x10...` which means it's in **Flash memory (XIP region)**!
| `0x10000000`+ | Flash (XIP) | **NO** - Read Only |
| `0x20000000`+ | SRAM | **YES** - Read/Write |
> 🎯 **This is why our direct string modification failed in GDB!** The string lives in flash memory, which is read-only at runtime. We had to create our malicious string in SRAM (`0x20000000`) instead.
> 🎯 **This is why our direct string modification failed in GDB!** The string lives in flash memory, which is read-only at runtime. We had to create our malicious string in SRAM at a safe address (`0x20040000`) instead.
##### Step 5: Examine Cross-References
@@ -1427,11 +1342,13 @@ This shows every place that calls `puts()`. In a larger program, you could find
The Decompile view makes attack planning easy:
```c
int main(void) {
stdio_init_all();
do {
__wrap_puts("hello, world"); // <-- Attack target identified!
} while (true);
int main(void)
{
stdio_init_all();
do {
__wrap_puts("hello, world\r");
} while( true );
}
```
@@ -1455,10 +1372,9 @@ When you navigate to the string address `0x100019cc`, you'll see the string stor
__boot2_end__ main:1000023a (*) ,
__EH_FRAME_BEGIN__ runtime_init:1000138a (R) ,
_elfSectionHeaders::0000005c (*)
100019cc 68 65 6c ds "hello, world\r"
100019cc 68 65 6c ds "hello, world\r"
6c 6f 2c
20 77 6f
```
This shows the raw bytes of our string: `68 65 6c 6c 6f 2c 20 77 6f...` which spell out "hello, world\r" in ASCII.
@@ -1484,7 +1400,7 @@ Ghidra allows you to modify data directly in the binary! Here's how to patch the
After patching, you'll see the change reflected in the Listing view:
```
100019cc 68 61 63 ds "hacky, world\r"
100019cc 68 61 63 ds "hacky, world\r"
6b 79 2c
20 77 6f
```
@@ -1499,8 +1415,6 @@ In future lessons, we will learn how to:
1. **Export the patched binary** from Ghidra to create a modified `.elf` or `.bin` file
2. **Flash the patched binary** to the Pico 2, making the hack **persistent**
3. **Understand patch verification** - how defenders detect modified binaries
4. **Bypass integrity checks** that try to prevent patching
The key difference:
@@ -1577,7 +1491,7 @@ BEFORE OUR HACK:
AFTER OUR HACK:
┌─────────────────┐ ┌──────────────────────────────┐
│ r0 = 0x20000000│ ───> │ SRAM: "hacky, world\r" │
│ r0 = 0x20040000│ ───> │ SRAM: "hacky, world"
└─────────────────┘ └──────────────────────────────┘
@@ -1605,18 +1519,24 @@ AFTER OUR HACK:
| `0x10000234` | Start of `main()` function | Read-only |
| `0x1000023c` | The `bl __wrap_puts` call | Read-only |
| `0x100019cc` | Original `"hello, world"` string | Read-only |
| `0x20000000` | Start of SRAM (our hack target) | Read-Write |
| `0x20040000` | Safe SRAM location (hack target) | Read-Write |
---
## ✅ Practice Exercises
These prompts are intentionally aligned 1:1 with the Week 2 exercise and solution files:
- `WEEK02-01.md` and `WEEK02-01-S.md`
- `WEEK02-02.md` and `WEEK02-02-S.md`
- `WEEK02-03.md` and `WEEK02-03-S.md`
- `WEEK02-04.md` and `WEEK02-04-S.md`
#### Exercise 1: Change the Message
Try creating a different message! Write your name to SRAM and make the program print it:
```gdb
(gdb) set {char[20]} 0x20000000 = {'Y','o','u','r',' ','N','a','m','e','!','\r','\0'}
(gdb) set $r0 = 0x20000000
(gdb) set {char[12]} 0x20040000 = {'Y','o','u','r',' ','N','a','m','e','!','\r','\0'}
(gdb) set $r0 = 0x20040000
(gdb) c
```
@@ -1624,8 +1544,8 @@ Try creating a different message! Write your name to SRAM and make the program p
The SRAM region is large. Try writing your string to a different address:
```gdb
(gdb) set {char[14]} 0x20001000 = {'h','a','c','k','e','d','!','!','!','\r','\0'}
(gdb) set $r0 = 0x20001000
(gdb) set {char[14]} 0x20041000 = {'h','a','c','k','e','d','!','!','!','\r','\0'}
(gdb) set $r0 = 0x20041000
(gdb) c
```
@@ -1633,7 +1553,7 @@ The SRAM region is large. Try writing your string to a different address:
Look at the bytes around your injected string:
```gdb
(gdb) x/20b 0x20000000
(gdb) x/20b 0x20040000
```
What do you see? Can you identify each character?
@@ -1643,8 +1563,8 @@ Create a GDB command sequence that does the full hack. You can use GDB's command
```gdb
(gdb) define hack
> set {char[14]} 0x20000000 = {'h','a','c','k','y',',',' ','w','o','r','l','d','\r','\0'}
> set $r0 = 0x20000000
> set {char[13]} 0x20040000 = "hacky, world"
> set $r0 = 0x20040000
> c
> end
(gdb) hack
+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 02</text>
<!-- Week Topic -->
<text x="600" y="440" text-anchor="middle" font-family="'Courier New',monospace" font-size="28" fill="#c0c0c0">Hello, World - Debugging and</text>
<text x="600" y="478" text-anchor="middle" font-family="'Courier New',monospace" font-size="28" fill="#c0c0c0">Hacking Basics: Debugging and Hacking</text>
<text x="600" y="516" text-anchor="middle" font-family="'Courier New',monospace" font-size="28" fill="#c0c0c0">a Basic Program for the Pico 2</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

+73
View File
@@ -0,0 +1,73 @@
<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"/>
<!-- Title -->
<text x="600" y="52" text-anchor="middle" class="title">Live Hacking Overview</text>
<text x="600" y="88" text-anchor="middle" class="dim">Introduction to Live Hacking</text>
<!-- Left Panel: What is live hacking -->
<rect x="30" y="105" width="540" height="675" class="pnl" rx="8"/>
<text x="300" y="148" text-anchor="middle" class="sub">What Is Live Hacking?</text>
<line x1="50" y1="163" x2="550" y2="163" stroke="#1a1a2e"/>
<text x="55" y="205" class="txt">Modify a program</text>
<text x="55" y="237" class="txt">WHILE it is running</text>
<text x="55" y="269" class="txt">on real hardware</text>
<line x1="50" y1="297" x2="550" y2="297" stroke="#1a1a2e"/>
<text x="55" y="337" class="amb">The Train Analogy</text>
<text x="55" y="372" class="txt">Train heading to NYC</text>
<text x="55" y="404" class="txt">Switch the tracks</text>
<text x="55" y="436" class="txt">while it moves</text>
<text x="55" y="468" class="red">Now it goes to LA!</text>
<line x1="50" y1="496" x2="550" y2="496" stroke="#1a1a2e"/>
<text x="55" y="536" class="cyn">Why It Matters</text>
<text x="55" y="571" class="txt">Security research</text>
<text x="55" y="603" class="txt">Penetration testing</text>
<text x="55" y="635" class="txt">Malware analysis</text>
<text x="55" y="667" class="txt">Hardware debugging</text>
<text x="300" y="740" text-anchor="middle" class="dim">No recompile needed!</text>
<!-- Right Panel: This Week's Goal -->
<rect x="600" y="105" width="570" height="675" class="pnl" rx="8"/>
<text x="885" y="148" text-anchor="middle" class="sub">This Week's Goal</text>
<line x1="620" y1="163" x2="1150" y2="163" stroke="#1a1a2e"/>
<text x="625" y="205" class="grn">Target Program</text>
<text x="625" y="240" class="txt">hello-world.c</text>
<text x="625" y="272" class="txt">Prints "hello, world"</text>
<text x="625" y="304" class="txt">in infinite loop</text>
<line x1="620" y1="332" x2="1150" y2="332" stroke="#1a1a2e"/>
<text x="625" y="372" class="red">Our Mission</text>
<text x="625" y="407" class="txt">Make it print</text>
<text x="625" y="439" class="txt">something ELSE</text>
<text x="625" y="471" class="txt">without changing</text>
<text x="625" y="503" class="txt">the source code</text>
<line x1="620" y1="531" x2="1150" y2="531" stroke="#1a1a2e"/>
<text x="625" y="571" class="amb">Tools Used</text>
<text x="625" y="606" class="txt">GDB = live debug</text>
<text x="625" y="638" class="txt">OpenOCD = HW bridge</text>
<text x="625" y="670" class="txt">Ghidra = analysis</text>
<text x="885" y="745" text-anchor="middle" class="dim">Hack the running binary</text>
</svg>
+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}
.cmd{font:bold 18px 'Courier New',monospace}
.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"/>
<!-- Title -->
<text x="600" y="52" text-anchor="middle" class="title">GDB Debug Session</text>
<text x="600" y="88" text-anchor="middle" class="dim">GDB Fundamentals</text>
<!-- Left Panel: Connection Steps -->
<rect x="30" y="105" width="540" height="675" class="pnl" rx="8"/>
<text x="300" y="148" text-anchor="middle" class="sub">Setup Steps</text>
<line x1="50" y1="163" x2="550" y2="163" stroke="#1a1a2e"/>
<!-- Step 1 -->
<text x="55" y="198" class="dim">Step 1: Start OpenOCD</text>
<rect x="55" y="213" width="490" height="88" rx="5" fill="#0f0f1a" stroke="#00d4ff" stroke-width="2"/>
<text x="300" y="233" text-anchor="middle" class="cyn cmd">openocd -s &lt;scripts&gt;</text>
<text x="300" y="253" text-anchor="middle" class="cyn cmd">-f interface/cmsis-dap.cfg</text>
<text x="300" y="273" text-anchor="middle" class="cyn cmd">-f target/rp2350.cfg</text>
<text x="300" y="293" text-anchor="middle" class="cyn cmd">-c "adapter speed 5000"</text>
<!-- Step 2 -->
<text x="55" y="331" class="dim">Step 2: Launch GDB</text>
<rect x="55" y="346" width="490" height="58" rx="5" fill="#0f1a0f" stroke="#00ff41" stroke-width="2"/>
<text x="300" y="369" text-anchor="middle" class="grn cmd">arm-none-eabi-gdb</text>
<text x="300" y="391" text-anchor="middle" class="grn cmd">build\0x0001_hello-world.elf</text>
<!-- Step 3 -->
<text x="55" y="434" class="dim">Step 3: Connect to target</text>
<rect x="55" y="449" width="490" height="50" rx="5" fill="#1a1a0f" stroke="#ffaa00" stroke-width="2"/>
<text x="300" y="481" text-anchor="middle" class="amb">target extended-remote :3333</text>
<!-- Step 4 -->
<text x="55" y="529" class="dim">Step 4: Reset + halt</text>
<rect x="55" y="544" width="490" height="50" rx="5" fill="#1a0f0f" stroke="#ff0040" stroke-width="2"/>
<text x="300" y="576" text-anchor="middle" class="red">monitor reset halt</text>
<!-- Step 5 -->
<text x="55" y="624" class="dim">Step 5: Set breakpoint</text>
<rect x="55" y="639" width="490" height="50" rx="5" fill="#0f1a0f" stroke="#00ff41" stroke-width="2"/>
<text x="300" y="671" text-anchor="middle" class="grn">break main</text>
<text x="300" y="725" text-anchor="middle" class="dim">Then: continue (c)</text>
<!-- Right Panel: What Each Does -->
<rect x="600" y="105" width="570" height="675" class="pnl" rx="8"/>
<text x="885" y="148" text-anchor="middle" class="sub">What Each Does</text>
<line x1="620" y1="163" x2="1150" y2="163" stroke="#1a1a2e"/>
<text x="625" y="205" class="cyn">openocd</text>
<text x="625" y="240" class="txt">Loads probe + chip</text>
<text x="625" y="272" class="txt">config files</text>
<text x="625" y="304" class="dim">Then listens on :3333</text>
<line x1="620" y1="337" x2="1150" y2="337" stroke="#1a1a2e"/>
<text x="625" y="377" class="grn">arm-none-eabi-gdb</text>
<text x="625" y="412" class="txt">ARM debugger from</text>
<text x="625" y="444" class="txt">the embedded toolchain</text>
<line x1="620" y1="472" x2="1150" y2="472" stroke="#1a1a2e"/>
<text x="625" y="512" class="amb">target extended-remote</text>
<text x="625" y="547" class="txt">GDB connects to</text>
<text x="625" y="579" class="txt">OpenOCD server</text>
<line x1="620" y1="607" x2="1150" y2="607" stroke="#1a1a2e"/>
<text x="625" y="647" class="red">monitor reset halt</text>
<text x="625" y="682" class="txt">Reset chip + stop</text>
<text x="625" y="714" class="txt">at very first instr</text>
<text x="625" y="746" class="dim">Clean starting state</text>
</svg>
+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"/>
<!-- Title -->
<text x="600" y="52" text-anchor="middle" class="title">Breakpoints</text>
<text x="600" y="88" text-anchor="middle" class="dim">GDB Breakpoint Types</text>
<!-- Left Panel: How Breakpoints Work -->
<rect x="30" y="105" width="540" height="675" class="pnl" rx="8"/>
<text x="300" y="148" text-anchor="middle" class="sub">How They Work</text>
<line x1="50" y1="163" x2="550" y2="163" stroke="#1a1a2e"/>
<!-- Normal execution -->
<text x="55" y="203" class="grn">Normal Execution</text>
<rect x="55" y="220" width="490" height="42" rx="4" fill="#0a0a0f" stroke="#1a1a2e"/>
<text x="70" y="248" class="txt">MOV r0, #5</text>
<rect x="55" y="272" width="490" height="42" rx="4" fill="#0a0a0f" stroke="#1a1a2e"/>
<text x="70" y="300" class="txt">MOV r1, #3</text>
<rect x="55" y="324" width="490" height="42" rx="4" fill="#0a0a0f" stroke="#1a1a2e"/>
<text x="70" y="352" class="txt">BL printf</text>
<!-- Breakpoint set -->
<text x="55" y="410" class="red">With Breakpoint</text>
<rect x="55" y="427" width="490" height="42" rx="4" fill="#0a0a0f" stroke="#1a1a2e"/>
<text x="70" y="455" class="txt">MOV r0, #5</text>
<rect x="55" y="479" width="490" height="42" rx="4" fill="#1a0f0f" stroke="#ff0040" stroke-width="2"/>
<text x="70" y="507" class="red">MOV r1, #3</text>
<text x="520" y="507" text-anchor="end" class="red">STOP</text>
<rect x="55" y="531" width="490" height="42" rx="4" fill="#0a0a0f" stroke="#1a1a2e" stroke-dasharray="6"/>
<text x="70" y="559" class="txt">BL printf</text>
<text x="520" y="559" text-anchor="end" class="dim">paused</text>
<text x="300" y="620" text-anchor="middle" class="txt">CPU halts BEFORE</text>
<text x="300" y="652" text-anchor="middle" class="txt">executing breakpoint</text>
<text x="300" y="684" text-anchor="middle" class="txt">instruction</text>
<text x="300" y="740" text-anchor="middle" class="dim">Now you can inspect</text>
<!-- Right Panel: GDB Commands -->
<rect x="600" y="105" width="570" height="675" class="pnl" rx="8"/>
<text x="885" y="148" text-anchor="middle" class="sub">GDB Breakpoints</text>
<line x1="620" y1="163" x2="1150" y2="163" stroke="#1a1a2e"/>
<text x="625" y="205" class="grn">break main</text>
<text x="625" y="240" class="txt">Stop at function</text>
<text x="625" y="272" class="dim">By symbol name</text>
<line x1="620" y1="300" x2="1150" y2="300" stroke="#1a1a2e"/>
<text x="625" y="340" class="grn">break *0x10000340</text>
<text x="625" y="375" class="txt">Stop at exact addr</text>
<text x="625" y="407" class="dim">By hex address</text>
<line x1="620" y1="435" x2="1150" y2="435" stroke="#1a1a2e"/>
<text x="625" y="475" class="cyn">info break</text>
<text x="625" y="510" class="txt">List all active</text>
<text x="625" y="542" class="txt">breakpoints</text>
<line x1="620" y1="570" x2="1150" y2="570" stroke="#1a1a2e"/>
<text x="625" y="610" class="amb">continue (c)</text>
<text x="625" y="645" class="txt">Resume running</text>
<text x="625" y="677" class="txt">until next break</text>
<line x1="620" y1="705" x2="1150" y2="705" stroke="#1a1a2e"/>
<text x="625" y="745" class="red">delete 1</text>
<text x="625" y="777" class="txt">Remove breakpoint #1</text>
</svg>
+102
View File
@@ -0,0 +1,102 @@
<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"/>
<!-- Title -->
<text x="600" y="52" text-anchor="middle" class="title">Stack in Action</text>
<text x="600" y="88" text-anchor="middle" class="dim">Runtime Stack Analysis</text>
<!-- Left Panel: Before Call -->
<rect x="30" y="105" width="350" height="675" class="pnl" rx="8"/>
<text x="205" y="148" text-anchor="middle" class="sub">Before Call</text>
<line x1="50" y1="163" x2="360" y2="163" stroke="#1a1a2e"/>
<text x="55" y="205" class="amb">0x20082000</text>
<text x="55" y="237" class="red">SP here</text>
<rect x="60" y="260" width="255" height="55" rx="5" fill="#0a0a0f" stroke="#1a1a2e" stroke-width="1" stroke-dasharray="6"/>
<text x="187" y="295" text-anchor="middle" class="dim">empty (0x20081FFC)</text>
<rect x="60" y="325" width="255" height="55" rx="5" fill="#0a0a0f" stroke="#1a1a2e" stroke-width="1" stroke-dasharray="6"/>
<text x="187" y="360" text-anchor="middle" class="dim">empty (0x20081FF8)</text>
<rect x="60" y="390" width="255" height="55" rx="5" fill="#0a0a0f" stroke="#1a1a2e" stroke-width="1" stroke-dasharray="6"/>
<text x="187" y="425" text-anchor="middle" class="dim">free stack space</text>
<rect x="60" y="455" width="255" height="55" rx="5" fill="#0a0a0f" stroke="#1a1a2e" stroke-width="1" stroke-dasharray="6"/>
<text x="187" y="490" text-anchor="middle" class="dim">unused lower space</text>
<text x="55" y="555" class="amb">0x20080000</text>
<text x="205" y="650" text-anchor="middle" class="red">Grows DOWN</text>
<line x1="205" y1="665" x2="205" y2="725" stroke="#ff0040" stroke-width="4"/>
<polygon points="193,725 205,750 217,725" fill="#ff0040"/>
<!-- Middle Panel: After PUSH {r4, lr} -->
<rect x="410" y="105" width="370" height="675" class="pnl" rx="8"/>
<text x="595" y="148" text-anchor="middle" class="sub">After PUSH</text>
<line x1="430" y1="163" x2="760" y2="163" stroke="#1a1a2e"/>
<text x="435" y="205" class="amb">0x20082000</text>
<text x="435" y="237" class="red">PUSH {r4, lr}</text>
<rect x="440" y="260" width="255" height="55" rx="5" fill="#1a0f0f" stroke="#ff0040" stroke-width="2"/>
<text x="567" y="295" text-anchor="middle" class="red">saved LR</text>
<rect x="440" y="325" width="255" height="55" rx="5" fill="#1a1a0f" stroke="#ffaa00" stroke-width="2"/>
<text x="567" y="360" text-anchor="middle" class="amb">saved r4</text>
<rect x="440" y="390" width="255" height="55" rx="5" fill="#0a0a0f" stroke="#1a1a2e" stroke-width="1" stroke-dasharray="6"/>
<text x="567" y="425" text-anchor="middle" class="dim">free stack space</text>
<rect x="440" y="455" width="255" height="55" rx="5" fill="#0a0a0f" stroke="#1a1a2e" stroke-width="1" stroke-dasharray="6"/>
<text x="567" y="490" text-anchor="middle" class="dim">free stack space</text>
<text x="435" y="555" class="red">SP now = 0x20081FF8</text>
<text x="435" y="620" class="dim" style="fill:#ff0040">SP moved down</text>
<text x="435" y="650" class="dim" style="fill:#ff0040">by 8 bytes</text>
<text x="435" y="720" class="cyn">GDB: x/4xw $sp</text>
<text x="435" y="752" class="dim">saved regs are now visible</text>
<!-- Right Panel: Key Points -->
<rect x="810" y="105" width="360" height="675" class="pnl" rx="8"/>
<text x="990" y="148" text-anchor="middle" class="sub">Key Points</text>
<line x1="830" y1="163" x2="1150" y2="163" stroke="#1a1a2e"/>
<text x="835" y="205" class="grn">PUSH saves</text>
<text x="835" y="240" class="txt">Preserves regs</text>
<text x="835" y="272" class="txt">before function</text>
<text x="835" y="304" class="txt">body runs</text>
<line x1="830" y1="332" x2="1150" y2="332" stroke="#1a1a2e"/>
<text x="835" y="372" class="red">POP restores</text>
<text x="835" y="407" class="txt">Puts values</text>
<text x="835" y="439" class="txt">back when func</text>
<text x="835" y="471" class="txt">returns</text>
<line x1="830" y1="499" x2="1150" y2="499" stroke="#1a1a2e"/>
<text x="835" y="539" class="amb">Watch in GDB</text>
<text x="835" y="574" class="txt">x/4xw $sp</text>
<text x="835" y="606" class="dim">See stack data</text>
<line x1="830" y1="634" x2="1150" y2="634" stroke="#1a1a2e"/>
<text x="835" y="674" class="cyn">stepi</text>
<text x="835" y="709" class="txt">Step 1 instr</text>
<text x="835" y="741" class="txt">watch stack</text>
<text x="835" y="773" class="dim">change live</text>
</svg>
+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"/>
<!-- Title -->
<text x="600" y="52" text-anchor="middle" class="title">LDR Instruction</text>
<text x="600" y="88" text-anchor="middle" class="dim">ARM Load Instructions</text>
<!-- Left Panel: LDR Flow -->
<rect x="30" y="105" width="540" height="675" class="pnl" rx="8"/>
<text x="300" y="148" text-anchor="middle" class="sub">How LDR Works</text>
<line x1="50" y1="163" x2="550" y2="163" stroke="#1a1a2e"/>
<!-- The instruction -->
<text x="55" y="205" class="dim">Instruction:</text>
<rect x="55" y="220" width="490" height="50" rx="5" fill="#0f1a0f" stroke="#00ff41" stroke-width="2"/>
<text x="300" y="252" text-anchor="middle" class="grn">LDR r0, [pc, #12]</text>
<!-- Step 1 -->
<text x="55" y="315" class="amb">Step 1: Calculate addr</text>
<rect x="55" y="335" width="490" height="50" rx="5" fill="#0a0a0f" stroke="#1a1a2e"/>
<text x="300" y="367" text-anchor="middle" class="txt">addr = PC + 12</text>
<!-- Step 2 -->
<text x="55" y="430" class="amb">Step 2: Read memory</text>
<rect x="55" y="450" width="490" height="50" rx="5" fill="#0a0a0f" stroke="#1a1a2e"/>
<text x="300" y="482" text-anchor="middle" class="txt">value = *(addr)</text>
<!-- Step 3 -->
<text x="55" y="545" class="amb">Step 3: Load into reg</text>
<rect x="55" y="565" width="490" height="50" rx="5" fill="#0f0f1a" stroke="#00d4ff" stroke-width="2"/>
<text x="300" y="597" text-anchor="middle" class="cyn">r0 = value</text>
<!-- Result -->
<text x="300" y="670" text-anchor="middle" class="txt">r0 now holds the</text>
<text x="300" y="702" text-anchor="middle" class="txt">address of our</text>
<text x="300" y="734" text-anchor="middle" class="grn">"hello, world" string</text>
<!-- Right Panel: Why It Matters -->
<rect x="600" y="105" width="570" height="675" class="pnl" rx="8"/>
<text x="885" y="148" text-anchor="middle" class="sub">Why It Matters</text>
<line x1="620" y1="163" x2="1150" y2="163" stroke="#1a1a2e"/>
<text x="625" y="205" class="grn">String Loading</text>
<text x="625" y="240" class="txt">printf needs addr</text>
<text x="625" y="272" class="txt">of string in r0</text>
<text x="625" y="304" class="dim">r0 = first argument</text>
<line x1="620" y1="332" x2="1150" y2="332" stroke="#1a1a2e"/>
<text x="625" y="372" class="cyn">PC-Relative</text>
<text x="625" y="407" class="txt">Address computed</text>
<text x="625" y="439" class="txt">relative to current</text>
<text x="625" y="471" class="txt">PC position</text>
<text x="625" y="503" class="dim">Works from any addr</text>
<line x1="620" y1="531" x2="1150" y2="531" stroke="#1a1a2e"/>
<text x="625" y="571" class="red">The Attack Point</text>
<text x="625" y="606" class="txt">If we change r0</text>
<text x="625" y="638" class="txt">AFTER the LDR</text>
<text x="625" y="670" class="txt">printf prints OUR</text>
<text x="625" y="702" class="txt">string instead!</text>
<line x1="620" y1="730" x2="1150" y2="730" stroke="#1a1a2e"/>
<text x="625" y="765" class="amb">This is the hack!</text>
</svg>
+93
View File
@@ -0,0 +1,93 @@
<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"/>
<!-- Title -->
<text x="600" y="52" text-anchor="middle" class="title">The Attack Plan</text>
<text x="600" y="88" text-anchor="middle" class="dim">Exploit Strategy</text>
<!-- Full Width: 4-Step Attack Flow -->
<rect x="30" y="105" width="1140" height="280" class="pnl" rx="8"/>
<text x="600" y="148" text-anchor="middle" class="sub">Attack Flow (4 Steps)</text>
<line x1="50" y1="163" x2="1150" y2="163" stroke="#1a1a2e"/>
<!-- Step 1 -->
<rect x="55" y="185" width="230" height="80" rx="6" fill="#0f0f1a" stroke="#00d4ff" stroke-width="2"/>
<text x="170" y="220" text-anchor="middle" class="cyn">1. Break at</text>
<text x="170" y="250" text-anchor="middle" class="cyn">printf call</text>
<!-- Arrow -->
<line x1="285" y1="225" x2="330" y2="225" stroke="#888888" stroke-width="3"/>
<polygon points="330,215 355,225 330,235" fill="#888888"/>
<!-- Step 2 -->
<rect x="360" y="185" width="230" height="80" rx="6" fill="#0f1a0f" stroke="#00ff41" stroke-width="2"/>
<text x="475" y="220" text-anchor="middle" class="grn">2. Write new</text>
<text x="475" y="250" text-anchor="middle" class="grn">string to SRAM</text>
<!-- Arrow -->
<line x1="590" y1="225" x2="635" y2="225" stroke="#888888" stroke-width="3"/>
<polygon points="635,215 660,225 635,235" fill="#888888"/>
<!-- Step 3 -->
<rect x="665" y="185" width="230" height="80" rx="6" fill="#1a1a0f" stroke="#ffaa00" stroke-width="2"/>
<text x="780" y="220" text-anchor="middle" class="amb">3. Set r0 to</text>
<text x="780" y="250" text-anchor="middle" class="amb">SRAM addr</text>
<!-- Arrow -->
<line x1="895" y1="225" x2="940" y2="225" stroke="#888888" stroke-width="3"/>
<polygon points="940,215 965,225 940,235" fill="#888888"/>
<!-- Step 4 -->
<rect x="970" y="185" width="180" height="80" rx="6" fill="#1a0f0f" stroke="#ff0040" stroke-width="2"/>
<text x="1060" y="220" text-anchor="middle" class="red">4. Continue</text>
<text x="1060" y="250" text-anchor="middle" class="red">execution</text>
<text x="600" y="340" text-anchor="middle" class="txt">printf reads r0, prints "hacky, world"!</text>
<!-- Bottom Left: Normal Flow -->
<rect x="30" y="405" width="560" height="375" class="pnl" rx="8"/>
<text x="310" y="448" text-anchor="middle" class="sub">Normal Flow</text>
<line x1="50" y1="463" x2="570" y2="463" stroke="#1a1a2e"/>
<rect x="55" y="485" width="500" height="42" rx="4" fill="#0a0a0f" stroke="#1a1a2e"/>
<text x="70" y="513" class="txt">LDR r0, ="hello"</text>
<rect x="55" y="537" width="500" height="42" rx="4" fill="#0a0a0f" stroke="#1a1a2e"/>
<text x="70" y="565" class="txt">BL printf</text>
<text x="310" y="630" text-anchor="middle" class="grn">Output:</text>
<text x="310" y="665" text-anchor="middle" class="txt">"hello, world"</text>
<text x="310" y="735" text-anchor="middle" class="dim">Prints original string</text>
<!-- Bottom Right: Hacked Flow -->
<rect x="620" y="405" width="550" height="375" class="pnl" rx="8"/>
<text x="895" y="448" text-anchor="middle" class="sub">Hacked Flow</text>
<line x1="640" y1="463" x2="1150" y2="463" stroke="#1a1a2e"/>
<rect x="645" y="485" width="500" height="42" rx="4" fill="#0a0a0f" stroke="#1a1a2e"/>
<text x="660" y="513" class="txt">LDR r0, ="hello"</text>
<rect x="645" y="537" width="500" height="42" rx="4" fill="#1a0f0f" stroke="#ff0040" stroke-width="2"/>
<text x="660" y="565" class="red">r0 = 0x20040000</text>
<rect x="645" y="589" width="500" height="42" rx="4" fill="#0a0a0f" stroke="#1a1a2e"/>
<text x="660" y="617" class="txt">BL printf</text>
<text x="895" y="682" text-anchor="middle" class="red">Output:</text>
<text x="895" y="717" text-anchor="middle" class="txt">"hacky, world"</text>
<text x="895" y="755" text-anchor="middle" class="dim">Prints our string</text>
</svg>
+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"/>
<!-- Title -->
<text x="600" y="52" text-anchor="middle" class="title">Failed vs Real Hack</text>
<text x="600" y="88" text-anchor="middle" class="dim">Attack Methodology</text>
<!-- Left Panel: Failed Attempt -->
<rect x="30" y="105" width="560" height="675" class="pnl" rx="8"/>
<text x="310" y="148" text-anchor="middle" class="sub">Failed Attempt</text>
<line x1="50" y1="163" x2="570" y2="163" stroke="#1a1a2e"/>
<text x="55" y="205" class="red">The Bad Idea</text>
<text x="55" y="240" class="txt">Set r0 to point</text>
<text x="55" y="272" class="txt">at a string literal</text>
<text x="55" y="304" class="txt">like "hacky"</text>
<line x1="50" y1="332" x2="570" y2="332" stroke="#1a1a2e"/>
<text x="55" y="372" class="amb">Why It Fails</text>
<text x="55" y="407" class="txt">r0 only holds a</text>
<text x="55" y="439" class="txt">32-bit number</text>
<text x="55" y="471" class="txt">Not a string itself!</text>
<line x1="50" y1="499" x2="570" y2="499" stroke="#1a1a2e"/>
<text x="55" y="539" class="red">set $r0 = "HACK"</text>
<text x="55" y="574" class="txt">GDB interprets this</text>
<text x="55" y="611" class="txt">as an address value</text>
<text x="55" y="643" class="txt">pointing to garbage</text>
<line x1="50" y1="671" x2="570" y2="671" stroke="#1a1a2e"/>
<text x="310" y="710" text-anchor="middle" class="red">Result: CRASH</text>
<text x="310" y="745" text-anchor="middle" class="dim">or prints garbage</text>
<!-- Right Panel: Real Hack -->
<rect x="620" y="105" width="550" height="675" class="pnl" rx="8"/>
<text x="895" y="148" text-anchor="middle" class="sub">Real Hack</text>
<line x1="640" y1="163" x2="1150" y2="163" stroke="#1a1a2e"/>
<text x="645" y="205" class="grn">The Right Way</text>
<text x="645" y="240" class="txt">1. Write string</text>
<text x="645" y="272" class="txt"> bytes to SRAM</text>
<text x="645" y="304" class="txt">2. Point r0 to</text>
<text x="645" y="336" class="txt"> that SRAM addr</text>
<line x1="640" y1="364" x2="1150" y2="364" stroke="#1a1a2e"/>
<text x="645" y="404" class="cyn">GDB Commands</text>
<rect x="645" y="425" width="480" height="42" rx="4" fill="#0a0a0f" stroke="#1a1a2e"/>
<text x="660" y="453" class="grn">set {char[13]}0x20040000</text>
<rect x="645" y="477" width="480" height="42" rx="4" fill="#0a0a0f" stroke="#1a1a2e"/>
<text x="660" y="505" class="grn"> = "hacky, world"</text>
<rect x="645" y="539" width="480" height="42" rx="4" fill="#0a0a0f" stroke="#1a1a2e"/>
<text x="660" y="567" class="amb">set $r0 = 0x20040000</text>
<line x1="640" y1="610" x2="1150" y2="610" stroke="#1a1a2e"/>
<text x="645" y="650" class="txt">String exists in</text>
<text x="645" y="682" class="txt">writable SRAM</text>
<text x="645" y="714" class="txt">r0 points to it</text>
<text x="895" y="760" text-anchor="middle" class="grn">"hacky, world" printed!</text>
</svg>
+83
View File
@@ -0,0 +1,83 @@
<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"/>
<!-- Title -->
<text x="600" y="52" text-anchor="middle" class="title">Writing to SRAM</text>
<text x="600" y="88" text-anchor="middle" class="dim">Memory Manipulation</text>
<!-- Left Panel: Memory View -->
<rect x="30" y="105" width="540" height="675" class="pnl" rx="8"/>
<text x="300" y="148" text-anchor="middle" class="sub">SRAM at 0x20040000</text>
<line x1="50" y1="163" x2="550" y2="163" stroke="#1a1a2e"/>
<!-- Before -->
<text x="55" y="205" class="red">Before (empty)</text>
<rect x="55" y="225" width="490" height="42" rx="4" fill="#0a0a0f" stroke="#1a1a2e"/>
<text x="70" y="253" class="dim">00 00 00 00 00 00 00 00</text>
<rect x="55" y="277" width="490" height="42" rx="4" fill="#0a0a0f" stroke="#1a1a2e"/>
<text x="70" y="305" class="dim">00 00 00 00 00 00 00 00</text>
<!-- After -->
<text x="55" y="370" class="grn">After writing</text>
<rect x="55" y="390" width="490" height="42" rx="4" fill="#0f1a0f" stroke="#00ff41" stroke-width="2"/>
<text x="70" y="418" class="grn">68 61 63 6b 79 2c 20 77</text>
<text x="55" y="470" class="dim">h a c k y , w</text>
<!-- The GDB command -->
<text x="55" y="530" class="amb">GDB Command:</text>
<rect x="55" y="548" width="490" height="90" rx="5" fill="#0a0a0f" stroke="#ffaa00" stroke-width="2"/>
<text x="70" y="580" class="txt">set {char[13]}</text>
<text x="70" y="612" class="txt">0x20040000 = "hacky, world"</text>
<!-- Verify -->
<text x="55" y="680" class="cyn">Verify with:</text>
<rect x="55" y="698" width="490" height="42" rx="5" fill="#0a0a0f" stroke="#1a1a2e"/>
<text x="70" y="726" class="txt">x/s 0x20040000</text>
<!-- Right Panel: Why SRAM -->
<rect x="600" y="105" width="570" height="675" class="pnl" rx="8"/>
<text x="885" y="148" text-anchor="middle" class="sub">Why SRAM?</text>
<line x1="620" y1="163" x2="1150" y2="163" stroke="#1a1a2e"/>
<text x="625" y="205" class="grn">SRAM = writable</text>
<text x="625" y="240" class="txt">RAM at 0x20000000</text>
<text x="625" y="272" class="txt">We can write any</text>
<text x="625" y="304" class="txt">data here via GDB</text>
<line x1="620" y1="332" x2="1150" y2="332" stroke="#1a1a2e"/>
<text x="625" y="372" class="red">Flash = read-only</text>
<text x="625" y="407" class="txt">XIP at 0x10000000</text>
<text x="625" y="439" class="txt">Cannot write to it</text>
<text x="625" y="471" class="txt">during execution</text>
<text x="625" y="503" class="dim">That's why we use RAM</text>
<line x1="620" y1="531" x2="1150" y2="531" stroke="#1a1a2e"/>
<text x="625" y="571" class="amb">Choosing Address</text>
<text x="625" y="606" class="txt">0x20040000 is safe</text>
<text x="625" y="638" class="txt">Far from stack</text>
<text x="625" y="670" class="txt">and heap regions</text>
<line x1="620" y1="698" x2="1150" y2="698" stroke="#1a1a2e"/>
<text x="625" y="738" class="cyn">Null terminator</text>
<text x="625" y="773" class="dim">\0 ends the string</text>
</svg>
+77
View File
@@ -0,0 +1,77 @@
<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"/>
<!-- Title -->
<text x="600" y="52" text-anchor="middle" class="title">Register Hijack</text>
<text x="600" y="88" text-anchor="middle" class="dim">Control Flow Attack</text>
<!-- Left Panel: Before Hijack -->
<rect x="30" y="105" width="540" height="675" class="pnl" rx="8"/>
<text x="300" y="148" text-anchor="middle" class="sub">Before Hijack</text>
<line x1="50" y1="163" x2="550" y2="163" stroke="#1a1a2e"/>
<text x="55" y="205" class="dim">r0 loaded by LDR:</text>
<rect x="55" y="225" width="490" height="55" rx="5" fill="#0f0f1a" stroke="#00d4ff" stroke-width="2"/>
<text x="70" y="260" class="cyn">r0 = 0x10001234</text>
<text x="55" y="320" class="dim">Points to flash:</text>
<rect x="55" y="340" width="490" height="55" rx="5" fill="#0a0a0f" stroke="#1a1a2e"/>
<text x="70" y="375" class="txt">"hello, world\r\n"</text>
<text x="55" y="440" class="dim">printf will read r0</text>
<text x="55" y="472" class="dim">and print that string</text>
<line x1="50" y1="510" x2="550" y2="510" stroke="#1a1a2e"/>
<text x="55" y="555" class="grn">The Hijack Command</text>
<rect x="55" y="575" width="490" height="55" rx="5" fill="#1a0f0f" stroke="#ff0040" stroke-width="2"/>
<text x="300" y="610" text-anchor="middle" class="red">set $r0 = 0x20040000</text>
<text x="300" y="680" text-anchor="middle" class="txt">Now r0 points to</text>
<text x="300" y="712" text-anchor="middle" class="txt">OUR string in SRAM</text>
<text x="300" y="744" text-anchor="middle" class="dim">instead of flash</text>
<!-- Right Panel: After Hijack -->
<rect x="600" y="105" width="570" height="675" class="pnl" rx="8"/>
<text x="885" y="148" text-anchor="middle" class="sub">After Hijack</text>
<line x1="620" y1="163" x2="1150" y2="163" stroke="#1a1a2e"/>
<text x="625" y="205" class="dim">r0 now contains:</text>
<rect x="625" y="225" width="520" height="55" rx="5" fill="#1a0f0f" stroke="#ff0040" stroke-width="2"/>
<text x="640" y="260" class="red">r0 = 0x20040000</text>
<text x="625" y="320" class="dim">Points to SRAM:</text>
<rect x="625" y="340" width="520" height="55" rx="5" fill="#0f1a0f" stroke="#00ff41" stroke-width="2"/>
<text x="640" y="375" class="grn">"hacky, world"</text>
<line x1="620" y1="430" x2="1150" y2="430" stroke="#1a1a2e"/>
<text x="625" y="470" class="amb">Then: continue</text>
<text x="625" y="510" class="txt">printf reads r0</text>
<text x="625" y="542" class="txt">Follows pointer</text>
<text x="625" y="574" class="txt">to 0x20040000</text>
<text x="625" y="606" class="txt">Finds "hacky, world"</text>
<text x="625" y="638" class="txt">Prints it!</text>
<line x1="620" y1="678" x2="1150" y2="678" stroke="#1a1a2e"/>
<text x="885" y="720" text-anchor="middle" class="grn">Output changed</text>
<text x="885" y="752" text-anchor="middle" class="grn">without touching code</text>
</svg>
+75
View File
@@ -0,0 +1,75 @@
<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"/>
<!-- Title -->
<text x="600" y="52" text-anchor="middle" class="title">GDB vs Ghidra</text>
<text x="600" y="88" text-anchor="middle" class="dim">Static vs Dynamic Analysis</text>
<!-- Left Panel: GDB -->
<rect x="30" y="105" width="560" height="675" class="pnl" rx="8"/>
<text x="310" y="148" text-anchor="middle" class="sub">GDB (Dynamic)</text>
<line x1="50" y1="163" x2="570" y2="163" stroke="#1a1a2e"/>
<text x="55" y="205" class="grn">Live analysis</text>
<text x="55" y="240" class="txt">Program is running</text>
<text x="55" y="272" class="txt">on real hardware</text>
<line x1="50" y1="300" x2="570" y2="300" stroke="#1a1a2e"/>
<text x="55" y="340" class="cyn">Capabilities</text>
<text x="55" y="375" class="txt">Set breakpoints</text>
<text x="55" y="407" class="txt">Read/write memory</text>
<text x="55" y="439" class="txt">Modify registers</text>
<text x="55" y="471" class="txt">Step instructions</text>
<text x="55" y="503" class="txt">Watch values change</text>
<line x1="50" y1="531" x2="570" y2="531" stroke="#1a1a2e"/>
<text x="55" y="571" class="amb">Best For</text>
<text x="55" y="606" class="txt">Live modification</text>
<text x="55" y="638" class="txt">Runtime behavior</text>
<text x="55" y="670" class="txt">Testing exploits</text>
<text x="55" y="702" class="txt">Verifying attacks</text>
<text x="310" y="755" text-anchor="middle" class="dim">Needs running target</text>
<!-- Right Panel: Ghidra -->
<rect x="620" y="105" width="550" height="675" class="pnl" rx="8"/>
<text x="895" y="148" text-anchor="middle" class="sub">Ghidra (Static)</text>
<line x1="640" y1="163" x2="1150" y2="163" stroke="#1a1a2e"/>
<text x="645" y="205" class="red">Offline analysis</text>
<text x="645" y="240" class="txt">Just the binary file</text>
<text x="645" y="272" class="txt">No hardware needed</text>
<line x1="640" y1="300" x2="1150" y2="300" stroke="#1a1a2e"/>
<text x="645" y="340" class="cyn">Capabilities</text>
<text x="645" y="375" class="txt">Disassembly view</text>
<text x="645" y="407" class="txt">Decompile to C</text>
<text x="645" y="439" class="txt">Find functions</text>
<text x="645" y="471" class="txt">Cross-references</text>
<text x="645" y="503" class="txt">String search</text>
<line x1="640" y1="531" x2="1150" y2="531" stroke="#1a1a2e"/>
<text x="645" y="571" class="amb">Best For</text>
<text x="645" y="606" class="txt">Planning attacks</text>
<text x="645" y="638" class="txt">Understanding code</text>
<text x="645" y="670" class="txt">Finding targets</text>
<text x="645" y="702" class="txt">Mapping functions</text>
<text x="895" y="755" text-anchor="middle" class="dim">Works with just ELF</text>
</svg>
+8 -8
View File
@@ -9,7 +9,7 @@ Hello, World - Debugging and Hacking Basics: Debugging and Hacking a Basic Progr
#### Answers
##### Attack Summary
The goal is to write a custom message into SRAM at `0x20000000` and redirect `r0` to print it instead of the original `"hello, world"` string, without changing the source code.
The goal is to write a custom message into SRAM at `0x20040000` and redirect `r0` to print it instead of the original `"hello, world"` string, without changing the source code.
##### GDB Commands
@@ -17,25 +17,25 @@ The goal is to write a custom message into SRAM at `0x20000000` and redirect `r0
(gdb) target extended-remote :3333
(gdb) monitor reset halt
(gdb) b *0x1000023c # Breakpoint before __wrap_puts
(gdb) c # Continue to breakpoint
(gdb) set {char[20]} 0x20000000 = {'Y','o','u','r',' ','N','a','m','e','!','\r','\0'}
(gdb) set $r0 = 0x20000000 # Redirect r0 to injected message
(gdb) c # Resume - serial shows custom message
(gdb) c # Continue to breakpoint
(gdb) set {char[12]} 0x20040000 = {'Y','o','u','r',' ','N','a','m','e','!','\r','\0'}
(gdb) set $r0 = 0x20040000 # Redirect r0 to injected message
(gdb) c # Resume - serial shows custom message
```
##### Verification
```gdb
(gdb) x/s 0x20000000 # Should show your injected message
(gdb) x/s 0x20040000 # Should show your injected message
(gdb) x/s 0x100019cc # Original string still in Flash
```
#### Reflection Answers
1. **Why does the string have to live in SRAM instead of flash during runtime?**
Flash memory is read-only at runtime. The original string at `0x100019cc` cannot be modified. SRAM starting at `0x20000000` is read-write, so that is where we must place our replacement string.
Flash memory is read-only at runtime. The original string at `0x100019cc` cannot be modified. SRAM is read-write, so we place our replacement string at the safe runtime address `0x20040000`.
2. **What would happen if you forgot the null terminator in your injected string?**
`puts()` reads characters until it encounters `\0`. Without it, `puts()` would continue reading past the intended string, printing garbage characters from adjacent memory until a null byte happens to appear. This could crash the program or leak sensitive data.
3. **How does changing `r0` alter the behavior of `puts()` without touching source code?**
In the ARM calling convention, the first function argument is passed in `r0`. When `bl __wrap_puts` executes at `0x1000023c`, it reads the string address from `r0`. By changing `r0` from `0x100019cc` (original Flash string) to `0x20000000` (our SRAM string), we redirect what `puts()` prints.
In the ARM calling convention, the first function argument is passed in `r0`. When `bl __wrap_puts` executes at `0x1000023c`, it reads the string address from `r0`. By changing `r0` from `0x100019cc` (original Flash string) to `0x20040000` (our SRAM string), we redirect what `puts()` prints.
+6 -6
View File
@@ -14,10 +14,10 @@ Write your own message into SRAM and redirect `r0` so the running program prints
- OpenOCD and `arm-none-eabi-gdb` available in your PATH
- Serial monitor (PuTTY/minicom/screen) set to 115200 baud
- `build\0x0001_hello-world.elf` present and flashed to the board
- Week 2 setup steps (0a0e) completed: OpenOCD, serial monitor, and GDB ready
- Week 2 setup steps (0a0e) completed: OpenOCD, serial monitor, and GDB ready
#### Task Description
You will create a custom string in SRAM at `0x20000000`, point `r0` at it just before `puts()` runs, and watch the live output change to your message.
You will create a custom string in SRAM at `0x20040000`, point `r0` at it just before `puts()` runs, and watch the live output change to your message.
#### Step-by-Step Instructions
@@ -63,13 +63,13 @@ arm-none-eabi-gdb build\0x0001_hello-world.elf
Replace the characters with your name as needed.
```gdb
(gdb) set {char[20]} 0x20000000 = {'Y','o','u','r',' ','N','a','m','e','!','\r','\0'}
(gdb) set {char[12]} 0x20040000 = {'Y','o','u','r',' ','N','a','m','e','!','\r','\0'}
```
##### Step 8: Point `r0` to Your Message
```gdb
(gdb) set $r0 = 0x20000000
(gdb) set $r0 = 0x20040000
```
##### Step 9: Resume and Observe
@@ -82,7 +82,7 @@ Check PuTTY for your custom string replacing "hello, world".
#### Expected Output
- GDB stops at `0x1000023c` before `__wrap_puts`.
- `x/s 0x20000000` shows your injected message.
- `x/s 0x20040000` shows your injected message.
- PuTTY displays your custom message after you continue execution.
#### Questions for Reflection
@@ -94,7 +94,7 @@ Check PuTTY for your custom string replacing "hello, world".
###### Question 3: How does changing `r0` alter the behavior of `puts()` without touching source code?
#### Tips and Hints
- Keep your string length within the allocated array (`char[20]`).
- Match the array length to your payload exactly (characters + `\0`). The example uses `char[12]`.
- If you miss the breakpoint, confirm OpenOCD is running and the address matches `Week 2` disassembly.
- Use `x/s $r0` to confirm the register points to the intended address before continuing.
+7 -7
View File
@@ -9,30 +9,30 @@ Hello, World - Debugging and Hacking Basics: Debugging and Hacking a Basic Progr
#### Answers
##### Attack Summary
Write the payload to `0x20001000` instead of `0x20000000` to demonstrate that multiple safe SRAM locations can be used for injection.
Write the payload to `0x20041000` instead of `0x20040000` to demonstrate that multiple safe SRAM locations can be used for injection.
##### GDB Commands
```gdb
(gdb) b *0x1000023c
(gdb) c
(gdb) set {char[14]} 0x20001000 = {'h','a','c','k','e','d','!','!','!','\r','\0'}
(gdb) set $r0 = 0x20001000
(gdb) set {char[14]} 0x20041000 = {'h','a','c','k','e','d','!','!','!','\r','\0'}
(gdb) set $r0 = 0x20041000
(gdb) c
```
##### Verification
```gdb
(gdb) x/s 0x20001000 # Shows "hacked!!!\r"
(gdb) x/s 0x20041000 # Shows "hacked!!!\r"
```
#### Reflection Answers
1. **How can you ensure `0x20001000` does not collide with stack usage?**
The stack pointer was observed at `0x20082000` (top of stack) and grows downward. Since `0x20001000` is far below the stack region, there is substantial separation. Use `info registers sp` in GDB to verify the current stack pointer is well above your injection address.
1. **How can you ensure `0x20041000` does not collide with stack usage?**
The stack pointer was observed at `0x20082000` (top of stack) and grows downward. Since `0x20041000` is well below the stack region, there is substantial separation. Use `info registers sp` in GDB to verify the current stack pointer is above your injection address.
2. **What symptoms would indicate you overwrote an active stack frame?**
The program would crash when attempting to return from a function. Symptoms include: unexpected address exceptions, invalid memory access faults, or the program jumping to random addresses. The Link Register return path gets corrupted.
3. **How would you pick a safe SRAM offset in a larger program with dynamic allocations?**
Start from the bottom of SRAM (`0x20000000`) for small static payloads, working upward. Check the linker script to understand memory regions. In this simple program with no heap allocations, both `0x20000000` and `0x20001000` are safe. In larger programs, examine the `.bss` and `.data` section boundaries.
Choose a region with clear separation from vectors, stack growth, and active data. In this simple program, `0x20040000` and `0x20041000` are practical safe offsets. In larger programs, inspect linker sections (`.data`, `.bss`, heap) and validate with runtime `sp` checks.
+8 -8
View File
@@ -7,16 +7,16 @@ Hello, World - Debugging and Hacking Basics: Debugging and Hacking a Basic Progr
### Non-Credit Practice Exercise 2: Use a Different SRAM Address
#### Objective
Practice writing to an alternate SRAM location and redirecting `r0` so your message prints from `0x20001000` instead of `0x20000000`.
Practice writing to an alternate SRAM location and redirecting `r0` so your message prints from `0x20041000` instead of `0x20040000`.
#### Prerequisites
- Raspberry Pi Pico 2 with debug probe connected
- OpenOCD, `arm-none-eabi-gdb`, and a serial monitor ready (Week 2 steps 0a0e complete)
- OpenOCD, `arm-none-eabi-gdb`, and a serial monitor ready (Week 2 steps 0a0e complete)
- `build\0x0001_hello-world.elf` flashed and running
- Comfortable setting breakpoints at `0x1000023c`
#### Task Description
You will inject a short string into `0x20001000`, point `r0` there, and verify the live output changes, demonstrating that any safe SRAM slot can host your payload.
You will inject a short string into `0x20041000`, point `r0` there, and verify the live output changes, demonstrating that any safe SRAM slot can host your payload.
#### Step-by-Step Instructions
@@ -47,16 +47,16 @@ openocd ^
(gdb) c
```
##### Step 5: Write a Payload at `0x20001000`
##### Step 5: Write a Payload at `0x20041000`
```gdb
(gdb) set {char[14]} 0x20001000 = {'h','a','c','k','e','d','!','!','!','\r','\0'}
(gdb) set {char[14]} 0x20041000 = {'h','a','c','k','e','d','!','!','!','\r','\0'}
```
##### Step 6: Redirect `r0`
```gdb
(gdb) set $r0 = 0x20001000
(gdb) set $r0 = 0x20041000
```
##### Step 7: Continue and Verify
@@ -68,13 +68,13 @@ openocd ^
Check PuTTY for the new output sourced from the alternate address.
#### Expected Output
- `x/s 0x20001000` shows `"hacked!!!\r"` (or your variant).
- `x/s 0x20041000` shows `"hacked!!!\r"` (or your variant).
- PuTTY prints the injected message instead of the original string.
- The program continues looping with your modified output.
#### Questions for Reflection
###### Question 1: How can you ensure `0x20001000` does not collide with stack usage?
###### Question 1: How can you ensure `0x20041000` does not collide with stack usage?
###### Question 2: What symptoms would indicate you overwrote an active stack frame?
+5 -5
View File
@@ -11,16 +11,16 @@ Hello, World - Debugging and Hacking Basics: Debugging and Hacking a Basic Progr
##### GDB Commands
```gdb
(gdb) set {char[14]} 0x20000000 = {'h','a','c','k','y',',',' ','w','o','r','l','d','\r','\0'}
(gdb) x/20b 0x20000000
(gdb) set {char[14]} 0x20040000 = {'h','a','c','k','y',',',' ','w','o','r','l','d','\r','\0'}
(gdb) x/20b 0x20040000
```
##### Byte Dump Output
```
0x20000000: 0x68 0x61 0x63 0x6b 0x79 0x2c 0x20 0x77
0x20000008: 0x6f 0x72 0x6c 0x64 0x0d 0x00 0x00 0x00
0x20000010: 0x00 0x00 0x00 0x00
0x20040000: 0x68 0x61 0x63 0x6b 0x79 0x2c 0x20 0x77
0x20040008: 0x6f 0x72 0x6c 0x64 0x0d 0x00 0x00 0x00
0x20040010: 0x00 0x00 0x00 0x00
```
##### ASCII Mapping
+5 -5
View File
@@ -13,7 +13,7 @@ Inspect the byte-level layout of your injected string in SRAM and correlate byte
- Pico 2 connected with OpenOCD, GDB, and a serial monitor ready
- `build\0x0001_hello-world.elf` flashed and running
- Ability to break before `__wrap_puts` at `0x1000023c`
- A payload already written to SRAM (e.g., at `0x20000000` from Exercise 1)
- A payload already written to SRAM (e.g., at `0x20040000` from Exercise 1)
#### Task Description
You will use `x/20b` to view the bytes surrounding your injected string, decode the characters, and confirm the presence of control characters and the null terminator.
@@ -38,14 +38,14 @@ You will use `x/20b` to view the bytes surrounding your injected string, decode
If needed, re-inject a payload:
```gdb
(gdb) set {char[14]} 0x20000000 = {'h','a','c','k','y',',',' ','w','o','r','l','d','\r','\0'}
(gdb) set $r0 = 0x20000000
(gdb) set {char[14]} 0x20040000 = {'h','a','c','k','y',',',' ','w','o','r','l','d','\r','\0'}
(gdb) set $r0 = 0x20040000
```
##### Step 4: Examine Bytes Around the String
```gdb
(gdb) x/20b 0x20000000
(gdb) x/20b 0x20040000
```
##### Step 5: Decode the Output
@@ -77,6 +77,6 @@ If needed, re-inject a payload:
- If the bytes look incorrect, re-run the injection command to reset the buffer.
#### Next Steps
- Try viewing a different address (e.g., `0x20001000`) to compare layouts.
- Try viewing a different address (e.g., `0x20041000`) to compare layouts.
- Experiment with longer strings and observe how the byte dump grows.
- Move on to Exercise 4 to automate the hack workflow.
+6 -6
View File
@@ -12,8 +12,8 @@ Hello, World - Debugging and Hacking Basics: Debugging and Hacking a Basic Progr
```gdb
(gdb) define hack
> set {char[14]} 0x20000000 = {'h','a','c','k','y',',',' ','w','o','r','l','d','\r','\0'}
> set $r0 = 0x20000000
> set {char[13]} 0x20040000 = "hacky, world"
> set $r0 = 0x20040000
> c
> end
```
@@ -39,7 +39,7 @@ hacky, world
#### Reflection Answers
1. **How could you parameterize the command to accept different strings or addresses?**
Standard GDB `define` blocks do not support function parameters directly. However, you can use GDB convenience variables (`set $myaddr = 0x20000000`) and reference them in the macro, or create multiple specific commands like `hack_addr1`, `hack_addr2`. For advanced parameterization, use GDB Python scripting.
Standard GDB `define` blocks do not support function parameters directly. However, you can use GDB convenience variables (`set $myaddr = 0x20040000`) and reference them in the macro, or create multiple specific commands like `hack_addr1`, `hack_addr2`. For advanced parameterization, use GDB Python scripting.
2. **What happens if you define `hack` before setting the breakpoint - will it still work as expected?**
The `define` command only creates a macro; it does not execute immediately. The breakpoint must be set and hit before invoking `hack`. The sequence matters: set breakpoint -> run/continue to hit breakpoint -> then call `hack`. Defining the macro before or after the breakpoint does not matter as long as you invoke it at the right time.
@@ -48,9 +48,9 @@ hacky, world
Extend the `define` block with additional commands:
```gdb
(gdb) define hack_verbose
> set {char[14]} 0x20000000 = {'h','a','c','k','y',',',' ','w','o','r','l','d','\r','\0'}
> x/20b 0x20000000
> set $r0 = 0x20000000
> set {char[13]} 0x20040000 = "hacky, world"
> x/20b 0x20040000
> set $r0 = 0x20040000
> info registers r0
> c
> end
+4 -4
View File
@@ -15,7 +15,7 @@ Create a reusable GDB command that injects a string into SRAM, repoints `r0`, an
- Familiarity with breaking at `0x1000023c` and injecting strings from prior exercises
#### Task Description
You will define a custom GDB command `hack` that writes a payload to `0x20000000`, repoints `r0`, and continues execution automatically.
You will define a custom GDB command `hack` that writes a payload to `0x20040000`, repoints `r0`, and continues execution automatically.
#### Step-by-Step Instructions
@@ -32,8 +32,8 @@ You will define a custom GDB command `hack` that writes a payload to `0x20000000
```gdb
(gdb) define hack
> set {char[14]} 0x20000000 = {'h','a','c','k','y',',',' ','w','o','r','l','d','\r','\0'}
> set $r0 = 0x20000000
> set {char[13]} 0x20040000 = "hacky, world"
> set $r0 = 0x20040000
> c
> end
```
@@ -56,7 +56,7 @@ You will define a custom GDB command `hack` that writes a payload to `0x20000000
###### Question 1: How could you parameterize the command to accept different strings or addresses?
###### Question 2: What happens if you define `hack` before setting the breakpointwill it still work as expected?
###### Question 2: What happens if you define `hack` before setting the breakpointwill it still work as expected?
###### Question 3: How would you adapt this pattern for multi-step routines (e.g., patch, dump, continue)?
+126 -208
View File
@@ -56,8 +56,6 @@ The techniques you'll learn today are *exactly* how this would be done. Understa
> 🔄 **REVIEW:** In Week 1, we learned about the RP2350's memory layout. This knowledge is essential for our hack!
> 📖 **Datasheet Reference:** The address map is in Section 2.2 (p. 31): Flash/XIP at `0x10000000`, SRAM at `0x20000000`. SRAM is 520 KB total across 10 banks (Section 2.2.3, p. 32; Section 4.2, p. 338339). Flash memory is accessed read-only via XIP during normal execution (Section 4.4, p. 340+).
Before we hack, let's remember where things live in memory on the RP2350:
#### The Code We're Hacking
@@ -99,7 +97,7 @@ Our goal: **Make it print something else WITHOUT changing the source code!**
└─────────────────────────────────────────────────────┘
```
> 🔄 **REVIEW:** In Week 1, we saw the stack pointer (SP) was around `0x20081fc8` - that's in the SRAM region! The stack "grows downward" from the top of SRAM.
> 🔄 **REVIEW:** In Week 1, we saw SP values in the `0x20081xxx` range (for example `0x20081fc8`) - that's in the SRAM region. In this run you may see values like `0x20081ff8` depending on where execution is paused. The stack "grows downward" from the top of SRAM.
#### Why This Matters for Our Hack
@@ -149,8 +147,8 @@ Before we start, make sure you have:
You will need **THREE** terminal windows:
1. **Terminal 1**: Running OpenOCD (the debug server)
2. **Terminal 2**: Running your serial monitor (to see output)
3. **Terminal 3**: Running GDB (where we do the hacking)
2. **Terminal 2**: Running GDB (where we do the hacking)
3. **PuTTY**: Running your serial monitor (to see output)
---
@@ -258,7 +256,8 @@ Now we need to connect GDB to OpenOCD. OpenOCD is listening on port `3333`.
```
Remote debugging using :3333
main () at 0x0001_hello-world/0x0001_hello-world.c:5.
main ()
at C:/Users/flare-vm/Desktop/Embedded-Hacking-main/0x0001_hello-world/0x0001_hello-world.c:5
5 stdio_init_all();
```
@@ -454,6 +453,24 @@ Before we execute the `push` instruction, let's see what's on the stack:
- The stack is empty (all zeros)
- This is the "top" of our stack in RAM
**Verify where this value came from (the Vector Table):**
Now let's trace back where this initial `0x20082000` value came from. It comes from the first entry in the vector table at `0x10000000`:
```gdb
(gdb) x/x $sp
0x20082000: 0x00000000
(gdb) x/x 0x10000000
0x10000000 <__vectors>: 0x20082000
```
**What this shows:**
- The first command `x/x $sp` reads one word at the stack pointer (currently `0x00000000`)
- The second command `x/x 0x10000000` reads the **first entry in the vector table** at address `0x10000000`
- That vector table entry contains `0x20082000` - this is the **initial stack pointer value**!
- The Boot ROM reads this value and puts it into the SP register when the chip starts
- This is why our SP register already has `0x20082000` before `main()` runs
##### Step 7: Execute One Instruction (Step Into)
Now let's execute just ONE assembly instruction:
@@ -742,143 +759,26 @@ There's our string! The `\r` is a carriage return character (part of `\r\n`).
---
## 🔬 Part 6: Starting the Debug Session for the Hack
## 🔬 Part 6: Continuing the Debug Session for the Hack
##### Step 1: Start OpenOCD (Debug Server)
You're right where you need to be from Part 5, so we **do not restart** OpenOCD or GDB here.
OpenOCD is the bridge between your computer and the Pico 2's debug interface. It creates a server that GDB can connect to.
Use this as a quick checkpoint before the hack:
**Open Terminal 1 and type:**
- OpenOCD is still running and listening on `:3333`
- GDB is still connected (`target extended-remote :3333` already done)
- The target is halted at a known point (or easy to re-halt)
```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"
```
If your session is still live, continue directly to Part 7.
**What this command means:**
- `openocd` = the OpenOCD program
- `-f interface/cmsis-dap.cfg` = use the CMSIS-DAP debug probe configuration
- `-f target/rp2350.cfg` = configure for the RP2350 chip
- `-c "adapter speed 5000"` = set the debug speed to 5000 kHz
**You should see output like:**
```
Open On-Chip Debugger 0.12.0
Licensed under GNU GPL v2
Info : Listening on port 3333 for gdb connections
Info : CMSIS-DAP: SWD supported
Info : CMSIS-DAP: Interface ready
```
**Important:** Leave this terminal running! Don't close it.
##### Step 2: Start Your Serial Monitor
**Open PuTTY** and start your serial monitor to watch the Pico 2's output.
**Example using screen (macOS/Linux):**
```bash
screen /dev/tty.usbmodem* 115200
```
**Example using minicom:**
```bash
minicom -D /dev/ttyACM0 -b 115200
```
**You should see:**
```
hello, world
hello, world
hello, world
hello, world
...
```
The program is running and printing `"hello, world"` in an infinite loop!
**Important:** Leave this terminal running! We'll watch it change when we hack the system.
##### Step 3: Start GDB and Load the Binary
**Open Terminal 3** and start GDB with your binary:
```powershell
arm-none-eabi-gdb build\0x0001_hello-world.elf
```
**What this command means:**
- `arm-none-eabi-gdb` = the ARM version of GDB
- `build\0x0001_hello-world.elf` = our compiled program with debug symbols
**You should see:**
```
GNU gdb (Arm GNU Toolchain 13.2) 13.2
Reading symbols from build\0x0001_hello-world.elf...
(gdb)
```
The `(gdb)` prompt means GDB is ready for commands!
##### Step 4: Connect to the Remote Debug Server
Now we need to connect GDB to OpenOCD. OpenOCD is listening on port `3333`.
**Type this command:**
If you got disconnected, run only this minimal recovery in GDB:
```gdb
(gdb) target extended-remote :3333
```
**What this command means:**
- `target remote` = connect to a remote debug server
- `:3333` = on localhost, port 3333 (where OpenOCD is listening)
**You should see:**
```
Remote debugging using :3333
warning: multi-threaded target stopped without sending a thread-id, using first non-exited thread
0x1000023c in main () at 0x0001_hello-world.c:8
8 printf("hello, world\r\n");
```
We're connected! GDB shows us the program is currently in the `main` function.
##### Step 5: Halt the Running Program
The program is still running (you can see "hello, world" still printing in your serial monitor). Let's stop it:
**Type this command:**
```gdb
(gdb) monitor reset halt
```
**What this command means:**
- `monitor` = send a command to OpenOCD (not GDB)
- `reset` = reset the processor
- `halt` = stop execution immediately
**You should see:**
```gdb
(gdb) monitor reset halt
[rp2350.cm0] halted due to debug-request, current mode: Thread
xPSR: 0xf9000000 pc: 0x00000088 msp: 0xf0000000
[rp2350.cm1] halted due to debug-request, current mode: Thread
xPSR: 0xf9000000 pc: 0x00000088 msp: 0xf0000000
```
**Check your serial monitor (Terminal 2):** The "hello, world" messages should have stopped! The processor is now frozen, waiting for our commands.
After that, continue to the analysis steps below.
---
@@ -908,7 +808,7 @@ Let's look at the main function to understand what we're dealing with:
0x10000234 <main>: push {r3, lr}
0x10000236 <main+2>: bl 0x1000156c <stdio_init_all>
0x1000023a <main+6>: ldr r0, [pc, #8] @ (0x10000244 <main+16>)
0x1000023c <main+8>: bl 0x100015fc <__wrap_puts>
=> 0x1000023c <main+8>: bl 0x100015fc <__wrap_puts>
0x10000240 <main+12>: b.n 0x1000023a <main+6>
```
@@ -968,8 +868,7 @@ We want to stop the program RIGHT BEFORE it calls `puts()`. That's at address `0
**You should see:**
```
Breakpoint 1 at 0x1000023c: file 0x0001_hello-world.c, line 8.
Note: automatically using hardware breakpoints for read-only addresses.
Breakpoint 2 at 0x1000023c: file C:/Users/flare-vm/Desktop/Embedded-Hacking-main/0x0001_hello-world/0x0001_hello-world.c, line 8
```
**What does "hardware breakpoints" mean?**
@@ -994,9 +893,9 @@ Now let's run the program until it hits our breakpoint:
```gdb
Continuing.
Thread 1 "rp2350.cm0" hit Breakpoint 1, 0x1000023c in main ()
at 0x0001_hello-world.c:8
8 printf("hello, world\r\n");
Thread 1 "rp2350.cm0" hit Breakpoint 2, 0x1000023c in main ()
at C:/Users/flare-vm/Desktop/Embedded-Hacking-main/0x0001_hello-world/0x0001_hello-world.c:8
8 printf("hello, world\r\n");
```
The program has stopped RIGHT BEFORE calling `puts()`! The string address is loaded into `r0`, but the function hasn't been called yet.
@@ -1055,7 +954,7 @@ Let's see what string `r0` is currently pointing to:
**You should see:**
```gdb
0x100019cc: "hello, world\r"
0x100019cc: "hello, world\r"
```
There it is! The register `r0` contains `0x100019cc`, which is the address of our `"hello, world"` string in flash memory.
@@ -1090,11 +989,13 @@ This is a very important lesson! Here's what happened:
1. When you type `"hacky, world\r"` in GDB, GDB interprets this as: "Create a new string and give me its address"
2. To create a new string at runtime, GDB would need to allocate memory using `malloc()`
2. To create a new string at runtime, GDB tries to allocate target memory using `malloc()`.
3. But our embedded system has **no operating system** and **no C runtime library loaded**! There's no `malloc()` function available.
3. If the target program exposed a working `malloc()` that GDB could call, this style of assignment can work.
4. GDB can't create the string because there's nowhere to put it!
4. In our case, this is a bare-metal firmware image and there is no usable `malloc()` path for GDB expression evaluation, so GDB cannot create temporary storage for that string literal.
5. That is why this command fails here, and why we switch to writing bytes directly into SRAM ourselves.
**Let's verify nothing changed:**
@@ -1105,7 +1006,7 @@ This is a very important lesson! Here's what happened:
**You should see:**
```
0x100019cc: "hello, world\r"
0x100019cc: "hello, world\r"
```
The original string is still there. Our hack attempt failed... but we're not giving up!
@@ -1121,13 +1022,13 @@ Since we can't use `malloc()`, we need to manually create our string somewhere i
- Flash (`0x10000000`): **Read-only** - can't write here
- SRAM (`0x20000000`): **Read-write** - we CAN write here!
> 🔄 **REVIEW:** In Week 1, we saw the stack pointer was at `0x20081fc8`. The stack lives at the TOP of SRAM and grows downward. We'll write our string at the BOTTOM of SRAM (`0x20000000`) to avoid conflicts!
> 🔄 **REVIEW:** In Week 1 we observed SP in the `0x20081xxx` range (for example `0x20081fc8`). In this run, after `push {r3, lr}`, you are seeing `0x20081ff8`, which is also correct and still near the top of SRAM. We'll write our string at a safer SRAM address (`0x20040000`) to avoid vector-table and stack conflicts.
We'll write our malicious string directly to SRAM, then point `r0` to it.
##### Step 13: Create Our Malicious String in SRAM
We need to write 14 bytes (13 characters + null terminator) to SRAM:
We need to write 13 bytes (12 characters + null terminator) to SRAM:
| Character | ASCII Hex |
| --------- | --------- |
@@ -1149,14 +1050,14 @@ We need to write 14 bytes (13 characters + null terminator) to SRAM:
**Type this command:**
```gdb
(gdb) set {char[14]} 0x20000000 = {'h','a','c','k','y',',',' ','w','o','r','l','d','\r','\0'}
(gdb) set {char[13]} 0x20040000 = "hacky, world"
```
**What this command means:**
- `set` = modify memory
- `{char[14]}` = treat the target as an array of 14 characters
- `0x20000000` = the address where we're writing (start of SRAM)
- `= {...}` = the characters to write
- `{char[13]}` = treat the target as an array of 13 characters
- `0x20040000` = the address where we're writing (safe SRAM offset)
- `= "hacky, world"` = the string bytes to write
**No output means success!**
@@ -1167,18 +1068,18 @@ Let's confirm our malicious string is in SRAM:
**Type this command:**
```gdb
(gdb) x/s 0x20000000
(gdb) x/s 0x20040000
```
**You should see:**
```gdb
0x20000000 <ram_vector_table>: "hacky, world\r"
0x20040000: "hacky, world"
```
**OUR STRING IS IN MEMORY!**
GDB shows it's at the `ram_vector_table` location - that's just a label from the linker script. The important thing is our string is there and ready to use.
The important thing is our string is in writable SRAM at a safe offset and ready to use.
---
@@ -1193,13 +1094,13 @@ Now for the magic moment! We'll change `r0` from pointing to the original string
**Type this command:**
```gdb
(gdb) set $r0 = 0x20000000
(gdb) set $r0 = 0x20040000
```
**What this command means:**
- `set` = modify a value
- `$r0` = the `r0` register
- `= 0x20000000` = change it to this address (where our string is)
- `= 0x20040000` = change it to this address (where our string is)
**No output means success!**
@@ -1207,19 +1108,33 @@ Now for the magic moment! We'll change `r0` from pointing to the original string
Let's confirm `r0` now points to our malicious string:
**First, check the raw value:**
**First, check one byte (explicit byte view):**
```gdb
(gdb) x/x $r0
(gdb) x/bx $r0
```
**You should see:**
```
0x20000000 <ram_vector_table>: 0x68
0x20040000: 0x68
```
The value `0x68` is the ASCII code for 'h' - the first character of "hacky"!
The value `0x68` is ASCII `'h'`, the first byte of `"hacky, world"`.
**Now check one 32-bit word (explicit word view):**
```gdb
(gdb) x/wx $r0
```
**You should see:**
```
0x20040000: 0x6b636168
```
This is the first 4 bytes (`h a c k`) packed into one 32-bit little-endian word.
**Now check it as a string:**
@@ -1230,7 +1145,7 @@ The value `0x68` is the ASCII code for 'h' - the first character of "hacky"!
**You should see:**
```
0x20000000 <ram_vector_table>: "hacky, world\r"
0x20040000: "hacky, world"
```
**THE HIJACK IS COMPLETE!** When `puts()` runs, it will read the string address from `r0` - which now points to our malicious string!
@@ -1254,9 +1169,9 @@ This is the moment of truth! Let's continue the program and watch our hack take
```gdb
Continuing.
Thread 1 "rp2350.cm0" hit Breakpoint 1, 0x1000023c in main ()
at 0x0001_hello-world.c:8
8 printf("hello, world\r\n");
Thread 1 "rp2350.cm0" hit Breakpoint 2, 0x1000023c in main ()
at C:/Users/flare-vm/Desktop/Embedded-Hacking-main/0x0001_hello-world/0x0001_hello-world.c:8
8 printf("hello, world\r\n");
```
The program ran through one loop iteration and hit our breakpoint again.
@@ -1307,40 +1222,41 @@ If you haven't already set up the Ghidra project from Week 1:
* FUNCTION
*************************************************************
int main (void )
assume LRset = 0x0
assume TMode = 0x1
int r0:4 <RETURN>
assume LRset = 0x0
assume TMode = 0x1
int r0:4 <RETURN>
main XREF[3]: Entry Point (*) ,
_reset_handler:1000018c (c) ,
.debug_frame::00000018 (*)
0x0001_hello-world.c:4 (2)
0x0001_hello-world.c:5 (2)
10000234 08 b5 push {r3,lr}
10000234 08 b5 push {r3,lr}
0x0001_hello-world.c:5 (4)
10000236 01 f0 99 f9 bl stdio_init_all _Bool stdio_init_all(void)
10000236 01 f0 99 f9 bl stdio_init_all _Bool stdio_init_all(void)
LAB_1000023a XREF[1]: 10000240 (j)
0x0001_hello-world.c:7 (6)
0x0001_hello-world.c:8 (6)
1000023a 02 48 ldr r0=>__EH_FRAME_BEGIN__ ,[DAT_10000244 ] = "hello, world\r"
1000023a 02 48 ldr r0=>__EH_FRAME_BEGIN__ ,[DAT_10000244 ] = "hello, world\r"
= 100019CCh
1000023c 01 f0 de f9 bl __wrap_puts int __wrap_puts(char * s)
1000023c 01 f0 de f9 bl __wrap_puts int __wrap_puts(char * s)
0x0001_hello-world.c:7 (8)
10000240 fb e7 b LAB_1000023a
10000240 fb e7 b LAB_1000023a
10000242 00 ?? 00h
10000243 bf ?? BFh
DAT_10000244 XREF[1]: main:1000023a (R)
10000244 cc 19 00 10 undefine 100019CCh ? -> 100019cc
10000244 cc 19 00 10 undefine 100019CCh ? -> 100019cc
```
**What you'll see in the Decompile View:**
```c
int main(void) {
stdio_init_all();
do {
__wrap_puts("hello, world");
} while (true);
int main(void)
{
stdio_init_all();
do {
__wrap_puts("hello, world\r");
} while( true );
}
```
@@ -1366,9 +1282,8 @@ Let's trace where the string actually lives:
LAB_1000023a XREF[1]: 10000240 (j)
0x0001_hello-world.c:7 (6)
0x0001_hello-world.c:8 (6)
1000023a 02 48 ldr r0=>__EH_FRAME_BEGIN__ ,[DAT_10000244 ] = "hello, world\r"
1000023a 02 48 ldr r0=>__EH_FRAME_BEGIN__ ,[DAT_10000244 ] = "hello, world\r"
= 100019CCh
```
2. **Double-click on `DAT_10000244`** to go to the data reference
@@ -1376,8 +1291,7 @@ Let's trace where the string actually lives:
3. You'll see:
```
DAT_10000244 XREF[1]: main:1000023a (R)
10000244 cc 19 00 10 undefine 100019CCh ? -> 100019cc
10000244 cc 19 00 10 undefine 100019CCh ? -> 100019cc
```
4. **Double-click on `100019CCh`** to navigate to the actual string
@@ -1395,10 +1309,9 @@ Let's trace where the string actually lives:
__boot2_end__ main:1000023a (*) ,
__EH_FRAME_BEGIN__ runtime_init:1000138a (R) ,
_elfSectionHeaders::0000005c (*)
100019cc 68 65 6c ds "hello, world\r"
100019cc 68 65 6c ds "hello, world\r"
6c 6f 2c
20 77 6f
```
##### Step 4: Understand Why We Needed SRAM
@@ -1412,7 +1325,7 @@ This starts with `0x10...` which means it's in **Flash memory (XIP region)**!
| `0x10000000`+ | Flash (XIP) | **NO** - Read Only |
| `0x20000000`+ | SRAM | **YES** - Read/Write |
> 🎯 **This is why our direct string modification failed in GDB!** The string lives in flash memory, which is read-only at runtime. We had to create our malicious string in SRAM (`0x20000000`) instead.
> 🎯 **This is why our direct string modification failed in GDB!** The string lives in flash memory, which is read-only at runtime. We had to create our malicious string in SRAM at a safe address (`0x20040000`) instead.
##### Step 5: Examine Cross-References
@@ -1429,11 +1342,13 @@ This shows every place that calls `puts()`. In a larger program, you could find
The Decompile view makes attack planning easy:
```c
int main(void) {
stdio_init_all();
do {
__wrap_puts("hello, world"); // <-- Attack target identified!
} while (true);
int main(void)
{
stdio_init_all();
do {
__wrap_puts("hello, world\r");
} while( true );
}
```
@@ -1457,10 +1372,9 @@ When you navigate to the string address `0x100019cc`, you'll see the string stor
__boot2_end__ main:1000023a (*) ,
__EH_FRAME_BEGIN__ runtime_init:1000138a (R) ,
_elfSectionHeaders::0000005c (*)
100019cc 68 65 6c ds "hello, world\r"
100019cc 68 65 6c ds "hello, world\r"
6c 6f 2c
20 77 6f
```
This shows the raw bytes of our string: `68 65 6c 6c 6f 2c 20 77 6f...` which spell out "hello, world\r" in ASCII.
@@ -1486,7 +1400,7 @@ Ghidra allows you to modify data directly in the binary! Here's how to patch the
After patching, you'll see the change reflected in the Listing view:
```
100019cc 68 61 63 ds "hacky, world\r"
100019cc 68 61 63 ds "hacky, world\r"
6b 79 2c
20 77 6f
```
@@ -1501,8 +1415,6 @@ In future lessons, we will learn how to:
1. **Export the patched binary** from Ghidra to create a modified `.elf` or `.bin` file
2. **Flash the patched binary** to the Pico 2, making the hack **persistent**
3. **Understand patch verification** - how defenders detect modified binaries
4. **Bypass integrity checks** that try to prevent patching
The key difference:
@@ -1579,7 +1491,7 @@ BEFORE OUR HACK:
AFTER OUR HACK:
┌─────────────────┐ ┌──────────────────────────────┐
│ r0 = 0x20000000│ ───> │ SRAM: "hacky, world\r" │
│ r0 = 0x20040000│ ───> │ SRAM: "hacky, world"
└─────────────────┘ └──────────────────────────────┘
@@ -1602,23 +1514,29 @@ AFTER OUR HACK:
#### Key Memory Addresses
| Address | What's There | Read/Write? | Datasheet Reference |
| ------------ | -------------------------------- | ----------- | ------------------- |
| `0x10000234` | Start of `main()` function | Read-only | (binary-specific) |
| `0x1000023c` | The `bl __wrap_puts` call | Read-only | (binary-specific) |
| `0x100019cc` | Original `"hello, world"` string | Read-only | XIP region, §2.2 (p. 31) |
| `0x20000000` | Start of SRAM (our hack target) | Read-Write | §2.2.3 SRAM (p. 32) |
| Address | What's There | Read/Write? |
| ------------ | -------------------------------- | ----------- |
| `0x10000234` | Start of `main()` function | Read-only |
| `0x1000023c` | The `bl __wrap_puts` call | Read-only |
| `0x100019cc` | Original `"hello, world"` string | Read-only |
| `0x20040000` | Safe SRAM location (hack target) | Read-Write |
---
## ✅ Practice Exercises
These prompts are intentionally aligned 1:1 with the Week 2 exercise and solution files:
- `WEEK02-01.md` and `WEEK02-01-S.md`
- `WEEK02-02.md` and `WEEK02-02-S.md`
- `WEEK02-03.md` and `WEEK02-03-S.md`
- `WEEK02-04.md` and `WEEK02-04-S.md`
#### Exercise 1: Change the Message
Try creating a different message! Write your name to SRAM and make the program print it:
```gdb
(gdb) set {char[20]} 0x20000000 = {'Y','o','u','r',' ','N','a','m','e','!','\r','\0'}
(gdb) set $r0 = 0x20000000
(gdb) set {char[12]} 0x20040000 = {'Y','o','u','r',' ','N','a','m','e','!','\r','\0'}
(gdb) set $r0 = 0x20040000
(gdb) c
```
@@ -1626,8 +1544,8 @@ Try creating a different message! Write your name to SRAM and make the program p
The SRAM region is large. Try writing your string to a different address:
```gdb
(gdb) set {char[14]} 0x20001000 = {'h','a','c','k','e','d','!','!','!','\r','\0'}
(gdb) set $r0 = 0x20001000
(gdb) set {char[14]} 0x20041000 = {'h','a','c','k','e','d','!','!','!','\r','\0'}
(gdb) set $r0 = 0x20041000
(gdb) c
```
@@ -1635,7 +1553,7 @@ The SRAM region is large. Try writing your string to a different address:
Look at the bytes around your injected string:
```gdb
(gdb) x/20b 0x20000000
(gdb) x/20b 0x20040000
```
What do you see? Can you identify each character?
@@ -1645,8 +1563,8 @@ Create a GDB command sequence that does the full hack. You can use GDB's command
```gdb
(gdb) define hack
> set {char[14]} 0x20000000 = {'h','a','c','k','y',',',' ','w','o','r','l','d','\r','\0'}
> set $r0 = 0x20000000
> set {char[13]} 0x20040000 = "hacky, world"
> set $r0 = 0x20040000
> c
> end
(gdb) hack