Glitch City Laboratories Archives

Glitch City Laboratories closed on 1 September 2020 (announcement). This is an archived copy of a thread from Glitch City Laboratories Forums.

You can join Glitch City Research Institute to ask questions or discuss current developments.

You may also download the archive of this forum in .tar.gz, .sql.gz, or .sqlite.gz formats.

Arbitrary Code Execution Discussion

Data injection via Link Cable in Gen 1 - Page 1

Data injection via Link Cable in Gen 1

Posted by: Aldrasio
Date: 2016-07-29 21:18:01
This project worked as a proof of concept that you could do ACE using a buffer overflow in R/B. I decided to take that a step further.

I designed a payload that allows you to dump an arbitrary amount of data to anywhere in the RAM, and then jump to it. I'm still playing with the possibilities, but the payload wouldn't need a whole lot of modification to work as an SRAM dumper. The payload is as follows:

F3 F0 44 FE 90 38 FA F0 40 E6 7F E0 40 1E 02 16
02 3E 81 E0 02 F0 02 E6 80 20 FA F0 01 15 28 03
4F 18 EE 47 C5 1D 20 E7 0E 80 21 10 C6 2A E2 0C
2A A7 0D 0A 20 FA C1 E1 E5 C3 80 FF 3E 81 E0 02
F0 02 E6 80 20 FA F0 01 22 0B 78 B1 20 EE C9


di
.displayloop
ld a, [$ff44]
cp $90
jr c, .displayloop
ld a, [$ff40]
and $7f
ld [$ff40], a

ld e, 2
.read2bytes
ld d, 2
.read
ld a, $81
ld [$ff02], a
.waitloop1
ld a, [$ff02]
and $80
jr nz, .waitloop1
ld a, [$ff01]
dec d
jr z, .next
ld c, a
jr .read
.next
ld b, a
push bc
dec e
jr nz, .read2bytes
ld c, $80
ld hl, .hramdata      ; $C610
ld a, [hli]
.loop
ld [c], a
inc c
ld a, [hli]
and a
jr nz, .loop
pop bc
pop hl
push hl
jp $ff80

.hramdata
ld a, $81
ld [$ff02], a
.waitloop2
ld a, [$ff02]
and $80
jr nz, .waitloop2
ld a, [$ff01]
ld [hli], a
dec bc
ld a, b
or c
jr nz, .hramdata
ret
nop


A little sloppy, but I was going for brevity. The nop at the end is important.

The way this payload works is that once the initial buffer overflow is finished, it disables interrupts (since I don't have control over interrupt vectors) and then disables the screen (seemed like a good idea). Then it takes 2 sets of 2 bytes and pushes them to the stack. The first set of 2 bytes is the starting address for the next wave of data. The second set of 2 bytes is the length of the data. Both sets are little-endian.

Once it has those values, it copies everything from ".hramdata" to the nop to HRAM, where OAM code usually sits. Then it jumps to $ff80. Once it's at $ff80, it can start loading data from the serial port to any part of the RAM (except, in this case, SRAM. SRAM was not enabled as part of the payload). Once it's reached the end of the final payload, it jumps to the starting address from the beginning of the payload.

The main reason I went ahead and coded a different serial data receiver than the one on the cart is because the one on the cart is designed to run alongside the rest of the game, so it's going to be slower if you want to send a lot of data. With the barebones receiver coded here, you can send arbitrary data over more quickly, although the Gameboy will have no way of responding if anything goes wrong.

I haven't tried this on hardware, and I'm still playing with the possibilities, but as it stands you can load an arbitrarily-sized program into RAM with this method.

Re: Data injection via Link Cable in Gen 1

Posted by: Spoink
Date: 2016-07-29 21:21:09
Kind of a stupid question, but what does dis/enabling interrupts do?

Re: Data injection via Link Cable in Gen 1

Posted by: Aldrasio
Date: 2016-07-29 21:47:58
Basically, an interrupt is something that the CPU reacts to something outside of the code it's currently executing. This causes the program counter to effectively call an interrupt vector (in the home bank at $0040,$0048,$0050,$0058, and $0060). For example, if the Joypad interrupt is enabled, then when any button is pressed the Program Counter will immediately jump to $0060, regardless of what it was doing before (in the case of RBY, this isn't a huge deal, since the only thing at $0060 is a RETI command). More on interrupts here.

Disabling interrupts means that the code will execute as written, without anything like that happening. It's more a precaution than anything.

Re: Data injection via Link Cable in Gen 1

Posted by: TheUnReturned
Date: 2016-07-29 21:51:57
It's a interesting way, but it'll be quite difficult to set this up…








However, could this possibly corrupt the save data by accident?

Re: Data injection via Link Cable in Gen 1

Posted by: Aldrasio
Date: 2016-08-10 18:41:21
Hey guys,

So I did some tinkering with this during the migration, and I figured out how to transfer save files into Red/Blue using this method.

https://www.youtube.com/watch?v=RMfiv63neUo

Here's the assembly that I sent over: http://pastebin.com/KBh9pTJW

So you might want to ask, "Hey Aldrasio, if you can use this to upload save files into the game, could you download save files as well?" The answer to that is: Maybe! But probably not. The issue with this method is that the buffer overflow puts you about 1/3 of the way into the game's event flags. At the beginning of the game, almost all of these are 0, so they don't affect much and form a nice NOP sled into the code we want to execute. But if you're trying to send over a more played save file, a lot of those event flags are going to be set. Some of them might form STOP commands or RST vectors, which are a big no-no on RBY. I know for a fact that if you go through Viridian Forest and only fight the Weedle Bug Catcher at the end, one of the event flag bytes will be 0x10, which is the STOP command. If that happens, the game locks up and there's nothing you can do about it.

EDIT:
However, could this possibly corrupt the save data by accident?


Yes, but only if you write 0x0A to any address in the range $0000-$1FFF. This is how you enable reading/writing to SRAM. If you avoid writing to that address range (and you should, unless you mean it), then the save file should be fine.

Re: Data injection via Link Cable in Gen 1

Posted by: ISSOtm
Date: 2016-08-16 22:23:28

EDIT:
However, could this possibly corrupt the save data by accident?


Yes, but only if you write 0x0A to any address in the range $0000-$1FFF. This is how you enable reading/writing to SRAM. If you avoid writing to that address range (and you should, unless you mean it), then the save file should be fine.

Good news, if 0x0A is ever written in that range, writing any other value should lock SRAM again.
Usually, the only values used by programs are 0x00 (lock) and 0x0A (unlock), but it looks like non-0x0A locks SRAM. I didn't test that, though.

Re: Data injection via Link Cable in Gen 1

Posted by: Max
Date: 2016-09-15 22:17:49
Can you have the master send packets of 0xFE-redacted SRAM followed by a patch list?
Maybe use self-modifying code  to get the 0xFE bytes in the bootstrap.

Re: Data injection via Link Cable in Gen 1

Posted by: Aldrasio
Date: 2016-09-19 16:47:13

Can you have the master send packets of 0xFE-redacted SRAM followed by a patch list?
Maybe use self-modifying code  to get the 0xFE bytes in the bootstrap.


It's not really necessary. The bootstrapper doesn't use 0xFE, and once it's loaded it accepts 0xFE just fine.

Re: Data injection via Link Cable in Gen 1

Posted by: jfb1337
Date: 2016-09-22 15:02:10
Could you use 8F to clear the event list back into a NOP sled to upload the game file?

Of course, if you're using 8F you could just code the upload script or the bootloader directly, but I'd rather use the smallest 8F script possible to minimise the chance of making a mistake, especially when SRAM is involved

Re: Data injection via Link Cable in Gen 1

Posted by: ISSOtm
Date: 2016-09-22 16:57:58
I'm not sure having the whole progress set to 00 will allow Cable Clubs to be used. Maybe some other non-canon NOP (and a ; ld c, c ; halt ; adc a, 8F ; etc) could do the job.
But that's really screwing up the file.

Re: Data injection via Link Cable in Gen 1

Posted by: Charmy
Date: 2016-09-23 00:06:58
Actualy, it won't allow you to use the Cable Club unless the Pokédex flag is set.

Re: Data injection via Link Cable in Gen 1

Posted by: ISSOtm
Date: 2016-09-23 03:07:22
So only 00s WILL fail. But maybe one of the aforementioned instructions would do the job.
I think a chain of FE will work (cp $FE)… but there my be a 1 byte problem.

Re: Data injection via Link Cable in Gen 1

Posted by: jfb1337
Date: 2016-09-23 19:35:07
According to https://github.com/pret/pokered/blob/master/constants/event_constants.asm, there seem to be a lot of unused event flags.

Maybe there could be a configuration of them such that combinations of the real flags would only ever spell out opcodes that essentially do nothing (maybe change the registers, but that doesn't matter as we can clear them in the payload).

Also, we don't need to worry about any event flags before the location we jump to, which is D7A3. There are 3 bits worth of event flags there, but they would only allow for opcodes 00 through 07, which are all harmless.

I was originally going to go through the file looking for event flags that could be a problem, and writing 1s before them to make them part of the addresses for a load opcode (into a register), but then I ran into problems with consecutive bytes full of flags. Then I realised it would just be easier to write a jump to one of the unused flags, to jump to the payload.

Since we want to jump to the player name at D887, we could write, say, at D7A7 a jr $+E0. Compiled, that's 18 E0. To write that, we'd need:


ld hl, $d7a7
inc b ; nop to avoid glitch items
ld (hl), $18
inc hl
ld (hl), $E0
ld bc $[any] ; another nop to avoid duplication
ret


In items, that's

[Any item] x [Any qty]
8F
Thunderstone x 167 ; Not completely without duping, but there's only 1 dupe involved
TM15 x 2
Max revive x 24
HP up x 35
TM24 x 1
[Any item] x [Any qty]
TM01 x [Any qty]


I am very new to asm, so there may be a mistake in this. Also I'm assuming that unused event flags are preserved when saving.

If not, possibly you could use 8F to copy the event flags somewhere else in memory, replace them with NOPs then the cable's payload can fix the save file later by copying it back. But that script would have to be run every time you wanted to do a cable ACE, which is not ideal.

Re: Data injection via Link Cable in Gen 1

Posted by: ISSOtm
Date: 2016-09-24 08:02:17
Your ASM is correct, but I didn't check for the items.