Box
2 minutos de lectura
Se nos proporciona el siguiente código en Python que cifra la flag:
from Crypto.Util.number import bytes_to_long
flag = open("flag.txt", "rb").read().strip()
TABLE = [
lambda a, b: f"({a}+{b})",
lambda a, b: f"({a}-{b})",
lambda a, b: f"({a}*{b})",
]
def build_box(s: bytes):
e = "(x)"
for b in s:
e = TABLE[b % len(TABLE)](e, b)
return eval(f"lambda x: {e}")
box = build_box(flag)
ct = box(bytes_to_long(flag))
print(ct)
print(box(1337))
print(box(0x1337))
"""
Output:
5545457088879574964209613711409478327714366805681091501255101702161458272094830554232779120250
3011454617406654839679120250
10002638090931457241529120250
"""
Se trata de una forma extraña de cifrar un mensaje. Básicamente, box
es un conjunto de operaciones que contiene una sola x
, y al llamar a box
con un valor dado, se sustituye dicho valor en la x
para obtener el resultado final.
Podemos ver cómo funciona box
:
$ python3 -q
>>>
>>> TABLE = [
... lambda a, b: f"({a}+{b})",
... lambda a, b: f"({a}-{b})",
... lambda a, b: f"({a}*{b})",
... ]
>>>
>>>
>>> def build_box(s: bytes):
... e = "(x)"
... for b in s:
... e = TABLE[b % len(TABLE)](e, b)
... return f"lambda x: {e}"
...
>>> box = build_box(b'ictf{fake_flag}')
>>> box
'lambda x: ((((((((((((((((x)+105)+99)*116)+102)+123)+102)-97)*107)*101)*95)+102)+108)-97)-103)*125)'
Como todas las operaciones son sumas y multiplicaciones, podemos expresar box
como una función lineal $\mathtt{box}{(x)} = mx + n$ para ciertos valores $m, n \in \mathbb{Z}$.
Nos dan $\mathtt{box}{(\mathtt{flag})}$, $\mathtt{box}{(1337)}$ y $\mathtt{box}{(0\text{x}1337)}$. Estos valores son suficientes para hallar $m$ y $n$ mediante un sistema de ecuaciones lineales:
$$ \begin{cases} \mathtt{box}{(1337)} = 1337 \cdot m + n \newline \mathtt{box}{(0\text{x}1337)} = 0\text{x}1337 \cdot m + n \newline \end{cases} $$
Por tanto,
$$ m = \frac{\mathtt{box}{(0\text{x}1337)} - \mathtt{box}{(1337)}}{0\text{x}1337 - 1337} \qquad n = \mathtt{box}{(1337)} - 1337 \cdot m $$
Una vez que tenemos $m$ y $n$, podemos encontrar la flag:
$$ \mathtt{box}{(\mathtt{flag})} = m \cdot \mathtt{flag} + n \iff \mathtt{flag} = \frac{\mathtt{box}{(\mathtt{flag})} - n}{m} $$
Ahora vamos a realizar las operaciones con Python:
>>> c = 5545457088879574964209613711409478327714366805681091501255101702161458272094830554232779120250
>>> c1 = 3011454617406654839679120250
>>> c2 = 10002638090931457241529120250
>>> m = (c2 - c1) // (0x1337 - 1337)
>>> n = c1 - 1337 * m
>>> x = (c - n) // m
>>> hex(x)
'0x696374667b776f775f737563685f6c696e6561725f736f5f656173797d'
>>> bytes.fromhex(hex(x)[2:])
b'ictf{wow_such_linear_so_easy}'