Files
Embedded-Hacking/WEEK09/WEEK09-02-S.md
T
2026-03-19 15:01:07 -04:00

67 lines
3.7 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Embedded Systems Reverse Engineering
[Repository](https://github.com/mytechnotalent/Embedded-Hacking)
## Week 9
Operators in Embedded Systems: Debugging and Hacking Operators w/ DHT11 Basics
### Non-Credit Practice Exercise 2 Solution: Invert the Temperature Reading
#### Answers
##### IEEE-754 Sign Bit Flip
| Value | IEEE-754 Hex | Little-Endian Bytes | Sign Bit |
|---------|--------------|--------------------|---------|
| +0.1f | 0x3DCCCCCD | CD CC CC 3D | 0 |
| -0.1f | 0xBDCCCCCD | CD CC CC BD | 1 |
Only the **last byte** changes in little-endian: `3D``BD`. This flips bit 31 (the IEEE-754 sign bit) from 0 to 1, negating the value.
##### Patch at File Offset 0x42C
```
Offset 0x42C:
Before: CD CC CC 3D (+0.1f)
After: CD CC CC BD (-0.1f)
```
Only 1 byte changes: offset `0x42F` from `0x3D` to `0xBD`.
##### How the Temperature Changes
The DHT11 returns raw integer and decimal parts (e.g., integer=24, decimal=0). The firmware computes:
```
temperature = integer_part + (decimal_part × 0.1f)
```
With `vfma.f32 s15, s13, s11`: result = s15 + (s13 × s11) = integer + (decimal × 0.1f)
After patching to -0.1f: result = integer + (decimal × -0.1f)
For a reading of 24.5°C: original = 24 + (5 × 0.1) = 24.5°C, patched = 24 + (5 × -0.1) = 23.5°C
For a reading of 24.0°C: integer=24, decimal=0, so 24 + (0 × -0.1) = 24.0°C (unchanged when decimal is 0).
##### Serial Output After Patch
```
Humidity: 51.0%, Temperature: 23.5°C
```
(Temperature decimal contribution is inverted; effect depends on the decimal component.)
#### Reflection Answers
1. **Why does changing the byte from 0x3D to 0xBD negate the float? What specific bit is being flipped?**
In IEEE-754 single-precision format, bit 31 is the **sign bit**: 0 = positive, 1 = negative. The byte `0x3D` in binary is `0011 1101` and `0xBD` is `1011 1101` — only bit 7 of that byte differs, which corresponds to bit 31 of the 32-bit float (since it's the MSB of the last byte in little-endian storage). The exponent and mantissa bits remain identical, so the magnitude stays exactly `0.1` — only the sign changes.
2. **Why does patching one constant affect both humidity AND temperature? They use different vfma instructions (at 0x410 and 0x414) — so why are both affected?**
Both `vfma` instructions at `0x410` (humidity) and `0x414` (temperature) load the scaling constant from the **same literal pool entry** at offset `0x42C`. The compiler recognized that both computations use the same `0.1f` value and stored it only once to save space. Both `vldr s11, [pc, #offset]` instructions resolve to address `0x1000042C`. So patching that single 4-byte value changes the scaling factor for both humidity and temperature simultaneously.
3. **What is the IEEE-754 encoding of 0.5f? If the raw sensor decimal reading was 8, what would the computed value be with 0.5f instead of 0.1f?**
0.5f in IEEE-754: sign=0, exponent=126 (`0x7E`), mantissa=0. Hex = `0x3F000000`. Little-endian bytes: `00 00 00 3F`. With a raw decimal reading of 8: `8 × 0.5 = 4.0`. So if the integer part was 24, the result would be `24 + 4.0 = 28.0°C` instead of `24 + 0.8 = 24.8°C`.
4. **Could you achieve the same inversion by patching the vfma instruction instead of the constant? What instruction change would work?**
Yes. You could change `vfma.f32` (fused multiply-add: d = d + a×b) to `vfms.f32` (fused multiply-subtract: d = d - a×b). This would compute `temperature = integer - (decimal × 0.1f)` instead of `integer + (decimal × 0.1f)`, achieving the same sign inversion on the decimal contribution. The instruction encoding difference between `vfma` and `vfms` is typically a single bit in the opcode. However, this approach is more complex than simply flipping the sign bit of the constant.