mirror of
https://github.com/mytechnotalent/Embedded-Hacking.git
synced 2026-06-01 20:11:47 +02:00
Update WEEK06
This commit is contained in:
+40
-43
@@ -1,6 +1,6 @@
|
||||
# Week 2: Hello, World - Debugging and Hacking Basics: Debugging and Hacking a Basic Program for the Pico 2
|
||||
|
||||
## 🎯 What You'll Learn This Week
|
||||
## What You'll Learn This Week
|
||||
|
||||
By the end of this tutorial, you will be able to:
|
||||
- Connect to a live embedded system using OpenOCD and GDB
|
||||
@@ -12,7 +12,7 @@ By the end of this tutorial, you will be able to:
|
||||
- Hijack register values to redirect program behavior
|
||||
- Modify a running program's output in real-time
|
||||
|
||||
## 🔄 Review from Week 1
|
||||
## Review from Week 1
|
||||
This week builds directly on Week 1 concepts. You should already be comfortable with:
|
||||
- **Registers** (`r0`-`r12`, SP, LR, PC) - We'll watch them change and manipulate `r0` to change program behavior
|
||||
- **Memory Layout** (Flash at `0x10000000`, RAM at `0x20000000`) - Critical for understanding where we can write
|
||||
@@ -54,7 +54,7 @@ The techniques you'll learn today are *exactly* how this would be done. Understa
|
||||
|
||||
## Part 2: Review - Memory Layout (from Week 1)
|
||||
|
||||
> 🔄 **REVIEW:** In Week 1, we learned about the RP2350's memory layout. This knowledge is essential for our hack!
|
||||
> **REVIEW:** In Week 1, we learned about the RP2350's memory layout. This knowledge is essential for our hack!
|
||||
|
||||
Before we hack, let's remember where things live in memory on the RP2350:
|
||||
|
||||
@@ -97,7 +97,7 @@ Our goal: **Make it print something else WITHOUT changing the source code!**
|
||||
+-----------------------------------------------------+
|
||||
```
|
||||
|
||||
> 🔄 **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.
|
||||
> **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
|
||||
|
||||
@@ -152,7 +152,7 @@ You will need **THREE** terminal windows:
|
||||
|
||||
---
|
||||
|
||||
## 🔬 Part 5: GDB Deep Dive - Exploring the Binary
|
||||
## Part 5: GDB Deep Dive - Exploring the Binary
|
||||
|
||||
Before we start hacking, let's use GDB to thoroughly understand our program. This hands-on tutorial will teach you to examine memory, step through code, and watch the stack in action.
|
||||
|
||||
@@ -164,12 +164,8 @@ OpenOCD is the bridge between your computer and the Pico 2's debug interface. It
|
||||
|
||||
**Open Terminal 1 and type:**
|
||||
|
||||
```powershell
|
||||
openocd ^
|
||||
-s "C:\Users\assem.KEVINTHOMAS\.pico-sdk\openocd\0.12.0+dev\scripts" ^
|
||||
-f interface/cmsis-dap.cfg ^
|
||||
-f target/rp2350.cfg ^
|
||||
-c "adapter speed 5000"
|
||||
```cmd
|
||||
openocd -s "%USERPROFILE%\.pico-sdk\openocd\0.12.0+dev\scripts" -f interface/cmsis-dap.cfg -f target/rp2350.cfg -c "adapter speed 5000"
|
||||
```
|
||||
|
||||
**What this command means:**
|
||||
@@ -224,7 +220,7 @@ The program is running and printing `"hello, world"` in an infinite loop!
|
||||
|
||||
**Open Terminal 3** and start GDB with your binary:
|
||||
|
||||
```powershell
|
||||
```cmd
|
||||
arm-none-eabi-gdb build\0x0001_hello-world.elf
|
||||
```
|
||||
|
||||
@@ -755,11 +751,11 @@ Let's tell GDB to show this as a string instead of a hex number:
|
||||
|
||||
There's our string! The `\r` is a carriage return character (part of `\r\n`).
|
||||
|
||||
> 🎯 **Key Discovery:** The string `"hello, world"` is stored at address `0x100019cc` in flash memory. This is the value that gets loaded into `r0` before calling `puts()`. We'll use this knowledge in our hack!
|
||||
> **Key Discovery:** The string `"hello, world"` is stored at address `0x100019cc` in flash memory. This is the value that gets loaded into `r0` before calling `puts()`. We'll use this knowledge in our hack!
|
||||
|
||||
---
|
||||
|
||||
## 🔬 Part 6: Continuing the Debug Session for the Hack
|
||||
## Part 6: Continuing the Debug Session for the Hack
|
||||
|
||||
You're right where you need to be from Part 5, so we **do not restart** OpenOCD or GDB here.
|
||||
|
||||
@@ -782,9 +778,9 @@ After that, continue to the analysis steps below.
|
||||
|
||||
---
|
||||
|
||||
## 🔬 Part 7: Analyzing the Target
|
||||
## Part 7: Analyzing the Target
|
||||
|
||||
> 🔄 **REVIEW:** We're using the same GDB commands we learned earlier. The `x` command examines memory, and `/5i` shows 5 instructions.
|
||||
> **REVIEW:** We're using the same GDB commands we learned earlier. The `x` command examines memory, and `/5i` shows 5 instructions.
|
||||
|
||||
##### Step 6: Examine the Main Function
|
||||
|
||||
@@ -812,14 +808,14 @@ Let's look at the main function to understand what we're dealing with:
|
||||
0x10000240 <main+12>: b.n 0x1000023a <main+6>
|
||||
```
|
||||
|
||||
> 🔄 **REVIEW:** This is the same disassembly we analyzed in Week 1! Remember:
|
||||
> **REVIEW:** This is the same disassembly we analyzed in Week 1! Remember:
|
||||
> - `push {r3, lr}` saves registers to the stack
|
||||
> - `bl` is "branch with link" - it calls a function and saves the return address in LR
|
||||
> - `b.n` is the infinite loop that jumps back to the `ldr` instruction
|
||||
|
||||
#### Understanding the Code Flow
|
||||
|
||||
> 🔄 **REVIEW:** In Week 1, we learned that `r0`-`r3` are used to pass arguments to functions. The first argument always goes in `r0`!
|
||||
> **REVIEW:** In Week 1, we learned that `r0`-`r3` are used to pass arguments to functions. The first argument always goes in `r0`!
|
||||
|
||||
Let's break down what happens each time through the loop:
|
||||
|
||||
@@ -847,9 +843,9 @@ If we can change what `r0` points to, we can make it print **anything we want**!
|
||||
|
||||
---
|
||||
|
||||
## 🔬 Part 8: Setting the Trap
|
||||
## Part 8: Setting the Trap
|
||||
|
||||
> 🔄 **REVIEW:** In Week 1, we used `b main` and `b *0x10000234` to set breakpoints. Now we'll use the same technique at a more strategic location!
|
||||
> **REVIEW:** In Week 1, we used `b main` and `b *0x10000234` to set breakpoints. Now we'll use the same technique at a more strategic location!
|
||||
|
||||
##### Step 7: Set a Strategic Breakpoint
|
||||
|
||||
@@ -932,9 +928,9 @@ Dump of assembler code for function main:
|
||||
|
||||
---
|
||||
|
||||
## 🔬 Part 9: Examining the Current State
|
||||
## Part 9: Examining the Current State
|
||||
|
||||
> 🔄 **REVIEW:** In Week 1, we used `x/s $r0` to view the "hello, world" string. We also learned about **little-endian** byte ordering - remember how `0x6c6c6568` spelled "lleh" backwards?
|
||||
> **REVIEW:** In Week 1, we used `x/s $r0` to view the "hello, world" string. We also learned about **little-endian** byte ordering - remember how `0x6c6c6568` spelled "lleh" backwards?
|
||||
|
||||
##### Step 10: Examine What's in r0
|
||||
|
||||
@@ -959,11 +955,11 @@ Let's see what string `r0` is currently pointing to:
|
||||
|
||||
There it is! The register `r0` contains `0x100019cc`, which is the address of our `"hello, world"` string in flash memory.
|
||||
|
||||
> 🔄 **REVIEW:** This is the same address `0x100019cc` we discovered in Week 1, Step 15 when we used `x/s $r0` after executing the `ldr` instruction!
|
||||
> **REVIEW:** This is the same address `0x100019cc` we discovered in Week 1, Step 15 when we used `x/s $r0` after executing the `ldr` instruction!
|
||||
|
||||
---
|
||||
|
||||
## 🔬 Part 10: The Failed Hack Attempt (Learning Why)
|
||||
## Part 10: The Failed Hack Attempt (Learning Why)
|
||||
|
||||
##### Step 11: Try to Directly Change the String (This Will Fail!)
|
||||
|
||||
@@ -1013,7 +1009,7 @@ The original string is still there. Our hack attempt failed... but we're not giv
|
||||
|
||||
---
|
||||
|
||||
## 🔬 Part 11: The Real Hack - Writing to SRAM
|
||||
## Part 11: The Real Hack - Writing to SRAM
|
||||
|
||||
##### Step 12: Understanding the Solution
|
||||
|
||||
@@ -1022,7 +1018,7 @@ 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 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.
|
||||
> **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.
|
||||
|
||||
@@ -1083,9 +1079,9 @@ The important thing is our string is in writable SRAM at a safe offset and ready
|
||||
|
||||
---
|
||||
|
||||
## 🔬 Part 12: Hijacking the Register
|
||||
## Part 12: Hijacking the Register
|
||||
|
||||
> 🔄 **REVIEW:** In Week 1, we learned that `r0` holds the first argument to a function. When `puts()` is called, it expects `r0` to contain a pointer to the string it should print. By changing `r0`, we change what gets printed!
|
||||
> **REVIEW:** In Week 1, we learned that `r0` holds the first argument to a function. When `puts()` is called, it expects `r0` to contain a pointer to the string it should print. By changing `r0`, we change what gets printed!
|
||||
|
||||
##### Step 15: Change r0 to Point to Our String
|
||||
|
||||
@@ -1152,7 +1148,7 @@ This is the first 4 bytes (`h a c k`) packed into one 32-bit little-endian word.
|
||||
|
||||
---
|
||||
|
||||
## 🔬 Part 13: Executing the Hack
|
||||
## Part 13: Executing the Hack
|
||||
|
||||
##### Step 17: Continue Execution
|
||||
|
||||
@@ -1189,13 +1185,13 @@ hello, world
|
||||
hacky, world <-- OUR HACK!
|
||||
```
|
||||
|
||||
🎉 **BOOM! WE DID IT!** 🎉
|
||||
**BOOM! WE DID IT!**
|
||||
|
||||
You just modified a running program on real hardware! The processor executed code that was supposed to print "hello, world" but instead printed "hacky, world" because we hijacked the data it was using!
|
||||
|
||||
---
|
||||
|
||||
## 🔬 Part 14: Static Analysis with Ghidra - Understanding the Hack
|
||||
## Part 14: Static Analysis with Ghidra - Understanding the Hack
|
||||
|
||||
Now that we've performed the hack dynamically with GDB, let's use Ghidra to understand the same concepts through static analysis. This shows how you could plan such an attack without even connecting to the hardware!
|
||||
|
||||
@@ -1271,7 +1267,7 @@ Notice:
|
||||
- The previous instruction at `0x1000023a` loaded `r0` with the string address
|
||||
- Ghidra shows `= "hello, world\r"` right in the listing!
|
||||
|
||||
> 🎯 **Key Insight:** Ghidra already tells us the string value! In the Listing, you can see `= "hello, world\r"` and `= 100019CCh`. This is the exact address we discovered through GDB!
|
||||
> **Key Insight:** Ghidra already tells us the string value! In the Listing, you can see `= "hello, world\r"` and `= 100019CCh`. This is the exact address we discovered through GDB!
|
||||
|
||||
##### Step 3: Find the String in Memory
|
||||
|
||||
@@ -1325,7 +1321,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 at a safe address (`0x20040000`) 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
|
||||
|
||||
@@ -1389,13 +1385,13 @@ Ghidra allows you to modify data directly in the binary! Here's how to patch the
|
||||
4. **Type** your new string: `"hacky, world\r"`
|
||||
5. **Press Enter** to apply the patch
|
||||
|
||||
> ⚠️ **Important:** The new string must be the **same length or shorter** than the original! If your new string is longer, it will overwrite adjacent data and likely crash the program.
|
||||
> **Important:** The new string must be the **same length or shorter** than the original! If your new string is longer, it will overwrite adjacent data and likely crash the program.
|
||||
|
||||
| Original String | Patched String | Result |
|
||||
| --------------- | -------------- | ------ |
|
||||
| `hello, world\r` (14 bytes) | `hacky, world\r` (14 bytes) | ✅ Works perfectly |
|
||||
| `hello, world\r` (14 bytes) | `PWNED!\r` (7 bytes) | ✅ Works (shorter is OK) |
|
||||
| `hello, world\r` (14 bytes) | `this is a much longer string\r` | ❌ Overwrites other data! |
|
||||
| `hello, world\r` (14 bytes) | `hacky, world\r` (14 bytes) | Works perfectly |
|
||||
| `hello, world\r` (14 bytes) | `PWNED!\r` (7 bytes) | Works (shorter is OK) |
|
||||
| `hello, world\r` (14 bytes) | `this is a much longer string\r` | Overwrites other data! |
|
||||
|
||||
After patching, you'll see the change reflected in the Listing view:
|
||||
|
||||
@@ -1409,7 +1405,7 @@ Notice how the bytes changed: `68 65 6c 6c 6f` ("hello") became `68 61 63 6b 79`
|
||||
|
||||
#### Looking Ahead: Persistent Binary Patching
|
||||
|
||||
> 🔮 **Coming in Future Lessons:** What we've done in Ghidra so far is just a **preview** of the patch - it modifies the data in Ghidra's view, but doesn't save it back to the actual binary file.
|
||||
> **Coming in Future Lessons:** What we've done in Ghidra so far is just a **preview** of the patch - it modifies the data in Ghidra's view, but doesn't save it back to the actual binary file.
|
||||
|
||||
In future lessons, we will learn how to:
|
||||
|
||||
@@ -1452,7 +1448,7 @@ This step helps you understand the mechanics of modifying binary data. Once you'
|
||||
|
||||
---
|
||||
|
||||
## 📊 Part 15: Summary and Review
|
||||
## Part 15: Summary and Review
|
||||
|
||||
#### What We Accomplished
|
||||
|
||||
@@ -1501,7 +1497,7 @@ AFTER OUR HACK:
|
||||
|
||||
| Command | What It Does | New/Review |
|
||||
| ---------------------------- | ----------------------------------- | ---------- |
|
||||
| `target remote :3333` | Connect to OpenOCD debug server | **New** |
|
||||
| `target extended-remote :3333` | Connect to OpenOCD debug server | **New** |
|
||||
| `monitor reset halt` | Reset and halt the processor | **New** |
|
||||
| `disas` | Disassemble the current function | Review |
|
||||
| `x/Ni ADDRESS` | Examine N instructions at ADDRESS | Review |
|
||||
@@ -1524,7 +1520,7 @@ AFTER OUR HACK:
|
||||
|
||||
---
|
||||
|
||||
## 🎓 Key Takeaways
|
||||
## Key Takeaways
|
||||
|
||||
#### Building on Week 1
|
||||
|
||||
@@ -1548,7 +1544,7 @@ AFTER OUR HACK:
|
||||
|
||||
---
|
||||
|
||||
## 🔐 Security Implications
|
||||
## Security Implications
|
||||
|
||||
#### How Would This Work in the Real World?
|
||||
|
||||
@@ -1571,7 +1567,7 @@ Imagine an attacker with physical access to an industrial control system:
|
||||
|
||||
---
|
||||
|
||||
## 📖 Glossary
|
||||
## Glossary
|
||||
|
||||
#### New Terms This Week
|
||||
|
||||
@@ -1598,3 +1594,4 @@ Imagine an attacker with physical access to an industrial control system:
|
||||
| **Little-Endian** | Storing the least significant byte at the lowest address | Part 10 - String storage |
|
||||
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user