Hacking Finding the 3DS Common Key

GPUs decrypt crazy fast... If someone created a folding at home type app that could use the GPU, CPU, Cell (hacked playstation 3s) have it go back to a network server.

We could easy get enough computer power to crazy that sucker in no time.


 
If there's some flaw in the encryption (or the way it was implemented) then that can take down the amount of time needed to crack it from years to hours (or even minutes/seconds, in the case of WEP).
http://www.techexams.net/forums/cwnp-certifications/20108-cracking-wep-keys-less-than-60-seconds-using-aircrack-ptw.html
(And this article is from years ago.)

If there's none known then bruteforcing is likely the approach, but the "size" of the key almost directly dictates the possible values. With some older formats the number of possible keys wasn't that large... say, a 32-bit value has 4,294,967,296 possibilities. With modern technology it's almost trivial to try that many combinations locally in a short amount of time (if we're talking something like trying password hashes online though, there's usually a timeout for failed logins to kill this method). The issue is a bit is a place value in binary, so adding one bit doubles the previous value... so just 33 bits is 8,589,934,592, double the number of keys from 32. So while going from 32 to 128 (to use the DSi example) may not look like a lot, but it's the difference between.
4,294,967,296
and
340,282,366,920,938,463,463,374,607,431,768,211,456.

GPUs are pretty good at parallel workloads, but I haven't heard about anybody using them to crack things.
 
Zip files are much weaker than RSA-2048/RSA-4096 encrypted files. Brute forcing an RSA-2048/RSA-4096 encrypted file would take about... ∞.
It's not going to happen. Stop thinking we can brute force the thing.

EDIT: Ninja'd
 
GPUs decrypt crazy fast... If someone created a folding at home type app that could use the GPU, CPU, Cell (hacked playstation 3s) have it go back to a network server.

We could easy get enough computer power to crazy that sucker in no time.
lol

There are 1.15 X 10^77 possible combinations in a 256 bit key.

Assuming a computer could brute force 1 billion keys per second (fat chance) it would take 3.67 X10^60 years to crack on average.

That's 3 followed by sixty zeros years.
 
This bruteforce thingy remind me the attempt of WB3000 back in 2009 with his dsi common key bruteforcer and the networked version by Asiekierka.

Nothing good resulted from both project.

Luck wasn't with them. ;)
 
oh so we are randomly throwing out ideas?
in that case im just gonna say this and hope im right:
you know how the RAM is meant to have the encryption/decryption key in it.
Why not just save that to notepad and use a computer to test all the data on the RAM to find a crack.
 
oh so we are randomly throwing out ideas?
in that case im just gonna say this and hope im right:
you know how the RAM is meant to have the encryption/decryption key in it.
Why not just save that to notepad and use a computer to test all the data on the RAM to find a crack.
I think placing the 3DS in the sun and overloading the IR sensor would be easier.
 
GPUs decrypt crazy fast... If someone created a folding at home type app that could use the GPU, CPU, Cell (hacked playstation 3s) have it go back to a network server.

We could easy get enough computer power to crazy that sucker in no time.
lol

There are 1.15 X 10^77 possible combinations in a 256 bit key.

Assuming a computer could brute force 1 billion keys per second (fat chance) it would take 3.67 X10^60 years to crack on average.

That's 3 followed by sixty zeros years.

To add a level of complexity to the crack, you realize you need to factor prime numbers to that magnitude also, so why not add a few (10^60 or whatever, i'm not about to do the math cuz i'm lazy) years to the mix there

It is computationally infeasible to crack the key which is why encryption works
 
Roh, you just have to program a malware that infect machines to compute the brute force attack and send back result in a cloud fashion.... the 3ds.bruteforcer malware... Easy no? (Sorry had to say that, really XD)
 
Roh, you just have to program a malware that infect machines to compute the brute force attack and send back result in a cloud fashion.... the 3ds.bruteforcer malware... Easy no? (Sorry had to say that, really XD)
I can actually see how that could work, is the sad part. :P
 
GPUs decrypt crazy fast... If someone created a folding at home type app that could use the GPU, CPU, Cell (hacked playstation 3s) have it go back to a network server.

We could easy get enough computer power to crazy that sucker in no time.
lol

There are 1.15 X 10^77 possible combinations in a 256 bit key.

Assuming a computer could brute force 1 billion keys per second (fat chance) it would take 3.67 X10^60 years to crack on average.

That's 3 followed by sixty zeros years.

To add a level of complexity to the crack, you realize you need to factor prime numbers to that magnitude also, so why not add a few (10^60 or whatever, i'm not about to do the math cuz i'm lazy) years to the mix there

It is computationally infeasible to crack the key which is why encryption works

That makes no sense, if there are 1.15 X 10^77 possibilities in a key then there are that many, there are no more no less, no matter what algorithm they used to develop it. Anyways, you guys are looking at it like it has to be the last key tried, It could be the 42nd key tried and take all of a second, or hell, it could be the first key. You never know.
 
  • Like
Reactions: 1 person
First, keys are made to have non-repeating segments. In any good key/hash creation, you don't end up with something that's "1111111111111111". This lowers the number of possible combinations.

Second, the amount of time taken is still too high even if you take a very small amount. If guessing all the keys would take 5,000,000 years, then guessing 0.001% of them would still take 50 years (and even after 50 years you have a 99.999% chance of failure).

It's "possible", but it's not "feasible", which is partially why encryption works.
 
Just for fun

Code:
using System;
using System.Security.Cryptography;
using System.IO;
using System.Net;
using System.Threading;
using System.Timers;
namespace AES_Decrypter
{
class Program
{
static RijndaelManaged rijndaelCipher;
//static SHA1 sha = new SHA1CryptoServiceProvider();
static SHA256 sha = new SHA256Managed();
static Random rnd = new Random();
static RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider();
static byte[] buffer;
static int num_tried;
static long total_num;
static bool keepgoing;
static void Main(string[] args)
{
Console.WriteLine("[]-[]-[]-[]-[]-[]-[]-[] Basic DSi Bruteforce Application []-[]-[]-[]-[]-[]-[]-[]");
// Create all the constants/variables...
const string DSiNUSURL = "http://nus.cdn.t.shop.nintendowifi.net/ccs/download/";
byte[] contsha1 = new byte[40] { 0x10, 0xb2, 0x8d, 0x8e, 0xcb, 0xcc, 0x73, 0xbc, 0xef, 0x40, 0xb0, 0x24, 0x06, 0x1f, 0x4f, 0xd6, 0xb8, 0x14, 0xdf, 0x08, 0x10, 0xb2, 0x8d, 0x8e, 0xcb, 0xcc, 0x73, 0xbc, 0xef, 0x40, 0xb0, 0x24, 0x06, 0x1f, 0x4f, 0xd6, 0xb8, 0x14, 0xdf, 0x08 };
byte[] testkey = new byte[16] { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
byte[] titleIV = new byte[16] { 0x00, 0x03, 0x00, 0x0f, 0x48, 0x4e, 0x4c, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
byte[] contentIV = new byte[16] { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
byte[] enccontentsha = new byte[40] { 0xFC, 0x20, 0x32, 0x5F, 0x92, 0x96, 0x2A, 0x05, 0x5A, 0xF5, 0x5F, 0xD3, 0x27, 0x2D, 0xD2, 0x04, 0x3D, 0x8D, 0x37, 0xC7, 0xFC, 0x20, 0x32, 0x5F, 0x92, 0x96, 0x2A, 0x05, 0x5A, 0xF5, 0x5F, 0xD3, 0x27, 0x2D, 0xD2, 0x04, 0x3D, 0x8D, 0x37, 0xC7 };
byte[] decfirstbytes = new byte[16] { 0x17, 0xFC, 0xB6, 0xF1, 0x78, 0x4F, 0x8D, 0x1E, 0x93, 0xE2, 0x47, 0x4F, 0x9C, 0x5F, 0x0E, 0xC5 };
Console.WriteLine("Downloading files to decrypt...\n");
WebClient generalWC = new WebClient();
byte[] data = null;
try
{
FileStream localtitle = new FileStream(@"/00000000", FileMode.Open);
data = ReadFully(localtitle);
localtitle.Close();
}
catch
{
try
{
data = generalWC.DownloadData(DSiNUSURL + "0004800F484E4C41/00000000");
}
catch
{ }
}
finally
{
if (data == null)
{
// Fail
Console.WriteLine("Error: NUS 00000003 not found online or locally!");
Console.ReadLine();
Environment.Exit(0);
}
}
Console.WriteLine(" - Received: 00000003");
byte[] titlekeytemp = null;
try
{
FileStream localtitle = new FileStream(@"\cetk", FileMode.Open);
titlekeytemp = ReadFully(localtitle);
localtitle.Close();
}
catch
{
try
{
titlekeytemp = generalWC.DownloadData(DSiNUSURL + "0004800F484E4C41/cetk");
}
catch
{ }
}
finally
{
if (titlekeytemp == null)
{
// Fail
Console.WriteLine("Error: NUS ticket not found online or locally!");
Console.ReadLine();
Environment.Exit(0);
}
}
Console.WriteLine(" - Received: Ticket (cetk)");
byte[] tmd = null;
try
{
FileStream localtitle = new FileStream(@"\tmd", FileMode.Open);
tmd = ReadFully(localtitle);
localtitle.Close();
}
catch
{
try
{
tmd = generalWC.DownloadData(DSiNUSURL + "0004800F484E4C41/tmd");
}
catch
{ }
}
finally
{
if (tmd == null)
{
// Fail
Console.WriteLine("Error: NUS tmd not found online or locally!");
Console.ReadLine();
Environment.Exit(0);
}
}
Console.WriteLine(" - Received: Title metadata (TMD)\n");
// Load latest SHA-1 from TMD
for (int i = 0; i < 40; i++)
{
contsha1[i] = tmd[0xB14 + i];
}
Console.WriteLine("Detected SHA-1: ");
DisplayBytes(contsha1);
// Optimize. Do this to reduce conversion later...
string decstring = Convert.ToBase64String(decfirstbytes);
//contentIV[15] = tmd[0x1E9]; //ichfly only use ID 0
Console.WriteLine("\n\nUsing IV: ");
DisplayBytes(contentIV);

if (Convert.ToBase64String(sha.ComputeHash(data)) != Convert.ToBase64String(enccontentsha))
{
Console.WriteLine("NUS Content has changed. Notify author, although program should still work...");
Console.ReadLine();
//Environment.Exit(0);
}
/*Create all the constants...
const string DSiNUSURL = "http://nus.cdn.shop.wii.com/ccs/download/";
byte[] contsha1 = new byte[20] { 0x10, 0x14, 0x79, 0x94, 0xc3, 0xc5, 0x98, 0x10, 0x4f, 0x1d, 0xd8, 0xea, 0xea, 0xf6, 0xa1, 0xea, 0xdc, 0x85, 0xee, 0x44 };
byte[] testkey = new byte[16] { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
byte[] finikey = new byte[16] { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
byte[] titleIV = new byte[16] { 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
byte[] contentIV = new byte[16] { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
Console.WriteLine("Downloading files to decrypt...\n");
WebClient generalWC = new WebClient();
byte[] data = generalWC.DownloadData(DSiNUSURL + "0000000100000010/00000002");
byte[] titlekeytemp = generalWC.DownloadData(DSiNUSURL + "0000000100000010/cetk");*/
// Get the Title Key from cetk...
byte[] titlekeyenc = new byte[16];
for (int i = 0; i < 0x10; i++)
{
titlekeyenc[i] = titlekeytemp[0x1BF + i];
}
Console.WriteLine("\n\nEncrypted Title Key of 03 Content...");
DisplayBytes(titlekeyenc);
// Take in any hex codes as parameters...
for (int i = 0; i < args.Length; i++)
{
testkey[i] = byte.Parse(args[i], System.Globalization.NumberStyles.HexNumber);
}
if (args.Length >= 1)
{
Console.WriteLine("\n\nCurrent starting point...");
DisplayBytes(testkey);
}
// Set 'mode' based on input...
Console.WriteLine("\n\nMode:");
Console.WriteLine("  [1] Standard");
Console.WriteLine("  [2] 'Secure' Random");
Console.WriteLine("  [3] '1' Bit Mode");
Console.WriteLine("\nObsolete Modes:");
Console.WriteLine("  [4] Standard Random");
Console.WriteLine("  [D] Debug Mode");
Console.WriteLine("\nSelect a mode: ");
int mode = 0;
System.ConsoleKeyInfo cks = Console.ReadKey(true);
if (cks.KeyChar == '1')
mode = 1;
else if (cks.KeyChar == '2')
mode = 2;
else if (cks.KeyChar == '3')
mode = 3;
else if (cks.KeyChar == '4')
mode = 4;
else if (cks.KeyChar == 'D')
mode = 9;
else
mode = 3;
// AES stuff
// This is for decryting title key from test common keys
// Cipher1 decrypts the Title Key with random common key
rijndaelCipher = new RijndaelManaged();
rijndaelCipher.Mode = CipherMode.CBC;
rijndaelCipher.Padding = PaddingMode.None;
rijndaelCipher.KeySize = 128;
rijndaelCipher.BlockSize = 128;
rijndaelCipher.IV = titleIV;
// Cipher2 decrypts the contents using the new TitleKey
RijndaelManaged finaldecrypter;
finaldecrypter = new RijndaelManaged();
finaldecrypter.Mode = CipherMode.CBC;
finaldecrypter.Padding = PaddingMode.None;
finaldecrypter.KeySize = 128;
finaldecrypter.BlockSize = 128;
finaldecrypter.IV = contentIV;
// Fun facts on how long it took...
long timeinms = DateTime.UtcNow.Ticks;
long timeinft = 0;
num_tried = 0;
total_num = 0;
// Optimization? lol
buffer = new byte[6992];
// Every 1 second, show info...
System.Timers.Timer t = new System.Timers.Timer(1000);
t.Elapsed += new ElapsedEventHandler(TimerTicked);
t.Start();
// wow
keepgoing = true;
// Small part of decrypted file...
byte[] encsmall = new byte[16];
for (int i = 0; i < 16; i++)
{
encsmall[i] = data[i];
}
while (keepgoing)
{
// Set the Title Key decrypter to the random test key...
rijndaelCipher.Key = testkey;
// The new key is the decrypted title key by test ckey...
finaldecrypter.Key = Decrypt(titlekeyenc, rijndaelCipher);
// If the miraculous SHA-1 should match...
if (Convert.ToBase64String(Decrypt(encsmall, finaldecrypter)) == decstring)
{
// Common Key is written to console...
Console.WriteLine("Common Key: ");
DisplayBytes(testkey);
Console.WriteLine("Title Key: ");
DisplayBytes(Decrypt(titlekeyenc, rijndaelCipher));
WriteFoundKey(testkey);
Console.WriteLine("\nKey written to /dsikey.bin. DO NOT CLOSE THIS UNTIL YOU CAN VERIFY FILE INTEGRITY.");
Console.WriteLine("\n");
Console.WriteLine("Verifying entire file...");
if (Convert.ToBase64String(sha.ComputeHash(Decrypt(data, finaldecrypter))) == Convert.ToBase64String(contsha1))
Console.WriteLine("SHA-1 test matches :D");
else
Console.WriteLine("SHA-1 failed, still SOMETHING happened :|");
num_tried = 0;
keepgoing = false;
}
// Depending on mode, increment or randomize the test key...
if (mode == 1)
testkey = incrementAtIndex(testkey, 15);
else if (mode == 2)
testkey = SecureRandomize();
else if (mode == 3)
{
testkey = SecureRandomize();
testkey[0] = SetBit(testkey[0], 7, true);
}
else if (mode == 9)
{
Console.WriteLine("\nCurrent COMMON KEY: ");
DisplayBytes(testkey);
Console.WriteLine("\nCurrent TITLE KEY: ");
DisplayBytes(finaldecrypter.Key);
Console.WriteLine("\nThis SHA-1: ");
DisplayBytes(sha.ComputeHash(Decrypt(data, finaldecrypter)));
Console.WriteLine("\nOfficial SHA-1: ");
DisplayBytes(contsha1);
Console.WriteLine("\nEncrypted Chunk: ");
DisplayBytes(encsmall);
Console.WriteLine("\nDecrypted Chunk: ");
DisplayBytes(Decrypt(encsmall, finaldecrypter));
//WriteFoundKey(testkey);
Console.ReadLine();

testkey = SecureRandomize();
testkey[0] = SetBit(testkey[0], 7, true);
}
else if (mode == 4)
testkey = PlainRandomize();
if (mode != 9)
{
num_tried += 1;
total_num += 1;
}
}
// Somehow it worked, so get the new time now...
timeinft = DateTime.UtcNow.Ticks;
// ... and write Done with the total time elapsed...
t.Dispose();
Console.WriteLine("\nDone - " + (timeinft - timeinms) + " Operation");
Console.ReadLine();
Console.ReadLine();
Console.ReadLine();
Console.ReadLine();
}
public static byte[] Decrypt(byte[] encryptedData, RijndaelManaged decrypter)
{
//ICryptoTransform transform = rijndaelCipher.CreateDecryptor();
ICryptoTransform transform = decrypter.CreateDecryptor();
using (MemoryStream ms = new MemoryStream(encryptedData))
{
using (CryptoStream cs = new CryptoStream(ms, transform, CryptoStreamMode.Read))
{
return ReadFully(cs);
}
}
}
public static byte[] ReadFully(Stream stream)
{
buffer = new byte[6992];
using (MemoryStream ms = new MemoryStream())
{
while (true)
{
int read = stream.Read(buffer, 0, buffer.Length);
if (read <= 0)
return ms.ToArray();
ms.Write(buffer, 0, read);
}
}
}
static void DisplayBytes(byte[] bytes)
{
for (int i = 0; i < bytes.Length; ++i)
{
Console.Write(bytes[i].ToString("X2") + " ");
//Console.Write(bytes[i].ToString("x4") + " ");
//if (i > 0 && i % 16 == 0) Console.Write("\n");
}
//Console.WriteLine("");
}
static public byte[] incrementAtIndex(byte[] array, int index)
{
if (array[index] == byte.MaxValue)
{
array[index] = 0;
if (index > 0)
incrementAtIndex(array, index - 1);
}
else
{
array[index]++;
}
return array;
}
static public byte[] PlainRandomize()
{
//Create random byte array
byte[] randomArray = new byte[16];
// Use 'secure' / regular randomization.
rnd.NextBytes(randomArray);
return randomArray;
}
static public byte[] SecureRandomize()
{
//Create random byte array
byte[] randomArray = new byte[16];
// Use 'secure' / regular randomization.
rng.GetNonZeroBytes(randomArray);
return randomArray;
}
static public void WriteFoundKey(byte[] ckey)
{
try
{
//Console.WriteLine("Writing to file...");
//DisplayBytes(ckey);
FileStream ckeystr = new FileStream(@"/dsikey.bin", FileMode.OpenOrCreate);
ckeystr.Write(ckey, 0, 16);
ckeystr.Close();
}
catch
{
//throw;
}
}
private static bool GetBit(byte b, byte position)
{
return ((b & (byte)(1 << position)) != 0);
}
private static byte SetBit(byte b, byte position, bool newBitValue)
{
byte mask = (byte)(1 << position);
if (newBitValue)
{
return (byte)(b | mask);
}
else
{
return (byte)(b & ~mask);
}
}
private static void TimerTicked(object sender, ElapsedEventArgs e)
{
if (num_tried != 0)
{
Console.Clear();
Console.WriteLine(num_tried + " Keys p/s. (Total: " + total_num + ")");
num_tried = 0;
}
}
}
}
 

Site & Scene News

Popular threads in this forum