ReversingHidden Investigations CTF 2026
Epsilon Drift
Static Fortran binary validates 4 doubles from a hex vector. The key insight: d2 must be fl(1.1+2.2)=3.3000000000000003 (not 3.3), and d3 must be negative zero — IEEE-754 rounding and signed zero matter.
What this one teaches
- IEEE-754 floating-point addition is not exact — 1.1+2.2 rounds to 3.3000000000000003, not 3.3, and a validator can check for this.
- Negative zero (-0.0) compares equal to +0.0 but has a different bit pattern (sign bit set), which programs can distinguish.
- Decomposing modular-arithmetic checks on 13-bit mantissa fields into a 2×2 linear system to recover the original doubles.
Task description
... recovered from the tail of a solver run log ... step 48216 residual 3.300000000000000e+00 WARN rounding step 48217 residual nominal step 48218 calibration vector ACCEPTED -> unlocked run config step 48219 checkpoint flushed -- validator kept standalone. feed it the calibration vector as one argument, hex-encoded; it reprints the run config it unlocks: ./epsilon-drift <hexvector> off-spec vectors just log drift. the vector itself was not archived.Linux x86-64 ELF.
Approach
The vector
d0 = 1.1, d1 = 2.2, d2 = fl(1.1 + 2.2) = 3.3000000000000003 (0x400A666666666667, NOT 3.3), d3 = -0.0
9a9999999999f13f9a999999999901406766666666660a400000000000000080
Derivation
Checks in MAIN__ (A = bits(d0), B = bits(d1), fields: sign, 11-bit exponent, mantissa as four 13-bit fields a0 (bits 0–12), a2 (13–25), a3 (26–38), a4 (39–51)):
- sign(A) = sign(B) = 0.
- bits(d0 + d1) == bits(d2) (exact double add, so rounding matters: this is the “WARN rounding” 3.3 in the log).
- For each field i: (a_i + b_i) mod 2^13 and (a_i + 2·b_i) mod 2^13 are fixed constants (0x1334/0xcce, 0x1998/0x664, 0xccc/0x1332, 0x666/0x999); exponent: (ea+eb) mod 2^11 = 0x7ff, (ea+2·eb) mod 2^11 = 0x3ff.
- Solving the pairs: b_i = t_i − s_i, a_i = 2·s_i − t_i. This gives mantissas 0x199999999999A for both, ea = 0x3ff, eb = 0x400 → d0 = 1.1, d1 = 2.2.
- d3 must compare equal to 0; its sign bit selects the success flag (esi=1 only for -0.0). +0.0 prints “out of band”, so d3 = -0.0 (bytes
...0080).
Running ./epsilon-drift <vector> prints the flag.
Lessons
- The “WARN rounding” in the log is the hint: 1.1 + 2.2 ≠ 3.3 in IEEE-754 doubles.
- Negative zero is a classic edge case in floating-point challenges — it compares equal to +0.0 but has a distinct bit pattern.
The flagReveal
hiCTF{1eee754_s1gn3d_z3r0_1u1p_dr1ft_eps!}This CTF was possibly solved, and the writeup most likely written by an LLM. Apologies for inconsistencies.