I think the game I played the most when I
was a kid was Pokemon Ruby, on GBA.
With my brother, we completed the regional
Pokedex, with 200/200 Pokemon catched.
Unfortunately, there still were two
Mythical Pokemons that we were
unable to catch, and for a good reason: those
were accessible only for those attending some
physical events, occuring only in some places
and sometimes only in Japan. This was the
early time of forums, and lot of rumors
started to flourish: you can unlock
Deoxys by beating the Battle Tower, by
waiting for the white stone of the spatial
center to be stolen, etc... But rumors,
that's all they were.
In 2021, I got interested into the
glitching scene, that is, how to exploit bugs
and flaws in games in order to do things that
the developers did not plan. That's where I
discovered that this wasn't a lie: it is
indeed possible to catch Deoxys without
attending physical events nor using any
cheating device! There are several methods to
achieve it, but the most reliable and
powerful way is via Arbitrary Code
Execution (ACE). It is the
Holy-Grail of glitchers: exploiting
the game until we are able to make it execute
any code we want! If I find some time, I'll
write something about it, because the process
to get there is very interestig in a
technical point of view. What's ironic is
that it is only possible to achieve that
thanks to... the protections added to the
game by the developpers in order to make
cheating more difficult (in particular, a
very basic kind of ASLR and some
checksum verifications) 🤦♂️
But achieving ACE is not an easy task: you
have to write some code in the memory, and
then make the game execute it. Both aspects
are very interesting, but the tool I made
focuses on the first one: how to write
machine code (ARM7TDMI) in a specific
location in memory. For that, we use a
mechanic of the game that allows us to rename
boxes of the in-game PC (where we store our
pokemons): it consists of 14 names of 8
characters each. Those 14 names are stored
consecutively in memory, one byte for each
character, but are separated by a
0xFF
byte (the EOF
character). Thus, it takes in total
(8+1)*14=126
bytes.
The main issue is that only about 1/3 of
the 256 possible values for each byte can be
written, due to the
character encoding used by the game. So,
we have to write machine code (using one of
the ARM or Thumb instruction sets), but by
being unable to write 2/3 of the possible
byte values... That sounds like an impossible
constraint! Fortunately, while it seems very
complicated to write Thumb code with this
constraint, it is possible, to write some
very useful ARM opcodes: some arithmetic ones
(ADC
,SBC
), and some
memory-related ones
(MOV
,STR(H)
,LDR(H)
).
Of course, only a small subset of registers
and immediate constants are accessible due to
the constraint on the charset. But it is
enough to write abritrary code: by doing the
right arithmetic operations using
MOV
, ADC
and
SBC
, we can compute any opcode
we want in a register, and then write it a
little ahead of the current instruction
(PC
register), using a command
STR
, for it to be executed.
Another constraint is the presence of a
0xFF
byte (EOF
),
which cannot be modified, at the end of each
box name. It forces us to insert some dummy
machine instructions that do nothing but
contain this EOF
byte. After
that, we just have to convert the machine
code we obtain into characters using the
character encoding, and we are done.
This whole process is what the tool I made
automates. It parses some ARM assembly code
written by the user (with some preprocessor
extensions), finds a way to write immediate
values using writable arithmetic operations,
assembles them and encodes the result, for
finally showing the box names one has to
enter in the game! Using this code generator,
it is also possible to setup a much more
powerful ACE environment, for instance by
bootstrapping
a code that allows you to get rid of the
limitations cited above. You can take a look
at this video
that shows a full exploitation of ACE in
order to inject a new Pokemon species in the
game!