Blkhurst

January 29 2025

Data Type Wrapping

Stage 2 Area 6

The ASRM program requires three numerical inputs when attempting to repair the fuel mix:

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.

Ozone Hydrogen×3=2\text{Ozone Hydrogen} \times 3 = 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:

  1. What data type is used for Ozone Hydrogen.
  2. 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
  1. The input is read as an unsigned 64-bit integer (unsigned long long).
  2. The multiplication is performed using 64 bit registers (rax, rdx).

Because Ozone Hydrogen is a 64-bit unsigned integer, it wraps modulo 2642^{64}.

Calculating the Correct Input

We need to find a value xx such that:

3x2(mod264)3x \equiv 2 \pmod{2^{64}}

Therefore:

x=264+23x = \frac{2^{64} + 2}{3}

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) == 2

Entering 6148914691236517206 as Ozone Hydrogen solves the challenge!

Avoiding Numerical Overflow

Since UINT64_MAX is defined as 26412^{64}-1, we can rewrite the equation to avoid numerical overflow during computation:

x=264+23=UINT64_MAX+33=UINT64_MAX3+1x = \frac{2^{64} + 2}{3} = \frac{\text{UINT64\_MAX} + 3}{3} = \frac{\text{UINT64\_MAX}}{3} + 1