Above#
Team : Dawn-DAMN
Score : 4733
Rank : 13
Crypto Solved 2 of 3
lost LFSR key#
task.py
from Crypto.Util.number import *
from secret import flag
from random import *
flag = flag.strip(b"DASCTF{").strip(b"}")
assert len(flag) == 64
class myRNG():
def init(self,seed=None):
if(seed):
self.seed = seed
else:
self.seed = getrandbits(64)
self.mask = getrandbits(64)
def next(self):
i = self.seed & self.mask
Out = 0
while i != 0:
Out = Out ^ (i & 1)
i = i >> 1
self.seed = ((self.seed << 1) | Out) & ((1 << 64) - 1)
return Out
def get_myRNG_randbits(self,n):
temp = 0
for i in range(n):
temp = (temp << 1) | self.next()
return temp
generator = myRNG()
key = generator.get_myRNG_randbits(64*8)
print("mask =", generator.mask)
print("c =", key ^ bytes_to_long(flag))
'''
mask = 9319439021858903464
c = 8882504877732087312989345828667663333297225833982945014279010438327750150593504327259176959316943362605442206624947923157363187067410478202161873663103506
'''pyLFSR的题 关键洞在
key = generator.get_myRNG_randbits(64*8)
c = key ^ bytes_to_long(flag) pyflag是给定的64字节 与key的8*64bits重合 而且flag的内部全是可视ASCII 意味着每8个bits中的最高位都一定是0 那我们就得到了64个已知的信息Bit
也就是说就是我们的key 也就是LFSR的输出 而LFSR的运算可以转化为上的线性运算 所以说64个已知位结合我们已知的64位mask ,可以构造64组方程 足矣解出我们初始的64位State 也就是Seed 获得Seed之后直接解出key 然后求flag即可
exp
from Crypto.Util.number import long_to_bytes
from itertools import product
# 题目给出的参数
mask = 9319439021858903464
c = 8882504877732087312989345828667663333297225833982945014279010438327750150593504327259176959316943362605442206624947923157363187067410478202161873663103506
# PRNG 类(用于验证和解密)
class myRNG:
def __init__(self, seed, mask):
self.seed = seed
self.mask = mask
def next(self):
i = self.seed & self.mask
Out = 0
while i != 0:
Out = Out ^ (i & 1)
i = i >> 1
self.seed = ((self.seed << 1) | Out) & ((1 << 64) - 1)
return Out
def get_myRNG_randbits(self, n):
temp = 0
for i in range(n):
temp = (temp << 1) | self.next()
return temp
def solve():
print("正在分析并求解线性方程组...")
N = 64
# 1. 收集约束条件
# Flag 为 64 字节,假定为 ASCII,则每字节最高位(MSB)为 0
# 对应关系: Key_bit ^ Flag_bit = C_bit => Key_bit = C_bit
targets = {}
for i in range(64):
# 512位整数中,第 i 个字节的 MSB 位置 (从高到低)
pos = 511 - 8 * i
# 该位是由 RNG 的第 step 步产生的
step = 8 * i
# 提取密文对应位
val = (c >> pos) & 1
targets[step] = val
# 2. 建立方程组
# state[k] 表示当前状态第 k 位受哪些初始 seed 位(x0...x63)的影响
state = [1 << k for k in range(N)]
equations = []
max_step = max(targets.keys())
for step in range(max_step + 1):
out_mask = 0
for k in range(N):
if (mask >> k) & 1:
out_mask ^= state[k]
if step in targets:
equations.append((out_mask, targets[step]))
new_state = [0] * N
new_state[0] = out_mask
for k in range(1, N):
new_state[k] = state[k-1]
state = new_state
M = [(eq[0] << 1) | eq[1] for eq in equations]
pivot_row = 0
pivots = {} # col -> row
for col in range(N):
pivot_idx = -1
for r in range(pivot_row, len(M)):
if (M[r] >> (col + 1)) & 1:
pivot_idx = r
break
if pivot_idx == -1:
continue
M[pivot_row], M[pivot_idx] = M[pivot_idx], M[pivot_row]
for r in range(len(M)):
if r != pivot_row:
if (M[r] >> (col + 1)) & 1:
M[r] ^= M[pivot_row]
pivots[col] = pivot_row
pivot_row += 1
# 4. 识别自由变量并遍历解空间
free_vars = [k for k in range(N) if k not in pivots]
print(f"矩阵秩: {len(pivots)}, 自由变量数量: {len(free_vars)}")
print(f"自由变量索引: {free_vars}")
for free_vals in product([0, 1], repeat=len(free_vars)):
seed_val = 0
# 设置自由变量的值
for i, k in enumerate(free_vars):
if free_vals[i]:
seed_val |= (1 << k)
for k in range(N):
if k in pivots:
r = pivots[k]
row = M[r]
rhs = row & 1
coeffs = row >> 1
# 排除 x_k 自身
coeffs &= ~(1 << k)
# 计算已知部分的异或和
p = 0
temp = coeffs & seed_val
while temp:
p ^= 1
temp &= (temp - 1)
if rhs ^ p:
seed_val |= (1 << k)
try:
gen = myRNG(seed_val, mask)
key = gen.get_myRNG_randbits(64*8)
flag_int = c ^ key
flag_bytes = long_to_bytes(flag_int)
if len(flag_bytes) < 64:
flag_bytes = b'\x00' * (64 - len(flag_bytes)) + flag_bytes
if all(0x20 <= b <= 0x7E for b in flag_bytes):
print("\n[+] 找到有效 Flag!")
print(f"Recovered Seed: {seed_val}")
try:
flag_content = flag_bytes.decode()
print(f"Flag: DASCTF{{{flag_content}}}")
return
except:
print(f"Flag Bytes: {flag_bytes}")
except Exception:
continue
if __name__ == "__main__":
solve()
'''
正在分析并求解线性方程组...
矩阵秩: 63, 自由变量数量: 1
自由变量索引: [62]
[+] 找到有效 Flag!
Recovered Seed: 15343720169816213745
Flag: DASCTF{f1nd_th3_hidden_Linear_R3lat1onShip_@nd_th3n_F1nd_My_Lo5t_KEY!!!}
'''pyTwo_Examples#
task.py
from Crypto.Util.number import *
import json
from hashlib import *
from gmpy2 import *
from flag import flag
n= 20
m = 30
p = getPrime(160)
A = [random_vector(GF(p),m) for _ in range(n)]
B = [random_vector(GF(p),m) for _ in range(n)]
A = matrix(GF(p),A)
B = matrix(GF(p),B)
s1 = random_vector(GF(p),n)
s2 = random_vector(GF(p),n)
e1 = vector(GF(p),[choice([-1,0,1]) for _ in range(m)])
e2 = vector(GF(p),[choice([-1,0,1]) for _ in range(m)])
b1 = s1*A + s2*B + e1
b2 = s2*A + s1*B + e2
with open('M.matrix','w') as f:
json.dump({"A": str(list(A)),"B": str(list(B)),"p":str(p)}, f)
with open('v.vector','w') as f:
json.dump({"b1": str(list(b1)),"b2": str(list(b2))}, f)
def vector_to_sha512_hex(vector):
vector_str = ''.join(str(i) for i in vector)
res = sha512(vector_str.encode()).hexdigest()
res = int(res,16)
return res
d = vector_to_sha512_hex(s1) + vector_to_sha512_hex(s2)
P = getPrime(512)
Q = getPrime(512)
N = P*Q
phi = (P-1)*(Q-1)
while gcd(d,phi) != 1:
d += 1
e = inverse(d,phi)
flag = bytes_to_long(flag)
c = power_mod(flag,e,N)
with open('RSA.enc','w') as f:
json.dump({"N": str(N),"c": str(c)}, f)py很经典的LWE问题了 choice的选取也非常小 在WMCTF的Lwe出过比这个更近一步的 我们直接参考鸡块师傅的板子 LWE | 糖醋小鸡块的blog (tangcuxiaojikuai.xyz) ↗
exp
import json
from hashlib import sha512
from Crypto.Util.number import long_to_bytes
from sage.all import *
print("[*] Loading data...")
try:
with open('M.matrix', 'r') as f:
data_m = json.load(f)
p = int(data_m["p"])
A_list = eval(data_m["A"])
B_list = eval(data_m["B"])
with open('v.vector', 'r') as f:
data_v = json.load(f)
b1_list = eval(data_v["b1"])
b2_list = eval(data_v["b2"])
with open('RSA.enc', 'r') as f:
data_rsa = json.load(f)
N = int(data_rsa["N"])
c = int(data_rsa["c"])
except FileNotFoundError:
print("[-] Error: Data files not found.")
exit()
# 初始化参数
n = 20
m = 30
F = GF(p)
A = matrix(F, A_list)
B = matrix(F, B_list)
b1 = vector(F, b1_list)
b2 = vector(F, b2_list)
print(f"[*] Parameters: n={n}, m={m}, p={p.bit_length()} bits")
M_plus = A + B
b_plus = b1 + b2
M_minus = A - B
b_minus = b1 - b2
# 3. 定义 Primal Attack 函数
def solve_primal_attack(M, b, modulus):
m_dim = M.ncols() # 30
n_dim = M.nrows() # 20
block1 = matrix.identity(m_dim) * modulus
block2 = M.change_ring(ZZ)
block3 = matrix(ZZ, -b)
col_zeros_m = matrix.zero(m_dim, 1)
col_zeros_n = matrix.zero(n_dim, 1)
col_one = matrix.identity(1)
# 组装
row1 = block1.augment(col_zeros_m) # 30 x 31
row2 = block2.augment(col_zeros_n) # 20 x 31
row3 = block3.augment(col_one) # 1 x 31
L = block_matrix([[row1], [row2], [row3]])
print(f" Running LLL on lattice dimension {L.nrows()}x{L.ncols()}...")
L_reduced = L.LLL()
e_vec = None
for row in L_reduced:
last_val = row[-1]
vec_part = row[:-1]
if last_val == 1:
e_candidate = vector(F, [-x for x in vec_part])
try:
target = b - e_candidate
s_sol = M.solve_left(target)
e_vec = e_candidate
print(" [+] Error recovered (row end 1).")
return s_sol, e_vec
except ValueError:
continue
elif last_val == -1:
# row = (e, -1) => e = vec_part
e_candidate = vector(F, [x for x in vec_part])
try:
target = b - e_candidate
s_sol = M.solve_left(target)
e_vec = e_candidate
print(" [+] Error recovered (row end -1).")
return s_sol, e_vec
except ValueError:
continue
raise ValueError("Failed to recover e using Primal Attack")
print("[*] Solving for s_plus (s1+s2)...")
s_plus, e_plus = solve_primal_attack(M_plus, b_plus, p)
print("[*] Solving for s_minus (s1-s2)...")
s_minus, e_minus = solve_primal_attack(M_minus, b_minus, p)
inv_2 = F(2).inverse()
s1 = (s_plus + s_minus) * inv_2
s2 = (s_plus - s_minus) * inv_2
print("[+] s1 and s2 reconstructed.")
def vector_to_sha512_hex(vec):
vector_str = ''.join(str(i) for i in vec)
res = sha512(vector_str.encode()).hexdigest()
res = int(res, 16)
return res
d_base = vector_to_sha512_hex(s1) + vector_to_sha512_hex(s2)
print(f"[*] Base d: {d_base}...")
print("[*] Searching for valid flag...")
for i in range(500):
d_guess = d_base + i
m_int = power_mod(c, d_guess, N)
try:
m_bytes = long_to_bytes(int(m_int))
if b'flag{' in m_bytes or b'CTF{' in m_bytes:
print("\n" + "#"*50)
print(f"FLAG FOUND with d_offset={i}:")
print(m_bytes.decode())
print("#"*50 + "\n")
break
except:
pass
else:
print("[-] Flag not found in range.")
'''
[*] Loading data...
[*] Parameters: n=20, m=30, p=160 bits
[*] Solving for s_plus (s1+s2)...
Running LLL on lattice dimension 51x31...
[+] Error recovered (row end 1).
[*] Solving for s_minus (s1-s2)...
Running LLL on lattice dimension 51x31...
[+] Error recovered (row end 1).
[+] s1 and s2 reconstructed.
[*] Base d: 15829519161807649604997063627428333703080852958448411437324803691092722399601763346879632976849254515081077292041342199672094869180782512862924423581282470...
[*] Searching for valid flag...
##################################################
FLAG FOUND with d_offset=3:
DASCTF{Y0U_Can_S01ve_The_lwe!!!!}
##################################################
'''pySerration#
main.py
from Crypto.Util.number import *
from hashlib import sha256
import socketserver
import signal
import os
import string
import random
from sympy.ntheory.modular import crt
from line_profiler import LineProfiler
flag = os.getenv('DASFLAG')
def euclide_ext(a, b):
x, xx, y, yy = 1, 0, 0, 1
while b:
q = a // b
a, b = b, a % b
x, xx = xx, x - xx * q
y, yy = yy, y - yy * q
return x, y, a
class Montgomery:
n: int
k: int
r: int
r_inv: int
n_inv: int
def __init__(self, n, k):
self.n = n
self.k = k
self.r = 2 ** k
self.r_inv, self.n_inv, gcd = euclide_ext(self.r, self.n)
self.n_inv = -self.n_inv
if gcd != 1:
raise ValueError("gcd(r,n) must be 1")
if self.r * self.r_inv - self.n * self.n_inv != 1:
raise ValueError(
f"For ({self.r} that created from {2} ** {k},{n}) doesn't exists diophantine equation decision"
)
self.r_inv = self.r_inv % self.n
def mon_pro(self, a_n, b_n):
t = a_n * b_n
u = (t + (t * self.n_inv % self.r) * self.n) >> self.k
if u > self.n:
u -= self.n
return u
def mon_exp(self, a: int, e: int):
a = a * self.r % self.n
x = self.r % self.n
for i in reversed(range(0, e.bit_length())):
x= self.mon_pro(x, x)
if (e & (1 << i)) :
x= self.mon_pro(x, a)
return self.mon_pro(x, 1)
class Task(socketserver.BaseRequestHandler):
def _recvall(self):
BUFF_SIZE = 2048
data = b''
while True:
part = self.request.recv(BUFF_SIZE)
data += part
if len(part) < BUFF_SIZE:
break
return data.strip()
def send(self, msg, newline=True):
try:
if newline:
msg += b'\n'
self.request.sendall(msg)
except:
pass
def recv(self, prompt=b'> '):
self.send(prompt, newline=False)
return self._recvall()
def handle(self):
bits=1024
p=getPrime(bits)
q=getPrime(bits)
e=getPrime(bits-10)
n=p*q
print(p,",",q)
print(flag)
P=Montgomery(p,bits)
Q=Montgomery(q,bits)
self.send(str((n,e)).encode())
signal.alarm(300)
for i in range(600):
lp = LineProfiler()
lp.add_function(Q.mon_pro)
lp_exp = lp(P.mon_exp)
lq_exp = lp(Q.mon_exp)
self.send(b"leave message 4 me",newline=False)
m=int(self.recv())
cp=lp_exp(m,e)
cq=lq_exp(m,e)
c=crt([p,q],[cp,cq])
d={}
for i in lp.code_map:
for j in lp.code_map[i]:
d[j]=(lp.code_map[i][j]['total_time'],lp.code_map[i][j]['nhits'])
self.send(str(d).encode())
self.send(b"can you break me?",newline=False)
guess=int(self.recv())
if guess in {p,q}:
self.send(flag.encode())
else:
self.send(b"sorry~")
exit
class ThreadedServer(socketserver.ThreadingMixIn, socketserver.TCPServer):
pass
class ForkedServer(socketserver.ForkingMixIn, socketserver.TCPServer):
pass
if __name__ == "__main__":
HOST, PORT = '0.0.0.0', 9999
print("HOST:POST " + HOST+":" + str(PORT))
server = ForkedServer((HOST, PORT), Task)
server.allow_reuse_address = True
server.serve_forever()
py题目构造了一个基于蒙哥马利额外约简的RSA靶机 在生成1024位的p q后要求你进行选择明文攻击 以RSA-CRT的形式对传入的m进行加密 随后告知你有关加密过程中某一个模数因子p的侧信道
d[j]=(lp.code_map[i][j]['total_time'],lp.code_map[i][j]['nhits'])py参考Paper https://link.springer.com/chapter/10.1007/3-540-44499-8_8 ↗
关键漏洞在我们的
def mon_pro(self, a_n, b_n):
t = a_n * b_n
u = (t + (t * self.n_inv % self.r) * self.n) >> self.k
if u > self.n:
u -= self.n
return u
py我们梳理一下
随后再考虑对进行约简 ,我们可以控制的是输入的 ,后续的 都是由第一次的计算结果递推而来,同时由于
P=Montgomery(p,bits)
Q=Montgomery(q,bits)py我们实际上用的是模数 所以说我们很难做到通过控制的来直接简单的估计最终进行约简比较的的范围 这计算很复杂 但是我们侧信道主要的时间开销差异也就是在
if u > self.n:
u -= self.npy而我们获得的total_time统计是混在一起的 所以说第一步我们需要把这里的Reduction_Line找出来 也就是剥离其他无关操作的影响
我们传入一个很小的数 0就不错 然后再一个很大的数 建议和的数量级接近 这样我们就能找到对大小最敏感的这一行的取值
剥离了噪音的影响 接下来我们的每次选择明文攻击都能直接揭示输入明文和其中模数之间的大小关系
也就是
guessbit为0或者1会对我们的产生巨大的影响 从而在我们的约简行中产生巨大的开销变化 但是这里不能精确观察到每一位Bit对我们的数据的影响 但是可以通过反复的假设来确定某一位的比特 600次轮询足够我们获取到超过550位的比特信息 剩下的地位交给CopperSmith
exp
from pwn import *
import ast
import time
HOST = '117.21.200.176'
PORT = 26057
RECOVER_BITS = 590
THRESHOLD = -80
context.log_level = 'info'
def solve():
# [Init] 连接
try:
io = remote(HOST, PORT)
except Exception as e:
log.error(f"连接失败: {e}")
return
log.info("接收公钥中...")
while True:
line = io.recvline().decode().strip()
if line.startswith('('):
n, e = ast.literal_eval(line)
break
log.success(f"N bits: {n.bit_length()}")
r_inv = inverse_mod(1 << 1024, n)
interaction_count = 0
def probe(val_int):
nonlocal interaction_count
try:
io.recvuntil(b"> ", timeout=5)
io.sendline(str(val_int).encode())
line = io.recvline().decode().strip()
interaction_count += 1
if not line: return {}
if '{' in line:
line = line[line.find('{'):]
return ast.literal_eval(line)
except Exception as e:
return {}
log.info("校准侧信道...")
d0 = probe(0)
payload_max = ((n - 1) * r_inv) % n
d1 = probe(payload_max)
leak_line = None
highest_diff = -1
unique_lines = set(d0.keys()) | set(d1.keys())
for k in unique_lines:
h0 = d0.get(k, (0,0))[1]
h1 = d1.get(k, (0,0))[1]
diff = h1 - h0
if diff > highest_diff:
highest_diff = diff
leak_line = k
baseline_hits = d0.get(leak_line, (0,0))[1]
log.success(f"Leak Line: {leak_line}")
log.info(f"Base Hits (Zero): {baseline_hits}")
log.info(f"Max Diff: {highest_diff}")
if highest_diff < 50:
log.warning("信噪比过低,可能失败")
log.info(f"开始恢复高位...")
recovered = 0
current_hits = baseline_hits
pbar = log.progress('Recovering')
for b in range(1023, 1023 - RECOVER_BITS, -1):
cand = recovered | (1 << b)
payload = (cand * r_inv) % n
stats = probe(payload)
obs_hits = stats.get(leak_line, (0, 0))[1]
diff = obs_hits - current_hits
if diff > THRESHOLD:
recovered = cand
current_hits = obs_hits
else:
pass
if (1023 - b) % 20 == 0:
pbar.status(f"Bits: {1023-b} | Hex: {hex(recovered)}...")
pbar.success("Done")
log.info(f"Recovered: {hex(recovered)}")
left = 600 - interaction_count
if left > 0:
log.info(f"消耗剩余 {left} 次查询...")
for _ in range(left):
probe(0)
log.info("运行 Coppersmith...")
p_high = recovered
unknown_bits = 1024 - RECOVER_BITS
P = PolynomialRing(Zmod(n), 'x')
x = P.gen()
f = p_high + x
f = f.monic()
try:
roots = f.small_roots(X=2**(unknown_bits + 15), beta=0.49, epsilon=0.03)
if roots:
p_cand = int(p_high + roots[0])
log.success(f"找到 p: {p_cand}")
if n % p_cand == 0:
log.success("验证成功,获取 Flag...")
io.recvuntil(b"can you break me?")
io.sendline(str(p_cand).encode())
flag = io.recvall().decode().strip()
print("\n" + "="*40)
print(flag)
print("="*40 + "\n")
else:
log.failure("p 验证失败")
else:
log.failure("未找到根,请检查恢复的高位是否正确 (是否为 0xee...)")
except Exception as e:
log.error(f"Coppersmith Error: {e}")
io.close()
if __name__ == "__main__":
solve()
'''
[x] Opening connection to 117.21.200.176 on port 26057
[x] Opening connection to 117.21.200.176 on port 26057: Trying 117.21.200.176
[+] Opening connection to 117.21.200.176 on port 26057: Done
[*] 接收公钥中...
[+] N bits: 2048
[*] 校准侧信道...
[+] Leak Line: 48
[*] Base Hits (Zero): 0
[*] Max Diff: 1042
[*] 开始恢复高位...
[x] Recovering
[x] Recovering: Bits: 0 | Hex: 0x8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000...
[x] Recovering: Bits: 20 | Hex: 0xf58c100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000...
[x] Recovering: Bits: 40 | Hex: 0xf58c1458f5800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000...
[x] Recovering: Bits: 60 | Hex: 0xf58c1458f5d43538000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000...
[x] Recovering: Bits: 80 | Hex: 0xf58c1458f5d4353d738e80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000...
[x] Recovering: Bits: 100 | Hex: 0xf58c1458f5d4353d738ec00ef800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000...
[x] Recovering: Bits: 120 | Hex: 0xf58c1458f5d4353d738ec00efb69ab8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000...
[x] Recovering: Bits: 140 | Hex: 0xf58c1458f5d4353d738ec00efb69abbcac380000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000...
[x] Recovering: Bits: 160 | Hex: 0xf58c1458f5d4353d738ec00efb69abbcac3fd10e800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000...
[x] Recovering: Bits: 180 | Hex: 0xf58c1458f5d4353d738ec00efb69abbcac3fd10edf2ee8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000...
[x] Recovering: Bits: 200 | Hex: 0xf58c1458f5d4353d738ec00efb69abbcac3fd10edf2eef26af00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000...
[x] Recovering: Bits: 220 | Hex: 0xf58c1458f5d4353d738ec00efb69abbcac3fd10edf2eef26af72184000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000...
[x] Recovering: Bits: 240 | Hex: 0xf58c1458f5d4353d738ec00efb69abbcac3fd10edf2eef26af72184115340000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000...
[x] Recovering: Bits: 260 | Hex: 0xf58c1458f5d4353d738ec00efb69abbcac3fd10edf2eef26af72184115344eeaf80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000...
[x] Recovering: Bits: 280 | Hex: 0xf58c1458f5d4353d738ec00efb69abbcac3fd10edf2eef26af72184115344eeafe63b9000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000...
[x] Recovering: Bits: 300 | Hex: 0xf58c1458f5d4353d738ec00efb69abbcac3fd10edf2eef26af72184115344eeafe63b92f65d8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000...
[x] Recovering: Bits: 320 | Hex: 0xf58c1458f5d4353d738ec00efb69abbcac3fd10edf2eef26af72184115344eeafe63b92f65dc442180000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000...
[x] Recovering: Bits: 340 | Hex: 0xf58c1458f5d4353d738ec00efb69abbcac3fd10edf2eef26af72184115344eeafe63b92f65dc4421d4bd4800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000...
[x] Recovering: Bits: 360 | Hex: 0xf58c1458f5d4353d738ec00efb69abbcac3fd10edf2eef26af72184115344eeafe63b92f65dc4421d4bd48ad4f8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000...
[x] Recovering: Bits: 380 | Hex: 0xf58c1458f5d4353d738ec00efb69abbcac3fd10edf2eef26af72184115344eeafe63b92f65dc4421d4bd48ad4fe9ff780000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000...
[x] Recovering: Bits: 400 | Hex: 0xf58c1458f5d4353d738ec00efb69abbcac3fd10edf2eef26af72184115344eeafe63b92f65dc4421d4bd48ad4fe9ff78b5cc000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000...
[x] Recovering: Bits: 420 | Hex: 0xf58c1458f5d4353d738ec00efb69abbcac3fd10edf2eef26af72184115344eeafe63b92f65dc4421d4bd48ad4fe9ff78b5cc263958000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000...
[x] Recovering: Bits: 440 | Hex: 0xf58c1458f5d4353d738ec00efb69abbcac3fd10edf2eef26af72184115344eeafe63b92f65dc4421d4bd48ad4fe9ff78b5cc2639594d6980000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000...
[x] Recovering: Bits: 460 | Hex: 0xf58c1458f5d4353d738ec00efb69abbcac3fd10edf2eef26af72184115344eeafe63b92f65dc4421d4bd48ad4fe9ff78b5cc2639594d69fa2cd800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000...
[x] Recovering: Bits: 480 | Hex: 0xf58c1458f5d4353d738ec00efb69abbcac3fd10edf2eef26af72184115344eeafe63b92f65dc4421d4bd48ad4fe9ff78b5cc2639594d69fa2cdb0f920000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000...
[x] Recovering: Bits: 500 | Hex: 0xf58c1458f5d4353d738ec00efb69abbcac3fd10edf2eef26af72184115344eeafe63b92f65dc4421d4bd48ad4fe9ff78b5cc2639594d69fa2cdb0f9206f4c80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000...
[x] Recovering: Bits: 520 | Hex: 0xf58c1458f5d4353d738ec00efb69abbcac3fd10edf2eef26af72184115344eeafe63b92f65dc4421d4bd48ad4fe9ff78b5cc2639594d69fa2cdb0f9206f4ce0943800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000...
[x] Recovering: Bits: 540 | Hex: 0xf58c1458f5d4353d738ec00efb69abbcac3fd10edf2eef26af72184115344eeafe63b92f65dc4421d4bd48ad4fe9ff78b5cc2639594d69fa2cdb0f9206f4ce09438f1198000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000...
[x] Recovering: Bits: 560 | Hex: 0xf58c1458f5d4353d738ec00efb69abbcac3fd10edf2eef26af72184115344eeafe63b92f65dc4421d4bd48ad4fe9ff78b5cc2639594d69fa2cdb0f9206f4ce09438f119b03c700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000...
[x] Recovering: Bits: 580 | Hex: 0xf58c1458f5d4353d738ec00efb69abbcac3fd10edf2eef26af72184115344eeafe63b92f65dc4421d4bd48ad4fe9ff78b5cc2639594d69fa2cdb0f9206f4ce09438f119b03c7085a1000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000...
[+] Recovering: Done
[*] Recovered: 0xf58c1458f5d4353d738ec00efb69abbcac3fd10edf2eef26af72184115344eeafe63b92f65dc4421d4bd48ad4fe9ff78b5cc2639594d69fa2cdb0f9206f4ce09438f119b03c7085a16f0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
[*] 消耗剩余 8 次查询...
[*] 运行 Coppersmith...
[+] 找到 p: 172429097507410753749360324069434774573326056285643619159530839220089684384284358252227573873460944498379010389385877801096996482383940540323712964002238748452591206174311356557104350281715335630645695769432958177929339447767743089610062182703951377113392046400256995866469372313962751823450782043260038939907
[+] 验证成功,获取 Flag...
[x] Receiving all data
[x] Receiving all data: 2B
[x] Receiving all data: 47B
[+] Receiving all data: Done (47B)
[*] Closed connection to 117.21.200.176 port 26057
========================================
> DASCTF{2f3d777c-b2c3-488b-8740-2b8c1689a3a3}
========================================
'''pythonAll Done