4dsdev
Views: 1,609,344 Main | Rules/FAQ | Memberlist | Active users | Last posts | Calendar | Stats | Online users | Search 11-21-24 03:47 PM
Guest:

0 users reading Accessing the NAND (via fopen / opendir) | 2 bots

Main - Homebrew discussion - Accessing the NAND (via fopen / opendir) Hide post layouts | New reply

Pages: 1 2
d0k3
Posted on 07-04-15 05:05 PM Link | #245
Posted by profi200
I saw your posts on GBAfail.

The method people get the correct CTR is unnecessary complicated. For CTR related partitions the CTR is the first half of a SHA256 hash over the NAND CID which can be found at the same place every time (see http://3dbrew.org/wiki/Memory_layout#ARM9_ITCM). For TWL partitions it's the first 16 bytes of a SHA1 hash over the NAND CID. The endianess/word order is different for TWL partitions so you need to experiment a bit with it. Otherwise it works exactly the same way as for CTR partitions.

Sorry for the double post. I think otherwise no one notices it :p

I just came here to ask exactly this, and there already is the answer. Thanks a million times! I'll try it and will let you know if I figured it out.

d0k3
Posted on 07-05-15 01:54 AM (rev. 5 of 07-06-15 12:29 AM) Link | #246
Posted by profi200
I saw your posts on GBAfail.

The method people get the correct CTR is unnecessary complicated. For CTR related partitions the CTR is the first half of a SHA256 hash over the NAND CID which can be found at the same place every time (see http://3dbrew.org/wiki/Memory_layout#ARM9_ITCM). For TWL partitions it's the first 16 bytes of a SHA1 hash over the NAND CID. The endianess/word order is different for TWL partitions so you need to experiment a bit with it. Otherwise it works exactly the same way as for CTR partitions.


Okay, I guess I need some more help. For the CTR partitions, calculating the SHA256 hash and using the first 16 byte of that as CTR works, and is by far the superior method.

However, I seem to can't get a usable result with the SHA1 hash for the TWL partitions. What I did to find out about the correct endianness is:
* Generate a TWLN xorpad (with the SHA1 CTR, otherwise same as I would generate a CTRNAND xorpad.
* Dump the encrypted TWLN partition.
* Reorder the encrypted TWLN partition to change endianness - that means reversing the order of bytes on blocks of 2, 4, 8 or 16 bytes. Then use the xorpad, hoping to get a result with some recognizable data.

So far, I had no success. Is anything wrong with my method? Maybe I even need new AES routines to be able to decrypt that? The new SHA1 hash algorithm is tested (it's from the same source as my SHA256 algorithms), and of course I'm always using a fresh copy of the encrypted TWLN before reordering. I'm using the offset from the start of the NAND (for the ctr_add function), same as I do for the CTRNAND.

profi200
Posted on 07-06-15 11:08 AM Link | #247
- Keyslot is 3 for both twln and p.
- CTR is the first 16 bytes of the SHA1 hash. Needs to be set with reversed word order and little endian.
- The en-/decryption params are little endian and reversed word order too.

d0k3
Posted on 07-06-15 09:30 PM (rev. 9 of 07-07-15 10:20 AM) Link | #248
Posted by profi200
- Keyslot is 3 for both twln and p.
- CTR is the first 16 bytes of the SHA1 hash. Needs to be set with reversed word order and little endian.
- The en-/decryption params are little endian and reversed word order too.

Okay, now I'm pretty sure I got everything correctly. I used http://3dbrew.org/wiki/AES_Registers and doublechecked that with my crypto library "original version by megazig" (or here) . Keyslot is 0x3, too.

Now, to even enable little endian / reversed order decryption, I had to change the code in the crypto library, from:
void _decrypt(uint32_t value, void* inbuf, void* outbuf, size_t blocks)
{
*REG_AESCNT = 0;
*REG_AESBLKCNT = blocks << 16;
*REG_AESCNT = value |
AES_CNT_START |
AES_CNT_INPUT_ORDER |
AES_CNT_OUTPUT_ORDER |
AES_CNT_INPUT_ENDIAN |
AES_CNT_OUTPUT_ENDIAN |
AES_CNT_FLUSH_READ |
AES_CNT_FLUSH_WRITE;
aes_fifos(inbuf, outbuf, blocks);
}
to... (changes not on Github) (value has the bit set for AES CTR)
void _decrypt(uint32_t value, void* inbuf, void* outbuf, size_t blocks)
{
*REG_AESCNT = 0;
*REG_AESBLKCNT = blocks << 16;
*REG_AESCNT = value |
AES_CNT_START |
AES_CNT_OUTPUT_ORDER |
AES_CNT_OUTPUT_ENDIAN |
AES_CNT_FLUSH_READ |
AES_CNT_FLUSH_WRITE;
aes_fifos(inbuf, outbuf, blocks);
}
(I know, that breaks everything else, but it is just for testing)

The setctr function handles everything correctly (if I give the correct order / endian modes). No change needed:
void set_ctr(int mode, void* iv)
{
uint32_t * _iv = (uint32_t*)iv;
*REG_AESCNT = (*REG_AESCNT & ~(AES_CNT_INPUT_ENDIAN|AES_CNT_INPUT_ORDER)) | (mode << 23);
if (mode & AES_NORMAL_INPUT)
{
*(REG_AESCTR + 0) = _iv[3];
*(REG_AESCTR + 1) = _iv[2];
*(REG_AESCTR + 2) = _iv[1];
*(REG_AESCTR + 3) = _iv[0];
}
else
{
*(REG_AESCTR + 0) = _iv[0];
*(REG_AESCTR + 1) = _iv[1];
*(REG_AESCTR + 2) = _iv[2];
*(REG_AESCTR + 3) = _iv[3];
}
}

Now, the crypto.h / crypto.c library looks like it has been tampered with (or edited by too many people), even before I made my additional change. I guess it should still be usable.

As I said, decrypting the CTRNAND works with the same routines. For TWL, I calculated the CTR via SHA-1 (only the first 16 bytes), changed the keyslot, changed the set mode to reversed and little endian (same for decryption mode, see above). Other than that, everything stays the same. I also tried incrementing the counter in a different way once, but that doesn't help either.

Usable output should be pretty easy to recognize as I have the offsets for the start of the FAT16 / FAT12 images. In other words, the first 16 bytes are enough to decide if everything is okay (I looked further, of course).

So, why I'm writing all this? It still doesn't give usable output :|. Even with my method from before (this time generating xorpads correctly), I do not get anything useful.

Do you have any additional ideas? Maybe there is some interim result that I could check somewhere, so that I can be sure my implementation is correct at least to that point? And did someone already manage to decrypt the TWLNAND without resorting to archives? And maybe there's some place on the web where there's mroe information about TWL decryption (didn't find anything usable on 3Dbrew).


EDIT: Maybe there are prerequisites to being able to decrypt the TWL?
http://3dbrew.org/wiki/AES_Registers#Keyslots
I stumbled over the 'NATIVE_FIRM hard-boot' in that table, and 'probably unset' in table right above. If that is useful information, I'm using Brahma as a loader.

EDIT2: Okay, I dug a little deeper and found this:
http://dsibrew.org/wiki/Bootloader
Stage1 uses the AES_Engine with mode AES-CTR to decrypt each ARM9/ARM7 binary, where keyY is from the above signature. The AES_Engine keyslot used here is the same one used for the shared areas for Tad, therefore the keyX is the same as the one used for that. The following is used for the CTR, where "binblk->binblocksize" is the above binary size aligned to 0x200-bytes:

Could that mean I need to retrieve and set the KeyY? (that wasn't needed for CTRNAND decyption)

Sorry for the long post, too.

profi200
Posted on 07-07-15 04:59 PM (rev. 2 of 07-07-15 05:02 PM) Link | #249
No.

https://gist.github.com/profi200/469f9fac6a394d23e8e1
Very old code but it worked. I just slapped some comments in it. The way i calculated the CTR with the offset is really shit and could overflow. For me it worked.

d0k3
Posted on 07-07-15 07:30 PM (rev. 5 of 07-08-15 07:14 AM) Link | #250
Posted by profi200
No.

https://gist.github.com/profi200/469f9fac6a394d23e8e1
Very old code but it worked. I just slapped some comments in it. The way i calculated the CTR with the offset is really shit and could overflow. For me it worked.

Alright, thanks a ton, again. From the first look I think my error was that I did not manually change the endianness ("EndianSwap") of the CTR (I did, in some of my experiments, but in those I did other things wrong). I'll have to thoroughly look it through.

BTW: I already made a local copy, just in case that gist was only temporary.

Update: I got it. What I needed to do was to manually reverse the word order and endian (in fact, reversing it byte by byte) for the SHA-1 hash before doing anything else. Then increment it and start decoding. If I do it any other way (ie. use the AES parameters to handle endian in setctr), the add ctr function doesn't work in the correct way. So, what I got wrong was the incrementation - I thought that should work the same, regardless of endian / order. I also had to change word order / endian (via the respective parameters, not for the data) for the actual decryption, but that I had before. Thank you again!

The set AES bits 12 and 13, btw, don't seem to do anything, and they are undocumented on 3dbrew.

profi200
Posted on 07-08-15 04:23 PM Link | #251
I don't know what these bits do. Apparently it is from reverse engineering Nintendos code. I just used the knowledge and some of Normmats code as base.

d0k3
Posted on 07-09-15 08:12 PM Link | #252
Okay, one last question about that code: Does it decrypt the AGBSAVE correctly? It's difficult to test if it does. A comment in the rxTools source code says it (decrypting AGBSAVE) doesn't work that way. Personally, I'd have suspected that it requires the same method as the TWL partitions, not the same as the CTR partitions.

profi200
Posted on 07-10-15 05:20 AM Link | #253
It's handled like a CTR partition and it can only be properly decrypted if it exist logically. The AGB_FIRM savegame area is just blank if no GBA game ever was running.
The code i linked works for all partitions. The AGB_FIRM savegame should contain the latest savegame(s) of the games you played in plaintext (after decrypting).

d0k3
Posted on 07-10-15 08:22 AM (rev. 2 of 07-14-15 01:45 PM) Link | #254
I never ran a GBA game, so it's all zeroes in there, and if I try to decrypt I essentially get a xorpad :). Anyways, testers say it's fine, too!

d0k3
Posted on 07-14-15 01:25 PM (rev. 2 of 07-14-15 02:49 PM) Link | #258
Alright, back again. I've got some trouble accessing the NAND CID via the GW browser method. In short, I can not access that memory (0x01FFCD80) without the 3DS freezing. Works fine on Brahma though.

Is there any alternative method of retrieving the NAND CID that could work?

More info (but maybe nothing too useful) here:
https://github.com/d0k3/Decrypt9/issues/14

And more info... I already searched for information, and there seems to be a GetNandCid() function somewhere:
http://3dbrew.org/wiki/FSPXI:GetNandCid
http://3dbrew.org/wiki/Filesystem_services
... but how to access this? No idea.
Pages: 1 2

Main - Homebrew discussion - Accessing the NAND (via fopen / opendir) Hide post layouts | New reply

Page rendered in 0.043 seconds. (2048KB of memory used)
MySQL - queries: 28, rows: 85/85, time: 0.009 seconds.
[powered by Acmlm] Acmlmboard 2.064 (2018-07-20)
© 2005-2008 Acmlm, Xkeeper, blackhole89 et al.