magnify
magnify
Home JavaScript 3DS Parental Tool: Reset / Unlock online
category

3DS Parental Tool: Reset / Unlock online

Published on April 13, 2015 by in JavaScript

Reset / Unlock your Nintendo 3DS parental code using this online tool:




Explanation

When my niece bought a second-hand 3DS, it had a parental code. I was quite surprised to not find any online tool to unlock it (unlike for wii).

So, based on the code of an unlock tool in C, I decided to write my own in JavaScript.

The main problem is that lot of operations are typed and a lot of them need specific size (uint8, uint32, uint64…).

So, here are some tips to know when you need to deal with these kind of operation.

First one is to know the “>>>” operator (Unsigned Right Shift Operator) and its main limitation (unsigned 32 bits).

A trick with this operator is to convert any value to an unsigned variable

var value = 123 >>> 0;

In the C code, there is a variable which is a uint8_t (8 bits), so, after each operation on it, I simply remove the >8 bits using a mask with 0xff.

Based on these 2 first notes, here is an example of the translated code:

	y = 0xFFFFFFFF;
	x = generator[0];

	for(i=0; i<4; i++)
	{
		x ^= y;
		y = table[x] ^ (y>>8);
		x = generator[1+i*2] ^ y;
		y = table[x] ^ (y>>8);
		x = generator[2+i*2];
	}

Become

    y = 0xFFFFFFFF;
    x = generator.charCodeAt(0);
    for(i=0; i<4; i++)
    {
        x ^= y;
        x &= 0xff; // uint8
        y = table[x] ^ (y>>>8);
        x = generator.charCodeAt(1+i*2) ^ y;
        x &= 0xff; // uint8
        y = table[x] ^ (y>>>8);
        x = generator.charCodeAt(2 + i*2);
        x &= 0xff; // uint8
    }

You’ll notice that generator[0] became generator.charCodeAt(0), because generator is a string of digit (i.e. 01014545) and generator[0] which is the digit “0” (as string) should be used as 0 (numeric) instead of 48 (ascii 48 = “0”)

The last caveat was in the code:

	yhi = (yll>>48);

It is a bit rotation from an unsigned long long int, problem is >>> is limited to 32 bits, so, I had to write a small function to execute this rotation:

function ullRShift(ullValue, shift) {
    while(shift) {
        shift--;
        ullValue = ullValue / 2;
    }
    return ullValue >>> 0;
}

Here is the full code:

function lpad(s, len, chr) {
    s += "";
    while(s.length < len) {
        s = chr + s;
    }
    return s;
}

function ullRShift(ullValue, shift) {
    while(shift) {
        shift--;
        ullValue = ullValue / 2;
    }
    return ullValue >>> 0;
}

function calculateMasterKey(generator) {
    var table = [];
    var data, i, j, y, x, yll, yhi;

    for(i=0; i<0x100; i++)
    {
        data = i;
        for(j=0; j<4; j++)
        {
            if (data & 1)
                data = 0xEDBA6320 ^ (data>>>1);
            else
                data = data>>>1;

            if (data & 1)
                data = 0xEDBA6320 ^ (data>>>1);
            else
                data = data>>>1;
        }

        table[i] = data;
    }

    y = 0xFFFFFFFF;
    x = generator.charCodeAt(0);
    for(i=0; i<4; i++)
    {
        x ^= y;
        x &= 0xff; // uint8
        y = table[x] ^ (y>>>8);
        x = generator.charCodeAt(1+i*2) ^ y;
        x &= 0xff; // uint8
        y = table[x] ^ (y>>>8);
        x = generator.charCodeAt(2 + i*2);
        x &= 0xff; // uint8
    }

    y ^= 0xAAAA;
    y += 0x1657;

    yll = y;
    yll = (yll+1) * 0xA7C5AC47;

    yhi = ullRShift(yll, 48);
    yhi *= 0xFFFFF3CB;
    y += (yhi<<5);

    return lpad(y, 5, "0");
}

function getMasterKey(servicecode, month, day) {

    servicecode %= 10000;
    day %= 100;
    month %= 100;

    return calculateMasterKey(lpad(month, 2, "0") + lpad(day, 2, "0") + lpad(servicecode, 4, "0"));
}
 
 Share on Facebook Share on Twitter Share on Reddit Share on LinkedIn
No Comments  comments 

You must be logged in to post a comment.