Updated WEEK04

This commit is contained in:
Kevin Thomas
2026-05-09 11:42:33 -04:00
parent 005fd08646
commit ee664b6733
165 changed files with 3952 additions and 13308 deletions
-63
View File
@@ -1,63 +0,0 @@
# Embedded Systems Reverse Engineering
[Repository](https://github.com/mytechnotalent/Embedded-Hacking)
## Week 4
Variables in Embedded Systems: Debugging and Hacking Variables w/ GPIO Output Basics
### Non-Credit Practice Exercise 1 Solution: Analyze Variable Storage in Ghidra
#### Answers
##### Main Function Analysis
| Item | Value/Location | Notes |
|-----------------------|---------------|---------------------------------|
| Main function address | 0x10000234 | Entry point of program |
| Age value (hex) | 0x2b | Optimized constant |
| Age value (decimal) | 43 | Original variable value |
| Variable in memory? | No | Compiler optimized it away |
| printf address | 0x10003100 | Standard library function |
| stdio_init_all addr | 0x100030cc | I/O initialization |
| Format string | "age: %d\r\n" | Located in .rodata section |
##### Decompiled main() After Renaming
```c
int main(void)
{
stdio_init_all();
do {
printf("age: %d\r\n", 0x2b);
} while (true);
}
```
##### Hex-to-Decimal Conversion
```
0x2b = (2 × 16) + 11 = 32 + 11 = 43
```
The compiler replaced both `age = 42` and `age = 43` with the final constant value `0x2b` (43) as an immediate operand in `movs r1, #0x2b`.
##### Assembly Listing
```assembly
movs r1, #0x2b ; Load 43 directly into r1 (printf argument)
ldr r0, [pc, #...] ; Load format string address
bl printf ; Call printf
```
#### Reflection Answers
1. **Why did the compiler optimize away the `age` variable?**
The compiler performs **dead store elimination** and **constant propagation**. The initial assignment `age = 42` is immediately overwritten by `age = 43` with no intervening reads of the value 42. Since the only value ever observed is 43, the compiler replaces all references to `age` with the constant `0x2b` (43) as an immediate operand. No memory allocation is needed—the value lives entirely in the instruction encoding (`movs r1, #0x2b`).
2. **In what memory section would `age` have been stored if it wasn't optimized away?**
As a local variable declared inside `main()`, `age` would have been stored on the **stack** (in RAM at `0x2000xxxx`). The compiler would allocate space by subtracting from SP, store the value with a `str` instruction, and load it back with `ldr` before passing it to `printf`. If `age` were declared as a global initialized variable, it would be placed in the **`.data`** section (RAM, initialized from flash at boot). If declared as `static` or global but uninitialized, it would go in the **`.bss`** section (RAM, zeroed at boot).
3. **Where is the string "age: %d\r\n" stored, and why can't it be in RAM?**
The format string is stored in the **`.rodata`** (read-only data) section in flash memory at `0x1000xxxx`. It cannot be in RAM because: (a) string literals are constants that never change, so storing them in limited RAM would waste space; (b) flash is non-volatile—the string persists across power cycles without needing to be copied from anywhere; (c) the XIP (Execute In Place) mechanism allows the CPU to read directly from flash, so `.rodata` access is efficient.
4. **What would happen if we had used `age` in a calculation before reassigning it to 43?**
The compiler would be forced to preserve the value 42 because it's actually read before being overwritten. For example, `printf("before: %d\n", age); age = 43;` would require the compiler to generate both `movs r1, #0x2a` (42) for the first print and `movs r1, #0x2b` (43) for subsequent uses. Alternatively, a calculation like `age = age + 1` would allow the compiler to constant-fold `42 + 1 = 43` at compile time and still emit just `#0x2b`. Only if the value depends on runtime input would the variable require actual memory allocation.
-241
View File
@@ -1,241 +0,0 @@
# Embedded Systems Reverse Engineering
[Repository](https://github.com/mytechnotalent/Embedded-Hacking)
## Week 4
Variables in Embedded Systems: Debugging and Hacking Variables w/ GPIO Output Basics
### Non-Credit Practice Exercise 1: Analyze Variable Storage in Ghidra
#### Objective
Import and analyze the `0x0005_intro-to-variables.bin` binary in Ghidra to understand where variables are stored, identify memory sections, and trace how the compiler optimizes variable usage.
#### Prerequisites
- Ghidra installed and configured
- `0x0005_intro-to-variables.bin` binary available in your build directory
- Understanding of memory sections (`.data`, `.bss`, `.rodata`) from Week 4 Part 2
- Basic Ghidra navigation skills from Week 3
#### Task Description
You will import the binary into Ghidra, configure it for ARM Cortex-M33, analyze the code structure, resolve function names, and locate where the `age` variable is used in the compiled binary.
#### Step-by-Step Instructions
##### Step 1: Start Ghidra and Create New Project
```powershell
ghidraRun
```
1. Click **File** ? **New Project**
2. Select **Non-Shared Project**
3. Click **Next**
4. Enter Project Name: `week04-ex01-intro-to-variables`
5. Choose a project directory
6. Click **Finish**
##### Step 2: Import the Binary
1. Navigate to your file explorer
2. Find `Embedded-Hacking\0x0005_intro-to-variables\build\0x0005_intro-to-variables.bin`
3. **Drag and drop** the `.bin` file into Ghidra's project window
##### Step 3: Configure Import Settings
When the import dialog appears:
1. Click the three dots (**…**) next to **Language**
2. Search for: `Cortex`
3. Select: **ARM Cortex 32 little endian default**
4. Click **OK**
Now click **Options…** button:
1. Change **Block Name** to: `.text`
2. Change **Base Address** to: `10000000` (XIP flash base)
3. Click **OK**
Then click **OK** on the main import dialog.
##### Step 4: Analyze the Binary
1. Double-click the imported file in the project window
2. When prompted "Analyze now?" click **Yes**
3. Leave all default analysis options selected
4. Click **Analyze**
5. Wait for analysis to complete (watch bottom-right progress bar)
##### Step 5: Navigate to the Symbol Tree
Look at the left panel for the **Symbol Tree**. Expand **Functions** to see the auto-detected functions:
You should see function names like:
- `FUN_1000019a`
- `FUN_10000210`
- `FUN_10000234`
- Many more...
These are auto-generated names because we're analyzing a raw binary without debug symbols.
##### Step 6: Identify the Main Function
From Week 3, we know the typical boot sequence:
1. Reset handler copies data
2. `frame_dummy` runs
3. `main()` is called
Click on `FUN_10000234` - this should be our `main()` function.
**Look at the Decompile window:**
```c
void FUN_10000234(void)
{
FUN_100030cc();
do {
FUN_10003100("age: %d\r\n", 0x2b);
} while (true);
}
```
**Observations:**
- `FUN_100030cc()` is likely `stdio_init_all()`
- `FUN_10003100()` is likely `printf()`
- The magic value `0x2b` appears (what is this?)
##### Step 7: Convert 0x2b to Decimal
Let's figure out what `0x2b` means:
**Manual calculation:**
- `0x2b` in hexadecimal
- `2 × 16 + 11 = 32 + 11 = 43` in decimal
**In GDB (alternative method):**
```gdb
(gdb) p/d 0x2b
$1 = 43
```
So `0x2b = 43`! This matches our `age = 43` from the source code!
##### Step 8: Rename Functions for Clarity
Let's rename the functions to their actual names:
**Rename FUN_10000234 to main:**
1. Right-click on `FUN_10000234` in the Symbol Tree
2. Select **Rename Function**
3. Enter: `main`
4. Press **Enter**
**Update main's signature:**
1. In the Decompile window, right-click on `main`
2. Select **Edit Function Signature**
3. Change to: `int main(void)`
4. Click **OK**
**Rename FUN_100030cc to stdio_init_all:**
1. Click on `FUN_100030cc` in the decompile window
2. Right-click ? **Edit Function Signature**
3. Change name to: `stdio_init_all`
4. Change signature to: `bool stdio_init_all(void)`
5. Click **OK**
**Rename FUN_10003100 to printf:**
1. Click on `FUN_10003100`
2. Right-click ? **Edit Function Signature**
3. Change name to: `printf`
4. Check the **Varargs** checkbox (printf accepts variable arguments)
5. Click **OK**
##### Step 9: Examine the Optimized Code
After renaming, the decompiled main should now look like:
```c
int main(void)
{
stdio_init_all();
do {
printf("age: %d\r\n", 0x2b);
} while (true);
}
```
**Critical observation:** Where did our `age` variable go?
Original source code:
```c
uint8_t age = 42;
age = 43;
```
The compiler **optimized it completely away**!
**Why?**
1. `age = 42` is immediately overwritten
2. The value `42` is never used
3. The compiler replaces `age` with the constant `43` (`0x2b`)
4. No variable allocation in memory is needed!
##### Step 10: Examine the Assembly Listing
Click on the **Listing** window (shows assembly code):
Find the instruction that loads `0x2b`:
```assembly
10000xxx movs r1, #0x2b
10000xxx ...
10000xxx bl printf
```
**What this does:**
- `movs r1, #0x2b` - Moves the immediate value 0x2b (43) into register r1
- `bl printf` - Branches to printf, which expects format args in r1+
##### Step 11: Document Your Findings
Create a table of your observations:
| Item | Value/Location | Notes |
| --------------------- | -------------- | ------------------------------- |
| Main function address | `0x10000234` | Entry point of program |
| Age value (hex) | `0x2b` | Optimized constant |
| Age value (decimal) | `43` | Original variable value |
| Variable in memory? | No | Compiler optimized it away |
| Printf address | `0x10003100` | Standard library function |
| Format string | "age: %d\r\n" | Located in .rodata section |
#### Expected Output
After completing this exercise, you should be able to:
- Successfully import and configure ARM binaries in Ghidra
- Navigate the Symbol Tree and identify functions
- Understand how compiler optimization removes unnecessary variables
- Convert hexadecimal values to decimal
- Rename functions for better code readability
#### Questions for Reflection
###### Question 1: Why did the compiler optimize away the `age` variable?
###### Question 2: In what memory section would `age` have been stored if it wasn't optimized away?
###### Question 3: Where is the string "age: %d\r\n" stored, and why can't it be in RAM?
###### Question 4: What would happen if we had used `age` in a calculation before reassigning it to 43?
#### Tips and Hints
- Use **CTRL+F** in Ghidra to search for specific values or strings
- The **Data Type Manager** window shows all recognized data types
- If Ghidra's decompiler output looks wrong, try re-analyzing with different options
- Remember: optimized code often looks very different from source code
- The **Display** ? **Function Graph** shows control flow visually
#### Next Steps
- Proceed to Exercise 2 to learn binary patching
- Try analyzing `0x0008_uninitialized-variables.bin` to see how uninitialized variables behave
- Explore the `.rodata` section to find string literals
#### Additional Challenge
Find the format string "age: %d\r\n" in Ghidra. What address is it stored at? How does the program reference this string in the assembly code? (Hint: Look for an `ldr` instruction that loads the string address into a register.)
-53
View File
@@ -1,53 +0,0 @@
# Embedded Systems Reverse Engineering
[Repository](https://github.com/mytechnotalent/Embedded-Hacking)
## Week 4
Variables in Embedded Systems: Debugging and Hacking Variables w/ GPIO Output Basics
### Non-Credit Practice Exercise 2 Solution: Patch Binary to Change Variable Value
#### Answers
##### Patch Details
| Item | Original | Patched |
|--------------------|-------------- |---------------|
| Instruction | movs r1, #0x2b | movs r1, #0x46 |
| Hex bytes | 21 2b | 21 46 |
| Decimal value | 43 | 70 |
| Output | age: 43 | age: 70 |
##### Patching Steps
1. Located `movs r1, #0x2b` in Ghidra Listing view
2. Right-click → **Patch Instruction** → changed `#0x2b` to `#0x46`
3. Verified in Decompile window: `printf("age: %d\r\n", 0x46)`
4. Exported: **File → Export Program → Binary**`0x0005_intro-to-variables-h.bin`
5. Converted to UF2:
```powershell
python ..\uf2conv.py build\0x0005_intro-to-variables-h.bin --base 0x10000000 --family 0xe48bff59 --output build\hacked.uf2
```
6. Flashed via BOOTSEL → RPI-RP2 drive
##### Serial Output
```
age: 70
age: 70
age: 70
...
```
#### Reflection Answers
1. **Why do we need to convert to UF2 format instead of flashing the raw .bin file?**
The RP2350 bootloader (accessed via BOOTSEL) expects **UF2 (USB Flashing Format)** files. UF2 is a container format that includes metadata: the target flash address for each 256-byte block, a family ID (`0xe48bff59` for RP2350), and checksums. A raw `.bin` file contains only code bytes with no addressing information—the bootloader wouldn't know where in flash to write the data. UF2 also supports partial updates and is self-describing, making it safer for USB mass storage flashing.
2. **What is the significance of the base address 0x10000000 in the conversion command?**
`0x10000000` is the **XIP (Execute In Place) flash base address** on the RP2350. This tells the UF2 converter that byte 0 of the binary should be written to flash address `0x10000000`. The CPU fetches instructions directly from this address range via the XIP controller. If the base address were wrong (e.g., `0x20000000` for RAM), the code would be written to the wrong location and the processor would fail to boot because the vector table wouldn't be found at the expected address.
3. **What would happen if you patched the wrong instruction by mistake?**
The consequences depend on what was changed: (a) Patching a different `movs` might corrupt an unrelated function parameter, causing incorrect behavior or a crash. (b) Patching opcode bytes (not just the immediate) could create an invalid instruction, triggering a HardFault or UsageFault. (c) Patching inside a multi-byte instruction could split it into two unintended instructions, corrupting the entire subsequent instruction stream. The program would likely crash, output garbage, or hang—requiring reflashing with the original UF2 to recover.
4. **How can you verify a patch was applied correctly before exporting?**
Multiple verification methods: (a) Check the **Decompile window**—it should reflect the new value (e.g., `printf("age: %d\r\n", 0x46)`). (b) Inspect the **Listing window** bytes—confirm the instruction bytes changed from `21 2b` to `21 46`. (c) Use **right-click → Highlight → Highlight Difference** to see patched bytes highlighted. (d) Compare the patched instruction against the ARM Thumb encoding reference to verify the encoding is valid. (e) Check surrounding instructions are unchanged—patches should not accidentally modify adjacent code.
-220
View File
@@ -1,220 +0,0 @@
# Embedded Systems Reverse Engineering
[Repository](https://github.com/mytechnotalent/Embedded-Hacking)
## Week 4
Variables in Embedded Systems: Debugging and Hacking Variables w/ GPIO Output Basics
### Non-Credit Practice Exercise 2: Patch Binary to Change Variable Value
#### Objective
Use Ghidra's patching capabilities to modify the compiled binary, changing the value printed by the program from 43 to a different value of your choice, then convert and flash the modified binary to the Pico 2.
#### Prerequisites
- Completed Exercise 1 (binary imported and analyzed in Ghidra)
- Python installed for UF2 conversion
- `uf2conv.py` script available in your project directory
- Raspberry Pi Pico 2 connected via USB
- Serial monitor software (PuTTY, minicom, or screen)
#### Task Description
You will locate the instruction that loads the value 43 into a register, patch it to use a different value (70 in this example), export the modified binary, convert it to UF2 format, and flash it to verify the change.
#### Step-by-Step Instructions
##### Step 1: Open Your Ghidra Project
If you closed Ghidra from Exercise 1:
1. Launch `ghidraRun`
2. Open the project: `week04-ex01-intro-to-variables`
3. Double-click the binary file to open it
##### Step 2: Navigate to the Value Load Instruction
In Exercise 1, we found that `main()` calls `printf("age: %d\r\n", 0x2b)`.
**Find the assembly instruction:**
1. Click on the `main` function in the Symbol Tree
2. Look at the **Listing** window (assembly view)
3. Find the line with `movs r1, #0x2b`
The instruction should look like:
```assembly
10000xxx 21 2b movs r1, #0x2b
```
**What this instruction means:**
- Opcode: `21 2b` (encoded instruction bytes)
- Mnemonic: `movs r1, #0x2b`
- Operation: Move the immediate value 0x2b into register r1
- Register r1 will be used as the argument to printf
##### Step 3: Choose Your New Value
Let's change the value from `43` (0x2b) to `70` (0x46).
**Convert 70 to hexadecimal:**
- 70 ÷ 16 = 4 remainder 6
- Therefore: 70 decimal = 0x46 hexadecimal
You can verify this in Python:
```python
>>> hex(70)
'0x46'
>>> 0x46
70
```
##### Step 4: Patch the Instruction
Now we'll modify the binary:
1. **Right-click** on the instruction `movs r1, #0x2b`
2. Select **Patch Instruction**
3. A dialog appears showing the current instruction
4. Change `#0x2b` to `#0x46`
5. Press **Enter** or click **OK**
The instruction now reads:
```assembly
10000xxx 21 46 movs r1, #0x46
```
**Visual confirmation:**
- The patched instruction should be highlighted (usually in red or orange)
- The bytes should change from `21 2b` to `21 46`
- The decompiled view should update to show `printf("age: %d\r\n", 0x46);`
##### Step 5: Verify the Patch in Decompile Window
Click on the `main` function again and check the **Decompile** window:
```c
int main(void)
{
stdio_init_all();
do {
printf("age: %d\r\n", 0x46); // Changed from 0x2b!
} while (true);
}
```
Perfect! The decompiler recognized our patch.
##### Step 6: Export the Patched Binary
Now we need to save the modified binary:
1. Click **File****Export Program**
2. Set **Format** to: **Binary**
3. Navigate to your build directory:
- `Embedded-Hacking\0x0005_intro-to-variables\build\`
4. Set **Filename** to: `0x0005_intro-to-variables-h.bin`
- The `-h` suffix means "hacked"
5. Click **OK**
**Important:** Make sure you're exporting to the correct location!
##### Step 7: Convert to UF2 Format
The Pico 2 requires UF2 format. Open a terminal and run:
**Navigate to the project directory:**
```powershell
cd C:\path\to\Embedded-Hacking\0x0005_intro-to-variables
```
**Run the conversion:**
```powershell
python ..\uf2conv.py build\0x0005_intro-to-variables-h.bin --base 0x10000000 --family 0xe48bff59 --output build\hacked.uf2
```
**Command breakdown:**
- `uf2conv.py` - The conversion script
- `--base 0x10000000` - XIP flash base address (where code runs from)
- `--family 0xe48bff59` - RP2350 family ID
- `--output build\hacked.uf2` - Output filename
**Expected output:**
```
Converting to uf2, output size: 57856, start address: 0x10000000
Wrote 57856 bytes to build\hacked.uf2
```
##### Step 8: Flash the Hacked Binary
**Enter bootloader mode:**
1. Disconnect your Pico 2 from USB
2. Hold down the **BOOTSEL** button
3. While holding BOOTSEL, plug in the USB cable
4. Release BOOTSEL
5. A drive called **RPI-RP2** appears
**Flash the binary:**
1. Open the RPI-RP2 drive
2. Drag and drop `build\hacked.uf2` onto the drive
3. The Pico will automatically reboot
##### Step 9: Verify the Changes
**Open your serial monitor:**
For PuTTY:
1. Select **Serial** connection type
2. Set the COM port (check Device Manager)
3. Set speed to **115200**
4. Click **Open**
For PowerShell:
```powershell
# Find the COM port
Get-PnpDevice -Class Ports | Where-Object {$_.FriendlyName -like "*USB Serial*"}
# Connect (replace COM3 with your port)
$port = new-Object System.IO.Ports.SerialPort COM3,115200,None,8,one
$port.Open()
while($true) { $port.ReadLine() }
```
**Expected output:**
```
age: 70
age: 70
age: 70
age: 70
...
```
🎉 **Success!** You've successfully patched a binary and changed its behavior!
#### Expected Output
After completing this exercise, you should:
- See `age: 70` printing instead of `age: 43`
- Have a patched binary file (`0x0005_intro-to-variables-h.bin`)
- Have a UF2 file (`hacked.uf2`)
- Understand the complete patching workflow
#### Questions for Reflection
###### Question 1: Why do we need to convert to UF2 format instead of flashing the raw .bin file?
###### Question 2: What is the significance of the base address 0x10000000 in the conversion command?
###### Question 3: What would happen if you patched the wrong instruction by mistake?
###### Question 4: How can you verify a patch was applied correctly before exporting?
#### Tips and Hints
- Always make a backup of the original binary before patching
- Use descriptive names like `-h` (hacked) or `-patch` for modified binaries
- Test your patches on hardware to ensure they work as expected
- If something goes wrong, you can always flash the original UF2 file
- Use `File → Export Program → Original File` to revert all patches
#### Next Steps
- Try patching to different values (100, 255, etc.)
- Proceed to Exercise 3 to learn about GPIO control
- Experiment with patching multiple values in the same binary
#### Additional Challenge
Instead of changing the value to 70, change it to 255 (0xFF) - the maximum value for a `uint8_t`. What do you observe? Now try changing it to 256 (0x100). What happens and why? (Hint: Think about the size limits of the instruction encoding.)
-97
View File
@@ -1,97 +0,0 @@
# Embedded Systems Reverse Engineering
[Repository](https://github.com/mytechnotalent/Embedded-Hacking)
## Week 4
Variables in Embedded Systems: Debugging and Hacking Variables w/ GPIO Output Basics
### Non-Credit Practice Exercise 3 Solution: Analyze and Understand GPIO Control
#### Answers
##### Main Function Decompiled (After Renaming)
```c
int main(void)
{
stdio_init_all();
gpio_init(0x10); // Initialize GPIO 16
gpio_set_dir(0x10, 1); // Set as output (GPIO_OUT = 1)
while (true) {
printf("age: %d\r\n", 0); // Uninitialized variable = 0
gpio_put(0x10, 1); // LED ON
sleep_ms(0x1f4); // Wait 500ms
gpio_put(0x10, 0); // LED OFF
sleep_ms(0x1f4); // Wait 500ms
}
}
```
##### GPIO Function Identification Table
| Auto-Generated Name | Actual Function | Parameters | Identification Method |
|---------------------|-----------------|--------------------------------|--------------------------------------|
| FUN_100030cc | stdio_init_all | (void) | Called first, no parameters |
| FUN_xxxxxxxx | gpio_init | (uint gpio) | Single parameter = pin number (0x10) |
| FUN_xxxxxxxx | gpio_set_dir | (uint gpio, bool out) | Two params: pin + direction (1=out) |
| FUN_xxxxxxxx | gpio_put | (uint gpio, bool value) | Two params: pin + value (0 or 1) |
| FUN_xxxxxxxx | sleep_ms | (uint32_t ms) | Single param = delay (0x1f4 = 500) |
| FUN_10003100 | printf | (const char *fmt, ...) | Format string + varargs |
##### Key Value Conversions
| Hex | Decimal | Binary | Purpose |
|--------|---------|-------------|------------------------|
| 0x10 | 16 | 0000 1000 | GPIO pin number (red LED) |
| 0x1f4 | 500 | — | Sleep duration (ms) |
| 0x01 | 1 | 0000 0001 | GPIO_OUT / LED ON |
| 0x00 | 0 | 0000 0000 | GPIO_IN / LED OFF |
```
0x10 = (1 × 16) + 0 = 16
0x1f4 = (1 × 256) + (15 × 16) + 4 = 256 + 240 + 4 = 500
```
##### GPIO Memory Map
| Address | Register | Purpose |
|-------------|-------------|------------------------------|
| 0x40028000 | IO_BANK0 | GPIO function selection |
| 0x40038000 | PADS_BANK0 | GPIO pad configuration |
| 0xd0000000 | SIO | Single-cycle I/O |
GPIO 16 specific:
- Pad control: `0x40038000 + (16 × 4) = 0x40038040`
- Function select: `0x40028000 + (16 × 4) = 0x40028040`
##### gpio_put Coprocessor Instruction
```assembly
mcrr p0, #4, r4, r5, c0
```
- `mcrr` = Move to Coprocessor from two ARM Registers
- `p0` = Coprocessor 0 (GPIO coprocessor on RP2350)
- `r4` = GPIO pin number, `r5` = value (0 or 1)
- Single-cycle GPIO operation
##### Blink Timing Analysis
- ON duration: `sleep_ms(0x1f4)` = 500ms
- OFF duration: `sleep_ms(0x1f4)` = 500ms
- Total cycle: 1000ms = 1 second
- Blink rate: **1 Hz**
#### Reflection Answers
1. **Why does gpio_init() need to configure both PADS_BANK0 and IO_BANK0 registers?**
These registers control different aspects of GPIO operation. **PADS_BANK0** (`0x40038000`) configures the physical pad properties: input enable (IE), output disable (OD), pull-up/pull-down resistors, drive strength, and slew rate. **IO_BANK0** (`0x40028000`) configures the function multiplexer (FUNCSEL), selecting which internal peripheral drives the pin—SIO (function 5) for software control, UART, SPI, I2C, PWM, etc. Both must be configured: PADS sets the electrical characteristics of the physical pin, while IO_BANK0 routes the correct internal signal to it.
2. **What is the advantage of using the GPIO coprocessor instruction (`mcrr`) instead of writing to memory-mapped registers?**
The `mcrr` coprocessor instruction completes in a **single CPU cycle**, whereas writing to memory-mapped GPIO registers requires multiple cycles: an address load, a data load, and a store instruction (plus potential bus wait states). On the RP2350, the SIO coprocessor provides deterministic, single-cycle access to GPIO outputs, which is critical for bit-banging protocols (like SPI or custom serial) where precise timing is required. The coprocessor path bypasses the AHB/APB bus entirely.
3. **If you wanted to blink the LED at 10 Hz instead of 1 Hz, what value should `sleep_ms()` use?**
At 10 Hz, each full on/off cycle is 100ms. Since the loop has two `sleep_ms()` calls (one for ON, one for OFF), each should be `100 / 2 = 50ms`. In hex: `50 = 0x32`. So both `sleep_ms()` calls should use `sleep_ms(0x32)`.
4. **What would happen if you called `gpio_put()` on a pin that hasn't been initialized with `gpio_init()` first?**
The GPIO pin's function would still be set to its reset default (typically NULL/function 0), not SIO (function 5). The `gpio_put()` coprocessor instruction would update the SIO output register internally, but since the pin's function multiplexer isn't routing SIO to the physical pad, the electrical state of the pin wouldn't change. The LED would remain off. Additionally, without pad configuration, input enable and output disable bits may not be set correctly, further preventing any observable output.
-270
View File
@@ -1,270 +0,0 @@
# Embedded Systems Reverse Engineering
[Repository](https://github.com/mytechnotalent/Embedded-Hacking)
## Week 4
Variables in Embedded Systems: Debugging and Hacking Variables w/ GPIO Output Basics
### Non-Credit Practice Exercise 3: Analyze and Understand GPIO Control
#### Objective
Import the `0x0008_uninitialized-variables.bin` binary, analyze the GPIO initialization and control sequences, understand how `gpio_init()`, `gpio_set_dir()`, and `gpio_put()` work at the assembly level.
#### Prerequisites
- Completed Exercises 1 and 2
- Understanding of GPIO basics from Week 4 Part 3
- Raspberry Pi Pico 2 with an LED connected to GPIO 16
- Basic knowledge of ARM Thumb-2 instruction set
#### Task Description
You will import a new binary that controls GPIO pins, identify the GPIO-related function calls, trace the initialization sequence, and understand how the Pico SDK controls hardware at the low level.
#### Step-by-Step Instructions
##### Step 1: Flash the Original Binary
Before analysis, let's see what the program does:
1. Hold **BOOTSEL** and plug in your Pico 2
2. Flash `0x0008_uninitialized-variables.uf2` to the RPI-RP2 drive
3. Open your serial monitor
**Expected output:**
```
age: 0
age: 0
age: 0
...
```
**Expected behavior:**
- The red LED on GPIO 16 blinks on/off every 500ms
- The value `0` is printed (uninitialized variable)
##### Step 2: Create a New Ghidra Project
1. Launch Ghidra: `ghidraRun`
2. Click **File****New Project**
3. Select **Non-Shared Project**
4. Project Name: `week04-ex03-gpio-analysis`
5. Click **Finish**
##### Step 3: Import the GPIO Binary
1. Drag and drop `0x0008_uninitialized-variables.bin` into Ghidra
2. Set Language: **ARM Cortex 32 little endian default**
3. Click **Options…**
- Block Name: `.text`
- Base Address: `10000000`
4. Click **OK** on all dialogs
5. Double-click the file and click **Yes** to analyze
##### Step 4: Identify the Main Function
Look for the main function (likely `FUN_10000234` or similar):
**In the Symbol Tree:**
1. Expand **Functions**
2. Look for a function that appears to be an entry point
3. Click on potential `main` candidates
**Look for these patterns in the decompile:**
- Call to `stdio_init_all()`
- Call to `gpio_init()`
- Infinite while loop with `gpio_put()` and `sleep_ms()`
##### Step 5: Rename the Main Function
Once you identify `main`:
1. Right-click on the function name
2. Select **Edit Function Signature**
3. Change to: `int main(void)`
4. Click **OK**
**Expected decompiled code structure:**
```c
int main(void)
{
// Some initial value
stdio_init_all();
gpio_init(0x10); // GPIO 16
// ... more GPIO setup
while (true) {
printf(...);
gpio_put(0x10, 1);
sleep_ms(0x1f4);
gpio_put(0x10, 0);
sleep_ms(0x1f4);
}
}
```
##### Step 6: Identify GPIO Function Calls
Look in the decompiled main for function calls. You should see several undefined functions.
**Find and rename these GPIO functions:**
| Auto-Generated Name | Actual Function | How to Identify |
| ------------------- | ----------------- | ------------------------------------------ |
| `FUN_xxxxx` | `gpio_init` | Takes one parameter (pin number) |
| `FUN_xxxxx` | `gpio_set_dir` | Takes two parameters (pin, direction) |
| `FUN_xxxxx` | `gpio_put` | Takes two parameters (pin, value) |
| `FUN_xxxxx` | `sleep_ms` | Takes one parameter (milliseconds) |
| `FUN_xxxxx` | `stdio_init_all` | Takes no parameters, called first |
| `FUN_xxxxx` | `printf` | Takes variable args, has format string |
**Example renaming gpio_init:**
1. Click on the function call in the decompile window
2. Right-click → **Edit Function Signature**
3. Change name to: `gpio_init`
4. Set signature to: `void gpio_init(uint gpio)`
5. Click **OK**
##### Step 7: Analyze GPIO Initialization Sequence
After renaming, your decompiled main should look clearer:
```c
int main(void)
{
stdio_init_all();
gpio_init(0x10); // Initialize GPIO 16
gpio_set_dir(0x10, 1); // Set as output (1 = GPIO_OUT)
while (true) {
printf("age: %d\r\n", 0);
gpio_put(0x10, 1); // LED ON
sleep_ms(0x1f4); // Wait 500ms (0x1f4 = 500)
gpio_put(0x10, 0); // LED OFF
sleep_ms(0x1f4); // Wait 500ms
}
}
```
**Key observations:**
- `0x10` is hexadecimal for 16 (GPIO 16 - red LED)
- `0x1f4` is hexadecimal for 500 (milliseconds)
- `1` means GPIO_OUT (output direction)
- The LED is controlled by toggling between 1 (on) and 0 (off)
##### Step 8: Examine gpio_init Assembly
Double-click on `gpio_init` to jump to its implementation.
**Look for these key operations in the assembly:**
```assembly
; Load GPIO pin number into register
movs r4, r0 ; Save pin number
; Calculate pad register address
; Base address: 0x40038000 (PADS_BANK0)
; Offset: pin * 4
ldr r3, =0x40038000
lsls r5, r4, #2 ; pin * 4
add r3, r5 ; Calculate address
; Configure pad (clear OD bit, set IE bit)
ldr r2, [r3] ; Read current config
bic r2, #0x80 ; Clear output disable
orr r2, #0x40 ; Set input enable
str r2, [r3] ; Write back
; Set GPIO function to SIO (0x05)
ldr r3, =0x40028000 ; IO_BANK0 base
add r3, r5 ; Add offset
movs r2, #5 ; FUNCSEL = SIO
str r2, [r3] ; Set function
```
**What this does:**
1. Configures the GPIO pad registers (physical pin properties)
2. Sets the GPIO function to SIO (Software I/O)
3. Prepares the pin for software control
##### Step 9: Examine gpio_put Assembly
Find the `gpio_put` function and examine its implementation.
**Look for the GPIO coprocessor instruction:**
```assembly
gpio_put:
movs r4, r0 ; GPIO pin number
movs r5, r1 ; Value (0 or 1)
; Use ARM coprocessor to control GPIO
mcrr p0, #4, r4, r5, c0
bx lr ; Return
```
**Critical instruction: `mcrr p0, #4, r4, r5, c0`**
- `mcrr` = Move to Coprocessor from two ARM Registers
- `p0` = Coprocessor 0 (GPIO coprocessor in RP2350)
- `#4` = Operation code
- `r4, r5` = Source registers (pin number, value)
- `c0` = Coprocessor register (GPIO output control)
This is a **single-cycle GPIO operation** - extremely fast!
##### Step 10: Document the GPIO Memory Map
Create a reference table of the addresses you found:
| Address | Register | Purpose |
| ------------ | ------------- | ------------------------------- |
| `0x40028000` | IO_BANK0 | GPIO function selection |
| `0x40038000` | PADS_BANK0 | GPIO pad configuration |
| `0xd0000000` | SIO | Single-cycle I/O (coprocessor) |
**GPIO 16 specific addresses:**
- Pad control: `0x40038000 + (16 * 4) = 0x40038040`
- Function select: `0x40028000 + (16 * 4) = 0x40028040`
##### Step 11: Trace the Blink Timing
Calculate the actual timing:
**sleep_ms(0x1f4):**
- Convert: 0x1f4 = (1 × 256) + (15 × 16) + 4 = 256 + 240 + 4 = 500 decimal
- So the LED is on for 500ms, off for 500ms
- Total cycle time: 1000ms = 1 second
- Blink rate: 1 Hz
#### Expected Output
After completing this exercise, you should understand:
- How GPIO initialization configures hardware registers
- The role of the GPIO coprocessor in the RP2350
- How `gpio_put()` uses a single ARM instruction for fast I/O
- The memory-mapped addresses for GPIO control
- How timing delays are implemented with `sleep_ms()`
#### Questions for Reflection
###### Question 1: Why does gpio_init() need to configure both PADS_BANK0 and IO_BANK0 registers?
###### Question 2: What is the advantage of using the GPIO coprocessor instruction (`mcrr`) instead of writing to memory-mapped registers?
###### Question 3: If you wanted to blink the LED at 10 Hz instead of 1 Hz, what value should `sleep_ms()` use?
###### Question 4: What would happen if you called `gpio_put()` on a pin that hasn't been initialized with `gpio_init()` first?
#### Tips and Hints
- Use Ghidra's **References** feature (right-click → Find References) to see where functions are called
- The **Display****Memory Map** shows all memory regions
- Look for bit manipulation instructions (`bic`, `orr`) to understand register configuration
- The ARM Architecture Reference Manual has complete documentation on coprocessor instructions
- Use hex-to-decimal converters online if you're unsure about conversions
#### Next Steps
- Proceed to Exercise 4 to patch the GPIO binary
- Try to identify other SDK functions like `gpio_get()` if they appear
- Explore the full GPIO initialization in the SDK source code
#### Additional Challenge
Find the `gpio_set_dir()` function in Ghidra. Does it also use a GPIO coprocessor instruction? What coprocessor register does it use (c0, c4, or something else)? Compare its implementation to `gpio_put()` and document the differences.
-102
View File
@@ -1,102 +0,0 @@
# Embedded Systems Reverse Engineering
[Repository](https://github.com/mytechnotalent/Embedded-Hacking)
## Week 4
Variables in Embedded Systems: Debugging and Hacking Variables w/ GPIO Output Basics
### Non-Credit Practice Exercise 4 Solution: Patch GPIO Binary to Change LED Pin
#### Answers
##### Patch Summary
| Item | Original | Patched | Hex Change |
|---------------|-----------------|-----------------|---------------|
| LED pin | GPIO 16 | GPIO 17 | 0x10 → 0x11 |
| Printed value | 0 (uninitialized)| 66 | 0x00 → 0x42 |
| Blink timing | 500ms | 100ms | 0x1f4 → 0x64 |
##### Detailed Patch Locations
**1. gpio_init parameter:**
```assembly
; Before: movs r0, #0x10 (bytes: 10 20)
; After: movs r0, #0x11 (bytes: 11 20)
```
**2. gpio_set_dir parameter:**
```assembly
; Before: movs r3, #0x10 (bytes: 10 23)
; After: movs r3, #0x11 (bytes: 11 23)
```
**3. gpio_put (LED ON) parameter:**
```assembly
; Before: movs r4, #0x10 (bytes: 10 24)
; After: movs r4, #0x11 (bytes: 11 24)
```
**4. gpio_put (LED OFF) parameter:**
```assembly
; Before: movs r4, #0x10 (bytes: 10 24)
; After: movs r4, #0x11 (bytes: 11 24)
```
**5. printf value:**
```assembly
; Before: movs r1, #0x00 (bytes: 00 21)
; After: movs r1, #0x42 (bytes: 42 21)
```
**6. sleep_ms (both calls):**
```assembly
; Before: loads 0x1f4 (500ms)
; After: movs r0, #0x64 (100ms)
```
##### Hex Conversions
```
GPIO 17: 17 = 0x11 = 0001 0001 binary
Value 66: 66 = 0x42 = 0100 0010 binary
100ms: 100 = 0x64 = 0110 0100 binary
```
##### Decompiled Result After All Patches
```c
int main(void)
{
stdio_init_all();
gpio_init(0x11); // GPIO 17 (green LED)
gpio_set_dir(0x11, 1); // Output
while (true) {
printf("age: %d\r\n", 0x42); // Prints 66
gpio_put(0x11, 1); // Green LED ON
sleep_ms(0x64); // 100ms
gpio_put(0x11, 0); // Green LED OFF
sleep_ms(0x64); // 100ms
}
}
```
##### Hardware Verification
- GREEN LED (GPIO 17) blinks at 10 Hz (100ms on, 100ms off)
- RED LED (GPIO 16) remains off
- Serial output: `age: 66` repeating
#### Reflection Answers
1. **Why did we need to patch GPIO 16 in multiple places (gpio_init, gpio_set_dir, gpio_put)?**
Each function takes the GPIO pin number as a separate parameter. `gpio_init(16)` configures the pad and function mux for pin 16. `gpio_set_dir(16, 1)` sets pin 16's direction to output. `gpio_put(16, value)` toggles pin 16's output state. These are independent function calls with independent immediate values in the instruction stream—the compiler doesn't share or reuse a single "pin number variable." Each `movs rN, #0x10` loads the pin number fresh for its respective function call. Missing any one patch would result in a mismatch: e.g., initializing pin 17 but toggling pin 16.
2. **What would happen if you forgot to patch one of the gpio_put calls?**
You would get asymmetric behavior. For example, if you patched the "LED ON" `gpio_put` to pin 17 but left the "LED OFF" at pin 16: GPIO 17 (green) would turn on but never turn off (staying permanently lit), while GPIO 16 (red) would receive the "off" command for a pin that was never initialized—which would have no visible effect. The result: green LED stuck on, no blinking.
3. **How does the instruction encoding differ for immediate values less than 256 vs. greater than 255?**
In 16-bit Thumb encoding, `movs Rd, #imm8` can only encode immediate values 0255 in a single 2-byte instruction. For values > 255 (like 500 = 0x1f4), the compiler must use either: (a) a 32-bit Thumb-2 `movw Rd, #imm16` instruction (4 bytes, can encode 065535), (b) a multi-instruction sequence that constructs the value (e.g., `movs` + `lsls` + `add`), or (c) an `ldr Rd, [pc, #offset]` that loads the constant from a literal pool in flash. This is why patching `sleep_ms(500)` may be more complex than patching `gpio_put(16, 1)`.
4. **If you wanted to make the LED blink at exactly 5 Hz, what sleep_ms value would you use?**
At 5 Hz, each complete cycle is `1000 / 5 = 200ms`. With two `sleep_ms()` calls per cycle (ON and OFF), each call should be `200 / 2 = 100ms`. In hex: `100 = 0x64`. So `sleep_ms(0x64)` for each call—which is exactly the value used in this exercise's patch. For a different duty cycle (e.g., 150ms on, 50ms off), you'd use different values for each call while keeping the total at 200ms.
-345
View File
@@ -1,345 +0,0 @@
# Embedded Systems Reverse Engineering
[Repository](https://github.com/mytechnotalent/Embedded-Hacking)
## Week 4
Variables in Embedded Systems: Debugging and Hacking Variables w/ GPIO Output Basics
### Non-Credit Practice Exercise 4: Patch GPIO Binary to Change LED Pin
#### Objective
Patch the `0x0008_uninitialized-variables.bin` binary to change which LED blinks, modify the printed value, and change the blink timing, then verify all changes work correctly on hardware.
#### Prerequisites
- Completed Exercise 3 (GPIO binary analyzed in Ghidra)
- Understanding of how GPIO pin numbers are encoded
- Knowledge of hexadecimal-to-decimal conversion
- Pico 2 with ability to test multiple GPIO pins
#### Task Description
You will locate all instances where GPIO 16 is used, patch them to GPIO 17 (changing from red LED to green LED), modify the printed value from 0 to 66, and adjust the blink timing from 500ms to 100ms for faster blinking.
#### Step-by-Step Instructions
##### Step 1: Plan Your Patches
Before we start patching, let's identify what needs to change:
| Current Value | New Value | Description | Hex Conversion |
| ------------- | --------- | --------------------- | ------------------- |
| GPIO 16 | GPIO 17 | Change LED pin | 0x10 → 0x11 |
| age = 0 | age = 66 | Change printed value | 0x00 → 0x42 |
| 500ms | 100ms | Change blink timing | 0x1f4 → 0x64 |
**Verify the hex conversions:**
- 17 decimal = 0x11 hex ✓
- 66 decimal = 0x42 hex ✓
- 100 decimal = 0x64 hex ✓
##### Step 2: Open the GPIO Project in Ghidra
1. Launch Ghidra and open `week04-ex03-gpio-analysis`
2. Double-click the binary to open the CodeBrowser
3. Navigate to the `main` function
**Review the decompiled code:**
```c
int main(void)
{
stdio_init_all();
gpio_init(0x10);
gpio_set_dir(0x10, 1);
while (true) {
printf("age: %d\r\n", 0);
gpio_put(0x10, 1);
sleep_ms(0x1f4);
gpio_put(0x10, 0);
sleep_ms(0x1f4);
}
}
```
##### Step 3: Find and Patch gpio_init Parameter
Look at the **Listing** window (assembly view) for the main function.
**Find the gpio_init call:**
```assembly
1000023a 10 20 movs r0, #0x10
1000023c xx xx bl gpio_init
```
**Patch instruction:**
1. Right-click on `movs r0, #0x10`
2. Select **Patch Instruction**
3. Change `#0x10` to `#0x11`
4. Press **Enter**
**Result:**
```assembly
1000023a 11 20 movs r0, #0x11
```
The instruction bytes change from `10 20` to `11 20`.
##### Step 4: Find and Patch gpio_set_dir Parameter
Continue down the assembly listing:
```assembly
10000240 10 23 movs r3, #0x10
10000242 01 22 movs r2, #1
10000244 xx xx bl gpio_set_dir
```
**Patch the r3 load:**
1. Right-click on `movs r3, #0x10`
2. Select **Patch Instruction**
3. Change to `#0x11`
4. Press **Enter**
**Why r3 instead of r0?** The SDK might pass GPIO pin as the first parameter differently, or this could be due to register allocation. Trust the analysis!
##### Step 5: Find All gpio_put Calls
Inside the while loop, there are two `gpio_put` calls:
**First gpio_put (LED ON):**
```assembly
10000252 10 24 movs r4, #0x10
10000254 01 25 movs r5, #1
10000256 xx xx bl gpio_put
```
**Patch:**
1. Right-click on `movs r4, #0x10`
2. Change to `#0x11`
**Second gpio_put (LED OFF):**
```assembly
1000025e 10 24 movs r4, #0x10
10000260 00 25 movs r5, #0
10000262 xx xx bl gpio_put
```
**Patch:**
1. Right-click on `movs r4, #0x10`
2. Change to `#0x11`
**Note:** The exact addresses will vary, but the pattern is consistent.
##### Step 6: Patch the Printed Value
Find the printf call in the loop:
```assembly
1000024a 00 21 movs r1, #0x0
1000024c xx xx ldr r0, [pc, #offset]
1000024e xx xx bl printf
```
**Patch the value:**
1. Right-click on `movs r1, #0x0`
2. Select **Patch Instruction**
3. Change to `#0x42` (66 in decimal)
4. Press **Enter**
**Result:**
```assembly
1000024a 42 21 movs r1, #0x42
```
##### Step 7: Patch the Sleep Timing (First)
Find the first `sleep_ms(0x1f4)` call:
```assembly
10000258 f4 21 movs r1, #0xf4
1000025a 01 20 movs r0, #1
1000025c 00 04 lsls r0, r0, #16
1000025e 08 44 add r0, r1
10000260 xx xx bl sleep_ms
```
**Wait, this looks complex!** The value 0x1f4 (500) is being constructed:
- Load 1 into r0
- Shift left 16 bits: 1 << 16 = 0x10000
- Load 0xf4 into r1
- Add them: 0x10000 + 0xf4 = 0x1f4
**Alternative pattern (simpler):**
```assembly
10000xxx f4 20 movs r0, #0xf4
10000xxx 01 20 movs r1, #0x01
10000xxx ...
```
**For 100ms (0x64):**
Simply find where 0x1f4 is loaded and change it to 0x64.
**If the instruction is:**
```assembly
movs r0, #0x1f4
```
**Change to:**
```assembly
movs r0, #0x64
```
**Note:** The exact encoding depends on the instruction. For immediate values > 255, Thumb-2 uses different encodings.
##### Step 8: Handle Large Immediate Values
If `sleep_ms(500)` uses a multi-instruction sequence to load 0x1f4, you have two options:
**Option A: Patch both instructions**
If it's loading 0x1f4 as (0x100 + 0xf4):
1. Find where 0xf4 is loaded
2. Change it to 0x64
3. Find where 0x1 is loaded for the high byte
4. Change it to 0x0
**Option B: Simplify to single instruction**
Since 0x64 (100) fits in an 8-bit immediate, you can replace the multi-instruction sequence with:
```assembly
movs r0, #0x64
nop
nop
```
##### Step 9: Verify All Patches
Check the **Decompile** window to confirm changes:
```c
int main(void)
{
stdio_init_all();
gpio_init(0x11); // Changed from 0x10!
gpio_set_dir(0x11, 1);
while (true) {
printf("age: %d\r\n", 0x42); // Changed from 0!
gpio_put(0x11, 1); // Changed from 0x10!
sleep_ms(0x64); // Changed from 0x1f4!
gpio_put(0x11, 0); // Changed from 0x10!
sleep_ms(0x64); // Changed from 0x1f4!
}
}
```
Perfect! All changes are reflected.
##### Step 10: Export the Patched Binary
1. Click **File****Export Program**
2. Set Format: **Binary**
3. Navigate to: `Embedded-Hacking\0x0008_uninitialized-variables\build\`
4. Filename: `0x0008_uninitialized-variables-h.bin`
5. Click **OK**
##### Step 11: Convert to UF2
Open PowerShell and navigate to the project:
```powershell
cd C:\path\to\Embedded-Hacking\0x0008_uninitialized-variables
```
**Run conversion:**
```powershell
python ..\uf2conv.py build\0x0008_uninitialized-variables-h.bin --base 0x10000000 --family 0xe48bff59 --output build\hacked.uf2
```
**Expected output:**
```
Converting to uf2, output size: 61952, start address: 0x10000000
Wrote 61952 bytes to build\hacked.uf2
```
##### Step 12: Flash and Test
**Enter bootloader:**
1. Hold **BOOTSEL** button
2. Plug in USB
3. Release BOOTSEL
**Flash:**
1. Drag `build\hacked.uf2` to RPI-RP2 drive
2. Pico reboots automatically
**Test with serial monitor:**
```
age: 66
age: 66
age: 66
...
```
**Hardware verification:**
- ✅ GREEN LED (GPIO 17) should be blinking
- ✅ RED LED (GPIO 16) should be off
- ✅ Blink rate should be much faster (10 Hz instead of 1 Hz)
- ✅ Serial output shows 66 instead of 0
🎉 **Triple success!** You've patched three different aspects of the program!
#### Expected Output
After completing this exercise, you should:
- See `age: 66` printing continuously
- Observe the green LED (GPIO 17) blinking rapidly
- Understand how to find and patch all instances of a value
- Know how to handle different immediate value encoding schemes
#### Questions for Reflection
###### Question 1: Why did we need to patch GPIO 16 in multiple places (gpio_init, gpio_set_dir, gpio_put)?
###### Question 2: What would happen if you forgot to patch one of the gpio_put calls?
###### Question 3: How does the instruction encoding differ for immediate values less than 256 vs. greater than 255?
###### Question 4: If you wanted to make the LED blink at exactly 5 Hz, what sleep_ms value would you use?
#### Tips and Hints
- Use Ghidra's **Search****For Scalars** to find all instances of a hex value
- Right-click in Listing → **Highlight****Highlight Instruction** helps track your patches
- Make notes of addresses you've patched to avoid confusion
- Test incrementally - patch one thing at a time if you're unsure
- Keep the original UF2 to revert if needed
#### Next Steps
- Try patching to use GPIO 18 (blue LED) instead
- Change the printf format string to display in hexadecimal
- Experiment with different timing patterns (e.g., 200ms on, 800ms off)
#### Additional Challenge
**Advanced Multi-LED Pattern:**
Patch the binary to create an alternating pattern:
- GPIO 16 (red) blinks for 100ms
- GPIO 17 (green) blinks for 100ms
- GPIO 18 (blue) blinks for 100ms
- Repeat
This requires:
1. Adding new gpio_init and gpio_set_dir calls for GPIO 18
2. Restructuring the while loop to have three gpio_put sequences
3. Finding space in the binary or replacing existing code
**Hint:** You might need to NOP out some instructions and carefully insert new ones. This is advanced patching!
#### Verification Checklist
Before moving on, confirm:
- [ ] GPIO 17 LED blinks (not GPIO 16)
- [ ] Blink rate is approximately 10 Hz (100ms on/off)
- [ ] Serial output shows "age: 66"
- [ ] You can explain each patch you made
- [ ] You understand why each patch was necessary
- [ ] You successfully converted and flashed the UF2
**Congratulations!** You've completed all Week 4 exercises and mastered variable analysis, binary patching, and GPIO manipulation!
Binary file not shown.
+905 -955
View File
File diff suppressed because it is too large Load Diff
+79
View File
@@ -0,0 +1,79 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1200 800">
<style>
.bg{fill:#0a0a0f}.pnl{fill:#12121a;stroke:#1a1a2e}.hdr{fill:#12121a}
.title{font:bold 42px 'Courier New',monospace;fill:#00ff41}
.sub{font:bold 28px 'Courier New',monospace;fill:#00d4ff}
.txt{font:24px 'Courier New',monospace;fill:#c0c0c0}
.dim{font:20px 'Courier New',monospace;fill:#888}
.grn{font:bold 24px 'Courier New',monospace;fill:#00ff41}
.red{font:bold 24px 'Courier New',monospace;fill:#ff0040}
.cyn{font:bold 24px 'Courier New',monospace;fill:#00d4ff}
.amb{font:bold 24px 'Courier New',monospace;fill:#ffaa00}
.badge{stroke:#00ff41;rx:14}
</style>
<rect class="bg" width="1200" height="800"/>
<!-- Background grid decoration -->
<g opacity="0.06">
<line x1="0" y1="100" x2="1200" y2="100" stroke="#00ff41" stroke-width="1"/>
<line x1="0" y1="200" x2="1200" y2="200" stroke="#00ff41" stroke-width="1"/>
<line x1="0" y1="300" x2="1200" y2="300" stroke="#00ff41" stroke-width="1"/>
<line x1="0" y1="400" x2="1200" y2="400" stroke="#00ff41" stroke-width="1"/>
<line x1="0" y1="500" x2="1200" y2="500" stroke="#00ff41" stroke-width="1"/>
<line x1="0" y1="600" x2="1200" y2="600" stroke="#00ff41" stroke-width="1"/>
<line x1="0" y1="700" x2="1200" y2="700" stroke="#00ff41" stroke-width="1"/>
<line x1="200" y1="0" x2="200" y2="800" stroke="#00ff41" stroke-width="1"/>
<line x1="400" y1="0" x2="400" y2="800" stroke="#00ff41" stroke-width="1"/>
<line x1="600" y1="0" x2="600" y2="800" stroke="#00ff41" stroke-width="1"/>
<line x1="800" y1="0" x2="800" y2="800" stroke="#00ff41" stroke-width="1"/>
<line x1="1000" y1="0" x2="1000" y2="800" stroke="#00ff41" stroke-width="1"/>
</g>
<!-- Hex rain decoration -->
<g opacity="0.04" font-family="'Courier New',monospace" font-size="14" fill="#00ff41">
<text x="50" y="80">4F 70 65 6E 4F 43 44</text>
<text x="900" y="120">10 00 02 34 08 B5 01</text>
<text x="150" y="180">47 44 42 20 52 45 56</text>
<text x="800" y="240">20 08 20 00 FF AA 00</text>
<text x="80" y="350">52 50 32 33 35 30 00</text>
<text x="950" y="380">0A 0A 0F 12 12 1A 1A</text>
<text x="100" y="520">41 52 4D 76 38 2D 4D</text>
<text x="870" y="560">00 FF 41 00 D4 FF 88</text>
<text x="60" y="680">47 48 49 44 52 41 00</text>
<text x="920" y="720">FF 00 40 C0 C0 C0 00</text>
</g>
<!-- Corner accents -->
<polyline points="30,30 30,80 80,80" fill="none" stroke="#00ff41" stroke-width="2" opacity="0.3"/>
<polyline points="1170,30 1170,80 1120,80" fill="none" stroke="#00ff41" stroke-width="2" opacity="0.3"/>
<polyline points="30,770 30,720 80,720" fill="none" stroke="#00ff41" stroke-width="2" opacity="0.3"/>
<polyline points="1170,770 1170,720 1120,720" fill="none" stroke="#00ff41" stroke-width="2" opacity="0.3"/>
<!-- Top accent line -->
<rect x="100" y="140" width="1000" height="2" fill="#00ff41" opacity="0.4"/>
<!-- Course Title -->
<text x="600" y="210" text-anchor="middle" font-family="'Courier New',monospace" font-size="56" font-weight="bold" fill="#00ff41">Embedded Systems</text>
<text x="600" y="278" text-anchor="middle" font-family="'Courier New',monospace" font-size="56" font-weight="bold" fill="#00ff41">Reverse Engineering</text>
<!-- Divider -->
<rect x="300" y="310" width="600" height="2" fill="#00d4ff" opacity="0.6"/>
<!-- Week Number -->
<text x="600" y="380" text-anchor="middle" font-family="'Courier New',monospace" font-size="42" font-weight="bold" fill="#00d4ff">// WEEK 04</text>
<!-- Week Topic -->
<text x="600" y="440" text-anchor="middle" font-family="'Courier New',monospace" font-size="28" fill="#c0c0c0">Variables in Embedded Systems:</text>
<text x="600" y="478" text-anchor="middle" font-family="'Courier New',monospace" font-size="28" fill="#c0c0c0">Debugging and Hacking Variables</text>
<text x="600" y="516" text-anchor="middle" font-family="'Courier New',monospace" font-size="28" fill="#c0c0c0">w/ GPIO Output Basics</text>
<!-- Bottom accent line -->
<rect x="100" y="570" width="1000" height="2" fill="#00ff41" opacity="0.4"/>
<!-- University -->
<text x="600" y="635" text-anchor="middle" font-family="'Courier New',monospace" font-size="36" font-weight="bold" fill="#ffaa00">George Mason University</text>
<!-- Bottom badge -->
<rect x="400" y="670" width="400" height="40" rx="20" fill="none" stroke="#00ff41" stroke-width="1.5" opacity="0.5"/>
<text x="600" y="697" text-anchor="middle" font-family="'Courier New',monospace" font-size="20" fill="#00ff41" opacity="0.7">RP2350 // ARM Cortex-M33</text>
</svg>

After

Width:  |  Height:  |  Size: 4.4 KiB

+96
View File
@@ -0,0 +1,96 @@
<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">What is a Variable?</text>
<text x="600" y="88" text-anchor="middle" class="dim">Labeled Boxes in Memory (SRAM)</text>
<!-- Memory boxes visualization -->
<rect x="40" y="110" width="1120" height="200" rx="8" class="pnl"/>
<text x="60" y="148" class="sub">Memory — A Row of Numbered Boxes</text>
<!-- Box 0 -->
<rect x="70" y="170" width="170" height="80" rx="6" fill="#0a0a0f" stroke="#00ff41" stroke-width="2"/>
<text x="155" y="207" text-anchor="middle" class="grn">42</text>
<text x="155" y="240" text-anchor="middle" class="dim">age</text>
<text x="155" y="280" text-anchor="middle" class="dim">Box 0</text>
<!-- Box 1 -->
<rect x="260" y="170" width="170" height="80" rx="6" fill="#0a0a0f" stroke="#00d4ff" stroke-width="2"/>
<text x="345" y="207" text-anchor="middle" class="cyn">17</text>
<text x="345" y="240" text-anchor="middle" class="dim">score</text>
<text x="345" y="280" text-anchor="middle" class="dim">Box 1</text>
<!-- Box 2 -->
<rect x="450" y="170" width="170" height="80" rx="6" fill="#0a0a0f" stroke="#ffaa00" stroke-width="2"/>
<text x="535" y="207" text-anchor="middle" class="amb">0</text>
<text x="535" y="240" text-anchor="middle" class="dim">count</text>
<text x="535" y="280" text-anchor="middle" class="dim">Box 2</text>
<!-- Box 3 -->
<rect x="640" y="170" width="170" height="80" rx="6" fill="#0a0a0f" stroke="#ff0040" stroke-width="2"/>
<text x="725" y="207" text-anchor="middle" class="red">255</text>
<text x="725" y="240" text-anchor="middle" class="dim">max</text>
<text x="725" y="280" text-anchor="middle" class="dim">Box 3</text>
<!-- Box 4 -->
<rect x="830" y="170" width="170" height="80" rx="6" fill="#0a0a0f" stroke="#1a1a2e"/>
<text x="915" y="207" text-anchor="middle" class="txt">99</text>
<text x="915" y="240" text-anchor="middle" class="dim">temp</text>
<text x="915" y="280" text-anchor="middle" class="dim">Box 4</text>
<!-- Anatomy Panel -->
<rect x="40" y="330" width="1120" height="200" rx="8" class="pnl"/>
<text x="60" y="368" class="sub">Anatomy of a Declaration</text>
<rect x="60" y="390" width="1080" height="50" rx="4" fill="#0a0a0f" stroke="#00ff41" stroke-width="2"/>
<text x="80" y="422" class="grn">uint8_t age = 42;</text>
<text x="80" y="472" class="cyn">uint8_t</text>
<text x="280" y="472" class="dim">Data type (1 byte)</text>
<text x="80" y="502" class="amb">age</text>
<text x="280" y="502" class="dim">Variable name (label)</text>
<text x="600" y="472" class="red">= 42</text>
<text x="760" y="472" class="dim">Initial value</text>
<text x="600" y="502" class="txt">;</text>
<text x="760" y="502" class="dim">End of statement</text>
<!-- Key concepts -->
<rect x="40" y="555" width="540" height="215" rx="8" class="pnl"/>
<text x="60" y="593" class="sub">Key Concepts</text>
<rect x="60" y="610" width="500" height="42" rx="4" fill="#0a0a0f" stroke="#1a1a2e"/>
<text x="75" y="638" class="grn">Declaration</text>
<text x="290" y="638" class="dim">name + type</text>
<rect x="60" y="660" width="500" height="42" rx="4" fill="#0a0a0f" stroke="#1a1a2e"/>
<text x="75" y="688" class="cyn">Definition</text>
<text x="290" y="688" class="dim">allocates memory</text>
<rect x="60" y="710" width="500" height="42" rx="4" fill="#0a0a0f" stroke="#1a1a2e"/>
<text x="75" y="738" class="amb">Initialization</text>
<text x="290" y="738" class="dim">assigns value</text>
<!-- Rule -->
<rect x="620" y="555" width="540" height="215" rx="8" class="pnl"/>
<text x="640" y="593" class="sub">Important Rule</text>
<text x="640" y="640" class="txt">You MUST declare a</text>
<text x="640" y="672" class="txt">variable BEFORE you</text>
<text x="640" y="704" class="txt">use it!</text>
<text x="640" y="748" class="dim">Compiler needs to know the type</text>
</svg>

After

Width:  |  Height:  |  Size: 4.4 KiB

+86
View File
@@ -0,0 +1,86 @@
<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">Data Types &amp; Sizes</text>
<text x="600" y="88" text-anchor="middle" class="dim">How Much Memory Each Type Uses</text>
<!-- Table -->
<rect x="40" y="110" width="1120" height="660" rx="8" class="pnl"/>
<!-- Header -->
<rect x="60" y="130" width="1080" height="45" rx="4" fill="#1a1a2e"/>
<text x="80" y="160" class="cyn">Type</text>
<text x="300" y="160" class="cyn">Size</text>
<text x="460" y="160" class="cyn">Range</text>
<text x="880" y="160" class="cyn">Description</text>
<!-- uint8_t -->
<rect x="60" y="185" width="1080" height="55" rx="4" fill="#0a0a0f" stroke="#00ff41" stroke-width="1"/>
<text x="80" y="220" class="grn">uint8_t</text>
<text x="300" y="220" class="txt">1 byte</text>
<text x="460" y="220" class="txt">0 — 255</text>
<text x="880" y="220" class="dim">Unsigned 8-bit</text>
<!-- int8_t -->
<rect x="60" y="250" width="1080" height="55" rx="4" fill="#0a0a0f" stroke="#1a1a2e"/>
<text x="80" y="285" class="amb">int8_t</text>
<text x="300" y="285" class="txt">1 byte</text>
<text x="460" y="285" class="txt">-128 — 127</text>
<text x="880" y="285" class="dim">Signed 8-bit</text>
<!-- uint16_t -->
<rect x="60" y="315" width="1080" height="55" rx="4" fill="#0a0a0f" stroke="#00d4ff" stroke-width="1"/>
<text x="80" y="350" class="cyn">uint16_t</text>
<text x="300" y="350" class="txt">2 bytes</text>
<text x="460" y="350" class="txt">0 — 65,535</text>
<text x="880" y="350" class="dim">Unsigned 16-bit</text>
<!-- int16_t -->
<rect x="60" y="380" width="1080" height="55" rx="4" fill="#0a0a0f" stroke="#1a1a2e"/>
<text x="80" y="415" class="amb">int16_t</text>
<text x="300" y="415" class="txt">2 bytes</text>
<text x="460" y="415" class="txt">-32,768 — 32,767</text>
<text x="880" y="415" class="dim">Signed 16-bit</text>
<!-- uint32_t -->
<rect x="60" y="445" width="1080" height="55" rx="4" fill="#0a0a0f" stroke="#00ff41" stroke-width="1"/>
<text x="80" y="480" class="grn">uint32_t</text>
<text x="300" y="480" class="txt">4 bytes</text>
<text x="460" y="480" class="txt">0 — 4,294,967,295</text>
<text x="880" y="480" class="dim">Unsigned 32-bit</text>
<!-- int32_t -->
<rect x="60" y="510" width="1080" height="55" rx="4" fill="#0a0a0f" stroke="#1a1a2e"/>
<text x="80" y="545" class="amb">int32_t</text>
<text x="300" y="545" class="txt">4 bytes</text>
<text x="460" y="545" class="txt">-2.1B — 2.1B</text>
<text x="880" y="545" class="dim">Signed 32-bit</text>
<!-- Visual size comparison -->
<text x="60" y="600" class="sub">Size Comparison</text>
<rect x="60" y="620" width="80" height="40" rx="4" fill="#0f1a0f" stroke="#00ff41" stroke-width="2"/>
<text x="100" y="646" text-anchor="middle" class="dim">1B</text>
<text x="160" y="646" class="grn">uint8_t</text>
<rect x="60" y="670" width="160" height="40" rx="4" fill="#0a0a1f" stroke="#00d4ff" stroke-width="2"/>
<text x="140" y="696" text-anchor="middle" class="dim">2B</text>
<text x="240" y="696" class="cyn">uint16_t</text>
<rect x="60" y="720" width="320" height="40" rx="4" fill="#0a0a0f" stroke="#ffaa00" stroke-width="2"/>
<text x="220" y="746" text-anchor="middle" class="dim">4 Bytes</text>
<text x="400" y="746" class="amb">uint32_t</text>
</svg>

After

Width:  |  Height:  |  Size: 3.8 KiB

+63
View File
@@ -0,0 +1,63 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1200 800">
<style>
.bg{fill:#0a0a0f}.pnl{fill:#12121a;stroke:#1a1a2e}.hdr{fill:#12121a}
.title{font:bold 42px 'Courier New',monospace;fill:#00ff41}
.sub{font:bold 28px 'Courier New',monospace;fill:#00d4ff}
.txt{font:24px 'Courier New',monospace;fill:#c0c0c0}
.dim{font:20px 'Courier New',monospace;fill:#888}
.grn{font:bold 24px 'Courier New',monospace;fill:#00ff41}
.red{font:bold 24px 'Courier New',monospace;fill:#ff0040}
.cyn{font:bold 24px 'Courier New',monospace;fill:#00d4ff}
.amb{font:bold 24px 'Courier New',monospace;fill:#ffaa00}
.badge{stroke:#00ff41;rx:14}
</style>
<rect class="bg" width="1200" height="800"/>
<!-- Title -->
<text x="600" y="52" text-anchor="middle" class="title">Memory Sections</text>
<text x="600" y="88" text-anchor="middle" class="dim">Where Variables Live After Compilation</text>
<!-- .data Section -->
<rect x="40" y="110" width="1120" height="170" rx="8" class="pnl"/>
<rect x="60" y="130" width="180" height="40" rx="6" fill="#0f1a0f" stroke="#00ff41" stroke-width="2"/>
<text x="150" y="157" text-anchor="middle" class="grn">.data</text>
<text x="260" y="157" class="txt">Flash -> copied to RAM at startup</text>
<text x="60" y="200" class="dim">Contains: Initialized global/static variables</text>
<text x="60" y="230" class="cyn">int counter = 42;</text>
<text x="60" y="260" class="dim">Initial value stored in flash, copied to SRAM by data_cpy</text>
<!-- .bss Section -->
<rect x="40" y="295" width="1120" height="170" rx="8" class="pnl"/>
<rect x="60" y="315" width="180" height="40" rx="6" fill="#1a0a0a" stroke="#ff0040" stroke-width="2"/>
<text x="150" y="342" text-anchor="middle" class="red">.bss</text>
<text x="260" y="342" class="txt">RAM — zeroed at startup</text>
<text x="60" y="385" class="dim">Contains: Uninitialized global/static variables</text>
<text x="60" y="415" class="cyn">int counter;</text>
<text x="60" y="445" class="dim">NOT stored in binary (saves space!) — memset to 0 at boot</text>
<!-- .rodata Section -->
<rect x="40" y="480" width="1120" height="170" rx="8" class="pnl"/>
<rect x="60" y="500" width="180" height="40" rx="6" fill="#0a0a1f" stroke="#00d4ff" stroke-width="2"/>
<text x="150" y="527" text-anchor="middle" class="cyn">.rodata</text>
<text x="260" y="527" class="txt">Flash — read only</text>
<text x="60" y="570" class="dim">Contains: Constants and string literals</text>
<text x="60" y="600" class="amb">const int MAX = 100;</text>
<text x="60" y="630" class="dim">Lives in flash permanently — cannot be modified at runtime</text>
<!-- Summary Table -->
<rect x="40" y="665" width="1120" height="115" rx="8" class="pnl"/>
<text x="80" y="700" class="grn">.data</text>
<text x="260" y="700" class="txt">RAM</text>
<text x="420" y="700" class="dim">Writable</text>
<text x="600" y="700" class="dim">Initialized globals</text>
<text x="80" y="730" class="red">.bss</text>
<text x="260" y="730" class="txt">RAM</text>
<text x="420" y="730" class="dim">Writable</text>
<text x="600" y="730" class="dim">Uninitialized globals (zeroed)</text>
<text x="80" y="760" class="cyn">.rodata</text>
<text x="260" y="760" class="txt">Flash</text>
<text x="420" y="760" class="dim">Read-only</text>
<text x="600" y="760" class="dim">Constants &amp; strings</text>
</svg>
+79
View File
@@ -0,0 +1,79 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1200 800">
<style>
.bg{fill:#0a0a0f}.pnl{fill:#12121a;stroke:#1a1a2e}.hdr{fill:#12121a}
.title{font:bold 42px 'Courier New',monospace;fill:#00ff41}
.sub{font:bold 28px 'Courier New',monospace;fill:#00d4ff}
.txt{font:24px 'Courier New',monospace;fill:#c0c0c0}
.dim{font:20px 'Courier New',monospace;fill:#888}
.grn{font:bold 24px 'Courier New',monospace;fill:#00ff41}
.red{font:bold 24px 'Courier New',monospace;fill:#ff0040}
.cyn{font:bold 24px 'Courier New',monospace;fill:#00d4ff}
.amb{font:bold 24px 'Courier New',monospace;fill:#ffaa00}
.badge{stroke:#00ff41;rx:14}
</style>
<rect class="bg" width="1200" height="800"/>
<!-- Title -->
<text x="600" y="52" text-anchor="middle" class="title">GPIO Basics</text>
<text x="600" y="88" text-anchor="middle" class="dim">General Purpose Input/Output on RP2350</text>
<!-- Left Panel: Pico 2 Pin Diagram -->
<rect x="40" y="110" width="520" height="300" rx="8" class="pnl"/>
<text x="300" y="148" text-anchor="middle" class="sub">Pico 2 GPIO Pins</text>
<text x="60" y="195" class="grn">GPIO 16</text>
<line x1="230" y1="189" x2="350" y2="189" stroke="#00ff41" stroke-width="2"/>
<text x="370" y="195" class="red">Red LED</text>
<text x="60" y="240" class="grn">GPIO 17</text>
<line x1="230" y1="234" x2="350" y2="234" stroke="#00ff41" stroke-width="2"/>
<text x="370" y="240" class="cyn">Green LED</text>
<text x="60" y="285" class="grn">GPIO 18</text>
<line x1="230" y1="279" x2="350" y2="279" stroke="#00ff41" stroke-width="2"/>
<text x="370" y="285" class="amb">Blue LED</text>
<text x="60" y="330" class="grn">GPIO 25</text>
<line x1="230" y1="324" x2="350" y2="324" stroke="#00ff41" stroke-width="2"/>
<text x="370" y="330" class="txt">Onboard LED</text>
<text x="60" y="385" class="dim">Software-controlled switches</text>
<!-- Right Panel: SDK Functions -->
<rect x="580" y="110" width="580" height="300" rx="8" class="pnl"/>
<text x="870" y="148" text-anchor="middle" class="sub">Pico SDK Functions</text>
<rect x="600" y="170" width="540" height="45" rx="4" fill="#0a0a0f" stroke="#1a1a2e"/>
<text x="615" y="200" class="cyn">gpio_init(pin)</text>
<text x="900" y="200" class="dim">Init pin</text>
<rect x="600" y="225" width="540" height="45" rx="4" fill="#0a0a0f" stroke="#1a1a2e"/>
<text x="615" y="255" class="cyn">gpio_set_dir(pin,d)</text>
<text x="900" y="255" class="dim">I/O dir</text>
<rect x="600" y="280" width="540" height="45" rx="4" fill="#0a0a0f" stroke="#1a1a2e"/>
<text x="615" y="310" class="cyn">gpio_put(pin,val)</text>
<text x="900" y="310" class="dim">Set H/L</text>
<rect x="600" y="335" width="540" height="45" rx="4" fill="#0a0a0f" stroke="#1a1a2e"/>
<text x="615" y="365" class="cyn">sleep_ms(ms)</text>
<text x="900" y="365" class="dim">Delay</text>
<!-- Bottom: LED Blink Code -->
<rect x="40" y="430" width="1120" height="350" rx="8" class="pnl"/>
<text x="60" y="468" class="sub">Basic LED Blink Code</text>
<rect x="60" y="485" width="1080" height="280" rx="6" fill="#0a0a0f" stroke="#00ff41" stroke-width="1"/>
<text x="80" y="515" class="cyn">#define LED_PIN 16</text>
<text x="80" y="540" class="txt">int main(void) {</text>
<text x="100" y="565" class="txt">gpio_init(LED_PIN);</text>
<text x="100" y="590" class="txt">gpio_set_dir(LED_PIN, GPIO_OUT);</text>
<text x="100" y="615" class="txt">while (true) {</text>
<text x="120" y="640" class="grn">gpio_put(LED_PIN, 1);</text>
<text x="500" y="640" class="dim">// ON</text>
<text x="120" y="665" class="txt">sleep_ms(500);</text>
<text x="120" y="690" class="red">gpio_put(LED_PIN, 0);</text>
<text x="500" y="690" class="dim">// OFF</text>
<text x="120" y="715" class="txt">sleep_ms(500);</text>
<text x="100" y="740" class="txt">}}</text>
</svg>

After

Width:  |  Height:  |  Size: 3.7 KiB

+79
View File
@@ -0,0 +1,79 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1200 800">
<style>
.bg{fill:#0a0a0f}.pnl{fill:#12121a;stroke:#1a1a2e}.hdr{fill:#12121a}
.title{font:bold 42px 'Courier New',monospace;fill:#00ff41}
.sub{font:bold 28px 'Courier New',monospace;fill:#00d4ff}
.txt{font:24px 'Courier New',monospace;fill:#c0c0c0}
.dim{font:20px 'Courier New',monospace;fill:#888}
.grn{font:bold 24px 'Courier New',monospace;fill:#00ff41}
.red{font:bold 24px 'Courier New',monospace;fill:#ff0040}
.cyn{font:bold 24px 'Courier New',monospace;fill:#00d4ff}
.amb{font:bold 24px 'Courier New',monospace;fill:#ffaa00}
.badge{stroke:#00ff41;rx:14}
</style>
<rect class="bg" width="1200" height="800"/>
<!-- Title -->
<text x="600" y="52" text-anchor="middle" class="title">Ghidra Binary Analysis</text>
<text x="600" y="88" text-anchor="middle" class="dim">Analyzing a Raw .bin Without Symbols</text>
<!-- Step 1: Import -->
<rect x="40" y="110" width="360" height="280" rx="8" class="pnl"/>
<text x="220" y="148" text-anchor="middle" class="sub">1. Import</text>
<rect x="60" y="165" width="320" height="40" rx="4" fill="#0a0a0f" stroke="#00ff41" stroke-width="1"/>
<text x="80" y="192" class="grn">File -> Import</text>
<text x="60" y="232" class="txt">Language:</text>
<text x="60" y="262" class="cyn">ARM Cortex 32 LE</text>
<text x="60" y="302" class="txt">Block:</text>
<text x="200" y="302" class="grn">.text</text>
<text x="60" y="340" class="txt">Base:</text>
<text x="200" y="340" class="amb">10000000</text>
<text x="60" y="370" class="dim">XIP address for RP2350</text>
<!-- Step 2: Analyze -->
<rect x="420" y="110" width="360" height="280" rx="8" class="pnl"/>
<text x="600" y="148" text-anchor="middle" class="sub">2. Analyze</text>
<rect x="440" y="165" width="320" height="40" rx="4" fill="#0a0a0f" stroke="#00ff41" stroke-width="1"/>
<text x="460" y="192" class="grn">Auto-Analyze: Yes</text>
<text x="440" y="235" class="txt">Ghidra finds:</text>
<text x="440" y="270" class="dim">FUN_1000019a</text>
<text x="440" y="300" class="dim">FUN_10000210</text>
<text x="440" y="330" class="dim">FUN_10000234</text>
<text x="440" y="365" class="dim">Auto-generated names</text>
<!-- Step 3: Resolve -->
<rect x="800" y="110" width="360" height="280" rx="8" class="pnl"/>
<text x="980" y="148" text-anchor="middle" class="sub">3. Resolve</text>
<rect x="820" y="165" width="320" height="40" rx="4" fill="#0a0a0f" stroke="#00ff41" stroke-width="1"/>
<text x="840" y="192" class="grn">Edit Function Sig</text>
<text x="820" y="235" class="txt">Rename to:</text>
<text x="820" y="270" class="cyn">data_cpy</text>
<text x="820" y="300" class="cyn">frame_dummy</text>
<text x="820" y="330" class="grn">main</text>
<text x="820" y="365" class="dim">Fix signatures</text>
<!-- Bottom: Decompiled Output -->
<rect x="40" y="410" width="1120" height="370" rx="8" class="pnl"/>
<text x="60" y="448" class="sub">Decompiled main() in Ghidra</text>
<rect x="60" y="465" width="520" height="295" rx="6" fill="#0a0a0f" stroke="#ff0040" stroke-width="1"/>
<text x="80" y="500" class="red">Before Resolving:</text>
<text x="80" y="535" class="txt">void FUN_10000234(void){</text>
<text x="100" y="570" class="dim">FUN_10002f54();</text>
<text x="100" y="605" class="txt">do {</text>
<text x="120" y="640" class="dim">FUN_100030e4(</text>
<text x="140" y="675" class="dim">DAT_10000244,0x2b);</text>
<text x="100" y="710" class="txt">} while(true);</text>
<text x="80" y="740" class="txt">}</text>
<rect x="600" y="465" width="540" height="295" rx="6" fill="#0a0a0f" stroke="#00ff41" stroke-width="1"/>
<text x="620" y="500" class="grn">After Resolving:</text>
<text x="620" y="535" class="txt">int main(void) {</text>
<text x="640" y="570" class="cyn">stdio_init_all();</text>
<text x="640" y="605" class="txt">do {</text>
<text x="660" y="640" class="cyn">printf(</text>
<text x="680" y="675" class="amb">"age: %d\r\n"</text>
<text x="680" y="700" class="grn">, 0x2b);</text>
<text x="640" y="725" class="txt">} while(true);</text>
<text x="620" y="750" class="txt">}</text>
</svg>
+77
View File
@@ -0,0 +1,77 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1200 800">
<style>
.bg{fill:#0a0a0f}.pnl{fill:#12121a;stroke:#1a1a2e}.hdr{fill:#12121a}
.title{font:bold 42px 'Courier New',monospace;fill:#00ff41}
.sub{font:bold 28px 'Courier New',monospace;fill:#00d4ff}
.txt{font:24px 'Courier New',monospace;fill:#c0c0c0}
.dim{font:20px 'Courier New',monospace;fill:#888}
.grn{font:bold 24px 'Courier New',monospace;fill:#00ff41}
.red{font:bold 24px 'Courier New',monospace;fill:#ff0040}
.cyn{font:bold 24px 'Courier New',monospace;fill:#00d4ff}
.amb{font:bold 24px 'Courier New',monospace;fill:#ffaa00}
.badge{stroke:#00ff41;rx:14}
</style>
<rect class="bg" width="1200" height="800"/>
<!-- Title -->
<text x="600" y="52" text-anchor="middle" class="title">Compiler Optimization</text>
<text x="600" y="88" text-anchor="middle" class="dim">Why Your Variable Disappeared</text>
<!-- Source Code Panel -->
<rect x="40" y="110" width="540" height="280" rx="8" class="pnl"/>
<text x="310" y="148" text-anchor="middle" class="sub">Source Code</text>
<rect x="60" y="165" width="500" height="205" rx="6" fill="#0a0a0f" stroke="#00d4ff" stroke-width="1"/>
<text x="80" y="195" class="txt">int main(void) {</text>
<text x="100" y="225" class="amb">uint8_t age = 42;</text>
<text x="100" y="255" class="red">age = 43;</text>
<text x="100" y="285" class="txt">stdio_init_all();</text>
<text x="100" y="315" class="txt">while (true)</text>
<text x="120" y="345" class="txt">printf("age: %d", age);</text>
<!-- Compiler Thought Bubble -->
<rect x="620" y="110" width="540" height="280" rx="8" class="pnl"/>
<text x="890" y="148" text-anchor="middle" class="sub">Compiler Thinks...</text>
<rect x="640" y="170" width="500" height="50" rx="4" fill="#0a0a0f" stroke="#ffaa00" stroke-width="2"/>
<text x="655" y="202" class="amb">age = 42 is NEVER read</text>
<rect x="640" y="232" width="500" height="50" rx="4" fill="#0a0a0f" stroke="#ff0040" stroke-width="2"/>
<text x="655" y="264" class="red">Dead store -> REMOVED</text>
<rect x="640" y="294" width="500" height="50" rx="4" fill="#0a0a0f" stroke="#00ff41" stroke-width="2"/>
<text x="655" y="326" class="grn">age = 43 -> constant fold</text>
<text x="640" y="370" class="dim">Replaces variable with literal</text>
<!-- Assembly Result -->
<rect x="40" y="410" width="1120" height="170" rx="8" class="pnl"/>
<text x="600" y="448" text-anchor="middle" class="sub">Resulting Assembly</text>
<rect x="60" y="465" width="1080" height="95" rx="6" fill="#0a0a0f" stroke="#00ff41" stroke-width="1"/>
<text x="80" y="498" class="grn">1000023a</text>
<text x="280" y="498" class="amb">2b 21</text>
<text x="420" y="498" class="txt">movs r1, #0x2b</text>
<text x="730" y="498" class="dim">; 0x2b = 43</text>
<text x="80" y="535" class="dim">No age=42 instruction — compiler removed it</text>
<!-- Key Takeaway -->
<rect x="40" y="600" width="1120" height="180" rx="8" class="pnl"/>
<text x="600" y="640" text-anchor="middle" class="sub">Key Takeaway</text>
<rect x="60" y="658" width="330" height="105" rx="6" fill="#0a0a0f" stroke="#ff0040" stroke-width="1"/>
<text x="225" y="693" text-anchor="middle" class="red">Source Code</text>
<text x="225" y="723" text-anchor="middle" class="txt">age = 42</text>
<text x="225" y="748" text-anchor="middle" class="txt">age = 43</text>
<text x="425" y="711" text-anchor="middle" dominant-baseline="middle" class="grn">-></text>
<rect x="460" y="658" width="310" height="105" rx="6" fill="#0a0a0f" stroke="#00ff41" stroke-width="1"/>
<text x="615" y="693" text-anchor="middle" class="grn">Binary</text>
<text x="615" y="733" text-anchor="middle" class="amb">movs r1, #0x2b</text>
<rect x="800" y="658" width="340" height="105" rx="6" fill="#0a0a0f" stroke="#1a1a2e" stroke-width="1"/>
<text x="970" y="698" text-anchor="middle" class="cyn">Compiler</text>
<text x="970" y="728" text-anchor="middle" class="dim">Optimizes dead</text>
<text x="970" y="748" text-anchor="middle" class="dim">stores away!</text>
</svg>
+86
View File
@@ -0,0 +1,86 @@
<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">Binary Patching</text>
<text x="600" y="88" text-anchor="middle" class="dim">Changing Values in the Binary</text>
<!-- Before Patch -->
<rect x="40" y="110" width="540" height="240" rx="8" class="pnl"/>
<text x="310" y="148" text-anchor="middle" class="sub">Before Patch</text>
<rect x="60" y="168" width="500" height="50" rx="4" fill="#0a0a0f" stroke="#ff0040" stroke-width="2"/>
<text x="80" y="200" class="grn">1000023a</text>
<text x="230" y="200" class="red">2b 21</text>
<text x="330" y="200" class="txt">movs r1,#0x2b</text>
<text x="60" y="248" class="dim">0x2b = 43 decimal</text>
<text x="60" y="278" class="txt">Output:</text>
<text x="200" y="278" class="amb">age: 43</text>
<text x="60" y="308" class="dim">Compiler-optimized constant</text>
<!-- After Patch -->
<rect x="620" y="110" width="540" height="240" rx="8" class="pnl"/>
<text x="890" y="148" text-anchor="middle" class="sub">After Patch</text>
<rect x="640" y="168" width="500" height="50" rx="4" fill="#0a0a0f" stroke="#00ff41" stroke-width="2"/>
<text x="660" y="200" class="grn">1000023a</text>
<text x="810" y="200" class="grn">46 21</text>
<text x="910" y="200" class="txt">movs r1,#0x46</text>
<text x="640" y="248" class="dim">0x46 = 70 decimal</text>
<text x="640" y="278" class="txt">Output:</text>
<text x="780" y="278" class="grn">age: 70</text>
<text x="640" y="308" class="dim">Changed program behavior!</text>
<!-- How To Patch -->
<rect x="40" y="370" width="1120" height="200" rx="8" class="pnl"/>
<text x="600" y="410" text-anchor="middle" class="sub">How to Patch in Ghidra</text>
<rect x="60" y="430" width="240" height="55" rx="6" fill="#0a0a0f" stroke="#00d4ff" stroke-width="1"/>
<text x="180" y="465" text-anchor="middle" class="cyn">1. Find Instr</text>
<text x="335" y="460" text-anchor="middle" dominant-baseline="middle" class="grn">-></text>
<rect x="370" y="430" width="220" height="55" rx="6" fill="#0a0a0f" stroke="#ffaa00" stroke-width="1"/>
<text x="480" y="465" text-anchor="middle" class="amb">2. Rt-Click</text>
<text x="620" y="460" text-anchor="middle" dominant-baseline="middle" class="grn">-></text>
<rect x="650" y="430" width="240" height="55" rx="6" fill="#0a0a0f" stroke="#ff0040" stroke-width="1"/>
<text x="770" y="465" text-anchor="middle" class="red">3. Patch Val</text>
<text x="920" y="460" text-anchor="middle" dominant-baseline="middle" class="grn">-></text>
<rect x="950" y="430" width="180" height="55" rx="6" fill="#0a0a0f" stroke="#00ff41" stroke-width="1"/>
<text x="1040" y="465" text-anchor="middle" class="grn">Done!</text>
<text x="60" y="540" class="dim">Patch Instruction: change operand</text>
<!-- Export Steps -->
<rect x="40" y="590" width="1120" height="190" rx="8" class="pnl"/>
<text x="600" y="630" text-anchor="middle" class="sub">Export Patched Binary</text>
<rect x="60" y="650" width="330" height="50" rx="4" fill="#0a0a0f" stroke="#1a1a2e"/>
<text x="225" y="682" text-anchor="middle" class="cyn">File: Export</text>
<rect x="420" y="650" width="300" height="50" rx="4" fill="#0a0a0f" stroke="#1a1a2e"/>
<text x="570" y="682" text-anchor="middle" class="amb">Format: Raw Bytes</text>
<rect x="750" y="650" width="380" height="50" rx="4" fill="#0a0a0f" stroke="#1a1a2e"/>
<text x="940" y="682" text-anchor="middle" class="grn">Save as *-h.bin</text>
<text x="60" y="745" class="dim">Exported binary has your patches</text>
</svg>

After

Width:  |  Height:  |  Size: 4.1 KiB

+99
View File
@@ -0,0 +1,99 @@
<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">GPIO Hacking</text>
<text x="600" y="88" text-anchor="middle" class="dim">Patching GPIO 16 to GPIO 17</text>
<!-- Original Code -->
<rect x="40" y="110" width="540" height="280" rx="8" class="pnl"/>
<text x="310" y="148" text-anchor="middle" class="sub">Original: GPIO 16</text>
<text x="60" y="185" class="red">Red LED on pin 16</text>
<rect x="60" y="205" width="500" height="42" rx="4" fill="#0a0a0f" stroke="#ff0040" stroke-width="1"/>
<text x="80" y="233" class="grn">1000023a</text>
<text x="230" y="233" class="red">10 20</text>
<text x="330" y="233" class="txt">movs r0,#0x10</text>
<rect x="60" y="255" width="500" height="42" rx="4" fill="#0a0a0f" stroke="#ff0040" stroke-width="1"/>
<text x="80" y="283" class="grn">10000244</text>
<text x="230" y="283" class="red">10 23</text>
<text x="330" y="283" class="txt">movs r3,#0x10</text>
<rect x="60" y="305" width="500" height="42" rx="4" fill="#0a0a0f" stroke="#ff0040" stroke-width="1"/>
<text x="80" y="333" class="grn">10000252</text>
<text x="230" y="333" class="red">10 24</text>
<text x="330" y="333" class="txt">movs r4,#0x10</text>
<text x="60" y="368" class="dim">0x10 = 16, three locations</text>
<!-- Patched Code -->
<rect x="620" y="110" width="540" height="280" rx="8" class="pnl"/>
<text x="890" y="148" text-anchor="middle" class="sub">Patched: GPIO 17</text>
<text x="640" y="185" class="grn">Green LED on pin 17</text>
<rect x="640" y="205" width="500" height="42" rx="4" fill="#0a0a0f" stroke="#00ff41" stroke-width="1"/>
<text x="660" y="233" class="grn">1000023a</text>
<text x="810" y="233" class="grn">11 20</text>
<text x="910" y="233" class="txt">movs r0,#0x11</text>
<rect x="640" y="255" width="500" height="42" rx="4" fill="#0a0a0f" stroke="#00ff41" stroke-width="1"/>
<text x="660" y="283" class="grn">10000244</text>
<text x="810" y="283" class="grn">11 23</text>
<text x="910" y="283" class="txt">movs r3,#0x11</text>
<rect x="640" y="305" width="500" height="42" rx="4" fill="#0a0a0f" stroke="#00ff41" stroke-width="1"/>
<text x="660" y="333" class="grn">10000252</text>
<text x="810" y="333" class="grn">11 24</text>
<text x="910" y="333" class="txt">movs r4,#0x11</text>
<text x="640" y="368" class="dim">0x11 = 17, all patched!</text>
<!-- What Each Patch Does -->
<rect x="40" y="410" width="1120" height="170" rx="8" class="pnl"/>
<text x="600" y="448" text-anchor="middle" class="sub">What Each Patch Controls</text>
<rect x="60" y="468" width="340" height="50" rx="4" fill="#0a0a0f" stroke="#00d4ff" stroke-width="1"/>
<text x="80" y="500" class="cyn">gpio_init</text>
<text x="240" y="500" class="dim">r0</text>
<rect x="420" y="468" width="340" height="50" rx="4" fill="#0a0a0f" stroke="#ffaa00" stroke-width="1"/>
<text x="440" y="500" class="amb">gpio_set_dir</text>
<text x="640" y="500" class="dim">r3</text>
<rect x="780" y="468" width="360" height="50" rx="4" fill="#0a0a0f" stroke="#00ff41" stroke-width="1"/>
<text x="800" y="500" class="grn">gpio_put</text>
<text x="960" y="500" class="dim">r4</text>
<text x="60" y="550" class="dim">ALL pin refs must be patched</text>
<!-- Bonus Patch -->
<rect x="40" y="600" width="1120" height="180" rx="8" class="pnl"/>
<text x="600" y="640" text-anchor="middle" class="sub">Bonus: Change Print Value</text>
<rect x="60" y="660" width="480" height="50" rx="4" fill="#0a0a0f" stroke="#ff0040" stroke-width="1"/>
<text x="80" y="692" class="red">00 21</text>
<text x="170" y="692" class="txt">movs r1,#0x0</text>
<text x="400" y="692" class="dim">age: 0</text>
<text x="570" y="692" text-anchor="middle" dominant-baseline="middle" class="grn">-></text>
<rect x="600" y="660" width="530" height="50" rx="4" fill="#0a0a0f" stroke="#00ff41" stroke-width="1"/>
<text x="620" y="692" class="grn">42 21</text>
<text x="720" y="692" class="txt">movs r1,#0x42</text>
<text x="960" y="692" class="grn">age: 66</text>
<text x="60" y="748" class="dim">Changed value: 0 to 66 (0x42)</text>
</svg>

After

Width:  |  Height:  |  Size: 4.6 KiB

+78
View File
@@ -0,0 +1,78 @@
<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">GPIO Coprocessor</text>
<text x="600" y="88" text-anchor="middle" class="dim">RP2350 Single-Cycle I/O via mcrr</text>
<!-- MCRR Instruction Anatomy -->
<rect x="40" y="110" width="1120" height="195" rx="8" class="pnl"/>
<text x="600" y="148" text-anchor="middle" class="sub">mcrr Instruction Breakdown</text>
<rect x="60" y="168" width="1080" height="50" rx="4" fill="#0a0a0f" stroke="#00ff41" stroke-width="2"/>
<text x="600" y="200" text-anchor="middle" class="grn">mcrr p0, #4, r4, r5, c0</text>
<text x="80" y="250" class="cyn">mcrr</text>
<text x="200" y="250" class="dim">Move to Coprocessor (2 regs)</text>
<text x="80" y="278" class="amb">p0</text>
<text x="200" y="278" class="dim">Coprocessor 0 (GPIO)</text>
<text x="620" y="250" class="grn">r4</text>
<text x="700" y="250" class="dim">GPIO pin number</text>
<text x="620" y="278" class="red">r5</text>
<text x="700" y="278" class="dim">Value (0=LOW, 1=HIGH)</text>
<!-- Two Coprocessor Registers -->
<rect x="40" y="320" width="540" height="210" rx="8" class="pnl"/>
<text x="310" y="358" text-anchor="middle" class="sub">Output Value (c0)</text>
<rect x="60" y="378" width="500" height="50" rx="4" fill="#0a0a0f" stroke="#00ff41" stroke-width="1"/>
<text x="80" y="410" class="grn">mcrr p0,#4,r4,r5,c0</text>
<text x="60" y="455" class="txt">r4 = pin number</text>
<text x="60" y="485" class="txt">r5 = 0 or 1</text>
<text x="60" y="515" class="dim">Controls GPIO output state</text>
<rect x="620" y="320" width="540" height="210" rx="8" class="pnl"/>
<text x="890" y="358" text-anchor="middle" class="sub">Output Enable (c4)</text>
<rect x="640" y="378" width="500" height="50" rx="4" fill="#0a0a0f" stroke="#ffaa00" stroke-width="1"/>
<text x="660" y="410" class="amb">mcrr p0,#4,r4,r5,c4</text>
<text x="640" y="455" class="txt">r4 = pin number</text>
<text x="640" y="485" class="txt">r5 = 1 (enable output)</text>
<text x="640" y="515" class="dim">Sets pin direction to OUTPUT</text>
<!-- GPIO Init Full Sequence -->
<rect x="40" y="545" width="1120" height="235" rx="8" class="pnl"/>
<text x="600" y="583" text-anchor="middle" class="sub">gpio_init(16) Sequence</text>
<rect x="60" y="603" width="340" height="80" rx="6" fill="#0a0a0f" stroke="#00d4ff" stroke-width="1"/>
<text x="230" y="633" text-anchor="middle" class="cyn">Step 1: Config Pad</text>
<text x="230" y="660" text-anchor="middle" class="dim">addr 0x40038044</text>
<rect x="420" y="603" width="340" height="80" rx="6" fill="#0a0a0f" stroke="#ffaa00" stroke-width="1"/>
<text x="590" y="633" text-anchor="middle" class="amb">Step 2: Set Func</text>
<text x="590" y="660" text-anchor="middle" class="dim">FUNCSEL = 5 (SIO)</text>
<rect x="780" y="603" width="340" height="80" rx="6" fill="#0a0a0f" stroke="#00ff41" stroke-width="1"/>
<text x="950" y="633" text-anchor="middle" class="grn">Step 3: Enable Out</text>
<text x="950" y="660" text-anchor="middle" class="dim">mcrr p0,#4,r4,r5,c4</text>
<line x1="400" y1="643" x2="420" y2="643" stroke="#00ff41" stroke-width="2"/>
<line x1="760" y1="643" x2="780" y2="643" stroke="#00ff41" stroke-width="2"/>
<text x="60" y="720" class="dim">Pad: clear OD, set IE, clear ISO</text>
<text x="60" y="750" class="dim">SIO = fast single-cycle GPIO access</text>
</svg>

After

Width:  |  Height:  |  Size: 3.9 KiB

+119
View File
@@ -0,0 +1,119 @@
<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">Full Patching Pipeline</text>
<text x="600" y="88" text-anchor="middle" class="dim">End-to-End Binary Hacking Workflow</text>
<!-- Step 1 -->
<rect x="40" y="115" width="365" height="160" rx="8" class="pnl"/>
<rect x="55" y="130" width="40" height="40" rx="20" fill="#0a0a0f" stroke="#00ff41" stroke-width="2"/>
<text x="75" y="158" text-anchor="middle" class="grn">1</text>
<text x="110" y="158" class="sub">Import .bin</text>
<text x="55" y="195" class="txt">Ghidra: Import</text>
<text x="55" y="225" class="cyn">ARM Cortex 32 LE</text>
<text x="55" y="252" class="dim">Base: 0x10000000</text>
<!-- Arrow 1-2 -->
<line x1="405" y1="195" x2="425" y2="195" stroke="#00ff41" stroke-width="2"/>
<!-- Step 2 -->
<rect x="425" y="115" width="345" height="160" rx="8" class="pnl"/>
<rect x="440" y="130" width="40" height="40" rx="20" fill="#0a0a0f" stroke="#00d4ff" stroke-width="2"/>
<text x="460" y="158" text-anchor="middle" class="cyn">2</text>
<text x="495" y="158" class="sub">Analyze</text>
<text x="440" y="195" class="txt">Auto-analyze</text>
<text x="440" y="225" class="txt">Rename functions</text>
<text x="440" y="252" class="dim">Fix signatures</text>
<!-- Arrow 2-3 -->
<line x1="770" y1="195" x2="790" y2="195" stroke="#00ff41" stroke-width="2"/>
<!-- Step 3 -->
<rect x="790" y="115" width="370" height="160" rx="8" class="pnl"/>
<rect x="805" y="130" width="40" height="40" rx="20" fill="#0a0a0f" stroke="#ffaa00" stroke-width="2"/>
<text x="825" y="158" text-anchor="middle" class="amb">3</text>
<text x="860" y="158" class="sub">Find Target</text>
<text x="805" y="195" class="txt">Listing window</text>
<text x="805" y="225" class="txt">Find movs rN,#val</text>
<text x="805" y="252" class="dim">Identify bytes to change</text>
<!-- Step 4 -->
<rect x="40" y="295" width="365" height="160" rx="8" class="pnl"/>
<rect x="55" y="310" width="40" height="40" rx="20" fill="#0a0a0f" stroke="#ff0040" stroke-width="2"/>
<text x="75" y="338" text-anchor="middle" class="red">4</text>
<text x="110" y="338" class="sub">Patch</text>
<text x="55" y="375" class="txt">Right-click:</text>
<text x="55" y="405" class="txt">Patch Instruction</text>
<text x="55" y="432" class="dim">Change operand value</text>
<!-- Arrow 4-5 -->
<line x1="405" y1="375" x2="425" y2="375" stroke="#00ff41" stroke-width="2"/>
<!-- Step 5 -->
<rect x="425" y="295" width="345" height="160" rx="8" class="pnl"/>
<rect x="440" y="310" width="40" height="40" rx="20" fill="#0a0a0f" stroke="#00ff41" stroke-width="2"/>
<text x="460" y="338" text-anchor="middle" class="grn">5</text>
<text x="495" y="338" class="sub">Export</text>
<text x="440" y="375" class="txt">File: Export</text>
<text x="440" y="405" class="amb">Format: Raw Bytes</text>
<text x="440" y="432" class="dim">Save as *-h.bin</text>
<!-- Arrow 5-6 -->
<line x1="770" y1="375" x2="790" y2="375" stroke="#00ff41" stroke-width="2"/>
<!-- Step 6 -->
<rect x="790" y="295" width="370" height="160" rx="8" class="pnl"/>
<rect x="805" y="310" width="40" height="40" rx="20" fill="#0a0a0f" stroke="#00d4ff" stroke-width="2"/>
<text x="825" y="338" text-anchor="middle" class="cyn">6</text>
<text x="860" y="338" class="sub">Convert UF2</text>
<text x="805" y="375" class="txt">uf2conv.py</text>
<text x="805" y="405" class="amb">--family 0xe48bff59</text>
<text x="805" y="432" class="dim">RP2350 family ID</text>
<!-- UF2 Command -->
<rect x="40" y="475" width="1120" height="90" rx="8" class="pnl"/>
<text x="60" y="505" class="sub">UF2 Command</text>
<rect x="60" y="518" width="1080" height="35" rx="4" fill="#0a0a0f" stroke="#00ff41" stroke-width="1"/>
<text x="80" y="542" class="grn">python uf2conv.py file.bin --base 0x10000000 -o hacked.uf2</text>
<!-- Flash & Verify -->
<rect x="40" y="585" width="540" height="195" rx="8" class="pnl"/>
<text x="310" y="623" text-anchor="middle" class="sub">Flash to Pico 2</text>
<text x="60" y="658" class="txt">1. Hold BOOTSEL + USB</text>
<text x="60" y="688" class="txt">2. Drop hacked.uf2</text>
<text x="60" y="718" class="txt">3. Pico reboots hacked</text>
<text x="60" y="748" class="dim">RPI-RP2 drive in BOOTSEL</text>
<!-- Key Memory Sections -->
<rect x="620" y="585" width="540" height="195" rx="8" class="pnl"/>
<text x="890" y="623" text-anchor="middle" class="sub">Key Sections</text>
<text x="640" y="658" class="grn">.text</text>
<text x="800" y="658" class="txt">Flash</text>
<text x="940" y="658" class="dim">Code</text>
<text x="640" y="688" class="cyn">.rodata</text>
<text x="800" y="688" class="txt">Flash</text>
<text x="940" y="688" class="dim">Constants</text>
<text x="640" y="718" class="amb">.data</text>
<text x="800" y="718" class="txt">RAM</text>
<text x="940" y="718" class="dim">Init globals</text>
<text x="640" y="748" class="red">.bss</text>
<text x="800" y="748" class="txt">RAM</text>
<text x="940" y="748" class="dim">Zeroed globals</text>
</svg>

After

Width:  |  Height:  |  Size: 5.5 KiB