Hello and welcome to my first post. As a first exercise, today we are going to dissect a stack buffer overflow worm present that exploits a vulnerabilty present on the video game pokemon red and blue on gameboy. We will use reverse engineering technics.

I choose to use gameboy because this architecture has no mitigation. It is a perfect example. Also the roms of gameboy are unpatchable. It is the definition of ROM: Read Only Memory. Then we could have friend with consentent friend to play with them and show them the exploit.

The goal is to understand how the worm works and then to modify the worm to make it “better”… Or worst, depends of what you expect.

I/Install tools.

First we are going to install the tools to be able to reverse engineer the malware. The full script is here:

sudo apt install cmake make gcc git -y;
sudo apt install pkg-config libpng-tools libpng-dev bison -y;

git clone https://github.com/radareorg/radare2;
sh ./radare2/sys/install.sh;

git clone https://github.com/gbdev/rgbds;
cmake -S . -B rgbds/build/ -DCMAKE_BUILD_TYPE=Release rgbds/;
cmake --build rgbds/build;
sudo cmake --install rgbds/build;
sudo make install -C rgbds;

git clone https://github.com/pret/pokered;
make -C pokered/;

git clone https://github.com/MrCheeze/pokered-self-replicator;
mv pokered-self-replicator/sav.dat pokered/pokered.sav;

wget https://bgb.bircd.org/bgbw64.zip;
mkdir bgb;
unzip bgbw64.zip -d bgb;

sudo dpkg --add-architecture i386
sudo wget -nc -O /usr/share/keyrings/winehq-archive.key https://dl.winehq.org/wine-builds/winehq.key
sudo wget -nc -P /etc/apt/sources.list.d/ https://dl.winehq.org/wine-builds/debian/dists/bullseye/winehq-bullseye.sources
sudo apt update
sudo apt install --yes --install-recommends winehq-devel

wine64 $(pwd)/bgb/bgb64.exe $(pwd)/pokered/pokered.gbc;

Copy it in a file. Name it install.sh and then open an terminal and do sh ./install.sh.

The script installs radare2. It is a framwork of reverse engineering. A reverse engineering framwork is a tool to dissect malware. But you can also dissect any file.

Then it installs the game boy rom compiler RGBDS.

After the script install and compile the documented rom of pokemon red and blue. This repository is an unofficial repository made to document the internals of the game pokemon red and blue. It has been created by the community to make games derivated from the original game (mods).

Then it install the current work on the virus that we want to dissect: https://github.com/MrCheeze/pokered-self-replicator

Then it installs bgb emulator. It is free but sadly not free software (libre) but it works… I plan to replace it with Emulicious to connect it with radare2 in the future. Then I will even replace Emulicious by Sameboy and then connect radare2 to SameBoy.

Wine is the windows Emulator. yes I use an emulator to emulate an emulator. It is pretty dirty. As I told I plan to remove it.

If the script works finely, you will the a screen with a game. You should hear sounds from the game also. Then it is ok.

II/Run the virus.

Let’s start by running the virus to see what it does. The command mv pokered-self-replicator/sav.dat pokered/pokered.sav; has moved and renamed the save file as the root directory of the disassembly to use the save file of the game. The script has started the virus. You can run it again at any moment. Go in the directory installed and do: wine64 $(pwd)/bgb/bgb64.exe $(pwd)/pokered/pokered.gbc;

According to the blog of the virus at https://github.com/MrCheeze/pokered-self-replicator when you exchange a pokemon, the receiver will caught a virus. So let’s do it.

So open two terminals:

wine64 $(pwd)/bgb/bgb64.exe $(pwd)/pokered/pokered.gbc;

and

wine64 $(pwd)/bgb/bgb64.exe $(pwd)/pokered/pokeblue.gbc;.

Then you have two choices. Either you plan the game until you are able to go to the nurse to exchange the pokemon. Or you use a save file to go directly to the location of the nurse. In this book, we will of course choose the second option.

So to download the save file do git clone https://github.com/gogo2464/pokemon-blue-save-file;

then put the file pokeblue.sav in the folder pokered.

So once again, open the two terminals:

wine64 $(pwd)/bgb/bgb64.exe $(pwd)/pokered/pokered.gbc;

and

wine64 $(pwd)/bgb/bgb64.exe $(pwd)/pokered/pokeblue.gbc;.

You will be in the location just on the Nurse. In BGB, select one game, right click on the screen, go to link/listen/click ok. Select the other game, right click on the screen, go to link/connect/click ok.

The games will be slower but it is ok. Go to the nurse and then exchange the pokemon. As the documentation of the worm tell, you should see weird characters on the games. It is exactly what is expected.

III/Document the virus.

Here comes the interesting part. We are going to dissect the virus to understand how it works in order to modify it. We already know from the official virus documentation that the virus infects save file. Then to read content of the save file, do: radare2 -a gb -e cfg.bigendian=false -e cfg.charset=pokered pokered.sav;

radare2 is the framework of reverse engineering that we use to dissect the virus.

The option -a gb tell to radare2 to disassemble the content of the file as gameboy machine code. machine code is code that has been compiled by a programming language like C. It should be understood only by computers, not programmers but can be also be understood by reversers with right tools.

The option -e cfg.bigendian=false set the endianess of the program to little endian. It tell to radare2 how works the gameboy architecture to let it show it’s real internals.

The option -e cfg.charset=pokered tell to radare2 how to understand data that represent printable text values.

Now in the interpreter ([0x00000000]>), type V and enter. You can scroll with the arrow keys of the keyboard to see the data of the save file. These are the values stored by the game to save progression. Some players have documented the save file. You can read the doc of the community driven pokemon red and blue save file here.

Now type p in the screen of radare2. You will see assembly language. The famous machine code. From now you can scroll on any point of the save file that has been presented in the virus documentation. See this link.

Today we will focus on the code located at the offset (the address in the file) at 0x3540. Then raise a console by typing : in the radare2 screen. Now, in the console, do s 0x3540. q to leave the console and to come back in visual mode. You should see code that starts by:

xor a
ld [0xcf92], a
ld hl, 0xda80
ld [hl], 0x14
xor a
ld [0xcca2], a
call 0x190f
call 0x20af
call 0x019a
ld a, 0xf6
ld bc, 0x0032
ld de, 0xffd3
ld hl, 0xc3b6
ld [hl], 0xf6
inc hl
ld [hl], a
add hl, bc
ld [hl], a
dec hl
ld [hl], 0xf7
add hl, de
inc a
jr nZ, 0xf3

...

Here we are!

It is generally better to know an assembly language programming. We will teach everything about assembly language in this book but if you are really lost when reading assembly code, you can learn the very common x86_32 Here. It is not a waste of time because you will need it latter when you will have to work on a modern architecture for a real exploitation script.

As told in the documentation of the virus, we are located at 0x3540, the offset of the object 8f. According to the documentation, the 8f object is an object that the virus let in the inventory of the victim once the victim is infected. It allow the victim to get any pokemon of the victim choice.

So basically, if we modify the save file at this offset, we can change the payload of the virus. Make a copy of the pokered.sav file. We are now going to modify the payload.

IV/Edit the virus.

Leave radare2 with the command q. Reopen it with: radare2 -a gb -e cfg.bigendian=false -e cfg.charset=pokered -s 0x3540 -w pokered.sav;.

The option s 0x3540 means that radare2 seeks at the offset 0x3540 at the openning of the file.

The option -w ask radare2 to open the file in write mode. It allows us to modify the file. If do not set it, then we can not patch it.

Then once you are at the offset 0x3540, you can patch the 8f object with the command “wa <instruction 1>; <instruction 2>; etc…”. All the technic not related to tools consists now to write your own asm code to patch the object. Let’s do an example.

Read the disassembly of pokemon red and blue.

As you can read. There is a assembly routine (it is the name for an assembly function) where PlaySound is defined. See here.

Sadly for the purpose of the virus, the routine must be called by it’s offset. Not by routine name. In the current version of radare2 used in this tutorial (

radare2 5.7.7 28577 @ linux-x86-64 git.5.7.6-11-gdc2862970
commit: dc2862970735c473770adedf17792669bf2a2f04 build: 2022-08-05__22:59:00

), radare2 does not analyses symbols yet. So open the ROM pokered.gbc with the command wine64 $(pwd)/bgb/bgb64.exe $(pwd)/pokered/pokered.gbc;. Left click in the bgb emulator and then type esc. Right click > go to > type PlaySound:

Then you should see that: image

The highligthed instruction is PlaySound, and contains the offset that we must rely on. The offset is 0x23b1.

According to the pokered documentation:

; plays music specified by a. If value is $ff, music is stopped

So we have to find the value of a to put the music of our choice.

After reading the source code of pokered, we can read the value of a value for the lavender music. As a macro, you can modify the source code of pokered and write:

PRINTT "The value of lavender a value is: "
PRINTT "{MUSIC_LAVENDER}"
PRINTT "\n"

At this line to debug.

The value of lavender a value is: 0xd4

We have the value 0xd4 !

So if we replace the code at the offset 0x3540 by

ld a, 0xd4
call 0x23b1 ;PlaySound
ret

The instruction ld a, 0xd4 put the value 0xd4 in the register a. In assembly language a register is a specific place to remember a value. For example in gameboy assembly, the register pc remember the value of the instruction currently executed and move to another instruction when the value is changed.

The instruction call 0x23b1 calls the routine at offset 0x23b1. Here is is PlaySound.

The instruction ret leaves the routine previously called: it more specifically get the value of the register pc pc saved previously by call and jump to it.

the 8f object will play a creepy music!

So to do that, in the install directory, do:

radare2 -a gb -e cfg.fortunes=false -e cfg.bigendian=false -e cfg.charset=pokered -s 0x3540 -w ./pokered/pokered.sav;
"wa ld a, 0xd4; call 0x23b1; ret;"
q

The option -e cfg.fortunes=false disables the tips for radare2. It is more convenient.

wine64 $(pwd)/bgb/bgb64.exe $(pwd)/pokered/pokered.gbc;

type enter > items > s > 8f.

The creepy music should comes… Congratulation! You just have patched the payload of the mister cheeze virus. Now you can modify the assembly by yourself and put what you want! Be creative!