diff --git a/WEEK01/WEEK01.md b/WEEK01/WEEK01.md index 1205b0b..c42b57e 100644 --- a/WEEK01/WEEK01.md +++ b/WEEK01/WEEK01.md @@ -1,22 +1,25 @@ # Week 1: Introduction and Overview of Embedded Reverse Engineering: Ethics, Scoping, and Basic Concepts ---- +*** **LEGAL DISCLAIMER:** The information, tools, and code provided in this repository and course are strictly for educational, research, and defensive purposes only. You are explicitly prohibited from using any materials contained herein to access, test, modify, or exploit any device, network, or system that you do not own 100% or for which you do not have explicit, documented, and legally binding authorization to interact with. By using this repository and course, you acknowledge and agree that: + 1. Any illegal, unauthorized, or malicious use of this information is solely your responsibility. 2. The author(s) and contributor(s) of this repository and course shall not be held liable for any damages, legal repercussions, criminal charges, or unauthorized actions resulting from the use, misuse, or abuse of the contents herein. 3. You will comply with all applicable local, state, national, and international laws regarding cybersecurity and computer fraud. **IF YOU DO NOT AGREE WITH THESE TERMS, DO NOT USE THIS REPOSITORY AND COURSE.** ---- + +*** ## What You'll Learn This Week By the end of this week, you will be able to: + - Understand what a microcontroller is and how it works - Know the basic registers of the ARM Cortex-M33 processor - Understand memory layout (Flash vs RAM) and why it matters @@ -40,6 +43,7 @@ The RP2350 has two "brains" inside it - we call these **cores**. One brain uses ### What is Reverse Engineering? Reverse engineering is like being a detective for code. Instead of writing code and compiling it, we take compiled code (the 1s and 0s that the computer actually runs) and figure out what it does. This is useful for: + - Understanding how things work - Finding bugs or security issues - Learning how software interacts with hardware @@ -68,6 +72,7 @@ The ARM Cortex-M33 has several important registers: These 13 registers are your "scratch paper." When the processor needs to add two numbers, subtract, or do any calculation, it uses these registers to hold the values. **Example:** If you want to add 5 + 3: + 1. Put 5 in `r0` 2. Put 3 in `r1` 3. Add them and store the result (8) in `r2` @@ -75,6 +80,7 @@ These 13 registers are your "scratch paper." When the processor needs to add two ##### The Stack Pointer (`r13` / SP) The **stack** is a special area of memory that works like a stack of plates: + - When you add something, you put it on top (called a **PUSH**) - When you remove something, you take it from the top (called a **POP**) @@ -85,11 +91,11 @@ The two Arm ABI documents we verified give the formal proof for these rules. In ``` Higher Memory Address (0x20082000) +------------------+ -| | ← Stack starts here (empty) +| | ← Stack starts here (empty) +------------------+ -| Pushed Item 1 | ← SP points here after 1 push +| Pushed Item 1 | ← SP points here after 1 push +------------------+ -| Pushed Item 2 | ← SP points here after 2 pushes +| Pushed Item 2 | ← SP points here after 2 pushes +------------------+ Lower Memory Address (0x20081FF8) ``` @@ -196,6 +202,7 @@ stdio_init_all(); ``` This function initializes all the standard I/O (input/output) for the Pico. It sets up: + - **USB CDC** (so you can see output when connected to a computer via USB) - **UART** (serial communication pins) @@ -225,6 +232,7 @@ while (true) ### Why This Code is Perfect for Learning This simple program is ideal for reverse engineering practice because: + - It has a clear, recognizable function call (`printf`) - It has an infinite loop we can observe - It's small enough to understand completely @@ -258,6 +266,7 @@ When done correctly, your Pico 2 will appear as a USB mass storage device (like ##### Step 3: Flash and Run Back in VS Code, click the **Run** button in the status bar. The extension will: + 1. Copy the compiled `.uf2` file to the Pico 2 2. The Pico 2 will automatically reboot and start running your code @@ -270,6 +279,7 @@ Once flashed, your Pico 2 will immediately start executing the hello-world progr ### Prerequisites Before we start, make sure you have: + 1. A Raspberry Pi Pico 2 board 2. GDB (GNU Debugger) installed 3. OpenOCD or another debug probe connection @@ -312,6 +322,7 @@ Breakpoint 1 at 0x10000234: file ../0x0001_hello-world.c, line 5. ``` **What this tells us:** + - GDB found our `main` function - It's located at address `0x10000234` in flash memory - The source file and line number are shown (because we have debug symbols) @@ -347,6 +358,7 @@ End of assembler dump. ``` **Understanding the output:** + - The `=>` arrow shows where we're currently stopped - Each line shows: `address : instruction operands` - We can see the calls to `stdio_init_all` and `__wrap_puts` (printf was optimized to puts) @@ -492,6 +504,7 @@ xpsr 0x69000000 1761607680 ``` **Key registers to watch:** + | Register | Value | Meaning | | -------- | ------------ | ----------------------------------------------- | | `pc` | `0x10000234` | Program Counter - we're at the start of `main` | @@ -637,6 +650,7 @@ int main(void) ##### Why We Start with .elf Files We're using the `.elf` file because it contains symbols that help us learn: + - Function names are visible (`main`, `stdio_init_all`, `puts`) - Variable names may be preserved - The structure of the code is easier to understand diff --git a/WEEK01/WEEK01.pdf b/WEEK01/WEEK01.pdf new file mode 100644 index 0000000..448c419 Binary files /dev/null and b/WEEK01/WEEK01.pdf differ diff --git a/WEEK02/WEEK02.md b/WEEK02/WEEK02.md index 98ff63e..ea41551 100644 --- a/WEEK02/WEEK02.md +++ b/WEEK02/WEEK02.md @@ -1,22 +1,25 @@ # Week 2: Hello, World - Debugging and Hacking Basics: Debugging and Hacking a Basic Program for the Pico 2 ---- +*** **LEGAL DISCLAIMER:** The information, tools, and code provided in this repository and course are strictly for educational, research, and defensive purposes only. You are explicitly prohibited from using any materials contained herein to access, test, modify, or exploit any device, network, or system that you do not own 100% or for which you do not have explicit, documented, and legally binding authorization to interact with. By using this repository and course, you acknowledge and agree that: + 1. Any illegal, unauthorized, or malicious use of this information is solely your responsibility. 2. The author(s) and contributor(s) of this repository and course shall not be held liable for any damages, legal repercussions, criminal charges, or unauthorized actions resulting from the use, misuse, or abuse of the contents herein. 3. You will comply with all applicable local, state, national, and international laws regarding cybersecurity and computer fraud. **IF YOU DO NOT AGREE WITH THESE TERMS, DO NOT USE THIS REPOSITORY AND COURSE.** ---- + +*** ## What You'll Learn This Week By the end of this tutorial, you will be able to: + - Connect to a live embedded system using OpenOCD and GDB - Step through code instruction by instruction and watch the stack change - Examine memory, registers, and decode little-endian values @@ -28,6 +31,7 @@ By the end of this tutorial, you will be able to: ## Review from Week 1 This week builds directly on Week 1 concepts. You should already be comfortable with: + - **Registers** (`r0`-`r12`, SP, LR, PC) - We'll watch them change and manipulate `r0` to change program behavior - **Memory Layout** (Flash at `0x10000000`, RAM at `0x20000000`) - Critical for understanding where we can write - **The Stack** and how `push`/`pop` work - We'll watch this in action @@ -48,6 +52,7 @@ Think of it like this: imagine a train is heading to New York City. Live hacking #### Why is This Important? Live hacking techniques are used for: + - **Security Research**: Finding vulnerabilities in embedded systems - **Penetration Testing**: Testing if systems can be compromised - **Malware Analysis**: Understanding how malicious code works @@ -58,6 +63,7 @@ Live hacking techniques are used for: > **"With great power comes great responsibility!"** Imagine you're a security researcher testing an industrial control system at a power plant. You need to verify that an attacker couldn't: + 1. Change the values being displayed to engineers 2. Make dangerous equipment appear safe 3. Hide malicious activity from monitoring systems @@ -89,6 +95,7 @@ int main(void) { ``` This simple program: + 1. Initializes I/O with `stdio_init_all()` 2. Enters an infinite `while(true)` loop 3. Prints `"hello, world\r\n"` forever @@ -151,6 +158,7 @@ Here's our step-by-step attack strategy: #### Prerequisites Before we start, make sure you have: + 1. A Raspberry Pi Pico 2 board with debug probe connected 2. OpenOCD installed and configured 3. GDB (arm-none-eabi-gdb) installed @@ -160,6 +168,7 @@ Before we start, make sure you have: #### What You'll Need Open You will need **THREE** terminal windows: + 1. **Terminal 1**: Running OpenOCD (the debug server) 2. **Terminal 2**: Running GDB (where we do the hacking) 3. **PuTTY**: Running your serial monitor (to see output) @@ -183,6 +192,7 @@ openocd -s "$env:USERPROFILE\.pico-sdk\openocd\0.12.0+dev\scripts" -f interface/ ``` **What this command means:** + - `openocd` = the OpenOCD program - `-s ...` = path to OpenOCD scripts folder - `-f interface/cmsis-dap.cfg` = use the CMSIS-DAP debug probe configuration @@ -239,6 +249,7 @@ arm-none-eabi-gdb build\0x0001_hello-world.elf ``` **What this command means:** + - `arm-none-eabi-gdb` = the ARM version of GDB - `build\0x0001_hello-world.elf` = our compiled program with debug symbols @@ -284,6 +295,7 @@ The program is still running (you can see "hello, world" still printing in PuTTY ``` **What this command means:** + - `monitor` = send a command to OpenOCD (not GDB) - `reset` = reset the processor - `halt` = stop execution immediately @@ -316,6 +328,7 @@ Our program code starts at address `0x10000000`. Let's look at the first 1000 in ``` **What this command means:** + - `x` = examine memory - `/1000i` = show 1000 instructions - `0x10000000` = starting address @@ -379,6 +392,7 @@ Note: automatically using hardware breakpoints for read-only addresses. ``` **What this means:** + - `b` = set breakpoint - `*0x10000234` = at this exact memory address - GDB confirms the breakpoint is set and even tells us which line of C code this corresponds to! @@ -404,6 +418,7 @@ Thread 1 "rp2350.cm0" hit Breakpoint 1, main () ``` **What happened:** + - The processor ran until it reached address `0x10000234` - It stopped right before executing the instruction at that address - GDB shows us we're at line 5 of our C source code @@ -446,6 +461,7 @@ Before we execute the `push` instruction, let's see what's on the stack: ``` **What this command means:** + - `x` = examine memory - `/10x` = show 10 values in hexadecimal - `$sp` = starting at the stack pointer address @@ -459,6 +475,7 @@ Before we execute the `push` instruction, let's see what's on the stack: ``` **What this shows:** + - The stack pointer is at address `0x20082000` - The stack is empty (all zeros) - This is the "top" of our stack in RAM @@ -475,6 +492,7 @@ Now let's trace back where this initial `0x20082000` value came from. It comes f ``` **What this shows:** + - The first command `x/x $sp` reads one word at the stack pointer (currently `0x00000000`) - The second command `x/x 0x10000000` reads the **first entry in the vector table** at address `0x10000000` - That vector table entry contains `0x20082000` - this is the **initial stack pointer value**! @@ -492,6 +510,7 @@ Now let's execute just ONE assembly instruction: ``` **What this command means:** + - `si` = step instruction (execute one assembly instruction) **You should see:** @@ -540,6 +559,7 @@ Now let's see what the push instruction did to our stack: ``` **What changed:** + - The stack pointer moved from `0x20082000` to `0x20081ff8` - That's 8 bytes lower (2 * 4-byte values) - Two new values appeared: `0xe000ed08` and `0x1000018f` @@ -621,6 +641,7 @@ Address Value Address Value ``` **Key Points:** + 1. The stack grows DOWNWARD (addresses get smaller) 2. The SP always points to the last item pushed 3. `r3` was pushed first, then `lr` was pushed on top of it @@ -657,6 +678,7 @@ We don't need to examine every instruction inside `stdio_init_all` - it's just s ``` **What this command means:** + - `n` = next (step over function calls, don't go inside them) **You should see:** @@ -731,6 +753,7 @@ This is loading a **pointer** - the address of our "hello, world" string! The value `0x6c6c6568` looks strange, but it's actually ASCII characters! Let's decode it: **ASCII Table Reference:** + | Hex | Character | | ------ | --------- | | `0x68` | h | @@ -753,6 +776,7 @@ Let's tell GDB to show this as a string instead of a hex number: ``` **What this command means:** + - `x` = examine memory - `/s` = show as a string - `$r0` = at the address stored in `r0` @@ -807,6 +831,7 @@ Let's look at the main function to understand what we're dealing with: ``` **What this command means:** + - `x` = examine memory (Week 1 review!) - `/5i` = show 5 instructions - `0x10000234` = the address of main (we found this in Week 1!) @@ -823,6 +848,7 @@ Let's look at the main function to understand what we're dealing with: ``` > **REVIEW:** This is the same disassembly we analyzed in Week 1! Remember: +> > - `push {r3, lr}` saves registers to the stack > - `bl` is "branch with link" - it calls a function and saves the return address in LR > - `b.n` is the infinite loop that jumps back to the `ldr` instruction @@ -847,6 +873,7 @@ while (true) ``` The compiler: + 1. Loads the string address into `r0` (first argument) 2. Calls `puts()` (optimized from `printf()` since we're just printing a string) 3. Loops back forever with `b.n` @@ -872,6 +899,7 @@ We want to stop the program RIGHT BEFORE it calls `puts()`. That's at address `0 ``` **What this command means:** + - `b` = set a breakpoint (same as Week 1!) - `*0x1000023c` = at this exact memory address (the asterisk means "address") @@ -896,6 +924,7 @@ Now let's run the program until it hits our breakpoint: ``` **What this command means:** + - `c` = continue (run until something stops us) **You should see:** @@ -921,6 +950,7 @@ Let's double-check where we are using the `disas` command: ``` **What this command means:** + - `disas` = disassemble the current function **You should see:** @@ -957,6 +987,7 @@ Let's see what string `r0` is currently pointing to: ``` **What this command means:** + - `x` = examine memory (Week 1 review!) - `/s` = display as a string - `$r0` = the address stored in register `r0` @@ -1054,7 +1085,7 @@ We need to write 13 bytes (12 characters + null terminator) to SRAM: | r | - | | l | - | | d | - | -| \r | - | +| `\r` | - | | \0 | - | **Type this command:** @@ -1064,6 +1095,7 @@ We need to write 13 bytes (12 characters + null terminator) to SRAM: ``` **What this command means:** + - `set` = modify memory - `{char[13]}` = treat the target as an array of 13 characters - `0x20040000` = the address where we're writing (safe SRAM offset) @@ -1108,6 +1140,7 @@ Now for the magic moment! We'll change `r0` from pointing to the original string ``` **What this command means:** + - `set` = modify a value - `$r0` = the `r0` register - `= 0x20040000` = change it to this address (where our string is) @@ -1277,6 +1310,7 @@ In our GDB hack, we set a breakpoint at `0x1000023c` - right before `bl __wrap_p **Click on address `0x1000023c` in the Listing view.** Notice: + - The instruction is `bl __wrap_puts` - a function call - The previous instruction at `0x1000023a` loaded `r0` with the string address - Ghidra shows `= "hello, world\r"` right in the listing! @@ -1363,6 +1397,7 @@ int main(void) ``` From this view, you can immediately see: + - The program loops forever (`do { } while (true)`) - It calls `__wrap_puts()` with a string argument - To change the output, you need to change what's passed to `puts()` @@ -1387,7 +1422,7 @@ When you navigate to the string address `0x100019cc`, you'll see the string stor 20 77 6f ``` -This shows the raw bytes of our string: `68 65 6c 6c 6f 2c 20 77 6f...` which spell out "hello, world\r" in ASCII. +This shows the raw bytes of our string: `68 65 6c 6c 6f 2c 20 77 6f...` which spell out `"hello, world\r"` in ASCII. ##### Step 8: Patching Data in Ghidra (Preview) diff --git a/WEEK02/WEEK02.pdf b/WEEK02/WEEK02.pdf new file mode 100644 index 0000000..ff3023f Binary files /dev/null and b/WEEK02/WEEK02.pdf differ diff --git a/WEEK03/WEEK03.md b/WEEK03/WEEK03.md index cece90b..f047c74 100644 --- a/WEEK03/WEEK03.md +++ b/WEEK03/WEEK03.md @@ -1,22 +1,25 @@ # Week 3: Embedded System Analysis: Understanding the RP2350 Architecture w/ Comprehensive Firmware Analysis ---- +*** **LEGAL DISCLAIMER:** The information, tools, and code provided in this repository and course are strictly for educational, research, and defensive purposes only. You are explicitly prohibited from using any materials contained herein to access, test, modify, or exploit any device, network, or system that you do not own 100% or for which you do not have explicit, documented, and legally binding authorization to interact with. By using this repository and course, you acknowledge and agree that: + 1. Any illegal, unauthorized, or malicious use of this information is solely your responsibility. 2. The author(s) and contributor(s) of this repository and course shall not be held liable for any damages, legal repercussions, criminal charges, or unauthorized actions resulting from the use, misuse, or abuse of the contents herein. 3. You will comply with all applicable local, state, national, and international laws regarding cybersecurity and computer fraud. **IF YOU DO NOT AGREE WITH THESE TERMS, DO NOT USE THIS REPOSITORY AND COURSE.** ---- + +*** ## What You'll Learn This Week By the end of this tutorial, you will be able to: + - Understand how the RP2350 boots from the on-chip bootrom - Know what the vector table is and why it's important - Trace the complete boot sequence from power-on to `main()` @@ -28,6 +31,7 @@ By the end of this tutorial, you will be able to: ## Review from Weeks 1-2 This week builds on your GDB and Ghidra skills from previous weeks: + - **GDB Commands** (`x`, `b`, `c`, `si`, `disas`, `i r`) - We'll use all of these to trace the boot process - **Memory Layout** (Flash at `0x10000000`, RAM at `0x20000000`) - Understanding where code and data live - **Registers** (`r0`-`r12`, SP, LR, PC) - We'll watch how they're initialized during boot @@ -161,6 +165,7 @@ Here's what it looks like in the Pico SDK: ``` **The magic numbers:** + - `0xffffded3` = Start marker ("I'm a valid Pico binary!") - `0xab123579` = End marker ("End of the header block") @@ -192,6 +197,7 @@ Contents of section .text: ``` Command 1 explained (`--start-address=0x1000013c --stop-address=0x10000150`): + - Starts at `0x1000013c`, so it does **not** include the start marker at `0x10000138` (`d3deffff`). - Shows IMAGE_DEF body fields and the end marker: - `42012110` = `42 01 21 10` (item type/size + secure mode field) @@ -201,6 +207,7 @@ Command 1 explained (`--start-address=0x1000013c --stop-address=0x10000150`): - `4ff00000` at `0x1000014c` is already the next instruction word after IMAGE_DEF. Command 2 explained (`--start-address=0x10000130 --stop-address=0x10000154`): + - Starts earlier, so it captures context **and** both IMAGE_DEF markers. - `a0010010 90a31ae7` = binary-info context before IMAGE_DEF. - `d3deffff` at `0x10000138` = `PICOBIN_BLOCK_MARKER_START`. @@ -223,6 +230,7 @@ assuming a fixed address. **XIP (Execute In Place)** means the processor can run code directly from flash memory without copying it to RAM first. Think of it like reading a book: + - **Without XIP**: You photocopy every page into a notebook, then read from the notebook - **With XIP**: You just read directly from the book! @@ -266,6 +274,7 @@ The XIP flash region starts at address `0x10000000`. This is where your compiled ### What is the Vector Table? The **vector table** is a list of addresses at the very beginning of your program. It tells the CPU: + 1. Where to set the stack pointer 2. Where to start executing code (reset handler) 3. Where to go when errors or interrupts happen @@ -297,10 +306,12 @@ On ARM Cortex-M processors, all code runs in **Thumb mode**. The processor uses | `0` (even) | ARM | "This is ARM code" (not used on Cortex-M) | So `0x1000015d` means: + - The actual code is at `0x1000015c` (even address) - The `+1` tells the processor "use Thumb mode" **GDB vs Ghidra:** + - GDB shows `0x1000015d` (with Thumb bit) - Ghidra shows `0x1000015c` (actual instruction address) - Both are correct! They're just displaying it differently. @@ -350,6 +361,7 @@ __StackTop = ORIGIN(SCRATCH_Y) + LENGTH(SCRATCH_Y); ``` Let's do the math: + - `ORIGIN(SCRATCH_Y)` = `0x20081000` - `LENGTH(SCRATCH_Y)` = `0x1000` (4 KB) - `__StackTop` = `0x20081000` + `0x1000` = **`0x20082000`** @@ -365,6 +377,7 @@ This value (`0x20082000`) is what we see at offset `0x00` in the vector table! ### Prerequisites Before we start, make sure you have: + 1. A Raspberry Pi Pico 2 board with debug probe connected 2. OpenOCD installed and configured 3. GDB (`arm-none-eabi-gdb`) installed @@ -409,6 +422,7 @@ Let's look at the first 4 entries of the vector table at `0x10000000`: ``` **What this command means:** + - `x` = examine memory (Week 1 review!) - `/4x` = show 4 values in hexadecimal - `0x10000000` = the address of the vector table @@ -451,6 +465,7 @@ Let's confirm our math by examining what's at `0x10000000`: ``` This matches: + - `SCRATCH_Y` starts at `0x20081000` - `SCRATCH_Y` is 4 KB (`0x1000` bytes) - `0x20081000` + `0x1000` = `0x20082000` @@ -510,6 +525,7 @@ This is "Compare and Branch if Zero". If `r0` is `0` (meaning we're on Core 0), The RP2350 has **two cores**, but only **Core 0** should run the startup code! If both cores tried to initialize the same memory and peripherals, chaos would ensue. So the reset handler checks: + - **Core 0?** -> Continue with startup - **Core 1?** -> Go back to the bootrom and wait @@ -629,11 +645,13 @@ The data copy table contains entries that describe what to copy where. Let's exa ``` The data_cpy_table contains multiple entries. Each entry has three values: + 1. **Source address** (in flash) 2. **Destination address** (in RAM) 3. **End address** (where to stop copying) In the output above, we see: + - **First entry**: `0x10001b4c` (source), `0x20000110` (dest), `0x200002ac` (end) - **Second entry starts**: `0x10001ce8` (source of next entry), ... @@ -904,6 +922,7 @@ That's not real code - it's the magic number `0xffffded3` being misinterpreted! ### Why Use Ghidra for Boot Analysis? While GDB is excellent for dynamic analysis (watching code execute), Ghidra excels at: + - **Seeing the big picture** - Understanding code flow without running it - **Cross-references** - Finding all places that call a function - **Decompilation** - Seeing C-like code even for assembly routines @@ -1222,14 +1241,17 @@ Understanding the boot process is critical for both attackers and defenders. Kno #### Real-World Applications **Industrial Control Systems:** + - An attacker with physical access could replace firmware to hide malicious behavior - Understanding the boot sequence helps identify the earliest point where security checks can be added **IoT Devices:** + - Compromised boot code could establish backdoors before the main application runs - Secure boot implementations verify the vector table and reset handler integrity **Medical Devices:** + - Boot-time attacks could modify critical safety parameters before device operation - Understanding initialization helps implement tamper detection @@ -1269,6 +1291,7 @@ Understanding the boot process is critical for both attackers and defenders. Kno #### 4. Memory Protection Unit (MPU) Configure the Cortex-M33's MPU to: + - Mark code regions as execute-only (no reading code as data) - Separate privileged and unprivileged memory regions - Prevent execution from RAM regions (defend against code injection) @@ -1364,6 +1387,7 @@ https://datasheets.raspberrypi.com/rp2350/rp2350-datasheet.pdf ### Pico SDK Source Code The startup code lives in: + - `crt0.S` - Main startup assembly (vector table at `.section .vectors`, reset handler, data copy, BSS clear, platform_entry) - `memmap_default.ld` - Default linker script (section ordering: `.vectors` -> `.binary_info_header` -> `.embedded_block` -> `.reset`) - `embedded_start_block.inc.S` - IMAGE_DEF block (replaces RP2040's `boot2_generic_03h.S`) @@ -1545,6 +1569,7 @@ well within the 4 KB scan window the bootrom uses (Datasheet 5.9.5, p. 429). ``` > **Datasheet References:** +> > - 5.1.5.1 (p. 357): Block markers `0xffffded3` (start) and `0xab123579` (end) > - 5.9.5 (p. 429): IMAGE_DEF must appear within first 4 kB of flash image > - 5.9.5.1 (p. 429): Bootrom enters via reset handler at vector table offset +4 diff --git a/WEEK03/WEEK03.pdf b/WEEK03/WEEK03.pdf new file mode 100644 index 0000000..32dea62 Binary files /dev/null and b/WEEK03/WEEK03.pdf differ diff --git a/WEEK04/WEEK04.md b/WEEK04/WEEK04.md index b0224e4..1d5e045 100644 --- a/WEEK04/WEEK04.md +++ b/WEEK04/WEEK04.md @@ -1,22 +1,25 @@ # Week 4: Variables in Embedded Systems: Debugging and Hacking Variables w/ GPIO Output Basics ---- +*** **LEGAL DISCLAIMER:** The information, tools, and code provided in this repository and course are strictly for educational, research, and defensive purposes only. You are explicitly prohibited from using any materials contained herein to access, test, modify, or exploit any device, network, or system that you do not own 100% or for which you do not have explicit, documented, and legally binding authorization to interact with. By using this repository and course, you acknowledge and agree that: + 1. Any illegal, unauthorized, or malicious use of this information is solely your responsibility. 2. The author(s) and contributor(s) of this repository and course shall not be held liable for any damages, legal repercussions, criminal charges, or unauthorized actions resulting from the use, misuse, or abuse of the contents herein. 3. You will comply with all applicable local, state, national, and international laws regarding cybersecurity and computer fraud. **IF YOU DO NOT AGREE WITH THESE TERMS, DO NOT USE THIS REPOSITORY AND COURSE.** ---- + +*** ## What You'll Learn This Week By the end of this tutorial, you will be able to: + - Understand what variables are and how they're stored in memory - Know the difference between initialized, uninitialized, and constant variables - Use Ghidra to analyze binaries without debug symbols @@ -142,11 +145,11 @@ uint8_t age; // This will be 0, not garbage! +-----------------------------------------------------------------+ | Raspberry Pi Pico 2 | | | -| GPIO 16 -------â–º Red LED | -| GPIO 17 -------â–º Green LED | -| GPIO 18 -------â–º Blue LED | +| GPIO 16 -------► Red LED | +| GPIO 17 -------► Green LED | +| GPIO 18 -------► Blue LED | | ... | -| GPIO 25 -------â–º Onboard LED | +| GPIO 25 -------► Onboard LED | +-----------------------------------------------------------------+ ``` @@ -167,11 +170,11 @@ Each high-level function calls lower-level code. Let's trace `gpio_init()`: ``` gpio_init(LED_PIN) - ↓ + ↓ gpio_set_dir(LED_PIN, GPIO_IN) // Initially set as input - ↓ + ↓ gpio_put(LED_PIN, 0) // Set output value to 0 - ↓ + ↓ gpio_set_function(LED_PIN, GPIO_FUNC_SIO) // Connect to SIO block ``` @@ -184,6 +187,7 @@ The SIO (Single-cycle I/O) block is a special hardware unit in the RP2350 that p ### Prerequisites Before we start, make sure you have: + 1. A Raspberry Pi Pico 2 board 2. Ghidra installed (for static analysis) 3. Python installed (for UF2 conversion) @@ -236,6 +240,7 @@ int main(void) { ``` **What this code does:** + 1. Declares a variable `age` and initializes it to `42` 2. Changes `age` to `43` 3. Initializes the serial output @@ -298,11 +303,13 @@ Ghidra will open. Now we need to create a new project. A dialog appears. The file is identified as a "BIN" (raw binary without debug symbols). **Click the three dots (...) next to "Language" and:** + 1. Search for "Cortex" 2. Select **ARM Cortex 32 little endian default** 3. Click **OK** **Click the "Options..." button and:** + 1. Change **Block Name** to `.text` 2. Change **Base Address** to `10000000` (the XIP address!) 3. Click **OK** @@ -324,6 +331,7 @@ Wait for analysis to complete (watch the progress bar in the bottom right). Look at the **Symbol Tree** panel on the left. Expand **Functions**. You'll see function names like: + - `FUN_1000019a` - `FUN_10000210` - `FUN_10000234` @@ -409,6 +417,7 @@ The compiler **optimized it out**! Here's what happened: 3. Compiler removes the unused `42` and just uses `43` directly **What is `0x2b`?** Let's check: + - `0x2b` in hexadecimal = `43` in decimal The compiler replaced our variable with the constant value! @@ -470,6 +479,7 @@ python ..\uf2conv.py build\0x0005_intro-to-variables-h.bin --base 0x10000000 --f ``` **What this command means:** + - `uf2conv.py` = the conversion script - `--base 0x10000000` = the XIP base address - `--family 0xe48bff59` = the RP2350 family ID @@ -529,6 +539,7 @@ int main(void) { ``` **What this code does:** + 1. Declares `age` without initializing it (will be 0 due to BSS zeroing) 2. Initializes GPIO 16 as an output 3. In a loop: prints age, blinks the LED @@ -644,6 +655,7 @@ This is used in `gpio_set_dir`. Patch this to `0x11` as well. This is inside the loop for `gpio_put`. Patch this to `0x11` as well. Patch each one with **Patch Instruction**, then verify: + - `10000244`: `10 23` -> `11 23` - `10000252`: `10 24` -> `11 24` @@ -694,6 +706,7 @@ age: 66 And now the **GREEN LED on GPIO 17** should be blinking instead of the red one! **We successfully:** + 1. Changed the printed value from 0 to 66 2. Changed which LED blinks from red (GPIO 16) to green (GPIO 17) @@ -713,6 +726,7 @@ mcrr p0, #4, r4, r5, c4 ; GPIO direction control ``` **What this means:** + - `mcrr` = Move to Coprocessor from two ARM Registers - `p0` = Coprocessor 0 (the GPIO coprocessor) - `r4` = Contains the GPIO pin number diff --git a/WEEK04/WEEK04.pdf b/WEEK04/WEEK04.pdf new file mode 100644 index 0000000..78fbd7d Binary files /dev/null and b/WEEK04/WEEK04.pdf differ diff --git a/WEEK05/WEEK05.md b/WEEK05/WEEK05.md index ed7f70e..e281ee0 100644 --- a/WEEK05/WEEK05.md +++ b/WEEK05/WEEK05.md @@ -1,22 +1,25 @@ # Week 5: Integers and Floats in Embedded Systems: Debugging and Hacking Integers and Floats w/ Intermediate GPIO Output Assembler Analysis ---- +*** **LEGAL DISCLAIMER:** The information, tools, and code provided in this repository and course are strictly for educational, research, and defensive purposes only. You are explicitly prohibited from using any materials contained herein to access, test, modify, or exploit any device, network, or system that you do not own 100% or for which you do not have explicit, documented, and legally binding authorization to interact with. By using this repository and course, you acknowledge and agree that: + 1. Any illegal, unauthorized, or malicious use of this information is solely your responsibility. 2. The author(s) and contributor(s) of this repository and course shall not be held liable for any damages, legal repercussions, criminal charges, or unauthorized actions resulting from the use, misuse, or abuse of the contents herein. 3. You will comply with all applicable local, state, national, and international laws regarding cybersecurity and computer fraud. **IF YOU DO NOT AGREE WITH THESE TERMS, DO NOT USE THIS REPOSITORY AND COURSE.** ---- + +*** ## What You'll Learn This Week By the end of this tutorial, you will be able to: + - Understand how integers and floating-point numbers are stored in memory - Know the difference between signed and unsigned integers (`uint8_t` vs `int8_t`) - Understand how floats and doubles are represented using IEEE 754 encoding @@ -141,6 +144,7 @@ Use this exact process any time you need to encode a decimal float manually. Quick decode check (reverse direction, fully expanded): Given the 32-bit pattern: + - `0 | 10000100 | 01010100000000000000000` Decode it field by field: @@ -207,6 +211,7 @@ int main(void) { > An ARM **literal pool** is a small table of constants that the assembler places near code in memory. Instead of encoding a large immediate value directly in an instruction, the CPU executes a load instruction (such as `ldr`) that reads the constant from that nearby table. That is why Ghidra can show constant loads rather than a classic stack local. **What this code does:** + 1. Declares a `float` variable `fav_num` and initializes it to `42.5` 2. Initializes the serial output 3. Prints `fav_num` forever in a loop using the `%f` format specifier @@ -272,11 +277,13 @@ Ghidra will open. Now we need to create a new project. A dialog appears. The file is identified as a "BIN" (raw binary without debug symbols). **Click the three dots (...) next to "Language" and:** + 1. Search for "Cortex" 2. Select **ARM Cortex 32 little endian default** 3. Click **OK** **Click the "Options..." button and:** + 1. Change **Block Name** to `.text` 2. Change **Base Address** to `10000000` (the XIP address!) 3. Click **OK** @@ -298,6 +305,7 @@ Wait for analysis to complete (watch the progress bar in the bottom right). Look at the **Symbol Tree** panel on the left. Expand **Functions**. You'll see function names like: + - `FUN_1000019a` - `FUN_10000210` - `FUN_10000234` @@ -752,6 +760,7 @@ int main(void) { ``` **What this code does:** + 1. Declares a `double` variable `fav_num` and initializes it to `42.52525` 2. Initializes the serial output 3. Prints `fav_num` forever in a loop using the `%lf` format specifier @@ -817,11 +826,13 @@ Ghidra will open. Now we need to create a new project. A dialog appears. The file is identified as a "BIN" (raw binary without debug symbols). **Click the three dots (...) next to "Language" and:** + 1. Search for "Cortex" 2. Select **ARM Cortex 32 little endian default** 3. Click **OK** **Click the "Options..." button and:** + 1. Change **Block Name** to `.text` 2. Change **Base Address** to `10000000` (the XIP address!) 3. Click **OK** @@ -843,6 +854,7 @@ Wait for analysis to complete (watch the progress bar in the bottom right). Look at the **Symbol Tree** panel on the left. Expand **Functions**. You'll see function names like: + - `FUN_1000019a` - `FUN_10000210` - `FUN_10000238` @@ -983,7 +995,7 @@ The sign bit is bit 63 of the 64-bit double, which is bit 31 of r3 (the high reg ``` r3 = 0x4045433B = 0100 0000 0100 0101 0100 0011 0011 1011 ^ - r3 bit 31 = 0 -> sign = 0 -> Positive number ✓ + r3 bit 31 = 0 -> sign = 0 -> Positive number ✓ ``` **2. Exponent - bits 62-52 = bits 30-20 of r3** @@ -1164,12 +1176,14 @@ Look in the Listing view for the two data constants: ### Step 20: Patch Both Constants **Patch the low word:** + 1. Click on the data at address `10000254` containing `645A1CAC` 2. Open the Bytes window and enable byte editing (Pencil icon) 3. Overwrite bytes `ac 1c 5a 64` with `8f c2 f5 28` (little-endian for `0x645A1CAC -> 0x28F5C28F`) 4. Press Enter **Patch the high word:** + 1. Click on the data at address `10000258` containing `4045433B` 2. Keep byte editing enabled in the Bytes window 3. Overwrite bytes `3b 43 45 40` with `5c ff 58 40` (little-endian for `0x4045433B -> 0x4058FF5C`) diff --git a/WEEK05/WEEK05.pdf b/WEEK05/WEEK05.pdf new file mode 100644 index 0000000..dd82424 Binary files /dev/null and b/WEEK05/WEEK05.pdf differ diff --git a/WEEK06/WEEK06.md b/WEEK06/WEEK06.md index a32b092..28cab05 100644 --- a/WEEK06/WEEK06.md +++ b/WEEK06/WEEK06.md @@ -1,22 +1,25 @@ # Week 6: Static Variables in Embedded Systems: Debugging and Hacking Static Variables w/ GPIO Input Basics ---- +*** **LEGAL DISCLAIMER:** The information, tools, and code provided in this repository and course are strictly for educational, research, and defensive purposes only. You are explicitly prohibited from using any materials contained herein to access, test, modify, or exploit any device, network, or system that you do not own 100% or for which you do not have explicit, documented, and legally binding authorization to interact with. By using this repository and course, you acknowledge and agree that: + 1. Any illegal, unauthorized, or malicious use of this information is solely your responsibility. 2. The author(s) and contributor(s) of this repository and course shall not be held liable for any damages, legal repercussions, criminal charges, or unauthorized actions resulting from the use, misuse, or abuse of the contents herein. 3. You will comply with all applicable local, state, national, and international laws regarding cybersecurity and computer fraud. **IF YOU DO NOT AGREE WITH THESE TERMS, DO NOT USE THIS REPOSITORY AND COURSE.** ---- + +*** ## What You'll Learn This Week By the end of this tutorial, you will be able to: + - Understand the difference between regular (automatic) variables and static variables - Know where different types of variables are stored (stack vs static storage) - Configure GPIO pins as inputs and use internal pull-up resistors @@ -35,6 +38,7 @@ By the end of this tutorial, you will be able to: A **static variable** is a special kind of variable that "remembers" its value between function calls or loop iterations. Unlike regular variables that get created and destroyed each time, static variables **persist** for the entire lifetime of your program. Think of it like this: + - **Regular variable:** Like writing on a whiteboard that gets erased after each class - **Static variable:** Like writing in a notebook that you keep forever @@ -218,10 +222,12 @@ gpio_put(LED_GPIO, pressed ? 0 : 1); ``` This is a compact if-else statement: + - If `pressed` is **true (1)**: output `0` (LED OFF... wait, that seems backwards!) - If `pressed` is **false (0)**: output `1` (LED ON) **Why is it inverted?** Because of the pull-up resistor! + - Button **released** -> GPIO reads `1` -> `pressed = 1` -> output `0` -> LED OFF - Button **pressed** -> GPIO reads `0` -> `pressed = 0` -> output `1` -> LED ON @@ -273,6 +279,7 @@ This is why when you look for `gpio_pull_up` in the binary, you might find `gpio ### Prerequisites Before we start, make sure you have: + 1. A Raspberry Pi Pico 2 board 2. A Raspberry Pi Pico Debug Probe 3. OpenOCD installed and configured @@ -287,6 +294,7 @@ Before we start, make sure you have: ### Hardware Setup Connect your button like this: + - One side of button -> GPIO 15 - Other side of button -> GND @@ -408,12 +416,14 @@ static_fav_num: 45 ``` **Notice the difference:** + - `regular_fav_num` stays at 42 every time (it's recreated each loop) - `static_fav_num` increases each time (it persists and remembers its value) ### Step 4: Test the Button Now test the button behavior: + - **Button NOT pressed:** LED should be OFF - **Button PRESSED:** LED should turn ON @@ -687,6 +697,8 @@ You can see this directly. Run `x/10i 0x1000028e` in GDB and you will get exactl ```gdb (gdb) x/s 0x10003578 0x10003578: "static_fav_num: %d\r\n" +``` + - `0x10003578` flash address of the `"static_fav_num: %d\r\n"` string literal, also in **`.rodata`** in flash for the same reason. So the pool contains addresses into three different regions: RAM `.data` (the static variable), and flash `.rodata` (both format strings). Only the RAM address needed to be in the pool, the flash addresses could in principle be reached other ways, but they are also too large to encode as 16-bit immediates, so they go in the pool too. @@ -985,6 +997,7 @@ file_offset = address - 0x10000000 ``` For example: + - Address `0x10000264` -> file offset `0x264` (612 in decimal) - Address `0x10000286` -> file offset `0x286` (646 in decimal) @@ -1046,6 +1059,7 @@ To change `eor.w r3, r3, #1` to `eor.w r3, r3, #0`: > ?? **Why offset `0x288` and not `0x286`?** The immediate value `#1` is in the **third byte** of the 4-byte instruction. The instruction starts at file offset `0x286`, so the immediate byte is at `0x286 + 2 = 0x288`. Now the logic is permanently changed: + - Button released (input = 1): `1 XOR 0 = 1` -> LED **ON** - Button pressed (input = 0): `0 XOR 0 = 0` -> LED **OFF** @@ -1076,6 +1090,7 @@ python ..\uf2conv.py build\0x0014_static-variables-h.bin --base 0x10000000 --fam ``` **What this command means:** + - `uf2conv.py` = the conversion script (in the parent `Embedded-Hacking` directory) - `--base 0x10000000` = the XIP base address where code runs from - `--family 0xe48bff59` = the RP2350 family ID @@ -1099,10 +1114,12 @@ static_fav_num: 43 ``` **Check the LED behavior:** + - LED should now be **ON by default** (when button is NOT pressed) - LED should turn **OFF** when you press the button **BOOM! We successfully:** + 1. Changed the printed value from 42 to 43 2. Inverted the LED/button logic diff --git a/WEEK06/WEEK06.pdf b/WEEK06/WEEK06.pdf new file mode 100644 index 0000000..5529512 Binary files /dev/null and b/WEEK06/WEEK06.pdf differ diff --git a/WEEK07/WEEK07.md b/WEEK07/WEEK07.md index 687cf58..46e5743 100644 --- a/WEEK07/WEEK07.md +++ b/WEEK07/WEEK07.md @@ -1,22 +1,25 @@ # Week 7: Constants in Embedded Systems: Debugging and Hacking Constants w/ 1602 LCD I2C Basics ---- +*** **LEGAL DISCLAIMER:** The information, tools, and code provided in this repository and course are strictly for educational, research, and defensive purposes only. You are explicitly prohibited from using any materials contained herein to access, test, modify, or exploit any device, network, or system that you do not own 100% or for which you do not have explicit, documented, and legally binding authorization to interact with. By using this repository and course, you acknowledge and agree that: + 1. Any illegal, unauthorized, or malicious use of this information is solely your responsibility. 2. The author(s) and contributor(s) of this repository and course shall not be held liable for any damages, legal repercussions, criminal charges, or unauthorized actions resulting from the use, misuse, or abuse of the contents herein. 3. You will comply with all applicable local, state, national, and international laws regarding cybersecurity and computer fraud. **IF YOU DO NOT AGREE WITH THESE TERMS, DO NOT USE THIS REPOSITORY AND COURSE.** ---- + +*** ## What You'll Learn This Week By the end of this tutorial, you will be able to: + - Understand the difference between `#define` macros and `const` variables - Know how constants are stored differently in memory (compile-time vs runtime) - Understand the I2C (Inter-Integrated Circuit) communication protocol @@ -341,6 +344,7 @@ bl i2c_init ; Call the function ### Prerequisites Before we start, make sure you have: + 1. A Raspberry Pi Pico 2 board 2. A Raspberry Pi Pico Debug Probe 3. OpenOCD installed and configured @@ -463,6 +467,7 @@ int main(void) { ### Step 3: Verify It's Working **Check the LCD:** + - Line 1 should show: `Reverse` - Line 2 should show: `Engineering` @@ -613,6 +618,7 @@ Look for this instruction: **Surprise!** The `const` variable is ALSO embedded as an immediate value - not loaded from memory! The compiler saw that `OTHER_FAV_NUM` is never address-taken (`&OTHER_FAV_NUM` is never used), so it optimized the `const` the same way as `#define` - as a constant embedded directly in the instruction. The difference is the instruction encoding: + - `FAV_NUM` (42): `movs r1, #0x2a` - 16-bit Thumb instruction (values 0-255) - `OTHER_FAV_NUM` (1337): `movw r1, #0x539` - 32-bit Thumb-2 instruction (values 0-65535) @@ -636,8 +642,8 @@ These are the values that `ldr rN, [pc, #offset]` instructions load: | `0x100002a8` | `0x2000062C` | &i2c1_inst (I2C struct in RAM) | | `0x100002ac` | `0x10003EE8` | "Reverse" string address | | `0x100002b0` | `0x10003EF0` | "Engineering" string address | -| `0x100002b4` | `0x10003EFC` | "FAV_NUM: %d\r\n" format str | -| `0x100002b8` | `0x10003F0C` | "OTHER_FAV_NUM: %d\r\n" fmt | +| `0x100002b4` | `0x10003EFC` | `"FAV_NUM: %d\r\n"` format str | +| `0x100002b8` | `0x10003F0C` | `"OTHER_FAV_NUM: %d\r\n"` fmt | > Tip: **Why does the disassembly at `0x100002a4` show `strh r0, [r4, #52]` instead of data?** Same reason as Week 6 - GDB's `x/i` tries to decode raw data as instructions. Use `x/wx` to see the actual word values or we can also use `x/x`. @@ -728,6 +734,7 @@ The value 42 is embedded directly in a 16-bit Thumb instruction. This is expecte The value 1337 is ALSO embedded directly in an instruction - but this time a 32-bit Thumb-2 `movw` because the value doesn't fit in 8 bits. **Why wasn't `const` stored in memory?** In theory, `const int OTHER_FAV_NUM = 1337` creates a variable in the `.rodata` section. But the compiler optimized it away because: + 1. We never take the address of `OTHER_FAV_NUM` (no `&OTHER_FAV_NUM`) 2. The value fits in a 16-bit `movw` immediate 3. Loading from an immediate is faster than loading from memory @@ -798,6 +805,7 @@ file_offset = address - 0x10000000 ``` For example: + - Address `0x1000028e` -> file offset `0x28E` (654 in decimal) - Address `0x10003ee8` -> file offset `0x3EE8` (16104 in decimal) @@ -905,6 +913,7 @@ python ..\uf2conv.py build\0x0017_constants-h.bin --base 0x10000000 --family 0xe ### Step 23: Verify the Hack **Check the LCD:** + - Line 1 should now show: `Exploit` (instead of "Reverse") - Line 2 should still show: `Engineering` diff --git a/WEEK07/WEEK07.pdf b/WEEK07/WEEK07.pdf new file mode 100644 index 0000000..e929fa9 Binary files /dev/null and b/WEEK07/WEEK07.pdf differ diff --git a/WEEK09/WEEK09.md b/WEEK09/WEEK09.md index 3c4d100..3589e26 100644 --- a/WEEK09/WEEK09.md +++ b/WEEK09/WEEK09.md @@ -1,22 +1,25 @@ # Week 9: Operators in Embedded Systems: Debugging and Hacking Operators w/ DHT11 Temperature & Humidity Sensor Single-Wire Protocol Basics. ---- +*** **LEGAL DISCLAIMER:** The information, tools, and code provided in this repository and course are strictly for educational, research, and defensive purposes only. You are explicitly prohibited from using any materials contained herein to access, test, modify, or exploit any device, network, or system that you do not own 100% or for which you do not have explicit, documented, and legally binding authorization to interact with. By using this repository and course, you acknowledge and agree that: + 1. Any illegal, unauthorized, or malicious use of this information is solely your responsibility. 2. The author(s) and contributor(s) of this repository and course shall not be held liable for any damages, legal repercussions, criminal charges, or unauthorized actions resulting from the use, misuse, or abuse of the contents herein. 3. You will comply with all applicable local, state, national, and international laws regarding cybersecurity and computer fraud. **IF YOU DO NOT AGREE WITH THESE TERMS, DO NOT USE THIS REPOSITORY AND COURSE.** ---- + +*** ## What You'll Learn This Week By the end of this tutorial, you will be able to: + - Understand all six types of C operators (arithmetic, increment, relational, logical, bitwise, assignment) - Know how the DHT11 temperature and humidity sensor communicates with the Pico 2 - Understand how post-increment operators affect variable values @@ -339,6 +342,7 @@ if (dht11_read(&hum, &temp)) { ### Prerequisites Before we start, make sure you have: + 1. A Raspberry Pi Pico 2 board 2. A Raspberry Pi Pico Debug Probe 3. Ghidra installed (for static analysis) @@ -572,6 +576,7 @@ x/32i 0x10000240 ``` You may see values like: + - `#0x32` (50) for arithmetic_operator - `#0x5` (5) for increment_operator - `#0x0` (0) for relational and logical operators @@ -589,6 +594,7 @@ i r r0 r1 ``` You should see: + - `r0` = address of format string - `r1` = value to print @@ -674,11 +680,13 @@ ghidraRun ### Step 20: Configure the Binary Format **Click the three dots (...) next to "Language" and:** + 1. Search for "Cortex" 2. Select **ARM Cortex 32 little endian default** 3. Click **OK** **Click the "Options..." button and:** + 1. Change **Block Name** to `.text` 2. Change **Base Address** to `10000000` 3. Click **OK** @@ -802,6 +810,7 @@ bl FUN_xxxxx ; dht11_init ``` **How do we know it's dht11_init?** + - The argument `4` is the GPIO pin number - We physically connected the DHT11 to GPIO 4! @@ -843,6 +852,7 @@ bl FUN_xxxxx ; dht11_read ``` **Understanding the stack offsets:** + - `sp + 0x8` = address of `hum` variable - `sp + 0xc` = address of `temp` variable - These are `float` pointers passed to the function @@ -1201,6 +1211,7 @@ Imagine a scenario where temperature sensors control critical systems: - **HVAC systems** - Climate control in sensitive environments By manipulating sensor readings, an attacker could: + - Cause equipment to overheat while displaying normal temperatures - Trigger false alarms - Bypass safety interlocks diff --git a/WEEK09/WEEK09.pdf b/WEEK09/WEEK09.pdf new file mode 100644 index 0000000..5a57599 Binary files /dev/null and b/WEEK09/WEEK09.pdf differ diff --git a/WEEK10/WEEK10.md b/WEEK10/WEEK10.md index 9d2a768..38d465f 100644 --- a/WEEK10/WEEK10.md +++ b/WEEK10/WEEK10.md @@ -1,22 +1,25 @@ # Week 10: Conditionals in Embedded Systems: Debugging and Hacking Static & Dynamic Conditionals w/ SG90 Servo Motor PWM Basics ---- +*** **LEGAL DISCLAIMER:** The information, tools, and code provided in this repository and course are strictly for educational, research, and defensive purposes only. You are explicitly prohibited from using any materials contained herein to access, test, modify, or exploit any device, network, or system that you do not own 100% or for which you do not have explicit, documented, and legally binding authorization to interact with. By using this repository and course, you acknowledge and agree that: + 1. Any illegal, unauthorized, or malicious use of this information is solely your responsibility. 2. The author(s) and contributor(s) of this repository and course shall not be held liable for any damages, legal repercussions, criminal charges, or unauthorized actions resulting from the use, misuse, or abuse of the contents herein. 3. You will comply with all applicable local, state, national, and international laws regarding cybersecurity and computer fraud. **IF YOU DO NOT AGREE WITH THESE TERMS, DO NOT USE THIS REPOSITORY AND COURSE.** ---- + +*** ## What You'll Learn This Week By the end of this tutorial, you will be able to: + - Understand the difference between static and dynamic conditionals in C - Know how if/else statements and switch/case blocks work at the assembly level - Understand Pulse Width Modulation (PWM) and how it controls servo motors @@ -377,6 +380,7 @@ The **SG90** is a small, inexpensive hobby servo motor commonly used in robotics **NEVER power the servo directly from the Pico's 3.3V pin!** Servos can draw over 1000mA during movement spikes. The Pico's 3.3V regulator cannot handle this and you will: + - Cause brownouts (Pico resets) - Damage the Pico's voltage regulator - Potentially damage your USB port @@ -410,6 +414,7 @@ Servos can draw over 1000mA during movement spikes. The Pico's 3.3V regulator ca ### Why the Capacitor? The **1000 uF capacitor** acts as a tiny battery: + - Absorbs sudden current demands when servo moves - Prevents voltage drops that could reset the Pico - Smooths out electrical noise @@ -421,6 +426,7 @@ The **1000 uF capacitor** acts as a tiny battery: ### Prerequisites Before we start, make sure you have: + 1. A Raspberry Pi Pico 2 board 2. A Raspberry Pi Pico Debug Probe 3. Ghidra installed (for static analysis) @@ -599,6 +605,7 @@ one ``` **Watch the servo:** + - It should sweep from 0° to 180° every second - The movement is continuous and repetitive @@ -789,11 +796,13 @@ ghidraRun ### Step 20: Configure the Binary Format **Click the three dots (...) next to "Language" and:** + 1. Search for "Cortex" 2. Select **ARM Cortex 32 little endian default** 3. Click **OK** **Click the "Options..." button and:** + 1. Change **Block Name** to `.text` 2. Change **Base Address** to `10000000` 3. Click **OK** @@ -849,9 +858,10 @@ bl FUN_10001884 undefined FUN_10001884() ``` **How do we know it's puts?** + - It takes a single string argument - The hex `0x31` is ASCII "1" -- The hex `0x0d` is carriage return "\r" +- The hex `0x0d` is carriage return `"\r"` - We saw "1" echoed in PuTTY 1. Right-click -> **Edit Function Signature** @@ -879,6 +889,7 @@ mov.cc.w r3,#0x3e8 ``` These values are: + - `0x7D0` (2000 decimal) - maximum pulse width - `0x3E8` (1000 decimal) - minimum pulse width @@ -931,6 +942,7 @@ Next, let's change the word "one" to "fun": 4. Click on the `6f` byte and type `66 75 6e` on your keyboard to overwrite those three bytes with "f-u-n". **ASCII Reference:** + | Character | Hex | | --------- | ---- | | o | 0x6f | @@ -1226,6 +1238,7 @@ Follow the same process: ### Step 52: Identify getchar Look for a function that: + - Returns a value in `r0` - That value is then compared against `0x31` ("1") @@ -1249,6 +1262,7 @@ ldr r0, =0x40070000 ; UART0 base address ``` Check the RP2350 datasheet Section 2.2 (Address Map): + - `0x40070000` = UART0 This confirms it's a UART initialization function! @@ -1311,6 +1325,7 @@ skip_printf: ### The Goal We want to create **secret commands** that: + 1. Respond to 'x' and 'y' instead of '1' and '2' 2. Move the servo WITHOUT printing anything 3. Leave NO trace in the terminal @@ -1318,10 +1333,12 @@ We want to create **secret commands** that: ### Step 54: Plan the Patches **Original behavior:** + - '1' (0x31) -> prints "1" and "one", moves servo - '2' (0x32) -> prints "2" and "two", moves servo **Hacked behavior:** + - 'x' (0x78) -> moves servo SILENTLY (replacing '1') - 'y' (0x79) -> moves servo SILENTLY (replacing '2') @@ -1395,6 +1412,7 @@ The compiler stored the 180.0 float value (`0x43340000`) in a literal pool at ad **New:** `0x41f00000` (30.0f) Here is how to apply the patch: + 1. Press `G` and jump to address `100002c4`. 2. In your **Bytes** window (make sure the Pencil icon is still clicked!), you will see the raw little-endian bytes: `00 00 34 43`. 3. Click on the first `00` and type `00 00 f0 41`. @@ -1545,8 +1563,8 @@ python ..\uf2conv.py build\0x0020_dynamic-conditionals-h.bin --base 0x10000000 - | '2' | 0x32 | 50 | | 'x' | 0x78 | 120 | | 'y' | 0x79 | 121 | -| '\r' | 0x0d | 13 | -| '\n' | 0x0a | 10 | +| `'\r'` | 0x0d | 13 | +| `'\n'` | 0x0a | 10 | ### IEEE-754 Common Angles @@ -1583,11 +1601,13 @@ python ..\uf2conv.py build\0x0020_dynamic-conditionals-h.bin --base 0x10000000 - The ability to create hidden commands has serious implications: **Legitimate Uses:** + - Factory test modes - Debugging interfaces - Emergency recovery features **Malicious Uses:** + - Backdoors in firmware - Hidden surveillance features - Unauthorized control of systems @@ -1595,6 +1615,7 @@ The ability to create hidden commands has serious implications: ### Real-World Example Imagine a drone with hacked firmware: + - Normal keys ('1', '2') control it visibly with logging - Hidden keys ('x', 'y') control it with NO log entries - An attacker could operate the drone while security monitors show nothing @@ -1602,6 +1623,7 @@ Imagine a drone with hacked firmware: ### The Nuclear Fuel Rod Analogy A fast-moving servo is like a nuclear fuel rod: + - Both are small components with immense power - Both require precise control to prevent damage - Both can "go critical" if pushed beyond limits diff --git a/WEEK10/WEEK10.pdf b/WEEK10/WEEK10.pdf new file mode 100644 index 0000000..5d300d2 Binary files /dev/null and b/WEEK10/WEEK10.pdf differ diff --git a/WEEK11/WEEK11.md b/WEEK11/WEEK11.md index 931bc26..e0eebc8 100644 --- a/WEEK11/WEEK11.md +++ b/WEEK11/WEEK11.md @@ -1,22 +1,25 @@ # Week 11: Structures and Functions in Embedded Systems: Debugging and Hacking w/ IR Remote Control and NEC Protocol Basics ---- +*** **LEGAL DISCLAIMER:** The information, tools, and code provided in this repository and course are strictly for educational, research, and defensive purposes only. You are explicitly prohibited from using any materials contained herein to access, test, modify, or exploit any device, network, or system that you do not own 100% or for which you do not have explicit, documented, and legally binding authorization to interact with. By using this repository and course, you acknowledge and agree that: + 1. Any illegal, unauthorized, or malicious use of this information is solely your responsibility. 2. The author(s) and contributor(s) of this repository and course shall not be held liable for any damages, legal repercussions, criminal charges, or unauthorized actions resulting from the use, misuse, or abuse of the contents herein. 3. You will comply with all applicable local, state, national, and international laws regarding cybersecurity and computer fraud. **IF YOU DO NOT AGREE WITH THESE TERMS, DO NOT USE THIS REPOSITORY AND COURSE.** ---- + +*** ## What You'll Learn This Week By the end of this tutorial, you will be able to: + - Understand C structures (structs) and how they organize related data - Know how structs are represented in memory and assembly code - Understand the NEC infrared (IR) protocol for remote control communication @@ -81,6 +84,7 @@ typedef struct { | `bool led3_state = false;` | ... (all in one container!) | **Benefits of Structs:** + 1. **Organization** - Related data stays together 2. **Readability** - Code is easier to understand 3. **Maintainability** - Changes are easier to make @@ -175,6 +179,7 @@ simple_led_ctrl_t leds = { ``` **Benefits:** + - Clear which value goes to which member - Order doesn't matter (can rearrange lines) - Self-documenting code @@ -412,6 +417,7 @@ bl gpio_init ; call gpio_init(18) ### Prerequisites Before we start, make sure you have: + 1. A Raspberry Pi Pico 2 board 2. A Raspberry Pi Pico Debug Probe 3. Ghidra installed (for static analysis) @@ -596,6 +602,7 @@ int main(void) { ### Step 4: Verify It's Working **Open PuTTY (115200 baud) and test:** + - Press "1" on remote -> Red LED lights, terminal shows `NEC command: 0x0C` - Press "2" on remote -> Green LED lights, terminal shows `NEC command: 0x18` - Press "3" on remote -> Yellow LED lights, terminal shows `NEC command: 0x5E` @@ -740,6 +747,7 @@ info registers r1 r2 r3 r4 ``` Depending on which button you pressed, one of the state registers will be `1` (ON) and the others will be `0` (OFF): + - `r1` = State for the **Red** LED (GPIO 16) - `r3` = State for the **Green** LED (GPIO 17) - `r4` = State for the **Yellow** LED (GPIO 18) @@ -785,11 +793,13 @@ ghidraRun ### Step 20: Configure the Binary Format **Click the three dots (...) next to "Language" and:** + 1. Search for "Cortex" 2. Select **ARM Cortex 32 little endian default** 3. Click **OK** **Click the "Options..." button and:** + 1. Change **Block Name** to `.text` 2. Change **Base Address** to `10000000` 3. Click **OK** @@ -838,6 +848,7 @@ Look for three consecutive calls with values 16, 17, 18: ``` This pattern reveals the struct members! Update the function signature: + 1. Right-click on `FUN_10000558` -> **Edit Function Signature** 2. Change to: `void gpio_init(uint gpio)` 3. Click **OK** @@ -985,6 +996,7 @@ python ..\uf2conv.py build\0x0023_structures-h.bin --base 0x10000000 --family 0x ### Step 34: Verify the Hack **Open PuTTY and test:** + - Press "1" on remote -> **GREEN** LED lights (was red!) - Terminal still shows `NEC command: 0x0C` - Press "2" on remote -> **RED** LED lights (was green!) @@ -1020,12 +1032,14 @@ python ..\uf2conv.py build\0x0023_structures-h.bin --base 0x10000000 --family 0x ### Real-World Example: Stuxnet **Stuxnet** was a cyberweapon that: + - Attacked Iranian nuclear centrifuges - Made centrifuges spin at dangerous speeds - Fed FALSE "everything normal" data to operators - Operators saw stable readings while equipment was destroyed Our LED example demonstrates the same principle: + - Logs show expected behavior - Hardware performs different actions - Attackers can hide malicious activity @@ -1319,6 +1333,7 @@ quit ### Step 52: Explore the Symbol Tree With .ELF files, you get more information: + 1. Look at the **Symbol Tree** panel 2. Expand **Functions** - you may see named functions! 3. Expand **Labels** - data labels may appear @@ -1342,6 +1357,7 @@ movs r0, #0x12 ; led3_pin = 18 We'll swap the red (GPIO 16) and yellow (GPIO 18) LEDs: **Find and patch in the .bin file:** + 1. Change `0x10` (16) to `0x12` (18) 2. Change `0x12` (18) to `0x10` (16) @@ -1375,6 +1391,7 @@ python ..\uf2conv.py build\0x0026_functions-h.bin --base 0x10000000 --family 0xe ### Step 57: Verify the Hack **Open PuTTY and test:** + - Press "1" -> **YELLOW** LED blinks (was red!) - Terminal shows: `LED 1 activated on GPIO 16` (WRONG - it's actually GPIO 18!) - Press "3" -> **RED** LED blinks (was yellow!) @@ -1554,12 +1571,14 @@ Over these weeks, you've built skills that few people possess: The techniques you've learned can be used for: **Good:** + - Security research - Debugging proprietary systems - Understanding how things work - Career in cybersecurity **Danger:** + - Unauthorized system access - Sabotage of critical infrastructure - Fraud and deception @@ -1569,6 +1588,7 @@ The techniques you've learned can be used for: ### Keep Learning This is just the beginning: + - Explore more complex protocols (SPI, CAN bus) - Learn dynamic analysis with debuggers - Study cryptographic implementations diff --git a/WEEK11/WEEK11.pdf b/WEEK11/WEEK11.pdf new file mode 100644 index 0000000..54a2806 Binary files /dev/null and b/WEEK11/WEEK11.pdf differ