Hey!
In today's video I would like to walk you through how we managed to dump the internal
firmware of the Nintendo Game & Watch, using a relatively
simple exploit and only a few lines of assembly. But before we do so, I also want to give a
short update on what happened in the Game & Watch hacking community in the last few
weeks, because it has been pretty amazing to watch and be a part of it!
Now as you know, roughly 2 weeks ago we released the tools that allow anyone with basic hardware
hacking skills and decent knowledge of software development to backup the firmware of the
device. We also released resources for developing and flashing custom homebrew for the game
& watch - and we've seen some pretty awesome things come from the community.
One of the big achievements is that now we have reverse-engineered the entire hardware:
Jake Little, also known as Upcycle electronics traced every last connection on the device,
and made a great overview showing exactly which trace goes where, and how everything
is connected. He even created a full schematic in KiCAD! Great work!
A big help was also the fact that two Daniels, Daniel Padilla, and my good friend Daniel
Cuthbert, both provided high-resolution x-ray images images of the PCB. This allowed us
to see all the hidden layers and made reverse-engineering much easier, especially with the BGA components
that don’t allow for easy probing.
Furthermore, we now have a complete list of types and datasheets for all important components,
except for the display which seems to be custom. But as it’s fully working, this is not a
problem.
Sander van der Wel in the mean time even designed a custom 3d printed backside for the Game
& Watch which gives room for an easily accessible debug connector without having to modify the
original backside! The files are vailable on thingieverse, and so if you have a 3d printer
you can easily print your own!
Also on the hardware side: DNA64, Konrad Beckmann - who I hope you’re following on Twitter
and YouTube - and me have replaced the original flash chip, which only has 1 Megabyte of storage,
with a larger, 16 MB one - and we found that the Macronix MX25U12835FM2I is both compatible
with the stock firmware, while also being fast and easily usable for homebrew development!
These flash chips cost less than 3 dollars, and are really worth the investment.
Thougfh note that to put it in, you will need some experience in reworking PCBs and equipment
such as a hot air soldering gun.
There’s also a project that aim’s to build a custom motherboard for the Game & Watch,
with an FPGA instead of a microcontroller. This could be pretty awesome, as it would
allow cycle-exact emulation of processors and would also otherwise be awesome for expirmentation.
Others are planning to build a PCB with an ESP32 on it - which would give you a fast
processor with wifi and bluetooth. capabilities
Now lets talk about software, which also has seen some great progress!
On the NES & GameBoy emulator side we now have standby support: So when press the power-button
your current game state will be saved to flash, and resume when you turn the device back on!
As we are storing to flash, this also means that your game is saved even when your battery
runs out!
Konrad also implemented different screen interpolation methods, so that now all games run in full-screen,
and during compilation you can set different interpolation methods. In the future we will
make this configurable in the on-screen menu.
Speaking of on-screen menu: Konrad and me started working on a ROM chooser menu, based
on the original retro-go code, which now allows you to select different games when turning
on the device. This is quite far from being finished, but we are doing our best to get
it fully working. If you want to support our efforts there’s also now a Patreon where
you can support us, and will also allow you to join some patreon-only discord channels
and allow you to vote on some future video content.
Another awesome project comes from Alfonso Luna: He ported a CHIP-8 Emulator to the Game
& Watch, which comes with a couple of arcade-ish games such as Snake, Flight Runner etc. Pretty
fun and you can also add your own chip8 ROMs.
Then Cyanic came around, and he actually built a binary patch for the original firmware,
that fixes the language bug that the device ships with. So he is basically providing patches
for an officially non-updtable device - Pretty cool!
I also know that there is a lot of other software in the works, such as an emulator for the
original game & watch games, and so I’m pretty excited to see what else will get released
soon.
We’ve also received a ton of patches for the different scripts we published, and have
a great support community on Discord that helps new developers getting on board.
We are also in the process of creating detailed instructions on how to use different debug
adapters to backup and flash the game and watch, and Dean Huffman even already created
a guide on how to exactly use an STM32 Nucleo board to hack the game & watch.
I’m also excited that a talk about the Game & Watch has been accepted to this year’s
chaos computer club remote congress, the rc3! So stay tuned for that.
Now, lets talk about how we actually manage to dump the original firmware of the Nintendo
Game & Watch: After I teamed up with Konrad, we immediately
started discussing how we can potentially access the internal firmware. As a reminder,
the STM32 processor in the game & watch is set to read out protection level 1, which
allows us to read the RAM via the debug port, but prevents us from reading the stm32 internal
flash!
Now we started digging around a bit, and while looking through the reference manual (page
135) of the STM32, I noticed that it has a special RAM called ITCM-RAM, which is a tightly
coupled RAM that is super fast to access, and is primarily designed to be used to hold
code that gets called very often and is performance critical. And I realised that I never actually
looked at the contents of that RAM area! And so I dumped it from a device, and found that
it contains ARM code!
Now what if this ARM code is loaded from the encrypted external flash? In the same way
the ROM was loaded in the first video?
And so just like in the first video, I just put zeroes at the very beginning of the SPI
flash data, and checked whether the contents of this ITCM RAM area changed. And: It did!
Turns out that address 0 of the SPI flash, is loaded directly into the ITCM RAM of the
STM32. And so just like in the first video, we can
XOR the ITCM RAM data with the contents of the encrypted flash to get the XOR stream
that was used for the encryption This then allows us to encrypt our code that
will be loaded into the ITCM area! And so re-using the tools from the first video,
we can just XOR the encrypted flash contents, with the ITCM data we dumped, to get the XOR
stream we need to encrypt our own code that will be run on the device!
Now a big problem is: We don’t know WHICH code of this ITCM RAM will be executed. Like
we don’t know whether the firmware will jump to address 0, address 200 or whatever.
But there’s a simple solution: We can use something called a NOOP slide!
A NOOP - or no operation - is an instruction that simply does nothing. It’s often used
to ensure a certain number of CPU cycles have been passed, but in our case, we can basically
fill the ITCM RAM with NOP instructions and put our payload at the end.
This creates a slide of NOPs, and whereever the firmware jumps to, it will just start
executing NOPs, basically sliding down the NOPs into our payload.
Speaking about the payload: Konrad wrote a simple payload that just reads from the internal
flash, copies it into RAM and then just goes into an endless loop. This just takes 10 instructions,
and so we can have a pretty long NOP slide with a short payload.
And this is exactly what our backup scripts do: We use OpenOCD to dump the contents of
the ITCM - which, because it’s RAM, is readable, even though the device is running in read
protection level 1, an then we copy a piece of code to RAM called flashdumper, which copies
the contents of the external SPI flash into RAM. then we dump those RAM contents using
OpenOCD, which gives us the encrypted SPI flash contents.
Using the external flash contents and the ITCM contents we encrypt our own payload.
So now we have the external flash contents and the ITCM contents - which, as you just
saw, allows to encrypt our own payload. Next we copy another small tool called flashloader
to RAM,, which writes our encrypted payload into the external flash.
When we reboot the device now, the firmware will decrypt our payload and copy it into
ITCM RAM. As soon as our payload gets called, we get a copy of the STM32’s internal flash
in RAM - which we can then dump using the debugger.
And now we have a full backup of the device: We have the SPI flash contents, and the internal
firmware, and so now, even if we unlock the processor - which will cause a mass erase
- we can always go back to the original firmware.
As you can see, this exploit is quite simple, and so we were really excited to be able to
provide a relatively simple backup solution for other interested hardware hackers to use.
Now this is not yet ready for use by non-developers, but there are some projects in the works that
will make putting homebrew onto the game and watch much more accessible - and I’m really
looking forward to that!
I hope you enjoyed this video, and if you are interested in supporting more work on
the game & watch, please check out my patreon! Thanks, and I hope to see you on this channel
again soon!