mirror of
https://github.com/mytechnotalent/Embedded-Hacking.git
synced 2026-05-21 23:26:52 +02:00
Added WEEK04
This commit is contained in:
@@ -0,0 +1,220 @@
|
||||
# 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.)
|
||||
Reference in New Issue
Block a user