Update WEEK06

This commit is contained in:
Kevin Thomas
2026-05-30 16:50:15 -04:00
parent af0d84f9cc
commit f22ef2907e
21 changed files with 1554 additions and 425 deletions
+40 -39
View File
@@ -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
@@ -164,7 +164,7 @@ So the decoded value is exactly `42.5`.
| -------------- | ---------------------- | --------------------------- |
| **Size** | 1 byte | 4 bytes |
| **Precision** | Exact | ~7 decimal digits |
| **Range** | 0 to 255 | ±3.4 × 10^38 |
| **Range** | 0 to 255 | 3.4 10^38 |
| **Encoding** | Direct binary | IEEE 754 (sign/exp/mantissa)|
| **printf** | `%d` | `%f` |
@@ -224,13 +224,13 @@ 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
**Open a terminal and type:**
```powershell
```cmd
ghidraRun
```
@@ -277,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
@@ -311,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
@@ -548,7 +548,7 @@ Look at the **Listing** window (assembly view). Find the main function:
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
@@ -565,7 +565,7 @@ This confirms `printf` is called with the format string `"fav_num: %f\r\n"` and
---
## ✏️ 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
@@ -575,13 +575,13 @@ 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 (base 10) = 1100011 (base 2)
@@ -634,7 +634,7 @@ This changes the high word from `0x40454000` (42.5 as double) to `0x4058C000` (9
---
## 🚀 Part 2.9: Export and Test the Hacked Binary
## Part 2.9: Export and Test the Hacked Binary
### Step 21: Export the Patched Binary
@@ -648,13 +648,13 @@ This changes the high word from `0x40454000` (42.5 as double) to `0x4058C000` (9
**Open a terminal and navigate to your project directory:**
```powershell
```cmd
cd C:\Users\flare-vm\Desktop\Embedded-Hacking-main\0x000e_floating-point-data-type
```
**Run the conversion command:**
```powershell
```cmd
python ..\uf2conv.py build\0x000e_floating-point-data-type-h.bin --base 0x10000000 --family 0xe48bff59 --output build\hacked.uf2
```
@@ -673,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`!
---
@@ -711,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^38 | ±1.8 × 10^308 |
| **Range** | 3.4 10^38 | 1.8 10^308 |
| **printf** | `%f` | `%lf` |
| **ARM passing** | Promoted to double | Native in `r2:r3` |
@@ -769,13 +769,13 @@ 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
**Open a terminal and type:**
```powershell
```cmd
ghidraRun
```
@@ -822,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
@@ -856,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
@@ -938,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
@@ -969,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**
@@ -1097,7 +1097,7 @@ Look at the **Listing** window (assembly view). Find the main function:
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
@@ -1114,7 +1114,7 @@ This confirms `printf` is called with the format string `"fav_num: %lf\r\n"` and
---
## ✏️ 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
@@ -1163,11 +1163,11 @@ Look in the Listing view for the two data constants:
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
@@ -1181,13 +1181,13 @@ This changes the full 64-bit double from `0x4045433B645A1CAC` (42.52525) to `0x4
**Open a terminal and navigate to your project directory:**
```powershell
```cmd
cd C:\Users\flare-vm\Desktop\Embedded-Hacking-main\0x0011_double-floating-point-data-type
```
**Run the conversion command:**
```powershell
```cmd
python ..\uf2conv.py build\0x0011_double-floating-point-data-type-h.bin --base 0x10000000 --family 0xe48bff59 --output build\hacked.uf2
```
@@ -1206,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
@@ -1268,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.
@@ -1286,7 +1286,7 @@ fav_num: 99.990000
---
## 📖 Glossary
## Glossary
| Term | Definition |
| ----------------------- | ------------------------------------------------------------------------------ |
@@ -1310,7 +1310,7 @@ fav_num: 99.990000
---
## 📚 Additional Resources
## Additional Resources
### GPIO Coprocessor Reference
@@ -1349,4 +1349,5 @@ 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!