mirror of
https://github.com/mytechnotalent/Embedded-Hacking.git
synced 2026-07-16 17:07:34 +02:00
Updated WEEK04
This commit is contained in:
+295
-318
@@ -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)
|
||||
@@ -13,7 +13,7 @@ By the end of this tutorial, you will be able to:
|
||||
|
||||
---
|
||||
|
||||
## 📚 Part 1: Understanding C Operators
|
||||
## Part 1: Understanding C Operators
|
||||
|
||||
### What Are Operators?
|
||||
|
||||
@@ -32,7 +32,7 @@ By the end of this tutorial, you will be able to:
|
||||
|
||||
---
|
||||
|
||||
## 📚 Part 2: Arithmetic Operators
|
||||
## Part 2: Arithmetic Operators
|
||||
|
||||
### Basic Math in C
|
||||
|
||||
@@ -45,23 +45,23 @@ int result = x * y; // result = 50
|
||||
```
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────┐
|
||||
│ Arithmetic Operators │
|
||||
│ │
|
||||
│ Operator Example Result Description │
|
||||
│ ───────────────────────────────────────────────────────────── │
|
||||
│ + 5 + 10 15 Addition │
|
||||
│ - 10 - 5 5 Subtraction │
|
||||
│ * 5 * 10 50 Multiplication │
|
||||
│ / 10 / 5 2 Division │
|
||||
│ % 10 % 3 1 Modulus (remainder) │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────────┘
|
||||
+-----------------------------------------------------------------+
|
||||
| Arithmetic Operators |
|
||||
| |
|
||||
| Operator Example Result Description |
|
||||
| ------------------------------------------------------------- |
|
||||
| + 5 + 10 15 Addition |
|
||||
| - 10 - 5 5 Subtraction |
|
||||
| * 5 * 10 50 Multiplication |
|
||||
| / 10 / 5 2 Division |
|
||||
| % 10 % 3 1 Modulus (remainder) |
|
||||
| |
|
||||
+-----------------------------------------------------------------+
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📚 Part 3: Increment and Decrement Operators
|
||||
## Part 3: Increment and Decrement Operators
|
||||
|
||||
### Pre-Increment vs Post-Increment
|
||||
|
||||
@@ -77,29 +77,29 @@ int b = ++x; // Pre-increment: x becomes 7, then b = 7
|
||||
|
||||
| Type | Syntax | When Value Changes | Example Result |
|
||||
| ------------------ | ------ | --------------------- | -------------------- |
|
||||
| **Post-increment** | `x++` | AFTER the expression | `a = x++` → a=5, x=6 |
|
||||
| **Pre-increment** | `++x` | BEFORE the expression | `b = ++x` → x=7, b=7 |
|
||||
| **Post-increment** | `x++` | AFTER the expression | `a = x++` -> a=5, x=6 |
|
||||
| **Pre-increment** | `++x` | BEFORE the expression | `b = ++x` -> x=7, b=7 |
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────┐
|
||||
│ Post-Increment (x++) │
|
||||
│ │
|
||||
│ int x = 5; │
|
||||
│ int result = x++; │
|
||||
│ │
|
||||
│ Step 1: result = x (result gets 5) │
|
||||
│ Step 2: x = x + 1 (x becomes 6) │
|
||||
│ │
|
||||
│ Final: result = 5, x = 6 │
|
||||
│ │
|
||||
│ Think of it as: "Use first, THEN increment" │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────────┘
|
||||
+-----------------------------------------------------------------+
|
||||
| Post-Increment (x++) |
|
||||
| |
|
||||
| int x = 5; |
|
||||
| int result = x++; |
|
||||
| |
|
||||
| Step 1: result = x (result gets 5) |
|
||||
| Step 2: x = x + 1 (x becomes 6) |
|
||||
| |
|
||||
| Final: result = 5, x = 6 |
|
||||
| |
|
||||
| Think of it as: "Use first, THEN increment" |
|
||||
| |
|
||||
+-----------------------------------------------------------------+
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📚 Part 4: Relational Operators
|
||||
## Part 4: Relational Operators
|
||||
|
||||
### Comparing Values
|
||||
|
||||
@@ -112,24 +112,24 @@ bool result = (x > y); // false, because 6 is NOT greater than 10
|
||||
```
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────┐
|
||||
│ Relational Operators │
|
||||
│ │
|
||||
│ Operator Example Result Description │
|
||||
│ ───────────────────────────────────────────────────────────── │
|
||||
│ > 6 > 10 false Greater than │
|
||||
│ < 6 < 10 true Less than │
|
||||
│ >= 6 >= 6 true Greater than or equal │
|
||||
│ <= 6 <= 10 true Less than or equal │
|
||||
│ == 6 == 10 false Equal to │
|
||||
│ != 6 != 10 true Not equal to │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────────┘
|
||||
+-----------------------------------------------------------------+
|
||||
| Relational Operators |
|
||||
| |
|
||||
| Operator Example Result Description |
|
||||
| ------------------------------------------------------------- |
|
||||
| > 6 > 10 false Greater than |
|
||||
| < 6 < 10 true Less than |
|
||||
| >= 6 >= 6 true Greater than or equal |
|
||||
| <= 6 <= 10 true Less than or equal |
|
||||
| == 6 == 10 false Equal to |
|
||||
| != 6 != 10 true Not equal to |
|
||||
| |
|
||||
+-----------------------------------------------------------------+
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📚 Part 5: Logical Operators
|
||||
## Part 5: Logical Operators
|
||||
|
||||
### Combining Conditions
|
||||
|
||||
@@ -142,33 +142,33 @@ bool result = (x > y) && (y > x); // false AND true = false
|
||||
```
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────┐
|
||||
│ Logical Operators │
|
||||
│ │
|
||||
│ Operator Name Example Result │
|
||||
│ ───────────────────────────────────────────────────────────── │
|
||||
│ && AND true && true true │
|
||||
│ && AND true && false false │
|
||||
│ || OR true || false true │
|
||||
│ || OR false || false false │
|
||||
│ ! NOT !true false │
|
||||
│ │
|
||||
│ Truth Table for AND (&&): │
|
||||
│ ┌───────┬───────┬────────┐ │
|
||||
│ │ A │ B │ A && B │ │
|
||||
│ ├───────┼───────┼────────┤ │
|
||||
│ │ false │ false │ false │ │
|
||||
│ │ false │ true │ false │ │
|
||||
│ │ true │ false │ false │ │
|
||||
│ │ true │ true │ true │ │
|
||||
│ └───────┴───────┴────────┘ │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────────┘
|
||||
+-----------------------------------------------------------------+
|
||||
| Logical Operators |
|
||||
| |
|
||||
| Operator Name Example Result |
|
||||
| ------------------------------------------------------------- |
|
||||
| && AND true && true true |
|
||||
| && AND true && false false |
|
||||
| || OR true || false true |
|
||||
| || OR false || false false |
|
||||
| ! NOT !true false |
|
||||
| |
|
||||
| Truth Table for AND (&&): |
|
||||
| +-------+-------+--------+ |
|
||||
| | A | B | A && B | |
|
||||
| +-------+-------+--------+ |
|
||||
| | false | false | false | |
|
||||
| | false | true | false | |
|
||||
| | true | false | false | |
|
||||
| | true | true | true | |
|
||||
| +-------+-------+--------+ |
|
||||
| |
|
||||
+-----------------------------------------------------------------+
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📚 Part 6: Bitwise Operators
|
||||
## Part 6: Bitwise Operators
|
||||
|
||||
### Manipulating Individual Bits
|
||||
|
||||
@@ -180,21 +180,21 @@ int result = x << 1; // Shift left by 1: 0b00001100 = 12
|
||||
```
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────┐
|
||||
│ Bitwise Left Shift (<<) │
|
||||
│ │
|
||||
│ x = 6 = 0b00000110 │
|
||||
│ │
|
||||
│ x << 1 means "shift all bits LEFT by 1 position" │
|
||||
│ │
|
||||
│ Before: 0 0 0 0 0 1 1 0 (6) │
|
||||
│ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ │
|
||||
│ After: 0 0 0 0 1 1 0 0 (12) │
|
||||
│ │
|
||||
│ Each left shift DOUBLES the value! │
|
||||
│ 6 << 1 = 12 (same as 6 * 2) │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────────┘
|
||||
+-----------------------------------------------------------------+
|
||||
| Bitwise Left Shift (<<) |
|
||||
| |
|
||||
| x = 6 = 0b00000110 |
|
||||
| |
|
||||
| x << 1 means "shift all bits LEFT by 1 position" |
|
||||
| |
|
||||
| Before: 0 0 0 0 0 1 1 0 (6) |
|
||||
| ? ? ? ? ? ? ? ? |
|
||||
| After: 0 0 0 0 1 1 0 0 (12) |
|
||||
| |
|
||||
| Each left shift DOUBLES the value! |
|
||||
| 6 << 1 = 12 (same as 6 * 2) |
|
||||
| |
|
||||
+-----------------------------------------------------------------+
|
||||
```
|
||||
|
||||
**Common Bitwise Operators:**
|
||||
@@ -210,7 +210,7 @@ int result = x << 1; // Shift left by 1: 0b00001100 = 12
|
||||
|
||||
---
|
||||
|
||||
## 📚 Part 7: Assignment Operators
|
||||
## Part 7: Assignment Operators
|
||||
|
||||
### Shorthand for Math + Assign
|
||||
|
||||
@@ -222,69 +222,69 @@ x += 5; // Same as: x = x + 5; Result: x = 11
|
||||
```
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────┐
|
||||
│ Compound Assignment Operators │
|
||||
│ │
|
||||
│ Operator Example Equivalent To Result (if x=6) │
|
||||
│ ───────────────────────────────────────────────────────────── │
|
||||
│ += x += 5 x = x + 5 x = 11 │
|
||||
│ -= x -= 2 x = x - 2 x = 4 │
|
||||
│ *= x *= 3 x = x * 3 x = 18 │
|
||||
│ /= x /= 2 x = x / 2 x = 3 │
|
||||
│ %= x %= 4 x = x % 4 x = 2 │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────────┘
|
||||
+-----------------------------------------------------------------+
|
||||
| Compound Assignment Operators |
|
||||
| |
|
||||
| Operator Example Equivalent To Result (if x=6) |
|
||||
| ------------------------------------------------------------- |
|
||||
| += x += 5 x = x + 5 x = 11 |
|
||||
| -= x -= 2 x = x - 2 x = 4 |
|
||||
| *= x *= 3 x = x * 3 x = 18 |
|
||||
| /= x /= 2 x = x / 2 x = 3 |
|
||||
| %= x %= 4 x = x % 4 x = 2 |
|
||||
| |
|
||||
+-----------------------------------------------------------------+
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📚 Part 8: Understanding the DHT11 Sensor
|
||||
## Part 8: Understanding the DHT11 Sensor
|
||||
|
||||
### What is the DHT11?
|
||||
|
||||
The **DHT11** is a low-cost digital temperature and humidity sensor. It uses a single wire for communication (plus power and ground).
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────┐
|
||||
│ DHT11 Pinout │
|
||||
│ │
|
||||
│ ┌─────────────┐ │
|
||||
│ │ DHT11 │ │
|
||||
│ │ ┌─────┐ │ │
|
||||
│ │ │ │ │ │
|
||||
│ │ │ │ │ │
|
||||
│ │ └─────┘ │ │
|
||||
│ │ 1 2 3 4 │ │
|
||||
│ └──┬──┬──┬──┬─┘ │
|
||||
│ │ │ │ │ │
|
||||
│ VCC DATA NC GND │
|
||||
│ │
|
||||
│ Pin 1: VCC (3.3V or 5V) │
|
||||
│ Pin 2: DATA (connect to GPIO) │
|
||||
│ Pin 3: Not Connected │
|
||||
│ Pin 4: GND (Ground) │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────────┘
|
||||
+-----------------------------------------------------------------+
|
||||
| DHT11 Pinout |
|
||||
| |
|
||||
| +-------------+ |
|
||||
| | DHT11 | |
|
||||
| | +-----+ | |
|
||||
| | | | | |
|
||||
| | | | | |
|
||||
| | +-----+ | |
|
||||
| | 1 2 3 4 | |
|
||||
| +--+--+--+--+-+ |
|
||||
| | | | | |
|
||||
| VCC DATA NC GND |
|
||||
| |
|
||||
| Pin 1: VCC (3.3V or 5V) |
|
||||
| Pin 2: DATA (connect to GPIO) |
|
||||
| Pin 3: Not Connected |
|
||||
| Pin 4: GND (Ground) |
|
||||
| |
|
||||
+-----------------------------------------------------------------+
|
||||
```
|
||||
|
||||
### DHT11 Specifications
|
||||
|
||||
| Parameter | Range | Accuracy |
|
||||
| --------------- | ------------ | -------- |
|
||||
| **Humidity** | 20% - 90% RH | ±5% RH |
|
||||
| **Temperature** | 0°C - 50°C | ±2°C |
|
||||
| **Humidity** | 20% - 90% RH | ?5% RH |
|
||||
| **Temperature** | 0 deg C - 50 deg C | ?2 deg C |
|
||||
|
||||
### How DHT11 Communication Works
|
||||
|
||||
The DHT11 uses a custom one-wire protocol:
|
||||
|
||||
1. **Host sends start signal** - Pull data line LOW for 18ms
|
||||
2. **DHT11 responds** - Pulls line LOW for 80µs, then HIGH for 80µs
|
||||
2. **DHT11 responds** - Pulls line LOW for 80 us, then HIGH for 80 us
|
||||
3. **Data transmission** - 40 bits sent (8 humidity int, 8 humidity decimal, 8 temp int, 8 temp decimal, 8 checksum)
|
||||
|
||||
---
|
||||
|
||||
## 📚 Part 9: Understanding Pointers (Quick Review)
|
||||
## Part 9: Understanding Pointers (Quick Review)
|
||||
|
||||
### The & Operator (Address-Of)
|
||||
|
||||
@@ -295,32 +295,32 @@ float hum, temp;
|
||||
|
||||
// Pass ADDRESSES to the function so it can modify our variables
|
||||
if (dht11_read(&hum, &temp)) {
|
||||
printf("Humidity: %.1f%%, Temperature: %.1f°C\n", hum, temp);
|
||||
printf("Humidity: %.1f%%, Temperature: %.1f?C\n", hum, temp);
|
||||
}
|
||||
```
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────┐
|
||||
│ Passing by Reference │
|
||||
│ │
|
||||
│ Stack Memory │
|
||||
│ ┌────────────────────────────┐ │
|
||||
│ │ Address 0x20000008: hum │◄─── &hum (passed to function) │
|
||||
│ │ Value: 51.0 │ │
|
||||
│ ├────────────────────────────┤ │
|
||||
│ │ Address 0x2000000C: temp │◄─── &temp (passed to function) │
|
||||
│ │ Value: 23.8 │ │
|
||||
│ └────────────────────────────┘ │
|
||||
│ │
|
||||
│ dht11_read() receives the ADDRESSES, so it can write │
|
||||
│ new values directly into hum and temp! │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────────┘
|
||||
+-----------------------------------------------------------------+
|
||||
| Passing by Reference |
|
||||
| |
|
||||
| Stack Memory |
|
||||
| +----------------------------+ |
|
||||
| | Address 0x20000008: hum |?--- &hum (passed to function) |
|
||||
| | Value: 51.0 | |
|
||||
| +----------------------------+ |
|
||||
| | Address 0x2000000C: temp |?--- &temp (passed to function) |
|
||||
| | Value: 23.8 | |
|
||||
| +----------------------------+ |
|
||||
| |
|
||||
| dht11_read() receives the ADDRESSES, so it can write |
|
||||
| new values directly into hum and temp! |
|
||||
| |
|
||||
+-----------------------------------------------------------------+
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📚 Part 10: Setting Up Your Environment
|
||||
## Part 10: Setting Up Your Environment
|
||||
|
||||
### Prerequisites
|
||||
|
||||
@@ -344,43 +344,43 @@ Connect your DHT11 like this:
|
||||
| GND | GND |
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────┐
|
||||
│ DHT11 Wiring │
|
||||
│ │
|
||||
│ Pico 2 DHT11 Sensor │
|
||||
│ ┌──────────┐ ┌──────────┐ │
|
||||
│ │ │ │ │ │
|
||||
│ │ GPIO 4 │────────── DATA ──────►│ DATA │ │
|
||||
│ │ │ │ │ │
|
||||
│ │ 3.3V │────────── VCC ───────►│ VCC │ │
|
||||
│ │ │ │ │ │
|
||||
│ │ GND │────────── GND ───────►│ GND │ │
|
||||
│ │ │ │ │ │
|
||||
│ └──────────┘ └──────────┘ │
|
||||
│ │
|
||||
│ Note: Some DHT11 modules have a built-in pull-up resistor. │
|
||||
│ If yours doesn't, add a 10K resistor between DATA and VCC. │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────────┘
|
||||
+-----------------------------------------------------------------+
|
||||
| DHT11 Wiring |
|
||||
| |
|
||||
| Pico 2 DHT11 Sensor |
|
||||
| +----------+ +----------+ |
|
||||
| | | | | |
|
||||
| | GPIO 4 |---------- DATA ------?| DATA | |
|
||||
| | | | | |
|
||||
| | 3.3V |---------- VCC -------?| VCC | |
|
||||
| | | | | |
|
||||
| | GND |---------- GND -------?| GND | |
|
||||
| | | | | |
|
||||
| +----------+ +----------+ |
|
||||
| |
|
||||
| Note: Some DHT11 modules have a built-in pull-up resistor. |
|
||||
| If yours doesn't, add a 10K resistor between DATA and VCC. |
|
||||
| |
|
||||
+-----------------------------------------------------------------+
|
||||
```
|
||||
|
||||
### Project Structure
|
||||
|
||||
```
|
||||
Embedded-Hacking/
|
||||
├── 0x001a_operators/
|
||||
│ ├── build/
|
||||
│ │ ├── 0x001a_operators.uf2
|
||||
│ │ └── 0x001a_operators.bin
|
||||
│ ├── main/
|
||||
│ │ └── 0x001a_operators.c
|
||||
│ └── dht11.h
|
||||
└── uf2conv.py
|
||||
+-- 0x001a_operators/
|
||||
| +-- build/
|
||||
| | +-- 0x001a_operators.uf2
|
||||
| | +-- 0x001a_operators.bin
|
||||
| +-- main/
|
||||
| | +-- 0x001a_operators.c
|
||||
| +-- dht11.h
|
||||
+-- uf2conv.py
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🔬 Part 11: Hands-On Tutorial - The Operators Code
|
||||
## ? Part 11: Hands-On Tutorial - The Operators Code
|
||||
|
||||
### Step 1: Review the Source Code
|
||||
|
||||
@@ -417,7 +417,7 @@ int main(void) {
|
||||
|
||||
float hum, temp;
|
||||
if (dht11_read(&hum, &temp)) {
|
||||
printf("Humidity: %.1f%%, Temperature: %.1f°C\r\n", hum, temp);
|
||||
printf("Humidity: %.1f%%, Temperature: %.1f?C\r\n", hum, temp);
|
||||
} else {
|
||||
printf("DHT11 read failed\r\n");
|
||||
}
|
||||
@@ -432,20 +432,20 @@ int main(void) {
|
||||
Let's trace through what happens to `x`:
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────┐
|
||||
│ Variable x Through the Program │
|
||||
│ │
|
||||
│ Line │ x value │ Result │
|
||||
│ ──────────────────┼─────────┼───────────────────────────────── │
|
||||
│ int x = 5; │ 5 │ x initialized to 5 │
|
||||
│ x * y │ 5 │ arithmetic = 5 * 10 = 50 │
|
||||
│ x++ │ 5→6 │ increment = 5 (then x becomes 6) │
|
||||
│ x > y │ 6 │ relational = (6 > 10) = false │
|
||||
│ (x>y) && (y>x) │ 6 │ logical = false && true = false │
|
||||
│ x << 1 │ 6 │ bitwise = 6 << 1 = 12 │
|
||||
│ x += 5 │ 6→11 │ assignment = 6 + 5 = 11 │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────────┘
|
||||
+-----------------------------------------------------------------+
|
||||
| Variable x Through the Program |
|
||||
| |
|
||||
| Line | x value | Result |
|
||||
| ------------------+---------+--------------------------------- |
|
||||
| int x = 5; | 5 | x initialized to 5 |
|
||||
| x * y | 5 | arithmetic = 5 * 10 = 50 |
|
||||
| x++ | 5->6 | increment = 5 (then x becomes 6) |
|
||||
| x > y | 6 | relational = (6 > 10) = false |
|
||||
| (x>y) && (y>x) | 6 | logical = false && true = false |
|
||||
| x << 1 | 6 | bitwise = 6 << 1 = 12 |
|
||||
| x += 5 | 6->11 | assignment = 6 + 5 = 11 |
|
||||
| |
|
||||
+-----------------------------------------------------------------+
|
||||
```
|
||||
|
||||
### Step 3: Flash the Binary to Your Pico 2
|
||||
@@ -467,25 +467,25 @@ relational_operator: 0
|
||||
logical_operator: 0
|
||||
bitwise_operator: 12
|
||||
assignment_operator: 11
|
||||
Humidity: 51.0%, Temperature: 23.8°C
|
||||
Humidity: 51.0%, Temperature: 23.8 deg C
|
||||
```
|
||||
|
||||
**Understanding the Output:**
|
||||
|
||||
| Variable | Value | Explanation |
|
||||
| ------------------- | ------ | --------------------------------------------- |
|
||||
| arithmetic_operator | 50 | 5 × 10 = 50 |
|
||||
| arithmetic_operator | 50 | 5 * 10 = 50 |
|
||||
| increment_operator | 5 | Post-increment returns value BEFORE increment |
|
||||
| relational_operator | 0 | 6 > 10 is false (0) |
|
||||
| logical_operator | 0 | false AND true = false (0) |
|
||||
| bitwise_operator | 12 | 6 (0b0110) << 1 = 12 (0b1100) |
|
||||
| assignment_operator | 11 | 6 + 5 = 11 |
|
||||
| Humidity | 51.0% | Real reading from DHT11 |
|
||||
| Temperature | 23.8°C | Real reading from DHT11 |
|
||||
| Temperature | 23.8 deg C | Real reading from DHT11 |
|
||||
|
||||
---
|
||||
|
||||
## 🔬 Part 12: Debugging with GDB
|
||||
## ? Part 12: Debugging with GDB
|
||||
|
||||
### Step 5: Start OpenOCD (Terminal 1)
|
||||
|
||||
@@ -493,7 +493,7 @@ Open a terminal and start OpenOCD:
|
||||
|
||||
```powershell
|
||||
openocd ^
|
||||
-s "C:\Users\flare-vm\.pico-sdk\openocd\0.12.0+dev\scripts" ^
|
||||
-s "C:\Users\assem.KEVINTHOMAS\.pico-sdk\openocd\0.12.0+dev\scripts" ^
|
||||
-f interface/cmsis-dap.cfg ^
|
||||
-f target/rp2350.cfg ^
|
||||
-c "adapter speed 5000"
|
||||
@@ -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
|
||||
|
||||
@@ -652,7 +652,7 @@ ghidraRun
|
||||
|
||||
### Step 18: Create a New Project
|
||||
|
||||
1. Click **File** → **New Project**
|
||||
1. Click **File** -> **New Project**
|
||||
2. Select **Non-Shared Project**
|
||||
3. Click **Next**
|
||||
4. Enter Project Name: `0x001a_operators`
|
||||
@@ -666,12 +666,12 @@ ghidraRun
|
||||
|
||||
### Step 20: Configure the Binary Format
|
||||
|
||||
**Click the three dots (…) next to "Language" and:**
|
||||
**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:**
|
||||
**Click the "Options..." button and:**
|
||||
1. Change **Block Name** to `.text`
|
||||
2. Change **Base Address** to `10000000`
|
||||
3. Click **OK**
|
||||
@@ -686,25 +686,25 @@ Wait for analysis to complete.
|
||||
|
||||
---
|
||||
|
||||
## 🔬 Part 14: Finding the Reset_Handler
|
||||
## ? Part 14: Finding the Reset_Handler
|
||||
|
||||
### Step 22: Understand the Vector Table
|
||||
|
||||
In ARM Cortex-M, the **vector table** is at the base of flash (0x10000000). The second entry (offset 4) contains the Reset_Handler address.
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────┐
|
||||
│ ARM Vector Table at 0x10000000 │
|
||||
│ │
|
||||
│ Offset Contents Description │
|
||||
│ ───────────────────────────────────────────────────────────── │
|
||||
│ 0x00 Initial SP value Stack pointer at reset │
|
||||
│ 0x04 Reset_Handler addr First code to execute │
|
||||
│ 0x08 NMI_Handler addr Non-maskable interrupt │
|
||||
│ 0x0C HardFault_Handler Hard fault handler │
|
||||
│ ... │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────────┘
|
||||
+-----------------------------------------------------------------+
|
||||
| ARM Vector Table at 0x10000000 |
|
||||
| |
|
||||
| Offset Contents Description |
|
||||
| ------------------------------------------------------------- |
|
||||
| 0x00 Initial SP value Stack pointer at reset |
|
||||
| 0x04 Reset_Handler addr First code to execute |
|
||||
| 0x08 NMI_Handler addr Non-maskable interrupt |
|
||||
| 0x0C HardFault_Handler Hard fault handler |
|
||||
| ... |
|
||||
| |
|
||||
+-----------------------------------------------------------------+
|
||||
```
|
||||
|
||||
### Step 23: Read the Reset_Handler Address
|
||||
@@ -715,18 +715,18 @@ In ARM Cortex-M, the **vector table** is at the base of flash (0x10000000). The
|
||||
**Important:** This is **little-endian**, so we need to reverse the byte order!
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────┐
|
||||
│ Little-Endian Byte Order │
|
||||
│ │
|
||||
│ In memory: 5d 01 00 10 │
|
||||
│ Reversed: 10 00 01 5d │
|
||||
│ As hex: 0x1000015d │
|
||||
│ │
|
||||
│ But wait! ARM uses the THUMB bit! │
|
||||
│ The lowest bit indicates Thumb mode (always set for Cortex-M) │
|
||||
│ Real address: 0x1000015d - 1 = 0x1000015c │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────────┘
|
||||
+-----------------------------------------------------------------+
|
||||
| Little-Endian Byte Order |
|
||||
| |
|
||||
| In memory: 5d 01 00 10 |
|
||||
| Reversed: 10 00 01 5d |
|
||||
| As hex: 0x1000015d |
|
||||
| |
|
||||
| But wait! ARM uses the THUMB bit! |
|
||||
| The lowest bit indicates Thumb mode (always set for Cortex-M) |
|
||||
| Real address: 0x1000015d - 1 = 0x1000015c |
|
||||
| |
|
||||
+-----------------------------------------------------------------+
|
||||
```
|
||||
|
||||
### Step 24: Navigate to Reset_Handler
|
||||
@@ -740,7 +740,7 @@ If Ghidra didn't automatically recognize this as a function:
|
||||
|
||||
1. Click on the address `0x1000015c`
|
||||
2. Right-click and press `F` to create a function
|
||||
3. Right-click → **Edit Function Signature**
|
||||
3. Right-click -> **Edit Function Signature**
|
||||
4. Change the name to `Reset_Handler`
|
||||
5. Click **OK**
|
||||
|
||||
@@ -749,17 +749,17 @@ If Ghidra didn't automatically recognize this as a function:
|
||||
The Reset_Handler typically calls three functions:
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────┐
|
||||
│ Reset_Handler Flow (crt0.S) │
|
||||
│ │
|
||||
│ Reset_Handler: │
|
||||
│ 1. Call some_init() ◄── Initialize hardware │
|
||||
│ 2. Call main() ◄── THIS IS WHAT WE WANT! │
|
||||
│ 3. Call exit() ◄── Never returns │
|
||||
│ │
|
||||
│ The MIDDLE function is main! │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────────┘
|
||||
+-----------------------------------------------------------------+
|
||||
| Reset_Handler Flow (crt0.S) |
|
||||
| |
|
||||
| Reset_Handler: |
|
||||
| 1. Call some_init() ?-- Initialize hardware |
|
||||
| 2. Call main() ?-- THIS IS WHAT WE WANT! |
|
||||
| 3. Call exit() ?-- Never returns |
|
||||
| |
|
||||
| The MIDDLE function is main! |
|
||||
| |
|
||||
+-----------------------------------------------------------------+
|
||||
```
|
||||
|
||||
Look at the end of Reset_Handler for three function calls. The middle one is `main`!
|
||||
@@ -767,13 +767,13 @@ Look at the end of Reset_Handler for three function calls. The middle one is `ma
|
||||
### Step 27: Navigate to Main
|
||||
|
||||
1. Double-click on the middle function call (should be around `0x10000234`)
|
||||
2. Right-click → **Edit Function Signature**
|
||||
2. Right-click -> **Edit Function Signature**
|
||||
3. Change to: `int main(void)`
|
||||
4. Click **OK**
|
||||
|
||||
---
|
||||
|
||||
## 🔬 Part 15: Resolving Functions in Ghidra
|
||||
## ? Part 15: Resolving Functions in Ghidra
|
||||
|
||||
### Step 28: Resolve stdio_init_all
|
||||
|
||||
@@ -781,7 +781,7 @@ The first function call in main is `stdio_init_all`:
|
||||
|
||||
1. Find the call at approximately `0x10000238`
|
||||
2. Double-click to navigate to the function
|
||||
3. Right-click → **Edit Function Signature**
|
||||
3. Right-click -> **Edit Function Signature**
|
||||
4. Change to: `bool stdio_init_all(void)`
|
||||
5. Click **OK**
|
||||
|
||||
@@ -798,7 +798,7 @@ bl FUN_xxxxx ; dht11_init
|
||||
- The argument `4` is the GPIO pin number
|
||||
- We physically connected the DHT11 to GPIO 4!
|
||||
|
||||
1. Right-click → **Edit Function Signature**
|
||||
1. Right-click -> **Edit Function Signature**
|
||||
2. Change to: `void dht11_init(uint pin)`
|
||||
3. Click **OK**
|
||||
|
||||
@@ -807,7 +807,7 @@ bl FUN_xxxxx ; dht11_init
|
||||
Look for repeated function calls with string addresses:
|
||||
|
||||
1. Find a call like the one at `0x10000262`
|
||||
2. Right-click → **Edit Function Signature**
|
||||
2. Right-click -> **Edit Function Signature**
|
||||
3. Change to: `int printf(char *format, ...)`
|
||||
4. Check the **Varargs** checkbox
|
||||
5. Click **OK**
|
||||
@@ -821,7 +821,7 @@ ldr r0, =0x7d0 ; 2000 milliseconds
|
||||
bl FUN_xxxxx ; sleep_ms
|
||||
```
|
||||
|
||||
1. Right-click → **Edit Function Signature**
|
||||
1. Right-click -> **Edit Function Signature**
|
||||
2. Change to: `void sleep_ms(uint ms)`
|
||||
3. Click **OK**
|
||||
|
||||
@@ -840,7 +840,7 @@ bl FUN_xxxxx ; dht11_read
|
||||
- `sp + 0xc` = address of `temp` variable
|
||||
- These are `float` pointers passed to the function
|
||||
|
||||
1. Right-click → **Edit Function Signature**
|
||||
1. Right-click -> **Edit Function Signature**
|
||||
2. Change to: `bool dht11_read(float *humidity, float *temperature)`
|
||||
3. Click **OK**
|
||||
|
||||
@@ -853,32 +853,32 @@ ldr r0, ="DHT11 read failed"
|
||||
bl FUN_xxxxx ; puts
|
||||
```
|
||||
|
||||
1. Right-click → **Edit Function Signature**
|
||||
1. Right-click -> **Edit Function Signature**
|
||||
2. Change to: `int puts(char *s)`
|
||||
3. Click **OK**
|
||||
|
||||
---
|
||||
|
||||
## 🔬 Part 16: Understanding IEEE-754 Floating-Point
|
||||
## ? Part 16: Understanding IEEE-754 Floating-Point
|
||||
|
||||
### What is IEEE-754?
|
||||
|
||||
IEEE-754 is the standard for representing decimal numbers in binary. A 32-bit float is divided into three parts:
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────┐
|
||||
│ IEEE-754 Single Precision (32-bit) Float │
|
||||
│ │
|
||||
│ ┌─────┬─────────────┬───────────────────────────────────────┐ │
|
||||
│ │ S │ Exponent │ Mantissa (Fraction) │ │
|
||||
│ │ 1 │ 8 bits │ 23 bits │ │
|
||||
│ └─────┴─────────────┴───────────────────────────────────────┘ │
|
||||
│ bit bits bits │
|
||||
│ 31 30-23 22-0 │
|
||||
│ │
|
||||
│ Value = (-1)^S × (1 + Mantissa) × 2^(Exponent - 127) │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────────┘
|
||||
+-----------------------------------------------------------------+
|
||||
| IEEE-754 Single Precision (32-bit) Float |
|
||||
| |
|
||||
| +-----+-------------+---------------------------------------+ |
|
||||
| | S | Exponent | Mantissa (Fraction) | |
|
||||
| | 1 | 8 bits | 23 bits | |
|
||||
| +-----+-------------+---------------------------------------+ |
|
||||
| bit bits bits |
|
||||
| 31 30-23 22-0 |
|
||||
| |
|
||||
| Value = (-1)^S * (1 + Mantissa) * 2^(Exponent - 127) |
|
||||
| |
|
||||
+-----------------------------------------------------------------+
|
||||
```
|
||||
|
||||
### Example: Decoding 0x3dcccccc (0.1f)
|
||||
@@ -895,7 +895,7 @@ Let's decode the bytes `cc cc cc 3d`:
|
||||
4. **Calculate value:**
|
||||
- Actual exponent: 123 - 127 = -4
|
||||
- Mantissa value: 1.6 (approximately)
|
||||
- Final value: 1.6 × 2^(-4) ≈ 0.1
|
||||
- Final value: 1.6 * 2^(-4) ? 0.1
|
||||
|
||||
### Example: Encoding -1.0f as 0xbf800000
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -945,19 +945,19 @@ vfma.f32 s15, s13, s11 ; Fused multiply-add for temperature
|
||||
The constant `0.1` (at address `0x1000042c`) is loaded into register `s11` and used to scale the raw sensor readings.
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────┐
|
||||
│ DHT11 Scaling Calculation │
|
||||
│ │
|
||||
│ Raw sensor data: integer + decimal parts │
|
||||
│ Example: 238 (integer=23, decimal=8) │
|
||||
│ │
|
||||
│ Formula: result = integer + (decimal × 0.1) │
|
||||
│ 23.8 = 23 + (8 × 0.1) │
|
||||
│ │
|
||||
│ The vfma.f32 instruction does: s15 = s13 + (s11 × something) │
|
||||
│ Where s11 = 0.1f (our target!) │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────────┘
|
||||
+-----------------------------------------------------------------+
|
||||
| DHT11 Scaling Calculation |
|
||||
| |
|
||||
| Raw sensor data: integer + decimal parts |
|
||||
| Example: 238 (integer=23, decimal=8) |
|
||||
| |
|
||||
| Formula: result = integer + (decimal * 0.1) |
|
||||
| 23.8 = 23 + (8 * 0.1) |
|
||||
| |
|
||||
| The vfma.f32 instruction does: s15 = s13 + (s11 * something) |
|
||||
| Where s11 = 0.1f (our target!) |
|
||||
| |
|
||||
+-----------------------------------------------------------------+
|
||||
```
|
||||
|
||||
### Step 36: Identify Key Offsets
|
||||
@@ -972,11 +972,11 @@ 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
|
||||
|
||||
1. Click **Window** → **Bytes**
|
||||
1. Click **Window** -> **Bytes**
|
||||
2. A new panel appears showing raw hex bytes
|
||||
|
||||
### Step 38: Enable Editing
|
||||
@@ -1011,11 +1011,11 @@ print(f"New: {new}") # 5.0
|
||||
|
||||
---
|
||||
|
||||
## 🔬 Part 19: Exporting and Testing
|
||||
## ? Part 19: Exporting and Testing
|
||||
|
||||
### Step 41: Export the Patched Binary
|
||||
|
||||
1. Click **File** → **Export Program**
|
||||
1. Click **File** -> **Export Program**
|
||||
2. Set **Format** to **Binary**
|
||||
3. Navigate to your build directory
|
||||
4. Name the file `0x001a_operators-h.bin`
|
||||
@@ -1026,7 +1026,7 @@ print(f"New: {new}") # 5.0
|
||||
Open a terminal and run:
|
||||
|
||||
```powershell
|
||||
cd C:\Users\flare-vm\Desktop\Embedded-Hacking-main\0x001a_operators
|
||||
cd C:\Users\assem.KEVINTHOMAS\OneDrive\Documents\Embedded-Hacking\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
|
||||
|
||||
@@ -1055,18 +1055,18 @@ You should see dramatically increased temperature readings!
|
||||
### The Hacking Workflow
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────┐
|
||||
│ Binary Hacking Workflow │
|
||||
│ │
|
||||
│ 1. Analyze the binary in Ghidra │
|
||||
│ 2. Identify target values/instructions │
|
||||
│ 3. Calculate file offsets from memory addresses │
|
||||
│ 4. Determine replacement bytes │
|
||||
│ 5. Patch the binary (manual in hex editor) │
|
||||
│ 6. Export and convert to UF2 │
|
||||
│ 7. Flash and test │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────────┘
|
||||
+-----------------------------------------------------------------+
|
||||
| Binary Hacking Workflow |
|
||||
| |
|
||||
| 1. Analyze the binary in Ghidra |
|
||||
| 2. Identify target values/instructions |
|
||||
| 3. Calculate file offsets from memory addresses |
|
||||
| 4. Determine replacement bytes |
|
||||
| 5. Patch the binary (manual in hex editor) |
|
||||
| 6. Export and convert to UF2 |
|
||||
| 7. Flash and test |
|
||||
| |
|
||||
+-----------------------------------------------------------------+
|
||||
```
|
||||
|
||||
### Key Memory Addresses
|
||||
@@ -1082,34 +1082,9 @@ You should see dramatically increased temperature readings!
|
||||
|
||||
---
|
||||
|
||||
## ✅ Practice Exercises
|
||||
|
||||
### Exercise 1: Change the Sleep Duration
|
||||
Find the `sleep_ms(2000)` call and change it to 5000ms (5 seconds).
|
||||
|
||||
**Hint:** Look for `0x7d0` (2000) being loaded into r0.
|
||||
|
||||
### Exercise 2: Invert Temperature Reading
|
||||
Using HxD, change the scaling constant at offset `0x42C` to make temperature readings negative.
|
||||
|
||||
**Hint:** Encode -0.1f as IEEE-754 and write those bytes.
|
||||
|
||||
### Exercise 3: Add a Fixed Offset
|
||||
Using HxD, patch the instruction at offset `0x414` and the constant at `0x42C` to add exactly 10°C to every reading.
|
||||
|
||||
**Hint:** Change vfma to vadd and set the pool constant to 10.0f (`00 00 20 41`).
|
||||
|
||||
### Exercise 4: Find All printf Strings
|
||||
Search the binary for all format strings like "%d" and "%.1f".
|
||||
|
||||
**Hint:** Use GDB's `x/s` command to search flash memory, or scan in HxD's ASCII panel.
|
||||
|
||||
### Exercise 5: Trace the Variable Flow
|
||||
In Ghidra, trace how x changes through each operator. Match your findings to the output values.
|
||||
|
||||
---
|
||||
|
||||
## 🎓 Key Takeaways
|
||||
## ? Key Takeaways
|
||||
|
||||
1. **Post-increment returns the OLD value** - `x++` gives you x, THEN adds 1
|
||||
|
||||
@@ -1121,7 +1096,7 @@ In Ghidra, trace how x changes through each operator. Match your findings to the
|
||||
|
||||
5. **IEEE-754 is how floats are stored** - Sign, exponent, mantissa
|
||||
|
||||
6. **File offset = Memory address - Base** - 0x10000410 → offset 0x410
|
||||
6. **File offset = Memory address - Base** - 0x10000410 -> offset 0x410
|
||||
|
||||
7. **Little-endian reverses byte order** - 0x3dcccccc stored as cc cc cc 3d
|
||||
|
||||
@@ -1131,7 +1106,7 @@ In Ghidra, trace how x changes through each operator. Match your findings to the
|
||||
|
||||
---
|
||||
|
||||
## 📖 Glossary
|
||||
## ? Glossary
|
||||
|
||||
| Term | Definition |
|
||||
| ------------------ | --------------------------------------------------- |
|
||||
@@ -1156,7 +1131,7 @@ In Ghidra, trace how x changes through each operator. Match your findings to the
|
||||
|
||||
---
|
||||
|
||||
## 🔗 Additional Resources
|
||||
## ? Additional Resources
|
||||
|
||||
### IEEE-754 Float Quick Reference
|
||||
|
||||
@@ -1174,16 +1149,16 @@ In Ghidra, trace how x changes through each operator. Match your findings to the
|
||||
|
||||
| Instruction | Description |
|
||||
| --------------------- | ---------------------------------------- |
|
||||
| `vfma.f32 Sd, Sn, Sm` | Sd = Sd + (Sn × Sm) (fused multiply-add) |
|
||||
| `vfma.f32 Sd, Sn, Sm` | Sd = Sd + (Sn * Sm) (fused multiply-add) |
|
||||
| `vadd.f32 Sd, Sn, Sm` | Sd = Sn + Sm |
|
||||
| `vsub.f32 Sd, Sn, Sm` | Sd = Sn - Sm |
|
||||
| `vmul.f32 Sd, Sn, Sm` | Sd = Sn × Sm |
|
||||
| `vmul.f32 Sd, Sn, Sm` | Sd = Sn * Sm |
|
||||
| `vldr.f32 Sd, [addr]` | Load float from memory |
|
||||
| `vstr.f32 Sd, [addr]` | Store float to memory |
|
||||
|
||||
---
|
||||
|
||||
## 🚨 Real-World Implications
|
||||
## ? Real-World Implications
|
||||
|
||||
### Why This Matters
|
||||
|
||||
@@ -1210,4 +1185,6 @@ By manipulating sensor readings, an attacker could:
|
||||
|
||||
**Remember:** The techniques you learned today can be used for good (security research, debugging) or bad (sabotage, fraud). Always use your skills ethically and legally. Understanding how attacks work helps us build more secure systems!
|
||||
|
||||
Happy hacking! 🔧
|
||||
Happy hacking! ?
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user