Alles CTF 2020 - PWNkemon (hardware)
Hardware - PWNKemon
Disclaimer : my hardware skills are near zero, sorry for the mistakes and obvious shit if applicable. 20H before the end of the CTF, 28 team have flagged this hardware challenge and so weights 168 points. Here’s the description of the task :
The picture should explain everything.
Careful, flag format is in a different format:
CSCG(...)
files identification
Once the challenge files downloaded we get the previously mentioned image :
And the following file.
λ ackira ~/nextcloud/CTF/alles2020/hwd/pwnkemon » file pwnkemon.logicdata
pwnkemon.logicdata: CLIPPER COFF executable C1 R1 not stripped - version 15 -Ctnc -Cdnc
Two Game Boys Pocket are connected through their Game Link Cable and a device is plugged like a man in the middle in between.
I started by the principal tools like binwalk, strings and an hex editor and gathered the following string :
Timing Marker Pair
On Google, the first link bring us to https://www.saleae.com/, their products are logic analyzers. The aim of this kind of tool is to sniff multiples signals from a digital system or circuit and to later identify extracted data seeking for protocol, machine state or every data relative to the system execution.
If you zoom on the black device on the top of the picture, you will see saleae
written on it, also the .logicdata
extension is the name of the default output file extension generated by the associated software.
So we can assume that it’s a capture of the exchange between the two game boys made by the logic analyzer.
hardware specification
You can load the file in the saleae client (available through AUR), and then see 4 channels. I spent so much time wondering what I have to do here, I had no idea of which kind of protocol where used nor encoding.
Without these information you can’t extract data as you don’t know how 1
or 0
are transmitted. You have to know if the used protocol is about clock rising or falling edge for example.
Then I came across the following blog post Sniffing Game Boy serial traffic with an STM32F4 and Hooking up a Logic Analyzer. I learned that the protocol used was Serial Peripheral Interface (SPI) which consists of 4 wires (more VCC and GND ofc).
SCLK
: the internal clock of the master which is8192 Hz
SD
: not used in gamesSOUT
orMOSI
: master out data to slave inputSIN
orMISO
: master input data from slave output
With these information we can try to identify the different channels, the clock and SD
are easily spotable as the clock has regular pattern and SD
is continuous and not activated. However, SOUT
and SIN
can’t be differenced.
You can use the following configuration I stole from a blog post ( check the sources at the end), to add an analyzer on the panel at the right of the window. Thanks to the analyzer we can decode the logical data to get some numerical values.
I you pay attention the first byte you see are 0xFD
, I remembered read this value in one of my opened tab
The first few bytes appear to be preamble bytes (0xFD). After that the names of the players are transferred (up to 11 bytes, but both players had a name of only 4 characters, terminated by 0x50). The names are followed by the number of Pokémons in their party (6 for both players). The next 6 bytes represent the species of the Pokémon, terminated by 0xFF, and so on…
Pwnkemon exchange party m8 !
So we are just placed at the beginning of a Pokemon exchange ! Reading more about this kind of exchange I got a ton of information from this blog post : Arbitrary Code Execution in Pokemon Red.
So, some Pokemons names or trainers names should be presents. I looked for it in the decoded ASCII in Saleae software but nothing readable grabbed my eyes.
So I exported the output byte to a file thanks to the CSV export and a python parsing script
for data in open("value.csv", "r").read().split("\n")[1:-1]:
= data.split(",")[2]
x = findall(r"0x[a-zA-Z0-9]{2}", x)[1] # 0 is MOSI and 1 MISO
extracted += pack("B", int(extracted, 16))
tmp
open("out-miso.bin", "wb").write(tmp)
Once dumped the data look like this :
Generation I char encoding
Following the blog posts the structure starts with some 0xFD
and then the name of the player (11 chars max) which is ending with the byte 0x50
. This seems to happen at 0x7A
with \x91\x84\x83\x50
, but this string is not a valid ASCII name of a trainer. I struggled here for a while looking for others structures until I came across this video of LiveOverflow (the actual author of this challenge).
The name on this data save seems to be encoded and A
is 0x80
. With a bit of googling and some references you can find the char encoding according to your pokemon generation
So \x91\x84\x83
means RED
, seems promising. As I knew the flag format it was really easy to spot the flag in this encoded form which is present, at least, in the miso data transfer.
print(tmp.index(b"\x82\x92\x82\x86")) # CSCG encoded
$ 471
= tmp[471:].split(b"\x9b")[0] # ')' encoded
$ encoded_flag
$ '\x82\x92\x82\x86\x9a\x86\x8e\x8d\x8d\x80P\xe3\xa7\xa0\xa2\xaa\xe3\xa4\xac\xe3\x80P\xab\xab\xe3\x8f\x96\x8d\xaa\xa4\xac\xaeP\xad\xe7\xe7\xe7' b
0x9B
is)
in it encoded form, so the end of the flag
I did not found a script to decoded it so I wrote an ugly keymap table and just decoded it !
#!/usr/bin/python3
from re import findall
from struct import pack
from string import ascii_lowercase, ascii_uppercase
= ascii_uppercase + "():;[]" + ascii_lowercase
table
= 0
k = {0x50 : "\x00", 0xe3 : "-", 0xe6 : "?", 0xe7 : "!"}
dic
for i in range(0x8, 0xc):
for j in range(0, 0x10):
= i * 16 + j
nb if nb < 0xba:
= table[k]
dic[nb] +=1
k = 0
k
for i in range(0xf6, 0x100):
= str(k)
dic[i] +=1
k
assert dic[0xff] == "9"
def decode_prop(encoded):
= ""
tmp for char in encoded:
+= dic[char]
tmp return tmp
= b""
exchange_dump
for data in open("fff.csv", "r").read().split("\n")[1:-1]:
= data.split(",")[2]
x = findall(r"0x[a-zA-Z0-9]{2}", x)[1]
extracted += pack("B", int(extracted, 16))
exchange_dump
print(exchange_dump.index(b"\x82\x92\x82\x86"))
= tmp[471:].split(b"\x9b")[0]
encoded_flag
print(encoded_flag)
# open("out-miso.bin", "wb").write(tmp)
print(decode_prop(encoded_flag))
CSCG(GONNA-hack-em-All-PWNkemon!!!)
sources
https://6e726d.github.io/Challenge/Ekoparty15/https://phil242.wordpress.com/2018/03/29/insomnihack-2018-write-up-s3curlock-level-1-2-3/
https://hackaday.io/project/12932-game-link-online/log/49002-hooking-up-a-logic-analyzer
https://vaguilar.com/2015/05/26/arbitrary-code-execution-in-pokemon-red/
https://bulbapedia.bulbagarden.net/wiki/Character_encoding_in_Generation_I
https://bulbapedia.bulbagarden.net/wiki/Pok%C3%A9mon_data_structure_in_Generation_I
https://gbdev.gg8.se/wiki/articles/Serial_Data_Transfer_(Link_Cable)