Tags: crypto math 

Rating:

Notice that `' '`(`chr(32)`) becomes `0` after passing `stov()`,
we can construct a string with `' '`s and only one `chr(33)` in each half, so

$$\begin{bmatrix}
a_{11}& a_{12} &\dots & a_{1n}\\
a_{21}& a_{22} &\dots & a_{2n}\\
a_{31}& a_{32} &\dots & a_{3n}\\
\vdots & \vdots& \ddots & \vdots\\
a_{n1}& a_{n2} &\dots & a_{nn}
\end{bmatrix}
\begin{bmatrix}
0\\
\vdots\\
x_j=1\\
\vdots\\
0
\end{bmatrix}=
\begin{bmatrix}
a_{1j}\\
a_{2j}\\
a_{3j}\\
\vdots\\
a_{nj}
\end{bmatrix}$$

(The latex may be broken here, please refer to the original writeup)

In each query, we can reveal two columns of `A`, so in 10 queries, we can reveal all data in `A`. Then you can just use `A` to encrypt `fakeflag2` and get the flag.

```py
#!/usr/local/bin/python3

import numpy as np

n = 20

A = np.matrix([[0 for i in range(n)] for i in range(n)])

def stov(s):
return np.array([ord(c)-32 for c in s])

def vtos(v):
return ''.join([chr(v[0,i]+32) for i in range(n)])

def encrypt(s):
return vtos(np.matmul(A, stov(s))%95)

from pwn import *
# context(log_level='debug')

r = remote('lac.tf',31140)
# r = process(['python','chall.py'])

r.recvuntil(b'On the hill lies a stone. It reads:\n')
r.recvline()
r.recvline()
r.recvuntil(b'\nA mysterious figure offers you 10 attempts at decoding the stone:')
for i in range(10):
r.sendline(b' '*i+b'!'+b' '*(19-i)+b' '*(i+10)+b'!'+b' '*(9-i))
r.recvuntil(b'Incorrect:\n')
r1 = stov(r.recvline().decode().strip('\n'))
r2 = stov(r.recvline().decode().strip('\n'))
for j in range(n):
A[j,i] = r1[j]
A[j,i+10] = r2[j]

r.recvuntil(b"Create a new stone that decodes to the following:\n")
fakeflag2 = r.recvline().strip().decode()
f3 = encrypt(fakeflag2[:n])
f4 = encrypt(fakeflag2[n:])

r.recvuntil(b'Enter the first half: ')
r.sendline(f3.encode())
r.recvuntil(b'Enter the second half: ')
r.sendline(f4.encode())

r.interactive()

# lactf{tHeY_SaiD_l!NaLg_wOuLD_bE_fUN_115}
```

Original writeup (https://tiefsee5037008.github.io/posts/LA-CTF-Writeup/#hill-easy).