Homebrew TWLbf - a tool to brute force DSi Console ID or EMMC CID

Oleboy555

Well-Known Member
Member
Joined
Feb 8, 2017
Messages
907
Trophies
0
Location
Amsterdam
Website
3ds.guide
XP
2,308
Country
Netherlands
The EUR version is called "The Biggest Loser USA" as it's based on the USA show, which was also renamed to differentiate it from the locally produced version (at least in the UK).
yeah, I already ordered it and got it today, worked great! but because my dsi is a newer model I cannot install dsilink to run homebrew with it :( but I did retrieve my CID with it
 

JimmyZ

Sarcastic Troll
OP
Member
Joined
Apr 2, 2009
Messages
681
Trophies
0
XP
762
Country
Zimbabwe
yeah, I already ordered it and got it today, worked great! but because my dsi is a newer model I cannot install dsilink to run homebrew with it :( but I did retrieve my CID with it
Sorry but I don't get it, if you're gonna do hardmod anyway, why are you getting the biggest loser? well of course you can get it if you want to, but ... if you hardmod, then it's trivial to use a proper SD/MMC reader like RPi to get EMMC CID, and if you don't have that, EMMC CID brute force exists just for that.
 

Oleboy555

Well-Known Member
Member
Joined
Feb 8, 2017
Messages
907
Trophies
0
Location
Amsterdam
Website
3ds.guide
XP
2,308
Country
Netherlands
Sorry but I don't get it, if you're gonna do hardmod anyway, why are you getting the biggest loser? well of course you can get it if you want to, but ... if you hardmod, then it's trivial to use a proper SD/MMC reader like RPi to get EMMC CID, and if you don't have that, EMMC CID brute force exists just for that.
well, it was only 2 euros so theres that, and I wanted to use it for dslink to load homebrew but sadly that didnt work
 

JimmyZ

Sarcastic Troll
OP
Member
Joined
Apr 2, 2009
Messages
681
Trophies
0
XP
762
Country
Zimbabwe
I know this is already available in TWLTool but 3DS Console ID(I don't know if this is specific to the TWL part) brute force functionality added to both TWLbf and bfCL, and with the help of fwTool I just got my 2DS successfully brute forced :D kinda fun.

And mbr decryption in TWLbf for ... purposes...
 

dark_samus3

Well-Known Member
Member
Joined
May 30, 2015
Messages
2,372
Trophies
0
XP
2,042
Country
United States
First off: thanks for this tool :)
Second though; this tool's source code needs some love, I think. Seriously, I can't get it to compile at all with a recent OpenSSL, and the mbedtls folder is missing from the github? Specifically, in the .gitignore; https://github.com/Jimmy-Z/TWLbf/blob/master/.gitignore#L3-L9 . Maybe this is for licencing purposes, but a download of the necessary stuff should probably be linked to if that's the case. Further confusing, a download of the source code from the "releases" page yields a zip file with the mbedtls folder, but with only one file (config.h) and seems to be missing some files (aes.c/h, aesni.c/h, and version.h at least) this does coincide with the commit the source code was generated from, at least: https://github.com/Jimmy-Z/TWLbf/tree/6d1becd014e6796cc0921f4ba2f0e7ae189332cd anyway, I just figured I'd point these things out...

EDIT: fwiw, I did get the mbedtls version compiled. The required files to do so were:
https://github.com/ARMmbed/mbedtls/blob/development/include/mbedtls/aes.h
https://github.com/ARMmbed/mbedtls/blob/development/include/mbedtls/aesni.h
https://github.com/ARMmbed/mbedtls/blob/development/include/mbedtls/version.h
https://github.com/ARMmbed/mbedtls/blob/development/library/aes.c
https://github.com/ARMmbed/mbedtls/blob/development/library/aesni.c

these seem to have stayed fairly static, so I guess it's safe enough to just use those.

EDIT2: Seem to be having similar problems with the OpenCL port as well :/ it's missing "ocl_brute.h" at least.
 
Last edited by dark_samus3,

dark_samus3

Well-Known Member
Member
Joined
May 30, 2015
Messages
2,372
Trophies
0
XP
2,042
Country
United States
Oh, also, I should mention the "unknown" DSi from gbatek with console ID 08a19 is mine :)
eMMC CID: abd56e036c034d303046504100001500
ConsoleID: 08a1927016111108
Color: black
Region: U

Also, I'd love if people could post the third "ss" byte from their EMMC CID.
IE: MY ss ss ss ss ...
mine being 03 from above :)

Also, something interesting about the CIDs that I noticed....

some of the "known" bytes are actually ascii! Check it out:
00000010: abd5 6e03 6c03 4d30 3046 5041 0000 1500 ..n.l.M00FPA....

the "M00FPA" bit reversed is: APF00M which seems to be a shortened version of:
KMAPF0000M-S998 aka the eMMC #. The KLM5617EFW-B301 type of eMMC also follows this convention as well.
 
Last edited by dark_samus3,
  • Like
Reactions: Razor83

JimmyZ

Sarcastic Troll
OP
Member
Joined
Apr 2, 2009
Messages
681
Trophies
0
XP
762
Country
Zimbabwe
Just copy mbedtls files over, I followed twltool’s method of using it, I remember I documented this in the config.h or somewhere else.

Only later I found out mbedtls is available as a prebuilt library in MSYS2, It will only need a little effort to change to use that.

BTW you should use bfCL, it’s usually faster.
 
Last edited by JimmyZ,

dark_samus3

Well-Known Member
Member
Joined
May 30, 2015
Messages
2,372
Trophies
0
XP
2,042
Country
United States
Yeah, was trying to compile it (I use linux) and I noted the missing files ;P

anyway, I figured I'd show this off:

Code:
$ ./twlbf_mbedtls console_id_bcd 08a1900000000100 ab00000000034d303046504100001500 001f 60464d5a71ec18d32ae80a762a08b045 000000000000000000000000000055aa
mbed TLS 2.6.0, AES-NI supported
testing 08a190???????1??
testing 08a191???????1??
testing 08a192???????1??
Decrypted Block (Before Subtract): 24cf39bb0e7cfb4b146c5eed9520cb54
Decrypted Block (After Subtract): 24cf39bb0e7cfb4b146c5eed9520cb35
Encrypted Block: 493f3eeb9f7f5f1504bb5e365db26310
got a hit: 08a1927016111108
Target sha1 hash: 24cf39bb0e7cfb4b146c5eed9520cb35
00000000
10000000
20000000
30000000
40000000
50000000
60000000

found cid:abd56e036c034d303046504100001500
1116.00 seconds

bruteforced both my CID and consoleID ;)
 

JimmyZ

Sarcastic Troll
OP
Member
Joined
Apr 2, 2009
Messages
681
Trophies
0
XP
762
Country
Zimbabwe
I don't understand, how's that possible, from your log it seems to be brute force the Console ID then EMMC CID, if you can brute force Console ID without EMMC CID, that's something definitely worth noting.

BTW you don't need to 08a1900000000100, just 08a190000000000 is fine, actually anything after 08a19 is discarded:
https://github.com/Jimmy-Z/TWLbf/blob/master/dsi.c#L439
 

dark_samus3

Well-Known Member
Member
Joined
May 30, 2015
Messages
2,372
Trophies
0
XP
2,042
Country
United States
@JimmyZ it's "simple"
How it works:
You've seen how the encryption routine goes;
hash the emmc cid, add the block offset to the hashed cid, encrypt the hashed cid + block offset with the key derived from the Console ID with AES ECB, take the encrypted data, xor it with the plaintext block, the result of the xor is written to NAND.

working backwards:
xor a known plaintext NAND block with it's encrypted couterpart. You've now recovered the AES-ECB encrypted block. Guess a Console ID, generate a key, try to use it to decrypt the ECB encrypted block. If it was correct, you should have recovered the CID hash + block offset. Subtract the block offset to recover the emmc cid hash. You can check it was correct by using simply going through the normal encryption steps, but on another block. (I've hardcoded a block and it's offset into my code atm, for ease of testing). If the block you just encrypted using the derived "emmc cid hash" xor'd with the plaintext matches the second block you're using, you've recovered the actual emmc cid hash. From there you just bruteforce the emmc cid values, hash them and compare to the emmc cid hash you recovered. :)

EDIT: about the console ID template input. Yeah, I'm aware, I just copied my console ID (since I'm using a known one for testing) and added zeros in the non-constant places, for some reason. Dunno why, it was likely just the fact that it was a late-night coding session when I initially entered it, and all my subsequent tests just used the initial values ¯\_(ツ)_/¯
 
Last edited by dark_samus3,
  • Like
Reactions: Coto

JimmyZ

Sarcastic Troll
OP
Member
Joined
Apr 2, 2009
Messages
681
Trophies
0
XP
762
Country
Zimbabwe
;)

anyway, seriously, I'd love the ocl_brute.h file so I can compile bfCL and get it going

Oops, I missed that, will fix soon fixed.

I've updated the original post about your idea, hope you're fine with that. And I'll probably not accept PR, but if I got time to implement this, I'll credit you in the comment.

Reporting my stuff,
ConsoleID: 08 20 46 77 12 10 21 39
eMMC CID: 6E 4C 18 E6 EE 32 57 37 31 36 35 4D 00 01 15 00
Console Type: Light Blue DSi U
First 512 bytes of the eMMC dump:
https://mega.nz/#!Jgdx2bBL!U-_8sfJ-W7HRlaoBXxWGN-FHU-hm3l2magScGVfHIbY
Thanks!
 
Last edited by JimmyZ,

dark_samus3

Well-Known Member
Member
Joined
May 30, 2015
Messages
2,372
Trophies
0
XP
2,042
Country
United States
A quick code dump:

Code:
const u8 block_zero[16] = { 0x10, 0x63, 0xb2, 0x5d, 0x36, 0x5e, 0xbb, 0x04, 0x15, 0x5f, 0x7f, 0x9f, 0xeb, 0x3e, 0x3f, 0x49 }; //hardcoded for testing

    u8 block_zero_rev[16];

    byte_reverse_16(block_zero_rev, block_zero);

    u8 new_enc[16];

    u8 dec_data[16];

    u8 enc_data[16];
    xor_128(enc_data, ver, src);

    u8 enc_rev[16];
    byte_reverse_16(enc_rev, enc_data);

    u16 new_offset = u16be(offset);

    int succeed = 0;

    if(bcd){
        u64 start64 = (u64be(console_id_template) & 0xfffff00000000000ull) + 0x100;
        for (u64 i = 0; (i <= 9ull << 40) && !succeed; i += 1ull << 40) {
            printf("testing %06x???????1??\n", (u32)((start64 + i) >> 40));
            for (u64 j = 0; (j <= 9ull << 36) && !succeed; j += 1ull << 36) {
                for (u64 k = 0; (k <= 9ull << 32) && !succeed; k += 1ull << 32) {
                    for (u64 l = 0; (l <= 9ull << 28) && !succeed; l += 1ull << 28) {
                        for (u64 m = 0; (m <= 9ull << 24) && !succeed; m += 1ull << 24) {
                            for (u64 n = 0; (n <= 9ull << 20) && !succeed; n += 1ull << 20) {
                                for (u64 o = 0; (o <= 9ull << 16) && !succeed; o += 1ull << 16) {
                                    for (u64 p = 0; (p <= 9ull << 12) && !succeed; p += 1ull << 12) {
                                        for (u64 q = 0; (q <= 9ull << 4) && !succeed; q += 1ull << 4) {
                                            for (u64 r = 0; (r <= 9ull) && !succeed; r += 1ull) {
                                                u64 console_id = start64 + i + j + k + l + m + n + o + p + q + r;

                                                u64 key[2];
                                                dsi_make_key(key, console_id);
                                                u8 key_reversed[16];
                                                byte_reverse_16(key_reversed, (u8*)key);

                                                //apparently you have to set both an encryption *and* decryption key?? (enc key must be set after decryption)
                                                aes_128_ecb_set_key(key_reversed);

                                                aes_128_ecb_decrypt_1(dec_data, enc_rev);

                                                aes_128_ecb_set_dec_key(key_reversed);

                                                //assume we'll be looking at block 0
                                                dec_data[15] = dec_data[15] - new_offset;

                                                //block 0 (decrypted) is all zeros from every console I've looked at.
                                                //xor'ing something with zero has no change on the data
                                                //so just encrypting the CID hash, it should match directly with block 0
                                                aes_128_ecb_crypt_1(new_enc, dec_data);

                                                ++tested;

                                                if(!memcmp(block_zero_rev, new_enc, 16))
                                                {
                                                    printf("eMMC CID SHA1 Hash: ");
                                                    for(int s = 0; s < 16; s++)
                                                        printf("%02x", dec_data[s]);
                                                    printf("\n");

                                                    printf("Encrypted Block: ");
                                                    for(int s = 0; s < 16; s++)
                                                        printf("%02x", new_enc[s]);
                                                    printf("\n");

                                                    printf("got a hit: %08x%08x\n", (u32)(console_id >> 32), (u32)console_id);
                                                    succeed = 1;
                                                    break;
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }

could probably be optimized a bit, but it's a start :)

EDIT: I should note, this is substantially slower.
 
Last edited by dark_samus3,
  • Like
Reactions: nocash123

Site & Scene News

Popular threads in this forum

General chit-chat
Help Users
    Psionic Roshambo @ Psionic Roshambo: https://m.youtube.com/watch?v=_NTF5_qgH0o