Files
Embedded-Hacking/WEEK04/WEEK04-02.md
T
Kevin Thomas 29073bd383 Added WEEK04
2026-01-31 14:07:15 -05:00

221 lines
6.5 KiB
Markdown

# 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
### 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.)