diff --git a/WEEK01/WEEK01.md b/WEEK01/WEEK01.md index c827cfc..cc3460a 100644 --- a/WEEK01/WEEK01.md +++ b/WEEK01/WEEK01.md @@ -1,4 +1,4 @@ -๏ปฟ# Week 1: Introduction and Overview of Embedded Reverse Engineering: Ethics, Scoping, and Basic Concepts +# Week 1: Introduction and Overview of Embedded Reverse Engineering: Ethics, Scoping, and Basic Concepts ## ๐ŸŽฏ What You'll Learn This Week @@ -348,9 +348,9 @@ To see how the ELF is laid out in memory, use: ```gdb (gdb) info files -Symbols from "C:\Users\assem.KEVINTHOMAS\OneDrive\Documents\Embedded-Hacking\0x0001_hello-world\build\0x0001_hello-world.elf". +Symbols from "C:\Users\flare-vm\Desktop\Embedded-Hacking-main\0x0001_hello-world\build\0x0001_hello-world.elf". Extended remote target using gdb-specific protocol: - `C:\Users\assem.KEVINTHOMAS\OneDrive\Documents\Embedded-Hacking\0x0001_hello-world\build\0x0001_hello-world.elf', file type elf32-littlearm. + `C:\Users\flare-vm\Desktop\Embedded-Hacking-main\0x0001_hello-world\build\0x0001_hello-world.elf', file type elf32-littlearm. Entry point: 0x1000014c 0x10000000 - 0x100019cc is .text 0x100019cc - 0x10001b18 is .rodata @@ -366,7 +366,7 @@ Extended remote target using gdb-specific protocol: 0x10001ce8 - 0x10001cfc is .flash_end While running this, GDB does not access memory from... Local exec file: - `C:\Users\assem.KEVINTHOMAS\OneDrive\Documents\Embedded-Hacking\0x0001_hello-world\build\0x0001_hello-world.elf', file type elf32-littlearm. + `C:\Users\flare-vm\Desktop\Embedded-Hacking-main\0x0001_hello-world\build\0x0001_hello-world.elf', file type elf32-littlearm. Entry point: 0x1000014c 0x10000000 - 0x100019cc is .text 0x100019cc - 0x10001b18 is .rodata @@ -381,7 +381,7 @@ Local exec file: 0x20081000 - 0x20081800 is .stack_dummy 0x10001ce8 - 0x10001cfc is .flash_end (gdb) maintenance info sections -Exec file: `C:\Users\assem.KEVINTHOMAS\OneDrive\Documents\Embedded-Hacking\0x0001_hello-world\build\0x0001_hello-world.elf', file type elf32-littlearm. +Exec file: `C:\Users\flare-vm\Desktop\Embedded-Hacking-main\0x0001_hello-world\build\0x0001_hello-world.elf', file type elf32-littlearm. [0] 0x10000000->0x100019cc at 0x00001000: .text ALLOC LOAD READONLY CODE HAS_CONTENTS [1] 0x100019cc->0x10001b18 at 0x000029cc: .rodata ALLOC LOAD READONLY DATA HAS_CONTENTS [2] 0x10001b18->0x10001b20 at 0x00002b18: .ARM.exidx ALLOC LOAD READONLY DATA HAS_CONTENTS diff --git a/WEEK04/WEEK04.md b/WEEK04/WEEK04.md index a6e9edf..7ecc4c8 100644 --- a/WEEK04/WEEK04.md +++ b/WEEK04/WEEK04.md @@ -1,4 +1,4 @@ -๏ปฟ# Week 4: Variables in Embedded Systems: Debugging and Hacking Variables w/ GPIO Output Basics +# Week 4: Variables in Embedded Systems: Debugging and Hacking Variables w/ GPIO Output Basics ## ๐ŸŽฏ What You'll Learn This Week @@ -417,10 +417,10 @@ This instruction loads the value `0x2b` (43) into register `r1` before calling ` We're going to change `0x2b` (43) to `0x46` (70)! -1. Click on the instruction `movs r1,#0x2b` +1. At address `1000023a`, click the instruction `movs r1,#0x2b` 2. Right-click and select **Patch Instruction** -3. Change `0x2b` to `0x46` -4. Press Enter +3. Replace immediate `0x2b` with `0x46` +4. Press Enter and verify the instruction bytes change from `2b 21` to `46 21` The instruction now reads: ```assembly @@ -446,7 +446,7 @@ The Pico 2 expects UF2 files, not raw BIN files. We need to convert it! **Open a terminal and navigate to your project directory:** ```powershell -cd C:\Users\assem.KEVINTHOMAS\OneDrive\Documents\Embedded-Hacking\0x0005_intro-to-variables +cd C:\Users\flare-vm\Desktop\Embedded-Hacking-main\0x0005_intro-to-variables ``` **Run the conversion command:** @@ -609,10 +609,10 @@ This is where `gpio_init(LED_PIN)` is called with GPIO 16. We'll change the red LED (GPIO 16) to the green LED (GPIO 17)! -1. Find the instruction `movs r0,#0x10` +1. At address `1000023a`, select `movs r0,#0x10` 2. Right-click -> **Patch Instruction** -3. Change `0x10` to `0x11` (17 in hex) -4. Click **OK** +3. Replace immediate `0x10` with `0x11` (17 decimal) +4. Click **OK** and verify bytes change from `10 20` to `11 20` ### Step 28: Find All GPIO 16 References @@ -629,6 +629,9 @@ 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` ### Step 29: Bonus - Change the Printed Value @@ -639,8 +642,8 @@ Let's also change the printed value from `0` to `0x42` (66 in decimal): ``` 1. Right-click -> **Patch Instruction** -2. Change `0x0` to `0x42` -3. Click **OK** +2. Replace immediate `0x0` with `0x42` +3. Click **OK** and verify bytes change from `00 21` to `42 21` --- @@ -656,7 +659,7 @@ Let's also change the printed value from `0` to `0x42` (66 in decimal): ### Step 31: Convert to UF2 ```powershell -cd C:\Users\assem.KEVINTHOMAS\OneDrive\Documents\Embedded-Hacking\0x0008_uninitialized-variables +cd C:\Users\flare-vm\Desktop\Embedded-Hacking-main\0x0008_uninitialized-variables python ..\uf2conv.py build\0x0008_uninitialized-variables-h.bin --base 0x10000000 --family 0xe48bff59 --output build\hacked.uf2 ``` @@ -802,7 +805,7 @@ delay2: +-----------------------------------------------------------------+ | 3. Find the values/instructions to patch | | - Look in the assembly listing | -| - Right-click -> Patch Instruction | +| - Patch Instruction, then verify old bytes -> new bytes | +-----------------------------------------------------------------+ | 4. Export the patched binary | | - File -> Export Program | @@ -832,7 +835,7 @@ delay2: | Action | How To Do It | | ----------------- | ------------------------------------- | | Rename function | Right-click -> Edit Function Signature | -| Patch instruction | Right-click -> Patch Instruction | +| Patch instruction | Right-click -> Patch Instruction, then verify old bytes -> new bytes | | Export binary | File -> Export Program -> Raw Bytes | | Go to address | Press 'G' and enter address | @@ -903,4 +906,4 @@ The RP2350 GPIO coprocessor instructions: **Remember:** Every binary you encounter in the real world can be analyzed and understood using these same techniques. Practice makes perfect! Happy hacking! ๐Ÿ”ง - + diff --git a/WEEK05/WEEK05-SLIDES.pdf b/WEEK05/WEEK05-SLIDES.pdf index 78b8021..68bb942 100644 Binary files a/WEEK05/WEEK05-SLIDES.pdf and b/WEEK05/WEEK05-SLIDES.pdf differ diff --git a/WEEK05/WEEK05.md b/WEEK05/WEEK05.md index 059411c..df78ace 100644 --- a/WEEK05/WEEK05.md +++ b/WEEK05/WEEK05.md @@ -1,6 +1,6 @@ -๏ปฟ?# Week 5: Integers and Floats in Embedded Systems: Debugging and Hacking Integers and Floats w/ Intermediate GPIO Output Assembler Analysis +# ๐Ÿ“˜ Week 5: Integers and Floats in Embedded Systems: Debugging and Hacking Integers and Floats w/ Intermediate GPIO Output Assembler Analysis -## ? What You'll Learn This Week +## ๐ŸŽฏ 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 @@ -25,10 +25,10 @@ In C programming for embedded systems, we have special integer types that tell t +-----------------------------------------------------------------+ | Integer Types - Different Sizes for Different Needs | | | -| uint8_t: 1 byte (0 to 255) - like a small box | -| int8_t: 1 byte (-128 to 127) - can hold negatives! | -| uint16_t: 2 bytes (0 to 65,535) - medium box | -| uint32_t: 4 bytes (0 to 4 billion) - big box | +| uint8_t: 1 byte (0 to 255) - like a small box | +| int8_t: 1 byte (-128 to 127) - can hold negatives! | +| uint16_t: 2 bytes (0 to 65,535) - medium box | +| uint32_t: 4 bytes (0 to 4 billion) - big box | | | +-----------------------------------------------------------------+ ``` @@ -42,83 +42,9 @@ The difference between `uint8_t` and `int8_t` is whether the number can be **neg | `uint8_t` | `u` | 0 to 255 | Ages, counts, always positive | | `int8_t` | none | -128 to 127 | Temperature, can be negative | -Let's review the code in `0x000b_integer-data-type`. - -```assembly -#include -#include "pico/stdlib.h" - -int main(void) { - uint8_t age = 43; - int8_t range = -42; - - stdio_init_all(); - - __asm volatile ( - "ldr r3, =0x40038000\n" // address of PADS_BANK0_BASE - "ldr r2, =0x40028004\n" // address of IO_BANK0 GPIO0.ctrl - "movs r0, #16\n" // GPIO16 (start pin) - - "init_loop:\n" // loop start - "lsls r1, r0, #2\n" // pin * 4 (pad offset) - "adds r4, r3, r1\n" // PADS base + offset - "ldr r5, [r4]\n" // load current config - "bic r5, r5, #0x180\n" // clear OD+ISO - "orr r5, r5, #0x40\n" // set IE - "str r5, [r4]\n" // store updated config - - "lsls r1, r0, #3\n" // pin * 8 (ctrl offset) - "adds r4, r2, r1\n" // IO_BANK0 base + offset - "ldr r5, [r4]\n" // load current config - "bic r5, r5, #0x1f\n" // clear FUNCSEL bits [4:0] - "orr r5, r5, #5\n" // set FUNCSEL = 5 (SIO) - "str r5, [r4]\n" // store updated config - - "mov r4, r0\n" // pin - "movs r5, #1\n" // bit 1; used for OUT/OE writes - "mcrr p0, #4, r4, r5, c4\n" // gpioc_bit_oe_put(pin,1) - "adds r0, r0, #1\n" // increment pin - "cmp r0, #20\n" // stop after pin 18 - "blt init_loop\n" // loop until r0 == 20 - ); - - uint8_t pin = 16; - - while (1) { - __asm volatile ( - "mov r4, %0\n" // pin - "movs r5, #0x01\n" // bit 1; used for OUT/OE writes - "mcrr p0, #4, r4, r5, c0\n" // gpioc_bit_out_put(16, 1) - : - : "r"(pin) - : "r4","r5" - ); - sleep_ms(500); - - __asm volatile ( - "mov r4, %0\n" // pin - "movs r5, #0\n" // bit 0; used for OUT/OE writes - "mcrr p0, #4, r4, r5, c0\n" // gpioc_bit_out_put(16, 0) - : - : "r"(pin) - : "r4","r5" - ); - sleep_ms(500); - - pin++; - if (pin > 18) pin = 16; - - printf("age: %d\r\n", age); - printf("range: %d\r\n", range); - } -} -``` - -### Breaking Down the Code - #### The Integer Variables -This program declares two integer variables that demonstrate the difference between **signed** and **unsigned** types: +Let's say a program declares two integer variables that demonstrate the difference between **signed** and **unsigned** types: ```c uint8_t age = 43; @@ -127,48 +53,6 @@ int8_t range = -42; The variable `age` is a `uint8_t` - an **unsigned** 8-bit integer that can only hold values from `0` to `255`. Since age is always a positive number, unsigned is the right choice. The variable `range` is an `int8_t` - a **signed** 8-bit integer that can hold values from `-128` to `127`. The signed type allows it to represent negative numbers like `-42`. Under the hood, negative values are stored using **two's complement** encoding: the CPU flips all the bits of `42` (`0x2A`) and adds `1`, producing `0xD6`, which is how `-42` lives in a single byte of memory. -#### GPIO Initialization with Inline Assembly - -Instead of using the Pico SDK's `gpio_init()`, `gpio_set_dir()`, and `gpio_set_function()` helpers, this program configures GPIO pins **directly at the register level** using inline assembly. This gives us a window into how the hardware actually works on the RP2350. - -The initialization loop configures GPIO pins 16 through 19 (our red, green, blue, and yellow LEDs) in three steps per pin: - -**Step 1 - Configure the pad.** Each GPIO pin has a pad control register in `PADS_BANK0` starting at base address `0x40038000`. The code calculates the offset as `pin * 4`, loads the current register value, clears the **OD** (output disable) and **ISO** (isolation) bits with `bic r5, r5, #0x180`, and sets the **IE** (input enable) bit with `orr r5, r5, #0x40`. This ensures the pad is electrically active and ready to drive output. - -**Step 2 - Set the pin function.** Each GPIO pin has a control register in `IO_BANK0` starting at `0x40028004`. The offset is `pin * 8` because each pin's control block is 8 bytes wide. The code clears the `FUNCSEL` field (bits `[4:0]`) and sets it to `5`, which selects the **SIO** (Single-cycle I/O) function. SIO is the mode that lets software directly control pin state through the GPIO coprocessor. - -**Step 3 - Enable the output driver.** The instruction `mcrr p0, #4, r4, r5, c4` writes to the RP2350's GPIO coprocessor. Coprocessor register `c4` controls the **output enable** - with `r4` holding the pin number and `r5` set to `1`, this tells the hardware "this pin is an output." The `mcrr` (Move to Coprocessor from two ARM Registers) instruction is how the Cortex-M33 on the RP2350 talks to its dedicated GPIO coprocessor, bypassing the normal memory-mapped I/O path for single-cycle pin control. - -#### The Blink Loop with Inline Assembly - -Inside the `while (1)` loop, the program uses two inline assembly blocks to toggle the current LED on and off: - -```c -"mcrr p0, #4, r4, r5, c0\n" // gpioc_bit_out_put(pin, 1) -``` - -This time the coprocessor register is `c0` instead of `c4`. Register `c0` controls the **output value** - setting `r5 = 1` drives the pin HIGH (LED on), and `r5 = 0` drives it LOW (LED off). Each toggle is followed by `sleep_ms(500)` for a half-second delay, creating a visible blink. - -The GCC extended assembly syntax `"r"(pin)` tells the compiler to load the C variable `pin` into a general-purpose register and make it available as `%0` inside the assembly block. The clobber list `"r4","r5"` warns the compiler that those registers are modified, so it won't store anything important there. - -#### The Pin Cycling and Print Statements - -After each on/off cycle, the program increments `pin` and wraps it back to `16` when it exceeds `18`: - -```c -pin++; -if (pin > 18) pin = 16; -``` - -This cycles through GPIO 16, 17, and 18 - red, green, and blue LEDs - creating a rotating blink pattern. Finally, `printf` prints both integer variables over UART so we can observe their values on the serial terminal: - -``` -age: 43 -range: -42 -``` - -> Tip: **Why use inline assembly instead of the SDK?** This program is designed to teach you what happens *beneath* the SDK. When you call `gpio_put(16, 1)` in normal Pico code, the SDK ultimately does the same coprocessor write - `mcrr p0, #4, r4, r5, c0`. By writing the assembly directly, you can see exactly how the RP2350 hardware is controlled, which is essential knowledge for reverse engineering and binary patching. - --- ## Part 2: Understanding Floating-Point Data Types @@ -198,13 +82,89 @@ A **float** is a number that can have a decimal point. Unlike integers which can +-----------------------------------------------------------------+ ``` +### How to Compute This by Hand (42.5 -> IEEE 754) + +Use this exact process any time you need to encode a decimal float manually. + +1. Determine the sign bit. + - `42.5` is positive, so `sign = 0`. + +2. Convert the number to binary. + - Integer part: `42 = 101010 (base 2)` + - Fractional part: use repeated multiply-by-2 on the fraction. + - Start with `0.5` + - `0.5 * 2 = 1.0` -> integer part is `1` (this is the first binary fractional bit) + - Remaining fractional part is now `0.0`, so we stop. + - Therefore `0.5 = 0.1 (base 2)`. + - Combined: `42.5 = 101010.1 (base 2)` + +3. Normalize to the form `1.xxxxx * 2^n`. + - `101010.1 (base 2) = 1.010101 (base 2) * 2^5` + - So the true exponent is `n = 5`. + +4. Compute the stored exponent (bias 127 for float). + - `stored exponent = n + 127 = 5 + 127 = 132` + - `132` in binary is `10000100` (8 bits). + + > Tip: **Why 127?** The exponent field is 8 bits wide, giving $2^8 = 256$ total values. Half of that range should represent negative exponents and half positive. The midpoint is $(2^8 / 2) - 1 = 127$. So a stored exponent of `127` means a real exponent of **0**, values below `127` are negative exponents, and values above `127` are positive exponents. Doubles use an 11-bit exponent field so their midpoint (bias) is $( 2^{11} / 2) - 1 = 1023$ instead. + +5. Build the mantissa (fraction bits). + - Take bits after the leading `1.` from `1.010101` -> `010101` + - Pad with zeros to 23 bits: + - `01010100000000000000000` + +6. Assemble all fields. + - `sign | exponent | mantissa` + - `0 | 10000100 | 01010100000000000000000` + - Full 32-bit pattern: + - `01000010001010100000000000000000` + +7. Convert the 32-bit binary to hex (group by 4 bits). + - `0100 0010 0010 1010 0000 0000 0000 0000` + - `4 2 2 A 0 0 0 0` + - Final result: `0x422A0000` + +Quick decode check (reverse direction, fully expanded): + +Given the 32-bit pattern: +- `0 | 10000100 | 01010100000000000000000` + +Decode it field by field: + +1. Sign bit + - Sign bit is `0` -> number is positive. + - So the sign multiplier is `(+1)`. + +2. Exponent field + - Exponent bits are `10000100`. + - Convert to decimal: `10000100 (base 2) = 132`. + - Float bias is `127`, so true exponent is: + - `132 - 127 = 5`. + +3. Mantissa field + - Stored mantissa bits are `01010100000000000000000`. + - IEEE 754 normal numbers use an implicit leading `1`, so significand becomes: + - `1.010101 (base 2)`. + +4. Rebuild the value + - Formula: `value = (+1) * 1.010101 (base 2) * 2^5`. + - Shift binary point right by 5: + - `1.010101 * 2^5 = 101010.1 (base 2)`. + +5. Convert `101010.1 (base 2)` to decimal + - Integer part: `101010 = 32 + 8 + 2 = 42` + - Fraction part: `.1 = 1/2 = 0.5` + - Total: `42 + 0.5 = 42.5` + +So the decoded value is exactly `42.5`. + ### Float vs Integer - Key Differences | Property | Integer (`uint8_t`) | Float (`float`) | | -------------- | ---------------------- | --------------------------- | | **Size** | 1 byte | 4 bytes | | **Precision** | Exact | ~7 decimal digits | -| **Range** | 0 to 255 | ?3.4 * 10++ | +| **Range** | 0 to 255 | ยฑ3.4 ร— 10^38 | | **Encoding** | Direct binary | IEEE 754 (sign/exp/mantissa)| | **printf** | `%d` | `%f` | @@ -228,6 +188,10 @@ int main(void) { } ``` +> Note: `fav_num` is declared inside `main`, so by C rules it is an automatic (stack) variable. In optimized embedded builds, the compiler may avoid creating a real stack slot and instead materialize the value from read-only constant storage (typically `.rodata` and/or an ARM literal pool). +> +> 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 @@ -260,7 +224,7 @@ The program is printing `42.500000` because `printf` with `%f` defaults to 6 dec --- -## ? Part 2.5: Setting Up Ghidra for Float Analysis +## ๐Ÿ”ง Part 2.5: Setting Up Ghidra for Float Analysis ### Step 3: Start Ghidra @@ -313,7 +277,7 @@ Wait for analysis to complete (watch the progress bar in the bottom right). --- -## ? Part 2.6: Navigating and Resolving Functions +## ๐Ÿ” Part 2.6: Navigating and Resolving Functions ### Step 8: Find the Functions @@ -347,7 +311,7 @@ For `main`, let's also fix the return type: --- -## ? Part 2.7: Analyzing the Main Function +## ๐Ÿ”ฌ Part 2.7: Analyzing the Main Function ### Step 11: Examine Main in Ghidra @@ -357,6 +321,7 @@ You'll see something like: ```c int main(void) + { undefined4 uVar1; undefined4 extraout_r1; @@ -384,7 +349,7 @@ int main(void) 1. Click on `FUN_100030ec` 2. Right-click -> **Edit Function Signature** -3. Change to: `int __wrap_printf(char *format,...)` +3. Change to: `int printf(char *format,...)` 4. Check the **Varargs** checkbox (printf takes variable arguments!) 5. Click **OK** @@ -394,17 +359,18 @@ Look at the decompiled code after resolving functions: ```c int main(void) + { undefined4 uVar1; undefined4 extraout_r1; undefined4 uVar2; undefined4 extraout_r1_00; - FUN_10002f5c(); + stdio_init_all(); uVar1 = DAT_1000024c; uVar2 = extraout_r1; do { - FUN_100030ec(DAT_10000250,uVar2,0,uVar1); + printf(DAT_10000250,uVar2,0,uVar1); uVar2 = extraout_r1_00; } while( true ); } @@ -472,7 +438,7 @@ Now let's check it. IEEE 754 uses a simple rule for the sign bit: ``` r3 = 0x40454000 = 0100 0000 0100 0101 0100 0000 0000 0000 ^ - r3 bit 31 = 0 -> sign = 0 -> Positive number + r3 bit 31 = 0 -> sign = 0 -> Positive number ``` The topmost bit of r3 is `0`, so the number is **positive**. If that bit were `1` instead (e.g. `0xC0454000`), the number would be negative (`-42.5`). @@ -507,35 +473,35 @@ This means the number is scaled by $2^5 = 32$. In other words, the mantissa gets - **High 20 bits of mantissa** (bits 51-32) = bits 19-0 of r3: ``` -r3 bits 19-0: 0 1 0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +r3 bits 19-0: 0 1 0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ``` - **Low 32 bits of mantissa** (bits 31-0) = all of r2: ``` -r2 = 0x00000000 -> 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +r2 = 0x00000000 -> 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ``` Full 52-bit mantissa: ``` 0 1 0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 - ?? top 20 bits from r3 -> ?? bottom 32 bits from r2 (all zero) -> + <- top 20 bits from r3 -> <- bottom 32 bits from r2 (all zero) -> ``` IEEE 754 always prepends an **implied leading `1`**, so the actual value represented is: ``` -1.010101 00000... (the 1. is implicit, not stored) +1.010101 00000... (the 1. is implicit, not stored) ``` **4. Reconstruct the value** -$$1.010101_2 \times 2^5$$ +$$1.010101\text{ (base 2)} \times 2^5$$ Shift the binary point 5 places right: -$$101010.1_2$$ +$$101010.1\text{ (base 2)}$$ Now convert each bit position to decimal: @@ -547,9 +513,9 @@ Now convert each bit position to decimal: | `0` (bit 2) | $2^2$ | 0 | | `1` (bit 1) | $2^1$ | 2 | | `0` (bit 0) | $2^0$ | 0 | -| `1` (bit ?1) | $2^{-1}$ | 0.5 | +| `1` (bit -1) | $2^{-1}$ | 0.5 | -$$32 + 8 + 2 + 0.5 = \mathbf{42.5} ?$$ +$$32 + 8 + 2 + 0.5 = \mathbf{42.5}$$ ### Step 16: Examine the Assembly @@ -559,49 +525,47 @@ Look at the **Listing** window (assembly view). Find the main function: ************************************************************* * FUNCTION ************************************************************* - undefined FUN_10000234 () - undefined - FUN_10000234+1 XREF[1,1]: 1000018c (c) , 1000018a (*) - FUN_10000234 - 10000234 38 b5 push {r3,r4,r5,lr} - 10000236 02 f0 91 fe bl FUN_10002f5c undefined FUN_10002f5c() - 1000023a 00 24 movs r4,#0x0 - 1000023c 03 4d ldr r5,[DAT_1000024c ] = 40454000h + int __stdcall main (void ) + int r0:4 + main+1 XREF[1,1]: 1000018c (c) , 1000018a (*) + main + 10000234 38 b5 push {r3,r4,r5,lr} + 10000236 02 f0 91 fe bl stdio_init_all bool stdio_init_all(void) + 1000023a 00 24 movs r4,#0x0 + 1000023c 03 4d ldr r5,[DAT_1000024c ] = 40454000h LAB_1000023e XREF[1]: 10000248 (j) - 1000023e 22 46 mov r2,r4 - 10000240 2b 46 mov r3,r5 - 10000242 03 48 ldr r0=>s_fav_num:_%f_100034a8 ,[DAT_10000250 ] = "fav_num: %f\r\n" + 1000023e 22 46 mov r2,r4 + 10000240 2b 46 mov r3,r5 + 10000242 03 48 ldr r0=>s_fav_num:_%f_100034a8 ,[DAT_10000250 ] = "fav_num: %f\r\n" = 100034A8h - 10000244 02 f0 52 ff bl FUN_100030ec undefined FUN_100030ec() - 10000248 f9 e7 b LAB_1000023e + 10000244 02 f0 52 ff bl printf int printf(char * format, ...) + 10000248 f9 e7 b LAB_1000023e 1000024a 00 ?? 00h 1000024b bf ?? BFh - DAT_1000024c XREF[1]: FUN_10000234:1000023c (R) - 1000024c 00 40 45 40 undefine 40454000h - DAT_10000250 XREF[1]: FUN_10000234:10000242 (R) - 10000250 a8 34 00 10 undefine 100034A8h ? -> 100034a8 - + DAT_1000024c XREF[1]: main:1000023c (R) + 1000024c 00 40 45 40 undefine 40454000h + DAT_10000250 XREF[1]: main:10000242 (R) + 10000250 a8 34 00 10 undefine 100034A8h * -> 100034a8 ``` -> ? **Key Insight:** The `mov.w r2, #0x0` loads the low 32 bits (all zeros) and `ldr r3, [DAT_...]` loads the high 32 bits (`0x40454000`) of the double. Together, `r2:r3` = `0x40454000_00000000` = `42.5` as a double. +> ๐Ÿ’ก **Key Insight:** The `mov.w r2, #0x0` loads the low 32 bits (all zeros) and `ldr r3, [DAT_...]` loads the high 32 bits (`0x40454000`) of the double. Together, `r2:r3` = `0x40454000_00000000` = `42.5` as a double. ### Step 17: Find the Format String In the Listing view, click on the data reference to find the format string: ``` - s_fav_num:_%f_100034a8 XREF[1]: FUN_10000234:10000242 (*) - 100034a8 66 61 76 ds "fav_num: %f\r\n" - 5f 6e 75 - 6d 3a 20 - + s_fav_num:_%f_100034a8 XREF[1]: main:10000242 (*) + 100034a8 66 61 76 ds "fav_num: %f\r\n" + 5f 6e 75 + 6d 3a 20 ``` This confirms `printf` is called with the format string `"fav_num: %f\r\n"` and the double-precision value of `42.5`. --- -## ? Part 2.8: Patching the Float - Changing 42.5 to 99.0 +## โœ๏ธ Part 2.8: Patching the Float - Changing 42.5 to 99.0 ### Step 18: Calculate the New IEEE 754 Encoding @@ -611,15 +575,15 @@ We want to change `42.5` to `99.0`. First, we need to figure out the double-prec | Division | Quotient | Remainder | |---------------|----------|-----------| -| 99 ? 2 | 49 | **1** | -| 49 ? 2 | 24 | **1** | -| 24 ? 2 | 12 | **0** | -| 12 ? 2 | 6 | **0** | -| 6 ? 2 | 3 | **0** | -| 3 ? 2 | 1 | **1** | -| 1 ? 2 | 0 | **1** | +| 99 รท 2 | 49 | **1** | +| 49 รท 2 | 24 | **1** | +| 24 รท 2 | 12 | **0** | +| 12 รท 2 | 6 | **0** | +| 6 รท 2 | 3 | **0** | +| 3 รท 2 | 1 | **1** | +| 1 รท 2 | 0 | **1** | -Read remainders bottom-to-top: $99_{10} = 1100011_2$ +Read remainders bottom-to-top: 99 (base 10) = 1100011 (base 2) **Step B - Convert the fractional part (.0) to binary:** @@ -627,18 +591,18 @@ There is no fractional part - `.0` is exactly zero, so the fractional binary is **Step C - Combine:** -$$99.0_{10} = 1100011.0_2$$ +$$99.0\text{ (base 10)} = 1100011.0\text{ (base 2)}$$ **Step D - Normalize to IEEE 754 form** (move the binary point so there's exactly one `1` before it): -$$1100011.0_2 = 1.100011_2 \times 2^6$$ +$$1100011.0\text{ (base 2)} = 1.100011\text{ (base 2)} \times 2^6$$ We shifted the binary point 6 places left, so the exponent is **6**. **Step E - Extract the IEEE 754 fields:** 1. **Sign:** `0` (positive) -2. **Exponent:** $6 + 1023 = 1029 = 10000000101_2$ +2. **Exponent:** $6 + 1023 = 1029 = 10000000101\text{ (base 2)}$ 3. **Mantissa:** `1000110000000000...` (everything after the `1.`, padded with zeros to 52 bits) 4. **Full double:** `0x4058C00000000000` @@ -654,7 +618,7 @@ Since `r2` stays `0x00000000`, we only need to patch the high word loaded into ` Look in the Listing view for the data that loads the high word of the double: ``` - 10000248 00 40 45 40 undefined4 40454000h + 1000024c 00 40 45 40 undefined4 40454000h ``` This is the 32-bit constant that gets loaded into `r3` - the high word of our double `42.5`. @@ -662,16 +626,15 @@ This is the 32-bit constant that gets loaded into `r3` - the high word of our do ### Step 20: Patch the Constant 1. Click on Window -> Bytes -2. Click on Pencil Icon in Bytes Editor -2. Right-click and select **Patch Data** -3. Change `00404540` to `00C05840` +2. Click on the Pencil icon to enable byte editing +3. At address `1000024c`, overwrite `00 40 45 40` with `00 C0 58 40` (little-endian for `0x40454000 -> 0x4058C000`) 4. Press Enter This changes the high word from `0x40454000` (42.5 as double) to `0x4058C000` (99.0 as double). --- -## ? Part 2.9: Export and Test the Hacked Binary +## ๐Ÿš€ Part 2.9: Export and Test the Hacked Binary ### Step 21: Export the Patched Binary @@ -686,7 +649,7 @@ This changes the high word from `0x40454000` (42.5 as double) to `0x4058C000` (9 **Open a terminal and navigate to your project directory:** ```powershell -cd C:\Users\assem.KEVINTHOMAS\OneDrive\Documents\Embedded-Hacking\0x000e_floating-point-data-type +cd C:\Users\flare-vm\Desktop\Embedded-Hacking-main\0x000e_floating-point-data-type ``` **Run the conversion command:** @@ -710,7 +673,7 @@ fav_num: 99.000000 ... ``` -? **BOOM! We hacked the float!** The value changed from `42.5` to `99.0`! +๐ŸŽ‰ **BOOM! We hacked the float!** The value changed from `42.5` to `99.0`! --- @@ -748,7 +711,7 @@ A **double** (short for "double-precision floating-point") is like a `float` but | **Precision** | ~7 decimal digits | ~15 decimal digits | | **Exponent** | 8 bits (bias 127) | 11 bits (bias 1023) | | **Mantissa** | 23 bits | 52 bits | -| **Range** | ?3.4 * 10++ | ?1.8 * 10+++? | +| **Range** | ยฑ3.4 ร— 10^38 | ยฑ1.8 ร— 10^308 | | **printf** | `%f` | `%lf` | | **ARM passing** | Promoted to double | Native in `r2:r3` | @@ -806,7 +769,7 @@ The program is printing `42.525250` because `printf` with `%lf` defaults to 6 de --- -## ? Part 3.5: Setting Up Ghidra for Double Analysis +## ๐Ÿ”ง Part 3.5: Setting Up Ghidra for Double Analysis ### Step 3: Start Ghidra @@ -859,7 +822,7 @@ Wait for analysis to complete (watch the progress bar in the bottom right). --- -## ? Part 3.6: Navigating and Resolving Functions +## ๐Ÿ” Part 3.6: Navigating and Resolving Functions ### Step 8: Find the Functions @@ -893,7 +856,7 @@ For `main`, let's also fix the return type: --- -## ? Part 3.7: Analyzing the Main Function +## ๐Ÿ”ฌ Part 3.7: Analyzing the Main Function ### Step 11: Examine Main in Ghidra @@ -901,48 +864,9 @@ Click on `main` (or `FUN_10000234`). Look at the **Decompile** window: You'll see something like: -```c -void FUN_10000238(void) -{ - undefined4 uVar1; - undefined4 uVar2; - undefined4 extraout_r1; - undefined4 uVar3; - undefined4 extraout_r1_00; - undefined4 in_r3; - - uVar2 = DAT_10000258; - uVar1 = DAT_10000254; - FUN_10002f64(); - uVar3 = extraout_r1; - do { - FUN_100030f4(DAT_10000250,uVar3,uVar1,uVar2,in_r3); - uVar3 = extraout_r1_00; - } while( true ); -} -``` - -### Step 12: Resolve stdio_init_all - -1. Click on `FUN_10002f64` -2. Right-click -> **Edit Function Signature** -3. Change to: `bool stdio_init_all(void)` -4. Click **OK** - -### Step 13: Resolve printf - -1. Click on `FUN_100030f4` -2. Right-click -> **Edit Function Signature** -3. Change the name to `printf` -4. Check the **Varargs** checkbox (printf takes variable arguments!) -5. Click **OK** - -### Step 14: Understand the Double Encoding - -Look at the decompiled code after resolving functions: - ```c int main(void) + { undefined4 uVar1; undefined4 uVar2; @@ -961,6 +885,46 @@ int main(void) } ``` +### Step 12: Resolve stdio_init_all + +1. Click on `FUN_10002f64` +2. Right-click -> **Edit Function Signature** +3. Change to: `bool stdio_init_all(void)` +4. Click **OK** + +### Step 13: Resolve printf + +1. Click on `FUN_100030f4` +2. Right-click -> **Edit Function Signature** +3. Change to: `int printf(char *format,...)` +4. Check the **Varargs** checkbox (printf takes variable arguments!) +5. Click **OK** + +### Step 14: Understand the Double Encoding + +Look at the decompiled code after resolving functions: + +```c +int main(void) + +{ + undefined4 uVar1; + undefined4 uVar2; + undefined4 extraout_r1; + undefined4 uVar3; + undefined4 extraout_r1_00; + + uVar2 = DAT_10000258; + uVar1 = DAT_10000254; + stdio_init_all(); + uVar3 = extraout_r1; + do { + printf(DAT_10000250,uVar3,uVar1,uVar2); + uVar3 = extraout_r1_00; + } while( true ); +} +``` + **Where's `double fav_num = 42.52525`?** It's been optimized into immediate values! This time we see **two** non-zero values: `0x645a1cac` and `0x4045433b`. Unlike the float example where the low word was `0x0`, a double with a fractional part like `42.52525` needs **all 52 mantissa bits** - so both halves carry data. @@ -974,7 +938,7 @@ A 64-bit double is passed in two 32-bit registers: Together they form `0x4045433B645A1CAC` - the IEEE 754 **double-precision** encoding of `42.52525`. -> ? **Key Difference from Float:** In the float example, `r2` was `0x00000000` because `42.5` has a clean fractional part. But `42.52525` has a repeating binary fraction, so the low 32 bits are non-zero (`0x645A1CAC`). This means **both** registers matter when patching doubles with complex fractional values! +> ๐Ÿ’ก **Key Difference from Float:** In the float example, `r2` was `0x00000000` because `42.5` has a clean fractional part. But `42.52525` has a repeating binary fraction, so the low 32 bits are non-zero (`0x645A1CAC`). This means **both** registers matter when patching doubles with complex fractional values! ### Step 15: Verify the Double Encoding @@ -992,12 +956,10 @@ Bit: 63 62-52 (11 bits) 51-32 (20 bits) 3 +---+-----------------------+------------------------------------------+------------------------------------------+ | 0 | 1 0 0 0 0 0 0 0 1 0 0 | 0 1 0 1 0 1 0 0 0 0 1 1 0 0 1 1 1 0 1 1 | 01100100010110100001110010101100 | +---+-----------------------+------------------------------------------+------------------------------------------+ - Sign Exponent (11) Mantissa high 20 bits Mantissa low 32 bits - (from r3 bits 19-0) (from r2) + Sign Exponent (11) Mantissa high 20 bits Mantissa low 32 bits + (from r3 bits 19-0) (from r2) ``` -> ? **Key Difference from 42.5:** In the `42.5` example, r2 was `0x00000000` because `42.5` has a clean fractional part (`.5` = exactly one binary digit). But `42.52525` has a repeating binary fraction, so the low 32 bits are **non-zero** (`0x645A1CAC`). Every bit of both registers matters here! - **Step-by-step field extraction:** **1. Sign bit** @@ -1007,7 +969,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** @@ -1042,29 +1004,29 @@ r3 bits 19-0: 0 1 0 1 0 1 0 0 0 0 1 1 0 0 1 1 1 0 1 1 - **Low 32 bits of mantissa** (bits 31-0) = all of r2: ``` -r2 = 0x645A1CAC -> 0 1 1 0 0 1 0 0 0 1 0 1 1 0 1 0 0 0 0 1 1 1 0 0 1 0 1 0 1 1 0 0 +r2 = 0x645A1CAC -> 0 1 1 0 0 1 0 0 0 1 0 1 1 0 1 0 0 0 0 1 1 1 0 0 1 0 1 0 1 1 0 0 ``` Full 52-bit mantissa: ``` 0 1 0 1 0 1 0 0 0 0 1 1 0 0 1 1 1 0 1 1 | 0 1 1 0 0 1 0 0 0 1 0 1 1 0 1 0 0 0 0 1 1 1 0 0 1 0 1 0 1 1 0 0 - ?? top 20 bits from r3 -> ?? bottom 32 bits from r2 -> + <- top 20 bits from r3 -> <- bottom 32 bits from r2 -> ``` IEEE 754 always prepends an **implied leading `1`**, so the actual value represented is: ``` -1.0101010000110011101101100100010110100001110010101100 (the 1. is implicit, not stored) +1.0101010000110011101101100100010110100001110010101100 (the 1. is implicit, not stored) ``` **4. Reconstruct the value** -$$1.0101010000110011101101100100..._2 \times 2^5$$ +$$1.0101010000110011101101100100...\text{ (base 2)} \times 2^5$$ Shift the binary point 5 places right: -$$101010.10000110011101101100100010110100001110010101100_2$$ +$$101010.10000110011101101100100010110100001110010101100\text{ (base 2)}$$ **Integer part** (`101010`): @@ -1083,25 +1045,25 @@ $$32 + 8 + 2 = \mathbf{42}$$ | Bit position | Power of 2 | Decimal value | |---|---|---| -| `1` (bit ?1) | $2^{-1}$ | 0.5 | -| `0` (bit ?2) | $2^{-2}$ | 0 | -| `0` (bit ?3) | $2^{-3}$ | 0 | -| `0` (bit ?4) | $2^{-4}$ | 0 | -| `0` (bit ?5) | $2^{-5}$ | 0 | -| `1` (bit ?6) | $2^{-6}$ | 0.015625 | -| `1` (bit ?7) | $2^{-7}$ | 0.0078125 | -| `0` (bit ?8) | $2^{-8}$ | 0 | -| `0` (bit ?9) | $2^{-9}$ | 0 | -| `1` (bit ?10) | $2^{-10}$ | 0.0009765625 | -| `1` (bit ?11) | $2^{-11}$ | 0.00048828125 | -| `1` (bit ?12) | $2^{-12}$ | 0.000244140625 | +| `1` (bit -1) | $2^{-1}$ | 0.5 | +| `0` (bit -2) | $2^{-2}$ | 0 | +| `0` (bit -3) | $2^{-3}$ | 0 | +| `0` (bit -4) | $2^{-4}$ | 0 | +| `0` (bit -5) | $2^{-5}$ | 0 | +| `1` (bit -6) | $2^{-6}$ | 0.015625 | +| `1` (bit -7) | $2^{-7}$ | 0.0078125 | +| `0` (bit -8) | $2^{-8}$ | 0 | +| `0` (bit -9) | $2^{-9}$ | 0 | +| `1` (bit -10) | $2^{-10}$ | 0.0009765625 | +| `1` (bit -11) | $2^{-11}$ | 0.00048828125 | +| `1` (bit -12) | $2^{-12}$ | 0.000244140625 | | ... | ... | *(remaining 35 bits add smaller and smaller fractions)* | First 12 fractional bits sum: $0.5 + 0.015625 + 0.0078125 + 0.0009765625 + 0.00048828125 + 0.000244140625 \approx 0.5251$ The remaining 35 fractional bits refine this to $\approx 0.52525$. This is because `0.52525` is a **repeating fraction** in binary - it can never be represented with a finite number of bits, so double precision stores the closest possible 52-bit approximation. -$$42 + 0.52525 = \mathbf{42.52525} ?$$ +$$42 + 0.52525 = \mathbf{42.52525} \checkmark$$ ### Step 16: Examine the Assembly @@ -1111,58 +1073,57 @@ Look at the **Listing** window (assembly view). Find the main function: ************************************************************* * FUNCTION ************************************************************* - undefined FUN_10000238 () - undefined - FUN_10000238+1 XREF[1,1]: 1000018c (c) , 1000018a (*) - FUN_10000238 - 10000238 38 b5 push {r3,r4,r5,lr} - 1000023a 06 a5 adr r5,[0x10000254 ] - 1000023c d5 e9 00 45 ldrd r4,r5,[r5,#0x0 ]=>DAT_10000254 = 645A1CACh + int __stdcall main (void ) + int r0:4 + main+1 XREF[1,1]: 1000018c (c) , 1000018a (*) + main + 10000238 38 b5 push {r3,r4,r5,lr} + 1000023a 06 a5 adr r5,[0x10000254 ] + 1000023c d5 e9 00 45 ldrd r4,r5,[r5,#0x0 ]=>DAT_10000254 = 645A1CACh = 4045433Bh - 10000240 02 f0 90 fe bl FUN_10002f64 undefined FUN_10002f64() + 10000240 02 f0 90 fe bl stdio_init_all bool stdio_init_all(void) LAB_10000244 XREF[1]: 1000024e (j) - 10000244 22 46 mov r2,r4 - 10000246 2b 46 mov r3,r5 - 10000248 01 48 ldr r0=>s_fav_num:_%lf_100034b0 ,[DAT_10000250 ] = "fav_num: %lf\r\n" + 10000244 22 46 mov r2,r4 + 10000246 2b 46 mov r3,r5 + 10000248 01 48 ldr r0=>s_fav_num:_%lf_100034b0 ,[DAT_10000250 ] = "fav_num: %lf\r\n" = 100034B0h - 1000024a 02 f0 53 ff bl FUN_100030f4 undefined FUN_100030f4() - 1000024e f9 e7 b LAB_10000244 - DAT_10000250 XREF[1]: FUN_10000238:10000248 (R) - 10000250 b0 34 00 10 undefine 100034B0h ? -> 100034b0 - DAT_10000254 XREF[1]: FUN_10000238:1000023c (R) - 10000254 ac 1c 5a 64 undefine 645A1CACh - DAT_10000258 XREF[1]: FUN_10000238:1000023c (R) - 10000258 3b 43 45 40 undefine 4045433Bh + 1000024a 02 f0 53 ff bl printf int printf(char * format, ...) + 1000024e f9 e7 b LAB_10000244 + DAT_10000250 XREF[1]: main:10000248 (R) + 10000250 b0 34 00 10 undefine 100034B0h ? -> 100034b0 + DAT_10000254 XREF[1]: main:1000023c (R) + 10000254 ac 1c 5a 64 undefine 645A1CACh + DAT_10000258 XREF[1]: main:1000023c (R) + 10000258 3b 43 45 40 undefine 4045433Bh ``` -> ? **Key Insight:** Notice that **both** `r2` and `r3` are loaded from data constants using `ldr`. Compare this to the float example where `r2` was loaded with `mov.w r2, #0x0`. Because `42.52525` requires all 52 mantissa bits, neither word can be zero - the compiler must store both halves as separate data constants. +> ๐Ÿ’ก **Key Insight:** Notice that **both** `r2` and `r3` are loaded from data constants using `ldr`. Compare this to the float example where `r2` was loaded with `mov.w r2, #0x0`. Because `42.52525` requires all 52 mantissa bits, neither word can be zero - the compiler must store both halves as separate data constants. ### Step 17: Find the Format String In the Listing view, click on the data reference to find the format string: ``` - s_fav_num:_%lf_100034b0 XREF[1]: FUN_10000238:10000248 (*) - 100034b0 66 61 76 ds "fav_num: %lf\r\n" - 5f 6e 75 - 6d 3a 20 - + s_fav_num:_%lf_100034b0 XREF[1]: main:10000248 (*) + 100034b0 66 61 76 ds "fav_num: %lf\r\n" + 5f 6e 75 + 6d 3a 20 ``` This confirms `printf` is called with the format string `"fav_num: %lf\r\n"` and the double-precision value of `42.52525`. --- -## ? Part 3.8: Patching the Double - Changing 42.52525 to 99.99 +## โœ๏ธ Part 3.8: Patching the Double - Changing 42.52525 to 99.99 ### Step 18: Calculate the New IEEE 754 Encoding We want to change `42.52525` to `99.99`. First, we need to figure out the double-precision encoding of `99.99`: -1. $99.99 = 1.5623... \times 2^6 = 1.100011111111..._2 \times 2^6$ +1. $99.99 = 1.5623... \times 2^6 = 1.100011111111...\text{ (base 2)} \times 2^6$ 2. **Sign:** `0` (positive) -3. **Exponent:** $6 + 1023 = 1029 = 10000000101_2$ -4. **Mantissa:** `1000111111010111000010100011110101110000101000111..._2$ +3. **Exponent:** $6 + 1023 = 1029 = 10000000101\text{ (base 2)}$ +4. **Mantissa:** `1000111111010111000010100011110101110000101000111... (base 2)` 5. **Full double:** `0x4058FF5C28F5C28F` | Register | Old Value | New Value | @@ -1178,35 +1139,35 @@ Look in the Listing view for the two data constants: **Low word (loaded into `r2`):** ``` - 10000254 ac 1c 5a 64 undefined4 645A1CACh + 10000254 ac 1c 5a 64 undefined4 645A1CACh ``` **High word (loaded into `r3`):** ``` - 10000258 3b 43 45 40 undefined4 4045433Bh + 10000258 3b 43 45 40 undefined4 4045433Bh ``` ### Step 20: Patch Both Constants **Patch the low word:** 1. Click on the data at address `10000254` containing `645A1CAC` -2. Right-click and select **Patch Data** -3. Change `645A1CAC` to `28F5C28F` -> `8FC2F528` +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. Right-click and select **Patch Data** -3. Change `4045433B` to `4058FF5C` -> `5CFF5840` +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`) 4. Press Enter This changes the full 64-bit double from `0x4045433B645A1CAC` (42.52525) to `0x4058FF5C28F5C28F` (99.99). -> ? **Key Difference from Float Patching:** When we patched the float `42.5`, we only needed to change one word (the high word in `r3`) because the low word was all zeros. With `42.52525 -> 99.99`, **both** words change. Always check whether the low word is non-zero before patching! +> ๐Ÿ’ก **Key Difference from Float Patching:** When we patched the float `42.5`, we only needed to change one word (the high word in `r3`) because the low word was all zeros. With `42.52525 -> 99.99`, **both** words change. Always check whether the low word is non-zero before patching! --- -## ? Part 3.9: Export and Test the Hacked Binary +## ๐Ÿš€ Part 3.9: Export and Test the Hacked Binary ### Step 21: Export the Patched Binary @@ -1221,7 +1182,7 @@ This changes the full 64-bit double from `0x4045433B645A1CAC` (42.52525) to `0x4 **Open a terminal and navigate to your project directory:** ```powershell -cd C:\Users\assem.KEVINTHOMAS\OneDrive\Documents\Embedded-Hacking\0x0011_double-floating-point-data-type +cd C:\Users\flare-vm\Desktop\Embedded-Hacking-main\0x0011_double-floating-point-data-type ``` **Run the conversion command:** @@ -1245,11 +1206,11 @@ fav_num: 99.990000 ... ``` -? **BOOM! We hacked the double!** The value changed from `42.52525` to `99.99`! +๐ŸŽ‰ **BOOM! We hacked the double!** The value changed from `42.52525` to `99.99`! --- -## ? Part 3.95: Summary - Float and Double Analysis +## ๐Ÿ“Š Part 3.95: Summary - Float and Double Analysis ### What We Accomplished @@ -1293,7 +1254,7 @@ fav_num: 99.990000 | - Split into high/low words | +-----------------------------------------------------------------+ | 5. Patch the constant(s) in Ghidra | -| - Right-click -> Patch Data | +| - Edit bytes in the Bytes window (Pencil mode) | | - Replace the old encoding with the new one | +-----------------------------------------------------------------+ | 6. Export -> Convert to UF2 -> Flash -> Verify | @@ -1307,7 +1268,7 @@ fav_num: 99.990000 --- -## ? Key Takeaways +## ๐Ÿ’ก Key Takeaways 1. **Integers have fixed sizes** - `uint8_t` is 1 byte (0-255), `int8_t` is 1 byte (-128 to 127). The `u` prefix means unsigned. @@ -1325,7 +1286,7 @@ fav_num: 99.990000 --- -## ? Glossary +## ๐Ÿ“– Glossary | Term | Definition | | ----------------------- | ------------------------------------------------------------------------------ | @@ -1349,7 +1310,7 @@ fav_num: 99.990000 --- -## ? Additional Resources +## ๐Ÿ“š Additional Resources ### GPIO Coprocessor Reference @@ -1388,6 +1349,4 @@ The RP2350 GPIO coprocessor instructions: **Remember:** Every binary you encounter in the real world can be analyzed and understood using these same techniques. Whether it's an integer, a float, or a double - it's all just bits waiting to be decoded. Practice makes perfect! -Happy hacking! ? - - +Happy hacking! ๐ŸŽ‰ diff --git a/WEEK05/slides/WEEK05-IMG00.svg b/WEEK05/slides/WEEK05-IMG00.svg new file mode 100644 index 0000000..77db88a --- /dev/null +++ b/WEEK05/slides/WEEK05-IMG00.svg @@ -0,0 +1,79 @@ + + + + + + + + + + + + + + + + + + + + + + + 4F 70 65 6E 4F 43 44 + 10 00 02 34 08 B5 01 + 47 44 42 20 52 45 56 + 20 08 20 00 FF AA 00 + 52 50 32 33 35 30 00 + 0A 0A 0F 12 12 1A 1A + 41 52 4D 76 38 2D 4D + 00 FF 41 00 D4 FF 88 + 47 48 49 44 52 41 00 + FF 00 40 C0 C0 C0 00 + + + + + + + + + + + + +Embedded Systems +Reverse Engineering + + + + + +// WEEK 05 + + +Integers and Floats in Embedded Systems: +Debugging and Hacking Integers and Floats +w/ Intermediate GPIO Output Analysis + + + + + +George Mason University + + + +RP2350 // ARM Cortex-M33 + diff --git a/WEEK05/slides/WEEK05-IMG01.svg b/WEEK05/slides/WEEK05-IMG01.svg new file mode 100644 index 0000000..1659bfa --- /dev/null +++ b/WEEK05/slides/WEEK05-IMG01.svg @@ -0,0 +1,77 @@ + + + + + +Integer Data Types +Fixed-Size Types for Embedded Systems + + + +uint8_t +Unsigned 8-bit +1 byte +Range: +0 to 255 +Ages, counts, always positive + + + +int8_t +Signed 8-bit +1 byte +Range: +-128 to 127 +Temperature, can be negative + + + +uint16_t +Unsigned 16-bit +2 bytes +Range: +0 to 65,535 +Sensor readings, medium values + + + +uint32_t +Unsigned 32-bit +4 bytes +Range: +0 to ~4 billion +Addresses, timestamps + + + +Code Example + +uint8_t age = 43; +// unsigned, 0-255 +int8_t range = -42; +// signed, -128 to 127 + + + +Key Insight +The +u +prefix means +unsigned +(no negatives) +Without +u += signed (allows negatives) +Choose the smallest type that fits your data + \ No newline at end of file diff --git a/WEEK05/slides/WEEK05-IMG02.svg b/WEEK05/slides/WEEK05-IMG02.svg new file mode 100644 index 0000000..229f5e9 --- /dev/null +++ b/WEEK05/slides/WEEK05-IMG02.svg @@ -0,0 +1,79 @@ + + + + + +Two's Complement +How Negative Numbers are Stored + + + +Encoding -42 as int8_t + + +Step 1: Start +42 = 0x2A + + +Step 2: Flip +~0x2A = 0xD5 + + +Step 3: Add 1 +0xD5+1 = 0xD6 + +Binary: +00101010 +-> +11010101 +-> +11010110 + +Result: -42 stored as 0xD6 in memory +Top bit = 1 means negative + + + +Signed vs Unsigned: Same Bits! + +Hex +Binary +uint8_t +int8_t + + + +0x2A +00101010 +42 +42 + +0xD6 +11010110 +214 +-42 + +Same byte 0xD6 = 214 unsigned, -42 signed + + + +GDB Verification + + +(gdb) +x/1xb &range +0x200003e7: +0xd6 +// -42 in memory + \ No newline at end of file diff --git a/WEEK05/slides/WEEK05-IMG03.svg b/WEEK05/slides/WEEK05-IMG03.svg new file mode 100644 index 0000000..497a13d --- /dev/null +++ b/WEEK05/slides/WEEK05-IMG03.svg @@ -0,0 +1,75 @@ + + + + + +Inline Assembly GPIO +Direct Hardware Control via ASM + + + +GPIO Init Loop (pins 16-19) + + +1. Config Pad +PADS_BANK0 +Clear OD+ISO, set IE +0x40038000 + + +2. Set Function +IO_BANK0 +FUNCSEL = 5 (SIO) +0x40028004 + + +3. Enable Out +GPIO Coprocessor +mcrr p0,#4,r4,r5,c4 +Output Enable + +Loop: r0 = 16 to 19 +Red, Green, Blue, Yellow LEDs +Each pin: pad config + function select + OE + + + +Blink Loop + + +mcrr p0,#4,r4,r5,c0 + +r4 = pin, r5 = value +c0 = output value register +r5=1 ON, r5=0 OFF + + + +Pin Cycling + + +pin++; +if (pin > 18) pin=16; + +Cycles: 16 -> 17 -> 18 -> 16 +Red -> Green -> Blue -> repeat + + + +Why Inline Assembly? +gpio_put(16,1) calls +mcrr +underneath +Inline ASM shows what the SDK does at hardware level + \ No newline at end of file diff --git a/WEEK05/slides/WEEK05-IMG04.svg b/WEEK05/slides/WEEK05-IMG04.svg new file mode 100644 index 0000000..ecfa467 --- /dev/null +++ b/WEEK05/slides/WEEK05-IMG04.svg @@ -0,0 +1,83 @@ + + + + + +IEEE 754 Float +32-bit Single Precision Encoding + + + +Float Bit Layout (32 bits) + + +S + + +Exponent (8) + + +Mantissa (23) + +1 bit +sign + +8 bits +bias=127 + +23 bits ++implicit 1 + + + +Decode Formula +Value = (-1)^sign ร— 2^(exp-127) ร— (1 + mantissa) +Sign determines +/- Exponent scales with bias 127 Mantissa adds precision +Special cases: exp=0 or 255 (denorm, inf, NaN) + + + +Decode Example: 42.5 + +Sign Bit: 0 +Positive number + +Exponent: 10000100 += 132 decimal + +Bias subtraction: 132 - 127 = 5 + +Mantissa: 01010100...0 += 1.010101 + +Combine: 1.010101 ร— 2^5 = 42.5 + +Hex: 0x422A0000 + +Binary: 01000010001010100000000000000000 + + + +32-bit Storage Comparison + +Integer: +Exact values +Range: -2.1B to +2.1B +No decimals + +Float: +Approximate values +Range: ยฑ10^38 +~7 sig digits + \ No newline at end of file diff --git a/WEEK05/slides/WEEK05-IMG05.svg b/WEEK05/slides/WEEK05-IMG05.svg new file mode 100644 index 0000000..90e591f --- /dev/null +++ b/WEEK05/slides/WEEK05-IMG05.svg @@ -0,0 +1,76 @@ + + + + + +Float in Ghidra +Analyzing 42.5 in the Binary + + + +Decompiled main() + + +int main(void) { +stdio_init_all(); +uVar1 = DAT_1000024c; +do { +printf(fmt,0,uVar1); +} while(true); + + + +Key Discovery + +printf with %f always +receives a +double +(64-bit) + +C promotes float to double +for variadic functions! + + +42.5 sent as double + + + +Register Pair r2:r3 + + +r2 (low): +0x00000000 + + +r3 (high): +0x40454000 + +Combined: 0x4045400000000000 += 42.5 + + + +Assembly View + + +1000023a +00 24 +movs r4, #0x0 +// r2 = 0 + +1000023c +03 4d +ldr r5,[DAT...] +// r3 = 0x40454000 + \ No newline at end of file diff --git a/WEEK05/slides/WEEK05-IMG06.svg b/WEEK05/slides/WEEK05-IMG06.svg new file mode 100644 index 0000000..3c82e9e --- /dev/null +++ b/WEEK05/slides/WEEK05-IMG06.svg @@ -0,0 +1,87 @@ + + + + + +Patching Float +Changing 42.5 to 99.0 in Ghidra + + + +Calculate 99.0 as Double + +99 decimal = +1100011 +binary + +Normalize: +1.100011 x 2^6 + +Sign: +0 +Exp: +6+1023 = 1029 + +Mantissa: +100011000...0 + +Full double: 0x4058C00000000000 + + + +Before (42.5) + + +r2: +0x00000000 + + +r3: +0x40454000 + +Output: fav_num: 42.500000 + + +After (99.0) + + +r2: +0x00000000 +same! + + +r3: +0x4058C000 +changed + +Output: fav_num: 99.000000 + + + +Patch in Ghidra + + +1. Window: Bytes +Open byte editor + + +2. Find 00404540 +High word of 42.5 + + +3. Patch 00C05840 +High word of 99.0 + +Only one word to patch (low word is 0) + \ No newline at end of file diff --git a/WEEK05/slides/WEEK05-IMG07.svg b/WEEK05/slides/WEEK05-IMG07.svg new file mode 100644 index 0000000..d67d52e --- /dev/null +++ b/WEEK05/slides/WEEK05-IMG07.svg @@ -0,0 +1,75 @@ + + + + + +Double Precision +IEEE 754 64-bit Floating Point + + + +64-Bit Layout + + +Sign +1 bit + + +Exponent +11 bits (bias 1023) + + +Mantissa (Fraction) +52 bits + +Formula: (-1)^S x 1.Mantissa x 2^(Exp-1023) + + + +Encoding 42.52525 + +Sign: +0 (positive) + +Exponent: +5 + 1023 = 1028 += 0x404 (hex) + +Mantissa: +0101010000110011... + +Full 64-bit hex: +0x4045433B645A1CAC + + + +Float (32-bit) + +Size: 4 bytes +Exp: 8 bits +Mantissa: 23 bits +Precision: ~7 digits +Bias: 127 +1 register (ARM) + + +Double (64-bit) + +Size: 8 bytes +Exp: 11 bits +Mantissa: 52 bits +Precision: ~15 digits +Bias: 1023 +2 registers (r2:r3) + \ No newline at end of file diff --git a/WEEK05/slides/WEEK05-IMG08.svg b/WEEK05/slides/WEEK05-IMG08.svg new file mode 100644 index 0000000..ad7749c --- /dev/null +++ b/WEEK05/slides/WEEK05-IMG08.svg @@ -0,0 +1,71 @@ + + + + + +Double in Ghidra +Analyzing 42.52525 in memory + + + +Decompiled main() + + +int main(void) { +double fav_num + = 42.52525; +stdio_init_all(); +} + + + +Key Difference + +Float (42.5): +r2 = 0x00000000 (zero!) +r3 = 0x40454000 + +Double (42.52525): +r2 = 0x645A1CAC (non-zero!) + + + +Register Pair r2:r3 + + +r3 (HIGH): +0x4045433B + + +r2 (LOW): +0x645A1CAC + +Combined: 0x4045433B645A1CAC = 42.52525 + + + +Assembly (ldrd) + + +ldrd r2,r3,[PC,#0x10] +; Loads BOTH words at once +; r2 gets low word +; r3 gets high word + + +ldrd = Load +Register +Doubleword +ARM Cortex-M33 + \ No newline at end of file diff --git a/WEEK05/slides/WEEK05-IMG09.svg b/WEEK05/slides/WEEK05-IMG09.svg new file mode 100644 index 0000000..fcf359f --- /dev/null +++ b/WEEK05/slides/WEEK05-IMG09.svg @@ -0,0 +1,88 @@ + + + + + +Patching Double +Changing 42.52525 to 99.99 + + + +99.99 as IEEE 754 Double + +Sign: +0 +Exp: +6 + 1023 = 1029 + +Result: +0x4058FF5C28F5C28F + +r3 (HIGH) = 0x4058FF5C +r2 (LOW) = 0x28F5C28F + + + +Before (42.52525) + + +r3: +0x4045433B + + +r2: +0x645A1CAC + +printf: 42.525250 +Both words non-zero + + +After (99.99) + + +r3: +0x4058FF5C +changed + + +r2: +0x28F5C28F +changed + +printf: 99.990000 +BOTH words changed! + + + +Float Patch + +Words changed: +1 +r2 (low): +stays 0x0 +r3 (high): +patched +Easier to patch + + +Double Patch + +Words changed: +2 +r2 (low): +patched +r3 (high): +patched +Both words must change + \ No newline at end of file diff --git a/WEEK05/slides/WEEK05-IMG10.svg b/WEEK05/slides/WEEK05-IMG10.svg new file mode 100644 index 0000000..ce71556 --- /dev/null +++ b/WEEK05/slides/WEEK05-IMG10.svg @@ -0,0 +1,101 @@ + + + + + +IEEE 754 & Data Types +Data Types and IEEE 754 Reference + + + +IEEE 754 Hex Values + + +Value +Float (32b) +Double (64b) + + + + +42.0 +0x42280000 +0x4045000000000000 + + +42.5 +0x422A0000 +0x4045400000000000 + + +99.0 +0x42C60000 +0x4058C00000000000 + + +99.99 +0x42C7F5C3 +0x4058FF5C28F5C28F + + +3.14 +0x4048F5C3 +0x40091EB851EB851F + + +100.0 +0x42C80000 +0x4059000000000000 + +Tip: float low word often 0x0; double low word usually non-zero + + + +Patching Workflow + + +1. Identify +float / double + + +2. Check r2 +zero = float + + +3. Calculate +new hex value + + +4. Patch +in byte editor + + +5. Export +UF2 + test + + + +Integer Types + +uint8_t: 0-255 +int8_t: -128 to 127 +Two's complement for signed + + +Key Insight + +Float: patch 1 word +Double: patch 2 words +Check r2 to detect type + \ No newline at end of file diff --git a/WEEK06/WEEK06.md b/WEEK06/WEEK06.md index f8bc966..3ef04c8 100644 --- a/WEEK06/WEEK06.md +++ b/WEEK06/WEEK06.md @@ -1,6 +1,6 @@ -๏ปฟ?# Week 6: Static Variables in Embedded Systems: Debugging and Hacking Static Variables w/ GPIO Input Basics +# ๐Ÿ“˜ Week 6: Static Variables in Embedded Systems: Debugging and Hacking Static Variables w/ GPIO Input Basics -## ? What You'll Learn This Week +## ๐ŸŽฏ 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 @@ -312,7 +312,7 @@ Embedded-Hacking/ --- -## ? Part 5: Hands-On Tutorial - Static Variables and GPIO Input +## ๐Ÿ”ง Part 5: Hands-On Tutorial - Static Variables and GPIO Input ### Step 1: Review the Source Code @@ -422,7 +422,7 @@ This demonstrates unsigned integer overflow! --- -## ? Part 6: Debugging with GDB (Dynamic Analysis) +## ๐Ÿ› Part 6: Debugging with GDB (Dynamic Analysis) > ? **REVIEW:** This setup is identical to previous weeks. If you need a refresher on OpenOCD and GDB connection, refer back to Week 3 Part 6. @@ -613,7 +613,7 @@ TRY IT! --- -## ? Part 7: Understanding the Assembly +## ๐Ÿ”ฌ Part 7: Understanding the Assembly Now that we've explored the binary in GDB, let's make sense of the key patterns. @@ -720,7 +720,7 @@ This is an **unconditional branch** back to `0x10000264` (the `movs r1, #42` at --- -## ? Part 8: Hacking the Binary with a Hex Editor +## โœ๏ธ Part 8: Hacking the Binary with a Hex Editor Now for the fun part - we'll patch the `.bin` file directly using a hex editor! @@ -730,7 +730,7 @@ Now for the fun part - we'll patch the `.bin` file directly using a hex editor! 1. Open **HxD** (or your preferred hex editor: ImHex, 010 Editor, etc.) 2. Click **File** -> **Open** -3. Navigate to `C:\Users\assem.KEVINTHOMAS\OneDrive\Documents\Embedded-Hacking\0x0014_static-variables\build\` +3. Navigate to `C:\Users\flare-vm\Desktop\Embedded-Hacking-main\0x0014_static-variables\build\` 4. Open `0x0014_static-variables.bin` ### Step 18: Calculate the File Offset @@ -755,7 +755,7 @@ movs r1, #0x2a -> bytes: 2a 21 To change the value from 42 (`0x2a`) to 43 (`0x2b`): -1. In HxD, open `C:\Users\assem.KEVINTHOMAS\OneDrive\Documents\Embedded-Hacking\0x0014_static-variables\build\0x0014_static-variables.bin` +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 offset: `264` 4. You should see the byte `2A` at this position @@ -816,14 +816,14 @@ This is the **opposite** of the original behavior! --- -## ? Part 9: Converting and Flashing the Hacked Binary +## ๐Ÿš€ Part 9: Converting and Flashing the Hacked Binary ### Step 22: Convert to UF2 Format Open a terminal and navigate to your project directory: ```powershell -cd C:\Users\assem.KEVINTHOMAS\OneDrive\Documents\Embedded-Hacking\0x0014_static-variables +cd C:\Users\flare-vm\Desktop\Embedded-Hacking-main\0x0014_static-variables ``` Run the conversion command: @@ -859,13 +859,13 @@ static_fav_num: 43 - LED should now be **ON by default** (when button is NOT pressed) - LED should turn **OFF** when you press the button -? **BOOM! We successfully:** +๐ŸŽ‰ **BOOM! We successfully:** 1. Changed the printed value from 42 to 43 2. Inverted the LED/button logic --- -## ? Part 10: Summary and Review +## ๐Ÿ“Š Part 10: Summary and Review ### What We Accomplished @@ -945,7 +945,7 @@ static_fav_num: 43 --- -## ? Key Takeaways +## ๐Ÿ’ก Key Takeaways 1. **Static variables persist** - They keep their value between function calls and loop iterations. @@ -969,7 +969,7 @@ static_fav_num: 43 --- -## ? Glossary +## ๐Ÿ“– Glossary | Term | Definition | | --------------------- | ---------------------------------------------------------------- | @@ -992,7 +992,7 @@ static_fav_num: 43 --- -## ? Additional Resources +## ๐Ÿ“š Additional Resources ### GPIO Input Reference diff --git a/WEEK07/WEEK07.md b/WEEK07/WEEK07.md index 43dbbe8..9a10d28 100644 --- a/WEEK07/WEEK07.md +++ b/WEEK07/WEEK07.md @@ -1,6 +1,6 @@ -๏ปฟ?# Week 7: Constants in Embedded Systems: Debugging and Hacking Constants w/ 1602 LCD I2C Basics +# ๐Ÿ“˜ Week 7: Constants in Embedded Systems: Debugging and Hacking Constants w/ 1602 LCD I2C Basics -## ? What You'll Learn This Week +## ๐ŸŽฏ 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 @@ -385,7 +385,7 @@ Embedded-Hacking/ --- -## ? Part 7: Hands-On Tutorial - Constants and I2C LCD +## ๐Ÿ”ง Part 7: Hands-On Tutorial - Constants and I2C LCD ### Step 1: Review the Source Code @@ -463,7 +463,7 @@ OTHER_FAV_NUM: 1337 --- -## ? Part 8: Debugging with GDB (Dynamic Analysis) +## ๐Ÿ› Part 8: Debugging with GDB (Dynamic Analysis) > ? **REVIEW:** This setup is identical to previous weeks. If you need a refresher on OpenOCD and GDB connection, refer back to Week 3 Part 6. @@ -695,7 +695,7 @@ i r r0 r1 --- -## ? Part 9: Understanding the Assembly +## ๐Ÿ”ฌ Part 9: Understanding the Assembly Now that we've explored the binary in GDB, let's make sense of the key patterns we found. @@ -766,7 +766,7 @@ These are stored consecutively in the `.rodata` section. Note the addresses - we --- -## ? Part 10: Hacking the Binary with a Hex Editor +## โœ๏ธ Part 10: Hacking the Binary with a Hex Editor Now for the fun part - we'll patch the `.bin` file directly using a hex editor! @@ -776,7 +776,7 @@ Now for the fun part - we'll patch the `.bin` file directly using a hex editor! 1. Open **HxD** (or your preferred hex editor: ImHex, 010 Editor, etc.) 2. Click **File** -> **Open** -3. Navigate to `C:\Users\assem.KEVINTHOMAS\OneDrive\Documents\Embedded-Hacking\0x0017_constants\build\` +3. Navigate to `C:\Users\flare-vm\Desktop\Embedded-Hacking-main\0x0017_constants\build\` 4. Open `0x0017_constants.bin` ### Step 16: Calculate the File Offset @@ -870,14 +870,14 @@ From our GDB analysis in Step 10, we found the string at `0x10003ee8`. File offs --- -## ? Part 11: Converting and Flashing the Hacked Binary +## ๐Ÿš€ Part 11: Converting and Flashing the Hacked Binary ### Step 21: Convert to UF2 Format Open a terminal and navigate to your project directory: ```powershell -cd C:\Users\assem.KEVINTHOMAS\OneDrive\Documents\Embedded-Hacking\0x0017_constants +cd C:\Users\flare-vm\Desktop\Embedded-Hacking-main\0x0017_constants ``` Run the conversion command: @@ -909,11 +909,11 @@ OTHER_FAV_NUM: 1337 The numbers are unchanged - we only patched the LCD string! -? **BOOM! We successfully changed the LCD text from "Reverse" to "Exploit" without access to the source code!** +๐ŸŽ‰ **BOOM! We successfully changed the LCD text from "Reverse" to "Exploit" without access to the source code!** --- -## ? Part 12: Summary and Review +## ๐Ÿ“Š Part 12: Summary and Review ### What We Accomplished @@ -991,7 +991,7 @@ The numbers are unchanged - we only patched the LCD string! --- -## ? Key Takeaways +## ๐Ÿ’ก Key Takeaways 1. **#define is text replacement** - It happens before compilation, no memory used. @@ -1015,7 +1015,7 @@ The numbers are unchanged - we only patched the LCD string! --- -## ? Glossary +## ๐Ÿ“– Glossary | Term | Definition | | ----------------------- | --------------------------------------------------- | @@ -1036,7 +1036,7 @@ The numbers are unchanged - we only patched the LCD string! --- -## ? Additional Resources +## ๐Ÿ“š Additional Resources ### I2C Timing Reference diff --git a/WEEK09/WEEK09.md b/WEEK09/WEEK09.md index 9b32a2a..493c1ef 100644 --- a/WEEK09/WEEK09.md +++ b/WEEK09/WEEK09.md @@ -1,6 +1,6 @@ -๏ปฟ?# Week 9: Operators in Embedded Systems: Debugging and Hacking Operators w/ DHT11 Temperature & Humidity Sensor Single-Wire Protocol Basics. +# ๐Ÿ“˜ Week 9: Operators in Embedded Systems: Debugging and Hacking Operators w/ DHT11 Temperature & Humidity Sensor Single-Wire Protocol Basics. -## ? What You'll Learn This Week +## ๐ŸŽฏ 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) @@ -380,7 +380,7 @@ Embedded-Hacking/ --- -## ? Part 11: Hands-On Tutorial - The Operators Code +## ๐Ÿ”ง Part 11: Hands-On Tutorial - The Operators Code ### Step 1: Review the Source Code @@ -485,7 +485,7 @@ Humidity: 51.0%, Temperature: 23.8 deg C --- -## ? Part 12: Debugging with GDB +## ๐Ÿ› Part 12: Debugging with GDB ### Step 5: Start OpenOCD (Terminal 1) @@ -640,7 +640,7 @@ The program will loop, printing values to serial. --- -## ? Part 13: Setting Up Ghidra for Analysis +## ๐Ÿ”ง Part 13: Setting Up Ghidra for Analysis ### Step 17: Start Ghidra @@ -686,7 +686,7 @@ Wait for analysis to complete. --- -## ? Part 14: Finding the Reset_Handler +## ๐Ÿ” Part 14: Finding the Reset_Handler ### Step 22: Understand the Vector Table @@ -773,7 +773,7 @@ Look at the end of Reset_Handler for three function calls. The middle one is `ma --- -## ? Part 15: Resolving Functions in Ghidra +## ๐Ÿ” Part 15: Resolving Functions in Ghidra ### Step 28: Resolve stdio_init_all @@ -808,7 +808,7 @@ Look for repeated function calls with string addresses: 1. Find a call like the one at `0x10000262` 2. Right-click -> **Edit Function Signature** -3. Change to: `int printf(char *format, ...)` +3. Change to: `int printf(char *format,...)` 4. Check the **Varargs** checkbox 5. Click **OK** @@ -859,7 +859,7 @@ bl FUN_xxxxx ; puts --- -## ? Part 16: Understanding IEEE-754 Floating-Point +## ๐Ÿ”ฌ Part 16: Understanding IEEE-754 Floating-Point ### What is IEEE-754? @@ -927,7 +927,7 @@ print(f"Bytes: {encoded.hex()}") # 0000 80bf --- -## ? Part 17: Finding the Temperature Hack Point +## ๐Ÿ” Part 17: Finding the Temperature Hack Point ### Step 34: Locate the dht11_read Function @@ -972,7 +972,7 @@ Make note of these offsets in the binary file: --- -## ? Part 18: Manual Hacking in Ghidra +## โœ๏ธ Part 18: Manual Hacking in Ghidra ### Step 37: Open the Bytes Editor @@ -1011,7 +1011,7 @@ print(f"New: {new}") # 5.0 --- -## ? Part 19: Exporting and Testing +## ๐Ÿš€ Part 19: Exporting and Testing ### Step 41: Export the Patched Binary @@ -1026,7 +1026,7 @@ print(f"New: {new}") # 5.0 Open a terminal and run: ```powershell -cd C:\Users\assem.KEVINTHOMAS\OneDrive\Documents\Embedded-Hacking\0x001a_operators +cd C:\Users\flare-vm\Desktop\Embedded-Hacking-main\0x001a_operators python ..\uf2conv.py build\0x001a_operators-h.bin --base 0x10000000 --family 0xe48bff59 --output build\hacked.uf2 ``` @@ -1040,7 +1040,7 @@ You should see dramatically increased temperature readings! --- -## ? Part 20: Summary and Review +## ๐Ÿ“Š Part 20: Summary and Review ### What We Accomplished @@ -1084,7 +1084,7 @@ You should see dramatically increased temperature readings! --- -## ? Key Takeaways +## ๐Ÿ’ก Key Takeaways 1. **Post-increment returns the OLD value** - `x++` gives you x, THEN adds 1 @@ -1106,7 +1106,7 @@ You should see dramatically increased temperature readings! --- -## ? Glossary +## ๐Ÿ“– Glossary | Term | Definition | | ------------------ | --------------------------------------------------- | @@ -1131,7 +1131,7 @@ You should see dramatically increased temperature readings! --- -## ? Additional Resources +## ๐Ÿ“š Additional Resources ### IEEE-754 Float Quick Reference @@ -1158,7 +1158,7 @@ You should see dramatically increased temperature readings! --- -## ? Real-World Implications +## ๐ŸŒ Real-World Implications ### Why This Matters diff --git a/WEEK10/WEEK10.md b/WEEK10/WEEK10.md index b99456a..2ce552c 100644 --- a/WEEK10/WEEK10.md +++ b/WEEK10/WEEK10.md @@ -1,6 +1,6 @@ -๏ปฟ?# Week 10: Conditionals in Embedded Systems: Debugging and Hacking Static & Dynamic Conditionals w/ SG90 Servo Motor PWM Basics +# ๐Ÿ“˜ Week 10: Conditionals in Embedded Systems: Debugging and Hacking Static & Dynamic Conditionals w/ SG90 Servo Motor PWM Basics -## ? What You'll Learn This Week +## ๐ŸŽฏ 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 @@ -468,7 +468,7 @@ Embedded-Hacking/ --- -## ? Part 9: Hands-On Tutorial - Static Conditionals Code +## ๐Ÿ”ง Part 9: Hands-On Tutorial - Static Conditionals Code ### Step 1: Review the Source Code @@ -572,7 +572,7 @@ one --- -## ? Part 10: Debugging with GDB (Static Conditionals) +## ๐Ÿ› Part 10: Debugging with GDB (Static Conditionals) ### Step 5: Start OpenOCD (Terminal 1) @@ -704,7 +704,7 @@ quit --- -## ? Part 11: Setting Up Ghidra for Static Conditionals +## ๐Ÿ”ง Part 11: Setting Up Ghidra for Static Conditionals ### Step 17: Start Ghidra @@ -750,7 +750,7 @@ Wait for analysis to complete. --- -## ? Part 12: Resolving Functions in Ghidra (Static) +## ๐Ÿ” Part 12: Resolving Functions in Ghidra (Static) ### Step 22: Navigate to Main @@ -827,7 +827,7 @@ bl FUN_xxxxx ; sleep_ms --- -## ? Part 13: Hacking Static Conditionals +## โœ๏ธ Part 13: Hacking Static Conditionals ### Step 28: Open the Bytes Editor @@ -882,7 +882,7 @@ Find the sleep_ms delay value: Convert and flash: ```powershell -cd C:\Users\assem.KEVINTHOMAS\OneDrive\Documents\Embedded-Hacking\0x001d_static-conditionals +cd C:\Users\flare-vm\Desktop\Embedded-Hacking-main\0x001d_static-conditionals python ..\uf2conv.py build\0x001d_static-conditionals-h.bin --base 0x10000000 --family 0xe48bff59 --output build\hacked.uf2 ``` @@ -901,7 +901,7 @@ fun --- -## ? Part 14: Dynamic Conditionals - The Source Code +## ๐Ÿ“Œ Part 14: Dynamic Conditionals - The Source Code ### Step 34: Review the Dynamic Code @@ -972,7 +972,7 @@ int main(void) { --- -## ? Part 15: Debugging with GDB (Dynamic Conditionals) +## ๐Ÿ› Part 15: Debugging with GDB (Dynamic Conditionals) ### Step 37: Start OpenOCD (Terminal 1) @@ -1103,7 +1103,7 @@ quit --- -## ? Part 16: Setting Up Ghidra for Dynamic Conditionals +## ๐Ÿ”ง Part 16: Setting Up Ghidra for Dynamic Conditionals ### Step 49: Create New Project @@ -1159,7 +1159,7 @@ This confirms it's a UART initialization function! --- -## ? Part 17: Understanding Branch Instructions +## ๐Ÿ”ฌ Part 17: Understanding Branch Instructions ### ARM Branch Instructions @@ -1207,7 +1207,7 @@ skip_printf: --- -## ? Part 18: Advanced Hacking - Creating Stealth Commands +## โœ๏ธ Part 18: Advanced Hacking - Creating Stealth Commands ### The Goal @@ -1302,7 +1302,7 @@ Little-endian: 00 00 f0 41 2. Convert to UF2: ```powershell -cd C:\Users\assem.KEVINTHOMAS\OneDrive\Documents\Embedded-Hacking\0x0020_dynamic-conditionals +cd C:\Users\flare-vm\Desktop\Embedded-Hacking-main\0x0020_dynamic-conditionals python ..\uf2conv.py build\0x0020_dynamic-conditionals-h.bin --base 0x10000000 --family 0xe48bff59 --output build\hacked.uf2 ``` @@ -1314,7 +1314,7 @@ python ..\uf2conv.py build\0x0020_dynamic-conditionals-h.bin --base 0x10000000 - --- -## ? Part 19: Summary and Review +## ๐Ÿ“Š Part 19: Summary and Review ### What We Accomplished @@ -1380,7 +1380,7 @@ python ..\uf2conv.py build\0x0020_dynamic-conditionals-h.bin --base 0x10000000 - --- -## ? Key Takeaways +## ๐Ÿ’ก Key Takeaways 1. **Static conditionals have fixed outcomes** - The same path always executes @@ -1404,7 +1404,7 @@ python ..\uf2conv.py build\0x0020_dynamic-conditionals-h.bin --base 0x10000000 - --- -## ? Glossary +## ๐Ÿ“– Glossary | Term | Definition | | ----------------------- | --------------------------------------------------- | @@ -1422,7 +1422,7 @@ python ..\uf2conv.py build\0x0020_dynamic-conditionals-h.bin --base 0x10000000 - --- -## ? Additional Resources +## ๐Ÿ“š Additional Resources ### ASCII Reference Table @@ -1464,7 +1464,7 @@ python ..\uf2conv.py build\0x0020_dynamic-conditionals-h.bin --base 0x10000000 - --- -## ? Real-World Implications +## ๐ŸŒ Real-World Implications ### Why Stealth Commands Matter diff --git a/WEEK11/WEEK11.md b/WEEK11/WEEK11.md index dd5d933..b689382 100644 --- a/WEEK11/WEEK11.md +++ b/WEEK11/WEEK11.md @@ -1,6 +1,6 @@ -๏ปฟ?# Week 11: Structures and Functions in Embedded Systems: Debugging and Hacking w/ IR Remote Control and NEC Protocol Basics +# ๐Ÿ“˜ Week 11: Structures and Functions in Embedded Systems: Debugging and Hacking w/ IR Remote Control and NEC Protocol Basics -## ? What You'll Learn This Week +## ๐ŸŽฏ 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 @@ -476,7 +476,7 @@ Embedded-Hacking/ --- -## ? Part 9: Hands-On Tutorial - Structures Code +## ๐Ÿ”ง Part 9: Hands-On Tutorial - Structures Code ### Step 1: Review the Source Code @@ -588,7 +588,7 @@ int main(void) { --- -## ? Part 10: Debugging with GDB (Structures) +## ๐Ÿ› Part 10: Debugging with GDB (Structures) ### Step 5: Start OpenOCD (Terminal 1) @@ -724,7 +724,7 @@ quit --- -## ? Part 11: Setting Up Ghidra for Structures +## ๐Ÿ”ง Part 11: Setting Up Ghidra for Structures ### Step 17: Start Ghidra @@ -769,7 +769,7 @@ Wait for analysis to complete. --- -## ? Part 12: Resolving Functions - Structures Project +## ๐Ÿ” Part 12: Resolving Functions - Structures Project ### Step 22: Navigate to Main @@ -825,7 +825,7 @@ bl FUN_xxxxx ; ir_init Right after ir_init, look for the "IR receiver on GPIO" string being loaded: 1. Right-click -> **Edit Function Signature** -2. Change to: `int printf(char *format, ...)` +2. Change to: `int printf(char *format,...)` 3. Check the **Varargs** checkbox 4. Click **OK** @@ -858,7 +858,7 @@ bl FUN_xxxxx ; sleep_ms --- -## ? Part 13: Recognizing Struct Patterns in Assembly +## ๐Ÿ”ฌ Part 13: Recognizing Struct Patterns in Assembly ### Step 29: Identify GPIO Set Direction @@ -896,7 +896,7 @@ Create a mental (or written) map: --- -## ? Part 14: Hacking Structures +## โœ๏ธ Part 14: Hacking Structures ### Step 31: Open the Bytes Editor @@ -936,7 +936,7 @@ LED 2 (0x18) -> GPIO 16 -> Red LED (SWAPPED!) Convert and flash: ```powershell -cd C:\Users\assem.KEVINTHOMAS\OneDrive\Documents\Embedded-Hacking\0x0023_structures +cd C:\Users\flare-vm\Desktop\Embedded-Hacking-main\0x0023_structures python ..\uf2conv.py build\0x0023_structures-h.bin --base 0x10000000 --family 0xe48bff59 --output build\hacked.uf2 ``` @@ -952,7 +952,7 @@ python ..\uf2conv.py build\0x0023_structures-h.bin --base 0x10000000 --family 0x --- -## ? Part 15: Security Implications - Log Desynchronization +## โœ๏ธ Part 15: Security Implications - Log Desynchronization ### The Danger of Mismatched Logs @@ -990,7 +990,7 @@ Our LED example demonstrates the same principle: --- -## ? Part 16: Functions Project - Advanced Code +## โœ๏ธ Part 16: Functions Project - Advanced Code ### Step 35: Review the Functions Code @@ -1084,7 +1084,7 @@ int process_ir_led_command(int ir_command, simple_led_ctrl_t *leds, uint8_t blin --- -## ? Part 17: Debugging with GDB (Functions) +## ๐Ÿ› Part 17: Debugging with GDB (Functions) ### Step 38: Start OpenOCD (Terminal 1) @@ -1213,7 +1213,7 @@ quit --- -## ? Part 18: Analyzing .ELF Files in Ghidra +## ๐Ÿ”ฌ Part 18: Analyzing .ELF Files in Ghidra ### Step 50: Create New Ghidra Project @@ -1246,7 +1246,7 @@ With .ELF files, you get more information: --- -## ? Part 19: Hacking the Functions Project +## โœ๏ธ Part 19: Hacking the Functions Project ### Step 53: Find LED Pin Values @@ -1289,7 +1289,7 @@ Button 3 -> LED 3 -> GPIO 16 -> Red (SWAPPED!) ### Step 56: Convert and Flash ```powershell -cd C:\Users\assem.KEVINTHOMAS\OneDrive\Documents\Embedded-Hacking\0x0026_functions +cd C:\Users\flare-vm\Desktop\Embedded-Hacking-main\0x0026_functions python ..\uf2conv.py build\0x0026_functions-h.bin --base 0x10000000 --family 0xe48bff59 --output build\hacked.uf2 ``` @@ -1305,7 +1305,7 @@ python ..\uf2conv.py build\0x0026_functions-h.bin --base 0x10000000 --family 0xe --- -## ? Part 20: Summary and Review +## ๐Ÿ“Š Part 20: Summary and Review ### What We Accomplished @@ -1384,7 +1384,7 @@ python ..\uf2conv.py build\0x0026_functions-h.bin --base 0x10000000 --family 0xe --- -## ? Key Takeaways +## ๐Ÿ’ก Key Takeaways 1. **Structs group related data** - Better organization than separate variables @@ -1408,7 +1408,7 @@ python ..\uf2conv.py build\0x0026_functions-h.bin --base 0x10000000 --family 0xe --- -## ? Glossary +## ๐Ÿ“– Glossary | Term | Definition | | -------------------------- | -------------------------------------------------- | @@ -1426,7 +1426,7 @@ python ..\uf2conv.py build\0x0026_functions-h.bin --base 0x10000000 --family 0xe --- -## ? Additional Resources +## ๐Ÿ“š Additional Resources ### NEC IR Command Reference @@ -1459,7 +1459,7 @@ python ..\uf2conv.py build\0x0026_functions-h.bin --base 0x10000000 --family 0xe --- -## ? Real-World Implications +## ๐ŸŒ Real-World Implications ### What You've Learned in This Course