We denote the 20 characters of $x$ as $c_0, \dots, c_{19}$. Then $x = \sum_{i=0}^{20} 256^{19-i} \cdot c_i$. Note that $c_{15} = \_, c_{16} = c, \dots, c_{19} = t$.
We will try to adapt rkm's inequality solver here. The inequalities that we have is:
- $1 \leq x \cdot T_i - U_i - a_i \cdot q \leq q / 4$ for $1 \leq i \leq 90$.
- $c_i \leq c_{i+1}$ for $0 \leq i \leq 18$
- $c_{0}, \dots, c_{14}$ is ascii uppercase or digits.
- $c_{15}, \dots, c_{19}$ is constant
Unfortunately, this condtion is not enough to find appropriate vector in CVP. So we added customized conditions:
- $c_0$ to $c_3$ is digits and $c_4$ to $c_{14}$ is ascii uppercase.
- $c_0 < c_1 < c_2 < c_3$.
- $c_{i+1} - c_i \leq 5$ for $4 \leq i \leq 13$.
- $c_4 \in {A,B,C}, c_{14} \in {X,Y,Z}$.
We test all possible candidates $c_0, c_1, c_2, c_3, c_4, c_{14}$ for each connection.
The probability that randomly chosen $x$ satisfies this is about 1.4%
. And if $x$ satistfies this, $x$ is reveal with a probability about 60%
. So We can estimate that we can succeed after about 120 trials. In each connection, the running time is about 2 minutes in my PC. So I ran 10 parallel connections.
########
from sage.modules.free_module_integer import IntegerLattice
from sage.all import *
from pwn import *
from Crypto.Util.number import *
from itertools import combinations
from multiprocessing import Pool
from random import randint, choices, seed
from string import ascii_uppercase, digits
q = 0
T = []
U = []
r = None
def conn():
global r,q,T,U
r = remote("190.92.233.181", 23334)
r.recvuntil(b" = ")
q = int(r.recvline())
r.recvuntil(b" = ")
T = eval(r.recvline())
r.recvuntil(b" = ")
U = eval(r.recvline())
# Directly taken from rbtree's LLL repository
# From https://oddcoder.com/LOL-34c3/, https://hackmd.io/@hakatashi/B1OM7HFVI
#def Babai_CVP(mat, target, M, G):
def Babai_CVP(M, G, target):
diff = target
for i in reversed(range(G.nrows())):
diff -= M[i] * ((diff * G[i]) / (G[i] * G[i])).round()
return target - diff
def solve(mat, lb, ub, weight = None):
num_var = mat.nrows()
num_ineq = mat.ncols()
max_element = 0
for i in range(num_var):
for j in range(num_ineq):
max_element = max(max_element, abs(mat[i, j]))
if weight == None:
weight = num_ineq * max_element
# sanity checker
if len(lb) != num_ineq:
print("Fail: len(lb) != num_ineq")
return
if len(ub) != num_ineq:
print("Fail: len(ub) != num_ineq")
return
for i in range(num_ineq):
if lb[i] > ub[i]:
print("Fail: lb[i] > ub[i] at index", i)
return
# heuristic for number of solutions
DET = 0
if num_var == num_ineq:
DET = abs(mat.det())
num_sol = 1
for i in range(num_ineq):
num_sol *= (ub[i] - lb[i])
if DET == 0:
print("Zero Determinant")
else:
num_sol //= DET
# + 1 added in for the sake of not making it zero...
print("Expected Number of Solutions : ", num_sol + 1)
# scaling process begins
# max_diff = max([ub[i] - lb[i] for i in range(num_ineq)])
# applied_weights = []
# for i in range(num_ineq):
# ineq_weight = weight if lb[i] == ub[i] else max_diff // (ub[i] - lb[i])
# # customized
# # if i < 12: ineq_weight *= 1
# applied_weights.append(ineq_weight)
# for j in range(num_var):
# mat[j, i] *= ineq_weight
# lb[i] *= ineq_weight
# ub[i] *= ineq_weight
# Solve CVP
target = vector([(lb[i] + ub[i]) // 2 for i in range(num_ineq)])
result = Babai_CVP(M, G, target)
for i in range(num_ineq):
if (lb[i] <= result[i] <= ub[i]) == False:
#print("Fail : inequality does not hold after solving")
return result, -1
fin = None
if DET != 0:
mat = mat.transpose()
fin = mat.solve_right(result)
## recover your result
return result, fin
varnum = 9 + 90 # c5 to c13, a0 to a89 (we fix c0,c1,c2c3,c4,c14)
eqnum = 10 + 90 # 10 : c condition, 90 : given equation
B = bytes_to_long(b'_cfrt')
mat = matrix(ZZ, varnum, eqnum)
M = None
G = None
def init_mat():
FACTOR = (q//4) // 5
#print(FACTOR)
#print(U[0])
global mat, M, G
mat = matrix(ZZ, varnum, eqnum)
M = None
G = None
#varnum = 9 + 90 # c5 to c13, a0 to a89 (we fix c0,c1,c2c3,c4,c14)
#eqnum = 10 + 90 # 10 : c condition, 90 : given equation
mat[0, 0] = 1 * FACTOR
for i in range(8):
mat[i, i+1] = -1* FACTOR
mat[i+1, i+1] = 1* FACTOR
mat[8, 9] = 1* FACTOR
# given equation
for i in range(90):
for j in range(9):
mat[j, i + 10] = T[i] * 256^(14 - j)
mat[i+9, i + 10] = -q
M = IntegerLattice(mat, lll_reduce=True).reduced_basis
G = M.gram_schmidt()[0]
print("init_mat done")
def LLL(c0, c1, c2, c3, c4, c14):
FACTOR = (q//4) // 5
#print("now", c0,c1,c2,c3)
varnum = 9 + 90 # c5 to c13, a0 to a89 (we fix c0,c1,c2c3,c4,c14)
eqnum = 10 + 90 # 10 : c condition, 90 : given equation
lb = [0]*eqnum
ub = [0]*eqnum
# c condition
lb[0] = 65* FACTOR
ub[0] = 70* FACTOR
for i in range(8):
lb[i+1] = 0* FACTOR
ub[i+1] = 5* FACTOR
lb[9] = 85* FACTOR
ub[9] = 90* FACTOR
# given equation
for i in range(90):
lb[i+10] = U[i]+1 - T[i] * (B + c0 * 256^19 + c1 * 256^18 + c2 * 256^17 + c3 * 256^16 + c4 * 256^15 + c14 * 256^5)
ub[i+10] = U[i]+q//4 - T[i] * (B + c0 * 256^19 + c1 * 256^18 + c2 * 256^17 + c3 * 256^16 + c4 * 256^15 + c14 * 256^5)
res, fin = solve(M, lb, ub)
#for i in range(10):
# print(res[i] // FACTOR)
if fin == -1:
return None
S = chr(c0) + chr(c1) + chr(c2) + chr(c3) + chr(c4)
S += chr(res[0] // FACTOR)
for i in range(1,9):
gap = res[i] // FACTOR
S += chr(ord(S[-1]) + gap)
S += chr(c14)
S += '_cfrt'
print("!!!!!!!!!!!!!!!!!!!!!!!!!")
print(S)
print("!!!!!!!!!!!!!!!!!!!!!!!!!")
vv = bytes_to_long(S.encode())
r.sendline(str(vv).encode())
print(r.recvline())
r.interactive()
exit(0)
return S
def gogo():
conn()
init_mat()
COMB_NUM = list(combinations(list(range(48,58)), 4))
COMB = []
for a in range(65, 68):
for b in range(88, 91):
for elem in COMB_NUM:
z = list(elem[:])
z.append(a)
z.append(b)
COMB.append(z)
print("brute len", len(COMB))
#zz = sorted(key)
#recover = LLL(ord(zz[0]),ord(zz[1]),ord(zz[2]),ord(zz[3]),ord(zz[4]),ord(zz[14]))
#print("!!!", recover)
#input()
#exit()
#r = get_data()
with Pool(16) as p:
result = p.starmap(LLL, COMB)
for vv in result:
if vv: print(vv)
r.close()
CNT = 0
while True:
CNT+=1
print("@@@@@@ NOW ", CNT, "@@@@@@")
gogo()
#LLL(3,3,6,9)
'CTF > Crypto' 카테고리의 다른 글
[RCTF 2022] easyrsa (3) | 2022.12.13 |
---|---|
[RCTF 2022] magicsign (0) | 2022.12.13 |
[RCTF 2022] guess (2) | 2022.12.13 |
[SECCON CTF 2022] janken vs kurenaif (0) | 2022.11.13 |
[SECCON CTF 2022] this_is_not_lsb (0) | 2022.11.13 |
[LINE CTF 2022] lazy_stek (0) | 2022.03.27 |