January 29 2025
Data Type Wrapping
Stage 2 Area 6
The ASRM program requires three numerical inputs when attempting to repair the fuel mix:
- Liquid Oxygen
- Fluorine Diborane
- Ozone Hydrogen
- Must be greater than 5
- Multiplied by 3
When entering arbitrary values, the program reveals that the final fuel mix must equal 2:
[ERROR] Bad fuel mix - looking for the value "2"Although the program asks for all three values, inspecting the assembly shows that Liquid Oxygen and Fluorine Diborane are never used in the final fuel-mix comparison. As a result, the only value that matters is Ozone Hydrogen.
The challenge is therefore to find an Ozone Hydrogen value greater than 5 that, when multiplied by 3, produces a final fuel mix of 2.
Since Ozone Hydrogen is an integer, this equation cannot be satisfied under normal conditions. This is where integer wrapping comes in. When a value exceeds the maximum limit of its data type, it wraps around and resets to zero. To solve this challenge, we need to determine:
- What data type is used for Ozone Hydrogen.
- What input value wraps correctly so that, after being multiplied by 3, it results in 2.
To determine the correct input, we can inspect the assembly code to identify the exact data type used for Ozone Hydrogen.
Analysing the Assembly Code
Finding the Data Type in Assembly
Examining the function responsible for retrieving Ozone Hydrogen, we notice:
; unsigned long long var_18h = 0 (qword)
0x621919800bc9 48c745e80000. mov qword [var_18h], 0
...
; scanf("%llu", &var_18h)
0x621919800be2 488d45e8 lea rax, [var_18h]
0x621919800be6 4889c6 mov rsi, rax
0x621919800be9 488d3d410600. lea rdi, str._llu ; "%llu"
0x621919800bf5 e836fcffff call sym.imp.__isoc99_scanf
...
; var_10h = var_18h * 3
0x621919800c6f 488b55e8 mov rdx, qword [var_18h]
0x621919800c73 4889d0 mov rax, rdx
0x621919800c76 4801c0 add rax, rax
0x621919800c79 4801d0 add rax, rdx
0x621919800c7c 488945f0 mov qword [var_10h], rax
0x621919800c80 48837df002 cmp qword [var_10h], 2- The input is read as an unsigned 64-bit integer (
unsigned long long). - The multiplication is performed using 64 bit registers (
rax,rdx).
Because Ozone Hydrogen is a 64-bit unsigned integer, it wraps modulo .
Calculating the Correct Input
We need to find a value such that:
Therefore:
Using Python's arbitrary precision, we can determine the correct value that, when multiplied by 3, wraps to 2:
wrap_input = (2**64 + 2) // 3 # 6148914691236517206
assert (wrap_input * 3) % (2**64) == 2Entering 6148914691236517206 as Ozone Hydrogen solves the challenge!
Avoiding Numerical Overflow
Since UINT64_MAX is defined as , we can rewrite the equation to avoid numerical overflow during computation: