mirror of
https://github.com/mytechnotalent/Embedded-Hacking.git
synced 2026-05-16 13:19:14 +02:00
Updated WEEK02
This commit is contained in:
+9
-16
@@ -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
@@ -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)
|
||||
|
||||
@@ -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
@@ -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
|
||||
|
||||
|
||||
@@ -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
@@ -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
|
||||
|
||||
|
||||
@@ -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
@@ -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
@@ -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 );
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
@@ -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
@@ -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 (0a–0e) completed: OpenOCD, serial monitor, and GDB ready
|
||||
- Week 2 setup steps (0a�0e) 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.
|
||||
|
||||
|
||||
@@ -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
@@ -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 0a–0e complete)
|
||||
- OpenOCD, `arm-none-eabi-gdb`, and a serial monitor ready (Week 2 steps 0a�0e 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?
|
||||
|
||||
|
||||
@@ -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
@@ -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.
|
||||
|
||||
@@ -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
@@ -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 breakpoint—will it still work as expected?
|
||||
###### Question 2: What happens if you define `hack` before setting the breakpoint�will 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
@@ -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
|
||||
|
||||
@@ -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 |
@@ -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>
|
||||
@@ -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 <scripts></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>
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
@@ -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.
|
||||
|
||||
@@ -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 (0a–0e) completed: OpenOCD, serial monitor, and GDB ready
|
||||
- Week 2 setup steps (0a�0e) 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.
|
||||
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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 0a–0e complete)
|
||||
- OpenOCD, `arm-none-eabi-gdb`, and a serial monitor ready (Week 2 steps 0a�0e 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?
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 breakpoint—will it still work as expected?
|
||||
###### Question 2: What happens if you define `hack` before setting the breakpoint�will it still work as expected?
|
||||
|
||||
###### Question 3: How would you adapt this pattern for multi-step routines (e.g., patch, dump, continue)?
|
||||
|
||||
|
||||
+126
-208
@@ -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. 338–339). 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
|
||||
|
||||
Reference in New Issue
Block a user