ROM Hack [Release] 3DS_CTR_Decryptor-VOiD

  • Thread starter Thread starter Relys
  • Start date Start date
  • Views Views 649,442
  • Replies Replies 2,226
  • Likes Likes 30
Well sharing any copwritten code is not allowed, the xorpad is kind of part and parcel of the ROM (sort of like a mirror image) if you look around there has been people sharing bits of extracted ROMs on the internet, also if you just wanted to look at something and not any specific game the bigbluebox pokemon VC games don't need xorpads to be extracted
i am actually trying to hit on a specific Game, i need nothing from there, only some text files, for Review/FAQ purposes in my website.
 
Yeah, the original project had an example there using Tetris Axis plus 2 other games.
Now it has scripts to find and patch the necessary functions in any rom's extracted code.

The Patchrom have received a update, it can find the functions automatically
But i have not tested, i'm trying the re-xoring thing
 
Sorry for the bump, but I'm having an issue with modifying title ID's. When I do it manually with a Hex editor, the game no longer shows on the 3DS home screen when selected on the Gateway menu. AKA, I can't start it at all.

What issue is there in doing this that's preventing the game from launching?
 
What file are you modifying? It worked for me when I edited the names in icon.bin and rebuilt the whole rom, but the exefs has a checksum for each file that you need to fix if you modify it manually.


I'm just hex editing the ".3ds" rom itself. I would think it wouldn't be an issue considering you can modify everything like how the game saves without any problems.

I don't plan on using this tool until there's a practical way of repacking roms.
 
Yeah it's odd how some stuff in the headers is ok to modify, and other stuff is verified by checksums. If you want to change the name by hex editing the .3ds, you'd need to manually fix at least a couple of checksums, it's doable but I'm not sure it's worth the hassle.
 
Yeah it's odd how some stuff in the headers is ok to modify, and other stuff is verified by checksums. If you want to change the name by hex editing the .3ds, you'd need to manually fix at least a couple of checksums, it's doable but I'm not sure it's worth the hassle.


If it's that much trouble, I'll just wait until it's possible to rebuild roms (And actually play them).

Anyone else have any info on this?
 
Would it be possible to generate a xorpad for homebrew? i know you can easily decrypt it with ctrtool. but i want to inject something directly into a homebrew without using ctrtool or makerom.
(wel ctrtool is t the biggest problem, but makerom is making own exefsheaders, what i dont want)
 
Would it be possible to generate a xorpad for homebrew? i know you can easily decrypt it with ctrtool. but i want to inject something directly into a homebrew without using ctrtool or makerom.
(wel ctrtool is t the biggest problem, but makerom is making own exefsheaders, what i dont want)


Aren't homebrews just encrypted with a 0 key?
 
yes, but if you extract the raw data from it ( the -p parameter in ctrtool) and you used a 0 key it doesnt work.

The key itself is zeros and the encryption is AES-ECB, but it uses a custom counter, if you manually decrypt a NCCH, then you need to make your own counter algo.

Here how the encryption itself works (with C# code example).

In AES-ECB the xorpad is generated by encrypting a counter and then xoring that with the plaintext, that means we need 2 things, the key (zeros) and the init counter.

The init counter is titleid (8 Byte) + type (1 Byte) + blockid. (7 Byte)

Code:
example "VC Pokemon Red" by BigBlueBox: 00 04 00 00 0B 00 00 00 XX YY YY YY YY YY YY YY
 
00 04 00 00 0B 00 00 00 = Title ID
XX = type (ExHeader = 01, ExeFS = 02, RomFS = 03)
YY YY YY YY YY YY YY = block id in BigEndian (1 block = 16 byte)

Here the C# code to decrypt/encrypt NCCH's raw contents or if you give it a zeroes block, then you get the xorpad.
Code:
        private const int KEY_SIZE = 128;
        private const int BLOCK_SIZE = KEY_SIZE / 8;
 
        public static byte[] AES_CTR(byte[] key, byte[] counter, byte[] data)
        {
            byte[] result = data;
            byte[] block = counter, encBlock = new byte[BLOCK_SIZE];
            int blocklength = data.Length / BLOCK_SIZE;
 
            RijndaelManaged rm = new RijndaelManaged();
            rm.Mode = CipherMode.ECB;
            rm.Padding = PaddingMode.None;
            rm.KeySize = KEY_SIZE;
            rm.BlockSize = KEY_SIZE;
            rm.Key = key;
            rm.IV = new byte[0x10]; //iv is not needed in ECB mode
 
            using (ICryptoTransform ict = rm.CreateEncryptor())
            {
                for (int i = 0; i < blocklength; i++)
                {
                    //increase counter block id, note: we only use 4 byte, thats more then enough to encrypt up to 68 GB...
                    Array.Copy(BitConverter.GetBytes(i), 0, block, BLOCK_SIZE - 4, 4);
                    Array.Reverse(block, BLOCK_SIZE - 4, 4);
 
                    //encrypt counter
                    ict.TransformBlock(block, 0, BLOCK_SIZE, encBlock, 0);
 
                    //de/encrypt data
                    XorBlock(result, i * BLOCK_SIZE, encBlock);
                }
            }
            rm.Clear();
            return result;
        }
 
        public static void XorBlock(byte[] dst, int offset, byte[] xorBlock)
        {
            for (int i = 0; i < xorBlock.Length; i++)
                dst[i + offset] ^= xorBlock[i];
        }
 
The key itself is zeros and the encryption is AES-ECB, but it uses a custom counter, if you manually decrypt a NCCH, then you need to make your own counter algo.

Here how the encryption itself works (with C# code example).

In AES-ECB the xorpad is generated by encrypting a counter and then xoring that with the plaintext, that means we need 2 things, the key (zeros) and the init counter.

The init counter is titleid (8 Byte) + type (1 Byte) + blockid. (7 Byte)

Code:
example "VC Pokemon Red" by BigBlueBox: 00 04 00 00 0B 00 00 00 XX YY YY YY YY YY YY YY
 
00 04 00 00 0B 00 00 00 = Title ID
XX = type (ExHeader = 01, ExeFS = 02, RomFS = 03)
YY YY YY YY YY YY YY = block id in BigEndian (1 block = 16 byte)

Here the C# code to decrypt/encrypt NCCH's raw contents or if you give it a zeroes block, then you get the xorpad.
Code:
        private const int KEY_SIZE = 128;
        private const int BLOCK_SIZE = KEY_SIZE / 8;
 
        public static byte[] AES_CTR(byte[] key, byte[] counter, byte[] data)
        {
            byte[] result = data;
            byte[] block = counter, encBlock = new byte[BLOCK_SIZE];
            int blocklength = data.Length / BLOCK_SIZE;
 
            RijndaelManaged rm = new RijndaelManaged();
            rm.Mode = CipherMode.ECB;
            rm.Padding = PaddingMode.None;
            rm.KeySize = KEY_SIZE;
            rm.BlockSize = KEY_SIZE;
            rm.Key = key;
            rm.IV = new byte[0x10]; //iv is not needed in ECB mode
 
            using (ICryptoTransform ict = rm.CreateEncryptor())
            {
                for (int i = 0; i < blocklength; i++)
                {
                    //increase counter block id, note: we only use 4 byte, thats more then enough to encrypt up to 68 GB...
                    Array.Copy(BitConverter.GetBytes(i), 0, block, BLOCK_SIZE - 4, 4);
                    Array.Reverse(block, BLOCK_SIZE - 4, 4);
 
                    //encrypt counter
                    ict.TransformBlock(block, 0, BLOCK_SIZE, encBlock, 0);
 
                    //de/encrypt data
                    XorBlock(result, i * BLOCK_SIZE, encBlock);
                }
            }
            rm.Clear();
            return result;
        }
 
        public static void XorBlock(byte[] dst, int offset, byte[] xorBlock)
        {
            for (int i = 0; i < xorBlock.Length; i++)
                dst[i + offset] ^= xorBlock[i];
        }
Thanks a lot this is really helpfull! But what do i take as the blockid? The 16 bytes as it start with?
 
Thanks a lot this is really helpfull! But what do i take as the blockid? The 16 bytes as it start with?
The block id starts with 0 and after encrypting 16 bytes (1 block) it increases by 1.

just remember, it's BigEndian:
Block 0: 00 04 00 00 0B 00 00 00 03 00 00 00 00 00 00 00
Block 1: 00 04 00 00 0B 00 00 00 03 00 00 00 00 00 00 01
...
Block 9999: 00 04 00 00 0B 00 00 00 03 00 00 00 00 00 27 0F
 
What file are you modifying? It worked for me when I edited the names in icon.bin and rebuilt the whole rom, but the exefs has a checksum for each file that you need to fix if you modify it manually.

Did you test this to see if it will trick Miiverse into allowing you to post screenshots of games that the screenshot feature does not usually support? Can you please test this and post how to change the required ExeFS hash?

In addition, I keep getting errors when trying to extract, decrypt, and unpack the Mario & Luigi Dream Team ExeFS. I have tried various programs, such as the tools from patchrom (with the required .dll files set up) and xor.exe.

What method did you use to extract, decrypt, unpack, repack, encrypt and inject the ExeFS? Which game did you do this to and which game did you change the ID to?
 
  • Like
Reactions: The Cringe
Any progress on repacking retail roms?
well i just tried it for somebody and i noticed a few things:

1) some roms can be repacked and will work fine (kirby for example)
2) other roms need some adjustments after repacking (NSMB), which include changing the exheader afterwards (and hashes). (but i got it working)
 
  • Like
Reactions: cearp
Did you test this to see if it will trick Miiverse into allowing you to post screenshots of games that the screenshot feature does not usually support? Can you please test this and post how to change the required ExeFS hash?

In addition, I keep getting errors when trying to extract, decrypt, and unpack the Mario & Luigi Dream Team ExeFS. I have tried various programs, such as the tools from patchrom (with the required .dll files set up) and xor.exe.

What method did you use to extract, decrypt, unpack, repack, encrypt and inject the ExeFS? Which game did you do this to and which game did you change the ID to?

Wow lot of questions :) No I didn't test fooling MiiVerse, interesting thought tho. Will see if I can give it a go at some point.

I've mostly been messing with VC games rather than retail games. I know people have had trouble repacking retail roms, I haven't had more than one or two failed attempts as yet, haven't really tried to figure it out.

For the hashes in exefs, you just take a sha256 hash of the whole (code.bin or icon.bin or banner.bin) file. If you take this hash of the original file then you can hex search for it in the exefs.bin and replace it with the hash of the new file.
 
  • Like
Reactions: piratesephiroth
The refactored thingy doesn't seem to work on my 3DS.. it always freezes at 'Reading' of the ncchinfo.bin
The original code works, but still freezes half way through.

I looked through the source too, and dont see anything that could have went wrong.
 

Site & Scene News

Popular threads in this forum