Files
Embedded-Hacking/WEEK06/WEEK06-01.md
2026-03-19 15:01:07 -04:00

5.9 KiB

Embedded Systems Reverse Engineering

Repository

Week 6

Static Variables in Embedded Systems: Debugging and Hacking Static Variables w/ GPIO Input Basics

Non-Credit Practice Exercise 1: Change the Static Variable Initial Value from 42 to 100

Objective

Use GDB to locate the static variable static_fav_num in the .data section of the 0x0014_static-variables binary, calculate the corresponding file offset, patch the initial value from 42 (0x2A) to 100 (0x64) using a hex editor, convert the patched binary to UF2 format, and flash it to the Pico 2 to verify the change.

Prerequisites

  • Completed Week 6 tutorial (GDB section)
  • 0x0014_static-variables.bin binary available in your build directory
  • GDB (arm-none-eabi-gdb) and OpenOCD installed
  • A hex editor (HxD, ImHex, or similar)
  • Python installed (for UF2 conversion)
  • Raspberry Pi Pico 2 connected via USB
  • Serial monitor software (PuTTY, minicom, or screen)

Task Description

You will use GDB to examine the static variable at its known RAM address (0x200005a8), trace back to where the initial value is stored in the .data section of flash, calculate the file offset in the .bin file, patch the byte from 0x2A to 0x64 with a hex editor, and verify on hardware that the serial output now starts counting from 100 instead of 42.

Step-by-Step Instructions

Step 1: Start the Debug Session

Terminal 1 - Start OpenOCD:

openocd ^
  -s "C:\Users\flare-vm\.pico-sdk\openocd\0.12.0+dev\scripts" ^
  -f interface/cmsis-dap.cfg ^
  -f target/rp2350.cfg ^
  -c "adapter speed 5000"

Terminal 2 - Start GDB:

arm-none-eabi-gdb build\0x0014_static-variables.elf

Connect to target:

(gdb) target remote :3333
(gdb) monitor reset halt
Step 2: Examine the Static Variable in RAM

We know from the tutorial that the static variable lives at 0x200005a8. Examine its current value:

(gdb) x/1db 0x200005a8

You should see the current value (probably 42 or a count if the program has been running).

Step 3: Find Where the Initial Value Lives in Flash

Static variables that are initialized get their starting values from the .data section in flash. The startup code copies these values from flash to RAM before main() runs.

Examine the disassembly to find data copy references. The initial value 42 (0x2A) is stored somewhere in flash. Use GDB to search:

(gdb) find /b 0x10000000, 0x10010000, 0x2a

This searches the flash region for the byte 0x2A. You may get multiple hits — look for one that is in the data initialization area (typically near the end of the code section).

Step 4: Confirm the Address

Once you identify a candidate address, verify it by examining the surrounding bytes:

(gdb) x/8xb <candidate_address>

The 0x2A byte at this address should be the initialization value for our static variable.

Step 5: Calculate the File Offset

The binary is loaded at base address 0x10000000. To find the file offset:

file_offset = address - 0x10000000

For example, if the initial value is at 0x10004xxx:

  • File offset = 0x10004xxx - 0x10000000 = 0x4xxx
Step 6: Patch the Value with a Hex Editor
  1. In HxD, open C:\Users\flare-vm\Desktop\Embedded-Hacking-main\0x0014_static-variables\build\0x0014_static-variables.bin
  2. Press Ctrl+G (Go to offset)
  3. Enter the calculated offset
  4. You should see the byte 2A at this position
  5. Change 2A to 64 (100 in decimal)
  6. Click File ? Save As ? 0x0014_static-variables-h.bin (in the same build directory)
Step 7: Convert to UF2 and Flash
cd C:\Users\flare-vm\Desktop\Embedded-Hacking-main\0x0014_static-variables
python ..\uf2conv.py build\0x0014_static-variables-h.bin --base 0x10000000 --family 0xe48bff59 --output build\hacked.uf2
  1. Hold BOOTSEL and plug in your Pico 2
  2. Drag and drop hacked.uf2 onto the RPI-RP2 drive
  3. Open your serial monitor
Step 8: Verify the Hack

Expected serial output:

regular_fav_num: 42
static_fav_num: 100    ? Starts at 100 now!
regular_fav_num: 42
static_fav_num: 101
regular_fav_num: 42
static_fav_num: 102
...

The static variable now starts counting from 100 instead of 42!

Expected Output

After completing this exercise, you should be able to:

  • Use GDB find command to search for byte patterns in flash
  • Distinguish between RAM addresses (where the variable lives at runtime) and flash addresses (where the initial value is stored)
  • Calculate file offsets from memory addresses
  • Patch initialization values with a hex editor
  • Understand the .data section copy mechanism at startup

Questions for Reflection

Question 1: Why does the initial value live in flash AND get copied to RAM? Why not just use flash directly?
Question 2: The static variable wraps around at 255 (since it's uint8_t). After patching the initial value to 100, after how many iterations will it overflow back to 0?
Question 3: If you also wanted to change the regular_fav_num constant from 42, would you patch the same area of the binary? Why or why not?
Question 4: What would happen if the .data section had TWO static variables — would their initial values be adjacent in flash?

Tips and Hints

  • The find command in GDB can search for bytes, halfwords, or words in any memory range
  • Static variables with initial values are in .data; without initial values they're in .bss
  • The startup code (crt0) copies the entire .data section from flash to RAM before calling main()
  • HxD shows both hex and ASCII — the value 0x2A is the ASCII character *

Next Steps

  • Proceed to Exercise 2 to try a more complex hack (reversing GPIO logic)
  • Try patching the static variable to 0xFF (255) and observe immediate overflow behavior
  • Look at the startup code in GDB to find the memcpy that copies .data from flash to RAM