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.
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.
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.
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.
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
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.
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
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.
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.
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.
#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'.
No comments at all? Please consider this a RFC. Comments are wonderful, even if it's just a 'LGTM'.