Jump to content

0x1500 control code arbitrary code execution: Difference between revisions

Reorganized the page and added a summary of the modern setup.
>Torchickens
(Reorganized the page and added a summary of the modern setup.)
 
(29 intermediate revisions by 5 users not shown)
Line 1:
{{Arbitrary code execution}}
{{incomplete|Original speedrunning method needed. Cover starting menu ACE research as well.}}
[[File:0x1500 Lapras.png|thumb|right|160px|Traded Lapras method. In this case, the arbitrary code execution is triggered after exiting the inventory with A on Cancel with Antidote x21 at the bottom of the bag, and then viewing Lapras's summary.]]
 
'''0x1500 control code arbitrary code execution''' is an [[arbitrary code execution]] method found in {{Crystal}}. It does not occur in {{GS}}.
 
A specific variation of this glitch involving an [[unterminated name Pokémon (Generation II)|unterminated name glitch Pokémon]] is also known as '''unterminated name Pokémon arbitrary code execution'''.
 
Both of these exploits were discovered by Luckytyphlosionluckytyphlosion. The original method used for speedrunning purposes is not yet covered in this article.
 
This glitch involves the combination of the byte 0x15 ("Mobile" control character) followed by 0x00 in a text string, and will lead to arbitrary code execution at memory address $CD52. Once the code is terminated with a ret, the program counter by default will be at the location following where the 0x1500 sequence was in the RAM.
 
==Effects of the 0x15 control character==
The 0x15 control character signifies a "[[mobile script]]" in Crystal. When the text engine reads the byte 0x15, it uses the following bytes as jump table indices to a list of specific functions ("mobile functions"). The valid jump table indices are 0x01 to 0x0f (i.e. 1 to 15), and an index >= 0x10 would end the mobile script interpretation procedure instead of being used as a jump table index. Notice that some mobile functions may "take parameters" by consuming them from the text stream.
 
However, the byte 0x00 is not excluded by the above check. It would be interpreted as jump table index 256, and the jump target is $CD52, which is a WRAM address used in some mobile functions. Therefore, when the text engine sees the byte combination "0x15 0x00", it will jump there, leading to ACE exploits.
 
==General procedure==
Usually, there are three components to the setup for exploiting this glitch:
* "0x1500" setup: Have a string that, when displayed, cause the text engine read the byte sequence "0x15 0x00". This can be achieved by either putting the sequence in the string itself, or by trying to display an unterminated string, and putting the sequence somewhere after the text buffer.
* Bootstrap: Put some assembly instruction at or shortly after memory address $CD52, in order to jump to some more easily manipulated memory area, usually the box names.
* Payload: The actual arbitrary code to be executed.
 
These steps are not necessarily done in the above order. For example, the player may first set up the payload in the form of box names, as that is the most robust part of the setup. Then the player may use some specific movements to set up the BG map buffer for a multi-level bootstrap. Finally, the player may use an incomplete toss to set up 0x1500, and view the name of an [[unterminated name Pokémon (Generation II)|unterminated name glitch Pokémon]] to do the exploit.
 
This article will focus on the "0x1500" setup and the bootstrap. For some examples of payloads, see [[Crystal box name codes]].
 
==Setup and bootstrap methods==
This glitch involves the combination of the byte 0x15 ("Day" control character) followed by 0x00 in a text string, and will lead to arbitrary code execution at memory address 0xCD52. Once the code is terminated with a ret, the program counter by default will be at the location following where the 0x1500 sequence was in the RAM.
=== Modern setup procedure ===
{{main|Guides:Fast 0x1500 ACE}}
In most cases, the most convenient method of setting up 0x1500 ACE is through an unterminated nickname Pokémon ("bad clone") generated via the [[bad clone glitch]]. The method has been optimized by [[User:TimoVM|TimoVM]] and detailed in the [[Guides:Fast 0x1500 ACE|fast 0x1500 ACE guide]]. The below is a simplified description that assumes that the English version of Crystal is used (the full guide supports several other language versions).
 
[[File:Box English C Setup V2.png|thumb|right|160px|The box name code to set up wrong pocket TM15 ACE with this method.]]
There are various means of setting up this glitch:
====Requirements====
# ASM code to execute encoded as box names, starting from box 1.
#* Before returning, the payload will need to "fix the stack" by popping several superflous return addresses on the stack. In practice, it is the easiest to just execute [[Guides:Fast 0x1500 ACE#Box name payload|the payload crafted by TimoVM to set up a more convenient ACE method]] (based on [[TMHMDex/C:206|wrong pocket TM15]]).
# The name of the ''current'' box needs to be <code>p 0 5 ♀ Pk 'v G 1</code> (as a level-2 bootstrap that jumps to the name of box 1).
#* The level-1 bootstrap actually jumps to the screen tiles, where the name of the current box will be printed.
# A bad clone in the current PC box.
# Spearow in the first slot of the party.
 
====Steps====
==Unterminated name glitch Pokémon method w/ traded Lapras and box names==
# Stand in front of the PC on the second floor of a regular Pokémon Center. Walk one step down, one step left, then save and reset the game.
# After reloading the save, walk one step right, then one step up. (The player should be in front of the PC again, but should not use the PC yet.)
# Open the player's party from the Start menu, press A once on Spearow, then exit and close the Start menu.
# Open the PC and choose withdraw to display the name of the bad clone, which will trigger ACE.
 
===Self-contained setup and bootstrap===
If the player has the ability to put arbitrary data in a string, then both the setup and the bootstrap, and even potentially the entire payload, can actually be done from within the string itself:
* Instead of setting up "0x15 0x00" after the string buffer, 0x15 followed by 0x00 in the string itself could be used to trigger this glitch.
* By putting carefully constructed byte sequences between 0x15 and 0x00, valid mobile functions can be triggered and modify the value at $CD52.
* Due to how mobile functions use the stack, if the game encounters a <code>ret</code> instruction when executing code from $CD52, without other stack manipulation, the game will continue to run arbitrary code from the location following the 0x00 byte, which in this case would also be in the string itself.
This principle can be used after the player has already achieved ACE, to make subsequent execution of arbitrary code easier. Alternatively, they might be used to setup ACE by trading with another game, or with a [[game-altering device]].
 
The following self-contained setups are designed by pfero:
4F 15 08 05 C9 00 [code] 37 C9
This works in any unverified string, notably including Pokémon nickname and mail messages. This means that it can be transferred from any Generation I game (with just enough space to jump to a more convenient location) or Generation II game (with more space to possibly write a "built-in" payload).
{{Explanation|contents=
* The first byte, 0x4F, is the <code><nowiki><LINE></nowiki></code> control character, which signifies that the following text is to be printed in the bottom line of the dialogue box (Generation II dialogue boxes only displays two lines of text at a time). This sets the "cursor location" (where the next character would be printed) to a fixed value<ref>[https://github.com/pret/pokecrystal/blob/8fd66c080f201c401419674229f2714853de008f/home/text.asm#L474-L478 The function <code>LineChar</code> that handles the <code><nowiki><LINE></nowiki></code> control character]</ref>, namely 0xC5E1, which is used as a baseline for subsequent setup.
* The second byte, 0x15, makes the text engine go into mobile script mode.
** The third byte, 0x08, is interpreted as the index of a mobile function, namely <code>Function17f2cb</code> in the disassembly<ref>[https://github.com/pret/pokecrystal/blob/8fd66c080f201c401419674229f2714853de008f/mobile/mobile_5f.asm#L4006-L4035 The function <code>Function17f2cb</code> in the disassembly]</ref>. This function takes the next two bytes in the input stream (here "05 C9") as input parameters, and writes them to $CD54 and $CD55 in this order. It then calls the function <code>MobilePrintNum</code> to print a number; the actual number printed is not as important as the number of digits it is printed in, which is controlled by the first input parameter, here 0x05. Afterwards, the new "cursor location", now 0xC5E6, is stored in $CD52–$CD53 in little endian (i.e. [$CD52] = 0xE6, [$CD53] = 0xC5).
** The sixth byte, 0x00, triggers the glitch, causing the game to jump to $CD52. The byte sequence that has been set there so far is "E6 C5 05 C9", which translates to:
<pre>
and 0xC5 ; E6 C5
dec b ; 05
ret ; C9
</pre>
:: The first two instructions are "safe" slide instructions, and the third causes the game to return to the location after the 0x00 byte, as mentioned at the beginning of this section.</li>
* The last two bytes, "37 C9", are executed after the main payload, and translates to <code>scf</code> then <code>ret</code>. This will set the carry flag and then return to the main loop for the mobile script mode<ref>[https://github.com/pret/pokecrystal/blob/8fd66c080f201c401419674229f2714853de008f/mobile/mobile_5f.asm#L3543-L3546 The main loop for the mobile script mode]</ref>, where a set carry flag will cause the mobile script mode to terminate normally.
}}
15 0A C0 00 [code] E1 C9
15 0B C0 00 [code] E1 C9
The first setup is specifically designed for mail messages, the second one might be useful elsewhere. The first one depends on the value of <code>hl</code> (the location where the current character in the string is being printed to) translating to valid instructions to slide for two bytes; the second one depends on <code>hl+3</code> in the same way. The first setup might not work on Japanese versions, due to the behavior of mobile function 0x0A being different.
 
=== Historical methods ===
{{incomplete|Original speedrunning method needed. Cover starting menu ACE research as well. Add [https://xcellerator.github.io/posts/tetsuji/ Tetsuji's findings]}}
 
====Unterminated name glitch Pokémon method w/ traded Lapras and box names====
For this method, an [[unterminated name glitch Pokémon]] is required. A convenient way of getting one is through a box name corruption glitch in {{RBY}}, such as through the [[ItemDex/RB:094|9F (0x5E)]] glitch item in {{RB}}.
 
=====Video=====
{{YouTube|VtRFxxKW7mY|ChickasaurusGL}}
 
=====Requirements=====
1) A Lapras with Perish Song (level 29 in Generation II), Bide (TM34 in Generation I) and Safeguard (level 50 in Generation II) which will have its name corrupted. The Lapras should be able to gain experience with an Exp. Share or Rare Candies (in this video Rare Candies are used from outside of the items pack, which allows them to be used effectively infinitely).
 
Line 30 ⟶ 91:
4) Specific box names for storage box 1
 
=====Steps=====
1) Teach level 28 Lapras on Generation I Bide via TM34; move 2.
Line 44 ⟶ 105:
6) Trade to a new Generation II Crystal that just got to the Pokémon Center with Antidote x21 purchased
 
7) Do box name cheats and save every iteration. There are various examples below. Before doing a [[Crystal box name codes|box name cheat]] (box name cheats can be set via a PC by altering PC names), save and reset the game and then perform the following; In order to perform the box names cheats, have Antidote x21 at the bottom of the inventory, try to toss all x21 (move toss counter down to show all x21) but Cancel with B, scroll down and exit by pressing A on Cancel (not with B), and then view the Lapras summary to execute arbitrary code.
 
====Stored unterminated name Pokémon/bad clone method w/ stored PC items====
===Box name codes (from slot 1)===
 
=====Video=====
{{YouTube|YqD68-2aAjg|Crystal_}}
 
=====Requirements=====
====Get TM17 with code at DA47 to go to DB75:====
p0'déT2(Pk)5
 
(From Crystal_'s video)
p'vzéM5p5
 
1. Items in the PC item storage ended with a ret command, with register de set to a specific value (e.g. 0134)
'vd'v(éA45
 
2. A bad clone in the current PC box
p'vyé:5p5
 
3. Max Elixer or TM21 (Frustration) in the bag
'vLéB4p'vx
 
4. Quagsire in party slot 1, with Return as move 1, with a move with less than 10 characters in it, in slot 4
ém5p0555
 
5. Spearow holding TM50 (Nightmare) in party slot 2. TM49 may also work and depends on the number of items in the PC item storage.
éI4x'd
 
=====Steps=====
<tt>
1. Save and reset the game just outside of a regular Pokémon Center
xor a
 
2. Press up on the d-pad only, until the player character is one tile below the Pokémon Center desk
or a, d0
 
3. Move right only, until facing the wall/edge of map
ld (f893),a
 
4. Move up only until facing the PC. Do not use the PC yet.
pop hl
 
5. Press Start and open the player's bag
ei
 
6. Have the cursor point to Max Elixer or TM21, then exit the bag without pressing A on the item
ld d,b
xor a
 
7. Go to deposit a Pokémon and view your Quagsire's summary.
sub b9 ; 47
 
8. Exit and scroll down to Spearow, then exit Deposit
ld (fb8c),a
 
9. Choose withdraw and have the cursor on the bad clone/unterminated name Pokémon, which will force its name and the 0x1500 sequence that follows, and cause arbitrary code execution.
xor a
 
ei
 
ld d,b
 
sub a3
 
sub 9a ;c3
 
ld (fa80),a
 
ei
 
ld d,b
 
xor a
 
sub b8 ; 48
 
ld (fb9c),a
 
xor a
 
ei
 
ld d,b
 
sub 8b ; 75
 
ld (fa81),a
 
xor a
 
sub b7; 49
 
ld d,b
 
ld (fbac),a
 
xor a
 
or a, fb
 
ei
 
ei
 
ld d,b
 
ld (fa88),a
 
or a
 
ret nc
</tt>
 
====All badges:====
 
p'viéI5p5
 
'vjéL5p09
 
éA2éB2(Pk)'d
 
<tt>
xor a
 
sub a8
 
ld (fb88),a
 
xor a
 
ld d,b
 
ld d,b
 
sub a9
 
ld (fb8b),a
 
xor a
 
or a, ff
 
ld d,b
 
ld (f880),a
 
ld (f881),a
 
ld d,b
 
ld d,b
 
ld d,b
 
pop hl
 
or a
 
ret nc
</tt>
 
====Have Fly (DCE1 [move 1]=0x13):====
p0T'vAé(Pk)6
 
(Pk)x'd
<tt>
xor a
or a, 93
sub 80
ld (fce1),a
ld d,b
pop hl
or a
ret nc
ld d,b
</tt>
 
====Fly can go anywhere====
p09ée655
 
éf6ég6(Pk)5
 
éh6éi6x'd
 
<tt>
xor a
 
or a, ff
 
ld (fca4),a
 
ei
 
ei
 
ld d,b
 
ld (fca5),a
 
ld (fca6),a
 
pop hl
 
ei
 
ld d,b
 
ld (fca7),a
 
ld (fca8),a
 
or a
 
ret nc
 
ld d,b
</tt>
 
====Get GS Ball in Goldenrod City Pokémon Center====
p'vséJ5p(Pk)
 
0B'vAéI55
 
éAAp0N'vA
 
ée5p0B'vA
 
éd5p0K'vA
 
éBBp'va'vc
 
55555555
 
55555555
 
é'l5p'v(male)'v't
 
é'd5p0L'vA
 
éIIx'd
 
<tt>
 
xor a
 
sub b2 ;a=4e
 
ld (fb89),a
 
xor a
 
pop hl
 
ld d,b
 
or 81
 
sub 80 ;a=01
 
ld (fb88),a
 
ld d,b
 
ld d,b
 
ld (8080),a
 
xor a
 
or 8d
 
sub 80 ;0d
 
ld d,b
 
ld (fba4),a
 
xor a
 
or 81
 
sub 80
 
ld d,b
 
ld (fba3),a
 
xor a
 
or 8a
 
sub 80
 
ld d,b
 
ld (8181),a
 
xor a
 
sub a0
 
sub a2 ;be
 
ld d,b
 
ei
 
ei
 
ei
 
ei
 
ei
 
ei
 
ei
 
ei
 
ld d,b
 
ei
 
ei
 
ei
 
ei
 
ei
 
ei
 
ei
 
ei
 
ld d,b
 
ld (fbd1),a
 
xor a
 
sub ef
 
sub d5 ; 3c
 
ld d,b
 
ld (fbd0),a
 
xor a
 
or 8b
 
sub 80 ; 0b
 
ld d,b
 
ld (8888),a
 
or a
 
ret nc
 
ld d,b
 
ld d,b
</tt>
 
--What this does basically:
 
ld a,01
 
ld (4e01),a ;change to SRAM bank 1
 
ld a, 0a
 
ld (0d01),a ;this enables writing to SRAM
 
ld a, 0b
 
ld (be3c),a ;enable Celebi GS Ball event
 
====Get Master Ball items slot 2====
p0B'vAéV2
 
(Pk)x'd
 
<tt>
xor a
 
or 81
 
sub 80
 
ld (f895),a
 
ld d,b
 
pop hl
 
or a
 
ret nc
 
ld d,b
</tt>
 
 
====Get Rare Candy balls slot 1====
p0i'vA'v
 
éI5p0a'vA
 
éA2x(Pk)'d
 
<tt>
 
(fill box 1 name with 5 beforehand to prevent freeze)
xor a
 
or a8
 
sub 80
 
sub 50
 
ld d,b
 
ld d,b
 
ld (fb88),a
 
xor a
 
or a0
 
sub 80
 
ld d,b
 
ld (f880),a
 
or a
 
pop hl
 
ret nc
 
ld d,b
</tt>
 
 
====Make it a day+1 (D4B6 = 01)====
p0B'vAéw,
 
xPk'd
<tt>
 
xor a
 
or 81
 
sub 80
 
ld (f4b6),a
 
ld d,b
 
or a
 
pop hl
 
ret nc
 
ld d,b
</tt>
 
====Make it a day+2 (D4B6 = 02)====
p0C'vAéw,
 
xPk'd
<tt>
xor a
 
or 82
 
sub 80
 
ld (f4b6),a
 
ld d,b
 
or a
 
pop hl
 
ret nc
 
ld d,b
</tt>
 
 
====Get Mew (recommended Egg slot 1) DCDF=97====
 
p0?'vH'vA5
 
éI5p0X55
 
éA6(Pk)x'd
 
<tt>
xor a
 
or a, e6
 
sub 87
 
sub 80
 
ei
 
ld d,b
 
ld (fb88),a
 
xor a
 
or a,97
 
ei
 
ei
 
ld d,b
 
ld (fc80),a
 
pop hl
 
or a
 
ret nc
</tt>
 
====Hatch steps left = 1 cycle/1 happiness (DCFA=01)====
p0B'vAé46
 
Pkx'd
<tt>
xor a
 
or a, 81
 
sub 80
 
ld (fcfa),a
 
ld d,b
 
pop hl
 
or a
 
ret nc
 
ld d,b
</tt>
====Warp to Safari Zone====
p0D'vAév6
 
(Pk)p'vhéw6x
 
'd
 
<tt>
xor a
 
or a, 83
 
sub 80
 
ld (fcb5),a
 
ld d,b
 
pop hl
 
xor a
 
sub a7 (;59)
 
ld (fcb6),a
 
or a
 
ld d,b
 
ret nc
 
ld d,b
</tt>
 
==Technical details==
==Explanation==
Luckytyphlosion offers [https://forumsarchives.glitchcity.info/index.php?topic=forums/board-108/thread-7706/page-0.msg203310html#msg203310 the following explanation] on the forums:
 
"Basically, it's the cause of poor error checking by GameFreak. When the game has to print the Fake Bad Clone's name through the PlaceString function, it encounters 0x00 characters which aren't supposed to be printed.
Line 668 ⟶ 164:
</tt>
 
==Attribution==
==Stored unterminated name Pokémon/bad clone method w/ stored PC items==
* Much of the text in this article (specifically for the Lapras method) is courtesy of ChickasaurusGL's video description, with permission.
* Luckytyplosion offered [https://archives.glitchcity.info/forums/board-108/thread-7706/page-0.html#msg203310 an in-depth explanation] on the forums.
* Pfero introduced the idea of a self-contained setup, and did some preliminary research on the effects of valid mobile functions.
* TimoVM reverse engineered some of Pfero's setups, giving explanations on the purpose of each byte.
 
===Video= References ==
<references />
{{YouTube|YqD68-2aAjg|Crystal_}}
 
===Requirements===
 
(From Crystal_'s video)
 
1. Items in the PC item storage ended with a ret command, with register de set to a specific value (e.g. 0134)
 
2. A bad clone in the current PC box
 
3. Max Elixer or TM21 (Frustration) in the bag
 
4. Quagsire in party slot 1, with Return as move 1, with a move with less than 10 characters in it, in slot 4
 
5. Spearow holding TM50 (Nightmare) in party slot 2. TM49 may also work and depends on the number of items in the PC item storage.
 
===Steps===
1. Save and reset the game just outside of a regular Pokémon Center
 
2. Press up on the d-pad only, until the player character is one tile below the Pokémon Center desk
 
3. Move right only, until facing the wall/edge of map
 
4. Move up only until facing the PC. Do not use the PC yet.
 
5. Press Start and open the player's bag
 
6. Have the cursor point to Max Elixer or TM21, then exit the bag without pressing A on the item
 
7. Go to deposit a Pokémon and view your Quagsire's summary.
 
8. Exit and scroll down to Spearow, then exit Deposit
 
9. Choose withdraw and have the cursor on the bad clone/unterminated name Pokémon, which will force its name and the 0x1500 sequence that follows, and cause arbitrary code execution.
 
==Attribution==
*Much of the text in this article (specifically for the Lapras method) is courtesy of ChickasaurusGL's video description, with permission.
 
[[Category:Arbitrary code execution]]
Cookies help us deliver our services. By using our services, you agree to our use of cookies.