Contexte
Trouver un moyen d’afficher le flag qui se trouve au début de la pile de l’émulateur CHIP-8
Analyse
Il va falloir déterminer où se trouve l’adresse de début de la pile. Le programme challenge1.py nous donne un indice avec la ligne:
...
vm.untrusted_ctx.memory.data[Memory.O_STACK:Memory.O_STACK + len(FLAG_LV1)] = FLAG_LV1
...
Le début de la pile est donc Memory.O_STACK qui est définie dans le fichier components/memory.py et vaut 0x0EA0:
...
class Memory(collections.UserList):
SIZE = 0x1000
O_ROM = 0x0200
O_STACK = 0x0EA0
...
Le fichier components/cu.py définit tous les opcodes. Parmi ceux-ci on recherche ceux qui seront utiles pour récupérer les 16 octets situés à partir de l’adresse Memory.O_STACK:
- Annn : charge registre i avec valeur nnn
- Fx65 : charge registre v[x] avec valeur memory[i]
Maintenant que l’on sait comment récupérer un octet, on cherche comment l’afficher.
Dans la liste des opcodes il y a Dyxn:
...
self.cpu.processor.cf = self.cpu.context.io.display.update(
self.cpu.processor.i,
self.cpu.processor.v[y],
self.cpu.processor.v[x],
n
...
Cette fonction affiche à la position x, y de l’écran les n lignes d’un buffer contenant les chiffres hexadécimaux 0-9a-f sous forme de pixels 4x5 en commençant à la position i du buffer.
Exemple:
Cette suite d’opcodes affiche 7:
6007 # set v[0] to value to display, 7
F029 # multiply v[0] by 5
6E00 # set v[e] to 0, x coordinates
6F00 # set v[f] to 0, y coordinates
DEF5 # display
FFFF # end prog
$ nc localhost 40000
hex encoded rom:
6007F0296E006F00DEF5FFFF
Maintenant que l’on sait comment récupérer un octet et afficher un chiffre hexadecimal, le programme generate_ram.py suivant permet de créer la suite des opcodes permettant d’afficher le flag:
def init():
print(f'610F', end='') # v[1] = 0x0f (used as mask)
def display_char():
global x_term, y_term
# x coordinates
val_x = f'{x_term:02X}'
print(f'6E{val_x}', end='') # v[14] = val_x
# y coordinates
val_y = f'{y_term:02X}'
print(f'6F{val_y}', end='') # v[15] = val_y
# display char
print(f'DEF5', end='') # display
# move cursor
x_term = x_term + 5
if x_term == 40:
x_term = 0
y_term = y_term + 6
def print_addr(adress):
print(f'A{adress}', end='') # i = addr
print(f'F065', end='') # v[0] = memory[i]
print(f'8200', end='') # v{2] = v[0]
print(f'8206', end='') # v[2] >> 1
print(f'8206', end='') # v[2] >> 1
print(f'8206', end='') # v[2] >> 1
print(f'8206', end='') # v[2] >> 1
print(f'F229', end='') # i = v[2] * 5
display_char()
print(f'8012', end='') # v[0] & v[1]
print(f'F029', end='') # i = v[0] * 5
display_char()
def end():
print(f'FFFF', end='') # end
x_term = 0
y_term = 0
addr = 'EA0'
init()
while addr != 'EB0':
print_addr(addr)
value = int(addr, base=16)
value = value + 1
addr = f'{value:03X}'
end()
$ python3 generate_ram.py
610FAEA0F06582008206820682068206F2296E006F00DEF58012F0296E056F00DEF5AEA1F06582008206820682068206F2296E0A6F00DEF58012F0296E0F6F00DEF5AEA2F06582008206820682068206F2296E146F00DEF58012F0296E196F00DEF5AEA3F06582008206820682068206F2296E1E6F00DEF58012F0296E236F00DEF5AEA4F06582008206820682068206F2296E006F06DEF58012F0296E056F06DEF5AEA5F06582008206820682068206F2296E0A6F06DEF58012F0296E0F6F06DEF5AEA6F06582008206820682068206F2296E146F06DEF58012F0296E196F06DEF5AEA7F06582008206820682068206F2296E1E6F06DEF58012F0296E236F06DEF5AEA8F06582008206820682068206F2296E006F0CDEF58012F0296E056F0CDEF5AEA9F06582008206820682068206F2296E0A6F0CDEF58012F0296E0F6F0CDEF5AEAAF06582008206820682068206F2296E146F0CDEF58012F0296E196F0CDEF5AEABF06582008206820682068206F2296E1E6F0CDEF58012F0296E236F0CDEF5AEACF06582008206820682068206F2296E006F12DEF58012F0296E056F12DEF5AEADF06582008206820682068206F2296E0A6F12DEF58012F0296E0F6F12DEF5AEAEF06582008206820682068206F2296E146F12DEF58012F0296E196F12DEF5AEAFF06582008206820682068206F2296E1E6F12DEF58012F0296E236F12DEF5FFFF
$ nc localhost 40000
610FAEA0F06582008206820682068206F2296E006F00DEF58012F0296E056F00DEF5AEA1F06582008206820682068206F2296E0A6F00DEF58012F0296E0F6F00DEF5AEA2F06582008206820682068206F2296E146F00DEF58012F0296E196F00DEF5AEA3F06582008206820682068206F2296E1E6F00DEF58012F0296E236F00DEF5AEA4F06582008206820682068206F2296E006F06DEF58012F0296E056F06DEF5AEA5F06582008206820682068206F2296E0A6F06DEF58012F0296E0F6F06DEF5AEA6F06582008206820682068206F2296E146F06DEF58012F0296E196F06DEF5AEA7F06582008206820682068206F2296E1E6F06DEF58012F0296E236F06DEF5AEA8F06582008206820682068206F2296E006F0CDEF58012F0296E056F0CDEF5AEA9F06582008206820682068206F2296E0A6F0CDEF58012F0296E0F6F0CDEF5AEAAF06582008206820682068206F2296E146F0CDEF58012F0296E196F0CDEF5AEABF06582008206820682068206F2296E1E6F0CDEF58012F0296E236F0CDEF5AEACF06582008206820682068206F2296E006F12DEF58012F0296E056F12DEF5AEADF06582008206820682068206F2296E0A6F12DEF58012F0296E0F6F12DEF5AEAEF06582008206820682068206F2296E146F12DEF58012F0296E196F12DEF5AEAFF06582008206820682068206F2296E1E6F12DEF58012F0296E236F12DEF5FFFF
Flag: FCSC{e50f91bc6418a7a79b0c3fe74bb5e600}