Skip to content

Instantly share code, notes, and snippets.

@kitlith
Last active August 1, 2020 19:22
Show Gist options
  • Save kitlith/e6e03b5f26f9c6b50515 to your computer and use it in GitHub Desktop.
Save kitlith/e6e03b5f26f9c6b50515 to your computer and use it in GitHub Desktop.
Collection of Information about ntrcardhax

NTRCARDhax

This is in progress, and is by no means finished, fork and comment with a link to your changes and I'll update here. Information on the 3DS side should be about done. I still have questions, though, which would be nice to know the answers to.
My thoughts on implementing the gamecard side of things can be found here.

ARM9hax

ARM9 code uses REG_NTRCARDMCNT, at physical address 0x1016400 as a reference. ARM9 triggers reading by writing 4 bytes to 4 bytes after this address, REG_NTRCARDROMCNT. This is located at 0x10164004. The magic value 0x883F1FF is OR'd with R6 bitshifted left 24 times. The loop is comparing against the value at REG_NTRCARDROMCNT somehow. After reading starts, ARM11 kernel must somehow write 0x4000 to REG_NTRCARDROMCNT.

The Magic Value 0x883F1FF

Courtesy of gbatek:
REG_NTRCARDROMCNT controls a lot of stuff surrounding the reading of DS cartridges. In brief:

  • Bit 13 controls whether data is encrypted. (This is set to 0)
  • Bit 15 controls whether the seed is applied. (This is also 0)
  • Bit 22 controls whether commands are encrypted. (Also 0. Gee...)
  • Bit 23 tells us whether data is ready. (0. However, we can't write to this.)
  • Bits 24-26 controls the data length. (Alright! This is what we want! But... also all 0.)
  • Bit 27 controls the speed at which the 3DS requests data. (1. This means it's slower. Phew!)
  • Bit 31 says whether a data transfer is in progress or not. (We're starting one, therefore 1.)

So, transfer data with no encryption using commands with no encryption. But we're requesting nothing? Here comes the OR. We're ORing with a number, bitshifted 24 times. This lines up with bits 24-26, specifying length. How do these bits specify length? It requests 0x100 << n bytes. To get the normal 0x200 bytes, n is 1. To get our desired 0x4000 bytes, n is 6. Why not 7 (for 0x8000)? That's actually a special value that reads 4 bytes.

But what exactly do I need to write?

The value that we need to write from ARM11 kernel is 0x883F1FFF | (6 << 24) to physical address 0x1016400. For the record, the code listed in the talk uses an ADD(S) instruction rather than an ORR instruction.

Wait, that was a physical address...?

Yes, yes it was. And, appearantly, that section of IO isn't normally mapped. Though, when it is, it may be able to be found by adding 0xEB00000 to the address. So, the problem is that we need to figure out how to map IO... or perhaps just that we need to talk to the GPU in the right way. I think Normmatt has done just that, here: https://github.com/Normmatt/ntrcardhax

What does this do?

I assume that the loop in ARM9 extracts its ending address from the register, so by overwriting specifically those 3 bits in the register, we change the end condition, but the buffer is still created for the smaller size, and thus we have a buffer overflow into .bss.

TL;DR;

ARM11 kernel needs to write the value 0x8E3F1FFF to physical address 0x10164004 (Virtual Address 0x10164004 + 0xEB00000?) after ARM9 begins reading the game card. Boom. Buffer overflow. Now we need to exploit this using data we can control. Using hardware we control. And, if you want to see a way to trigger this in actual code, look here: https://github.com/Normmatt/ntrcardhax

Questions

Can we trigger the card being read from ARM11? Probably not.
Can we set a register to the command we want? Same as above, probably not.

Bootromhax

Say what?

The Bootrom makes NTRCARD reads if you hold down a certain button combination (Start+Select+X) while "the case is closed". This is presumably either used at factory or at repair shops.

It loads a FIRM from the cartridge, starting in the "secure area". This FIRM still requires a proper signature... oh, wait, we have sighax now. In addition, the firm requires some form of encryption. Since it is loading from a NTRCARD, we now have to deal with the wonderful world of NTRCARD encryption. Oh, look -- they hardcode the key they're using in the bootrom, so it isn't even guaranteed that it corrosponds to a gamecode.

So, when we go to write this data to a flashcart, we have to modify the blowfish key that is used (thankfully this is stored seperately on most flashcarts instead of being derived from the gamecode), and the commercial rom data starting in the secure area and continuing as long as you need.

This means that the biggest thing you need to figure out is how to read (backups are important!) and write to the flashcart.

Sources

https://youtu.be/UutYOidFx3c?t=3019 - The wonderful talk that started this.
https://www.3dbrew.org in general - for information having to do with the 3ds specifically.
http://problemkaputt.de/gbatek.htm - for documentation of registers common to the 3ds and the DS, cartridge protocol.
https://sciresm.github.io/33-and-a-half-c3/ - The sighax presentation, makes mention of the bootrom backdoor.

Thanks

#3dsdev at freenode.net and EFNet, and #dsdev at blitzed.org - for tolerating me as I blunder about, trying to do research and throw ideas around.
derrek, for being the one that told us all about about NTRCardhax.
Normatt, for being the other person "crazy enough" to work on 'ntrcardhax'.

External Hardware

May or may not need to decode commands sent from 3DS? Depending on how well we can predict commands, that may not be necessary.

Must be capable of keeping up with a 4.2Mhz clock for over 0x4000 bytes (around 0x4014 or more?) Actually, maybe not, because the important bits are the chipid and maybe the beginning of the header (around 0x214 bytes) and wherever the payload ends up. If we overwrite a pointer, and that's how we have execution, may be able to just have one repeating byte after a while, which requires no changing. But we overwrite stuff in the .bss section. shrugs

Bits of DS Game Card protocol

  • Pins 9-16 are the data pins, 9 being pin 0, 16 being pin 7.
  • Pin 2 is clock.
  • We need one of the chip select pins.
  • The pin used for detecting if a card is connected needs to be grounded.
  • What else is important?

Prototype Thoughts

Updatable Flashcards

It may be possible to update a flashcard with a header that we control. Though, we're not sure how one of these cards will react when a length of 0x4000 attempts to be read.

On the AK2i, all 0x4000 bytes are controlable, and can be used! Normmatt implemented this in his repository here: https://github.com/Normmatt/ntrcardhax

Arduino

The arduino has a clock speed of 16Mhz, and the the 3ds will clock at 4.2Mhz. If this would work, it would be extremely tight: around 3.8 cycles per byte that needs to be sent. And you'd also need to sync it to the clock. This isn't going to happen.

Teensy

Because of the low clock speed of the Arduino, I started looking elsewhere. I looked up the Teensy line, and found that the Teensy-LC has a clock speed of 48Mhz. This would mean ~11.4 cycles per byte, which is far more comfortable than the Arduino. If that isn't enough either, the Teensy 3.1/3.2 has a 72Mhz clock speed, giving ~17.1 cycles per byte. These also can be easily overclocked, which can bring us up to (over) 96Mhz. If we clock it at 96.6Mhz, we are now completely in sync with the 3DS at 23 times the speed. This can still be seen as tight, but it's a much wider margin than the Arduino gives us. This has not been attempted.

Raspberry Pi

Under Linux

This has not been tested, but the consensus is that it is unlikely that with the overhead of Linux that we would be able to do what we need to do fast enough. But what if we didn't have the overhead of an OS...?

Bare-metal

I've tried this and failed. Using a Raspberry Pi B+, it just isn't fast enough for the 6.3 Mhz clk, which was discoveded to be the initial speed that the 3ds seems to request at. :( It's available at https://https://github.com/kitling/NTRPi

Custom Hardware

Using a CPLD/FPGA. Not my area of expertiese, but I've been working on it here: https://github.com/kitling/FPGA_NotThatReal

TODO

  • Finish designing custom hardware...
  • Investigate using the PRUs on a beaglebone.

Sources

https://www.pjrc.com/teensy - Official website for the Teensy product line.

Thanks

#3dsdev and #Cakey at freenode.net, and #dsdev at blitzed.org - for tolerating me as I blunder about, trying to do research and throw ideas around.
hedgeberg, for helping to test NTRPi and their knowledge of actual hardware.

@kitlith
Copy link
Author

kitlith commented Jan 30, 2016

No comments at all? Please consider this a RFC. Comments are wonderful, even if it's just a 'LGTM'.

@ideal-fire
Copy link

LGTM.

@gnmmarechal
Copy link

It's a shame this didn't go anywhere. NTRCardhax seemed interesting.

@Valeri0p
Copy link

Valeri0p commented Jul 8, 2017

Are you still around?...
Anyways, thanks for the document, it can be very useful nowdays, whit magnethax/ntrboothax incoming...
If gateway was very interested on ntr*hax, they cloud simply modify the "blue card" bootloader and make $ with the same HW...but since the team seems dead, probably the community will do it themselves.
What about NTRPi? Are you still working on it? There's another exploit, on Dsi, that maybe needs some imput from the card slot. RocketLauncer. Who knows...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment