mirror of
https://github.com/rvtr/GodMode9i.git
synced 2025-11-02 00:11:07 -04:00
parent
0745202caa
commit
65394c34f1
@ -45,5 +45,6 @@ Once everything is downloaded and installed, `git clone` this repository, naviga
|
||||
* [zacchi4k](https://github.com/zacchi4k): Creator of the GodMode9i logo used in v1.3.1 and onwards.
|
||||
* [Edo9300](https://github.com/edo9300): Save reading code from his save manager tool.
|
||||
* [JimmyZ](https://github.com/JimmyZ): NAND code from twlnf (with writing code stripped for safety reasons).
|
||||
* [zoogie](https://github.com/zoogie): Code from dumpTool to get ConsoleID.
|
||||
* [devkitPro](https://github.com/devkitPro): devkitARM, libnds, original nds-hb-menu code, and screenshot code.
|
||||
* [d0k3](https://github.com/d0k3): Original GM9 app and name for the Nintendo 3DS, which this is inspired by.
|
||||
|
||||
@ -28,8 +28,7 @@
|
||||
|
||||
---------------------------------------------------------------------------------*/
|
||||
#include <nds.h>
|
||||
|
||||
//static u8 aesIvValues[0x10] = {0x80,0x6B,0xCF,0x4F,0x93,0xEE,0x6F,0x21,0xF9,0x86,0xDF,0x98,0x7D,0xE7,0xFD,0x07};
|
||||
#include <string.h>
|
||||
|
||||
unsigned int * SCFG_EXT=(unsigned int*)0x4004008;
|
||||
|
||||
@ -62,6 +61,32 @@ void powerButtonCB() {
|
||||
exitflag = true;
|
||||
}
|
||||
|
||||
void set_ctr(u32* ctr){
|
||||
for (int i = 0; i < 4; i++) REG_AES_IV[i] = ctr[3-i];
|
||||
}
|
||||
|
||||
// 10 11 22 23 24 25
|
||||
void aes(void* in, void* out, void* iv, u32 method){ //this is sort of a bodged together dsi aes function adapted from this 3ds function
|
||||
REG_AES_CNT = ( AES_CNT_MODE(method) | //https://github.com/TiniVi/AHPCFW/blob/master/source/aes.c#L42
|
||||
AES_WRFIFO_FLUSH | //as long as the output changes when keyslot values change, it's good enough.
|
||||
AES_RDFIFO_FLUSH |
|
||||
AES_CNT_KEY_APPLY |
|
||||
AES_CNT_KEYSLOT(3) |
|
||||
AES_CNT_DMA_WRITE_SIZE(2) |
|
||||
AES_CNT_DMA_READ_SIZE(1)
|
||||
);
|
||||
|
||||
if (iv != NULL) set_ctr((u32*)iv);
|
||||
REG_AES_BLKCNT = (1 << 16);
|
||||
REG_AES_CNT |= 0x80000000;
|
||||
|
||||
for (int j = 0; j < 0x10; j+=4) REG_AES_WRFIFO = *((u32*)(in+j));
|
||||
while(((REG_AES_CNT >> 0x5) & 0x1F) < 0x4); //wait for every word to get processed
|
||||
for (int j = 0; j < 0x10; j+=4) *((u32*)(out+j)) = REG_AES_RDFIFO;
|
||||
//REG_AES_CNT &= ~0x80000000;
|
||||
//if (method & (AES_CTR_DECRYPT | AES_CTR_ENCRYPT)) add_ctr((u8*)iv);
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------
|
||||
int main() {
|
||||
//---------------------------------------------------------------------------------
|
||||
@ -96,37 +121,36 @@ int main() {
|
||||
|
||||
setPowerButtonCB(powerButtonCB);
|
||||
|
||||
for (int i = 0; i < 8; i++) {
|
||||
*(u8*)(0x2FFFD00+i) = *(u8*)(0x4004D07-i); // Get ConsoleID
|
||||
}
|
||||
// Get ConsoleID
|
||||
/*for (int i = 0; i < 0x10; i++) {
|
||||
REG_AES_IV[i] = aesIvValues[i];
|
||||
}
|
||||
*(vu16*)0x4004406 = 1;*/
|
||||
if (isDSiMode()) {
|
||||
/*for (int i = 0; i < 8; i++) {
|
||||
*(u8*)(0x2FFFD00+i) = *(u8*)(0x4004D07-i); // Get ConsoleID
|
||||
}*/
|
||||
|
||||
/* *(u32*)(0x4004104+(0*0x1C)) = REG_AES_RDFIFO;
|
||||
*(u32*)(0x4004108+(0*0x1C)) = 0x2FFFD00;
|
||||
|
||||
*(u32*)(0x4004110+(0*0x1C)) = 2;
|
||||
|
||||
*(u32*)(0x4004114+(0*0x1C)) = 0x1;
|
||||
|
||||
*(u32*)(0x400411C+(0*0x1C)) = (1<<19 | 11<<28); */
|
||||
// For getting ConsoleID without reading from 0x4004D00...
|
||||
|
||||
/*REG_AES_WRFIFO = 0xFFFFFFFF;
|
||||
REG_AES_WRFIFO = 0xEEEEEEEE;
|
||||
REG_AES_WRFIFO = 0xDDDDDDDD;
|
||||
REG_AES_WRFIFO = 0xCCCCCCCC;
|
||||
REG_AES_CNT = (AES_RDFIFO_FLUSH | AES_CNT_DMA_READ_SIZE(1) | AES_CNT_KEY_APPLY | AES_CNT_KEYSLOT(3) | AES_CNT_MODE(0) | AES_CNT_IRQ | AES_CNT_ENABLE);
|
||||
*/
|
||||
/* *(u32*)(0x2FFFD00) = REG_AES_RDFIFO;
|
||||
for (int i = 0; i < 3; i++) {
|
||||
*(u32*)(0x2FFFD04) = REG_AES_RDFIFO;
|
||||
}*/
|
||||
/*for (int i = 0; i < 4; i++) {
|
||||
*(u8*)(0x2FFFD04+i) = *(u8*)(0x40044EC+i);
|
||||
}*/
|
||||
u8 base[16]={0};
|
||||
u8 in[16]={0};
|
||||
u8 iv[16]={0};
|
||||
u8 *scratch=(u8*)0x02300200;
|
||||
u8 *out=(u8*)0x02300000;
|
||||
u8 *key3=(u8*)0x40044D0;
|
||||
|
||||
aes(in, base, iv, 2);
|
||||
|
||||
//write consecutive 0-255 values to any byte in key3 until we get the same aes output as "base" above - this reveals the hidden byte. this way we can uncover all 16 bytes of the key3 normalkey pretty easily.
|
||||
//greets to Martin Korth for this trick https://problemkaputt.de/gbatek.htm#dsiaesioports (Reading Write-Only Values)
|
||||
for(int i=0;i<16;i++){
|
||||
for(int j=0;j<256;j++){
|
||||
*(key3+i)=j & 0xFF;
|
||||
aes(in, scratch, iv, 2);
|
||||
if(!memcmp(scratch, base, 16)){
|
||||
out[i]=j;
|
||||
//hit++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fifoSendValue32(FIFO_USER_03, *SCFG_EXT);
|
||||
fifoSendValue32(FIFO_USER_07, *(u16*)(0x4004700));
|
||||
|
||||
92
arm9/source/f_xy.c
Normal file
92
arm9/source/f_xy.c
Normal file
@ -0,0 +1,92 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <malloc.h>
|
||||
#include <stdint.h>
|
||||
#include "tonccpy.h"
|
||||
|
||||
//#define DEBUG
|
||||
|
||||
|
||||
void n128_lrot(uint64_t *num, uint32_t shift)
|
||||
{
|
||||
uint64_t tmp[2];
|
||||
|
||||
tmp[0] = num[0]<<shift;
|
||||
tmp[1] = num[1]<<shift;
|
||||
tmp[0] |= (num[1]>>(64-shift));
|
||||
tmp[1] |= (num[0]>>(64-shift));
|
||||
|
||||
num[0] = tmp[0];
|
||||
num[1] = tmp[1];
|
||||
}
|
||||
void n128_rrot(uint64_t *num, uint32_t shift)
|
||||
{
|
||||
uint64_t tmp[2];
|
||||
|
||||
tmp[0] = num[0]>>shift;
|
||||
tmp[1] = num[1]>>shift;
|
||||
tmp[0] |= (num[1]<<(64-shift));
|
||||
tmp[1] |= (num[0]<<(64-shift));
|
||||
|
||||
num[0] = tmp[0];
|
||||
num[1] = tmp[1];
|
||||
}
|
||||
|
||||
void n128_add(uint64_t *a, uint64_t *b)
|
||||
{
|
||||
uint64_t *a64 = a;
|
||||
uint64_t *b64 = b;
|
||||
uint64_t tmp = (a64[0]>>1)+(b64[0]>>1) + (a64[0] & b64[0] & 1);
|
||||
|
||||
tmp = tmp >> 63;
|
||||
a64[0] = a64[0] + b64[0];
|
||||
a64[1] = a64[1] + b64[1] + tmp;
|
||||
}
|
||||
|
||||
void n128_sub(uint64_t *a, uint64_t *b)
|
||||
{
|
||||
uint64_t *a64 = a;
|
||||
uint64_t *b64 = b;
|
||||
uint64_t tmp = (a64[0]>>1)-(b64[0]>>1) - ((a64[0]>>63) & (b64[0]>>63) & 1);
|
||||
|
||||
tmp = tmp >> 63;
|
||||
a64[0] = a64[0] - b64[0];
|
||||
a64[1] = a64[1] - b64[1] - tmp;
|
||||
}
|
||||
|
||||
void F_XY(uint32_t *key, uint32_t *key_x, uint32_t *key_y)
|
||||
{
|
||||
int i;
|
||||
unsigned char key_xy[16];
|
||||
|
||||
toncset(key_xy, 0, 16);
|
||||
toncset(key, 0, 16);
|
||||
for(i=0; i<16; i++)key_xy[i] = ((unsigned char*)key_x)[i] ^ ((unsigned char*)key_y)[i];
|
||||
|
||||
key[0] = 0x1a4f3e79;
|
||||
key[1] = 0x2a680f5f;
|
||||
key[2] = 0x29590258;
|
||||
key[3] = 0xfffefb4e;
|
||||
|
||||
n128_add((uint64_t*)key, (uint64_t*)key_xy);
|
||||
n128_lrot((uint64_t*)key, 42);
|
||||
}
|
||||
|
||||
//F_XY_reverse does the reverse of F(X^Y): takes (normal)key, and does F in reverse to generate the original X^Y key_xy.
|
||||
void F_XY_reverse(uint32_t *key, uint32_t *key_xy)
|
||||
{
|
||||
uint32_t tmpkey[4];
|
||||
toncset(key_xy, 0, 16);
|
||||
toncset(tmpkey, 0, 16);
|
||||
tonccpy(tmpkey, key, 16);
|
||||
|
||||
key_xy[0] = 0x1a4f3e79;
|
||||
key_xy[1] = 0x2a680f5f;
|
||||
key_xy[2] = 0x29590258;
|
||||
key_xy[3] = 0xfffefb4e;
|
||||
|
||||
n128_rrot((uint64_t*)tmpkey, 42);
|
||||
n128_sub((uint64_t*)tmpkey, (uint64_t*)key_xy);
|
||||
tonccpy(key_xy, tmpkey, 16);
|
||||
}
|
||||
|
||||
16
arm9/source/f_xy.h
Normal file
16
arm9/source/f_xy.h
Normal file
@ -0,0 +1,16 @@
|
||||
#ifndef _H_F_XY
|
||||
#define _H_F_XY
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
void F_XY(uint32_t *key, uint32_t *key_x, uint32_t *key_y);
|
||||
void F_XY_reverse(uint32_t *key, uint32_t *key_xy);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
@ -5,6 +5,8 @@
|
||||
#include <stdio.h>
|
||||
#include "crypto.h"
|
||||
#include "sector0.h"
|
||||
#include "tonccpy.h"
|
||||
#include "f_xy.h"
|
||||
|
||||
//#define SECTOR_SIZE 512
|
||||
#define CRYPT_BUF_LEN 64
|
||||
@ -24,6 +26,25 @@ void nandio_set_fat_sig_fix(u32 offset) {
|
||||
fat_sig_fix_offset = offset;
|
||||
}
|
||||
|
||||
void getConsoleID(u8 *consoleID){
|
||||
u8 *fifo=(u8*)0x02300000; //shared mem address that has our computed key3 stuff
|
||||
u8 key[16]; //key3 normalkey - keyslot 3 is used for DSi/twln NAND crypto
|
||||
u8 key_xy[16]; //key3_y ^ key3_x
|
||||
u8 key_x[16];////key3_x - contains a DSi console id (which just happens to be the LFCS on 3ds)
|
||||
u8 key_y[16] = {0x76, 0xDC, 0xB9, 0x0A, 0xD3, 0xC4, 0x4D, 0xBD, 0x1D, 0xDD, 0x2D, 0x20, 0x05, 0x00, 0xA0, 0xE1}; //key3_y NAND constant
|
||||
|
||||
tonccpy(key, fifo, 16); //receive the goods from arm7
|
||||
|
||||
F_XY_reverse((uint32_t*)key, (uint32_t*)key_xy); //work backwards from the normalkey to get key_x that has the consoleID
|
||||
|
||||
for(int i=0;i<16;i++){
|
||||
key_x[i] = key_xy[i] ^ key_y[i]; //''
|
||||
}
|
||||
|
||||
tonccpy(&consoleID[0], &key_x[0], 4);
|
||||
tonccpy(&consoleID[4], &key_x[0xC], 4);
|
||||
}
|
||||
|
||||
bool nandio_startup() {
|
||||
if (!nand_Startup()) return false;
|
||||
|
||||
@ -44,8 +65,17 @@ bool nandio_startup() {
|
||||
}
|
||||
}
|
||||
|
||||
u8 consoleID[8];
|
||||
u8 consoleIDfixed[8];
|
||||
|
||||
// Get ConsoleID
|
||||
getConsoleID(consoleID);
|
||||
for (int i = 0; i < 8; i++) {
|
||||
consoleIDfixed[i] = consoleID[7-i];
|
||||
}
|
||||
|
||||
// iprintf("sector 0 is %s\n", is3DS ? "3DS" : "DSi");
|
||||
dsi_crypt_init((const u8*)0x2FFFD00, (const u8*)0x2FFD7BC, is3DS);
|
||||
dsi_crypt_init((const u8*)consoleIDfixed, (const u8*)0x2FFD7BC, is3DS);
|
||||
dsi_nand_crypt(sector_buf, sector_buf, 0, SECTOR_SIZE / AES_BLOCK_SIZE);
|
||||
parse_mbr(sector_buf, is3DS, 0);
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user