mirror of
https://github.com/suchmememanyskill/TegraExplorer.git
synced 2024-11-22 11:56:42 +00:00
Include a (bad) method to dump with .cnmt.nca
This commit is contained in:
parent
81cf8c201c
commit
b42b52eb43
11 changed files with 204 additions and 63 deletions
|
@ -116,3 +116,5 @@ extern gpt_entry_rule gpt_fs_rules[];
|
||||||
extern menu_entry mmcmenu_start[];
|
extern menu_entry mmcmenu_start[];
|
||||||
|
|
||||||
extern menu_entry mmcmenu_filemenu[];
|
extern menu_entry mmcmenu_filemenu[];
|
||||||
|
|
||||||
|
extern menu_entry fwDump_typeMenu[];
|
|
@ -92,4 +92,11 @@ menu_entry mmcmenu_filemenu[] = {
|
||||||
{NULL, COLOR_VIOLET, {ISSKIP | ISMENU}},
|
{NULL, COLOR_VIOLET, {ISSKIP | ISMENU}},
|
||||||
{"\nBack", COLOR_WHITE, {ISMENU}},
|
{"\nBack", COLOR_WHITE, {ISMENU}},
|
||||||
{"Dump to SD", COLOR_YELLOW, {ISMENU}}
|
{"Dump to SD", COLOR_YELLOW, {ISMENU}}
|
||||||
|
};
|
||||||
|
|
||||||
|
menu_entry fwDump_typeMenu[] = {
|
||||||
|
{"Back\n", COLOR_WHITE, {ISMENU}},
|
||||||
|
{"Firmware format type:", COLOR_WHITE, {ISMENU | ISSKIP}},
|
||||||
|
{"Daybreak (prod.keys required!)", COLOR_BLUE, {ISMENU}},
|
||||||
|
{"ChoiNX", COLOR_VIOLET, {ISMENU}}
|
||||||
};
|
};
|
|
@ -218,9 +218,6 @@ int dump_biskeys(){
|
||||||
//sdmmc_storage_set_mmc_partition(&storage, 0);
|
//sdmmc_storage_set_mmc_partition(&storage, 0);
|
||||||
//nx_emmc_gpt_parse(&sys_gpt, &storage);
|
//nx_emmc_gpt_parse(&sys_gpt, &storage);
|
||||||
|
|
||||||
|
|
||||||
se_aes_key_set(8, bis_key[2] + 0x00, 0x10);
|
|
||||||
se_aes_key_set(9, bis_key[2] + 0x10, 0x10);
|
|
||||||
|
|
||||||
pkg1inf.ver = pkg1_id->kb;
|
pkg1inf.ver = pkg1_id->kb;
|
||||||
strcpy(pkg1inf.id, pkg1_id->id);
|
strcpy(pkg1inf.id, pkg1_id->id);
|
||||||
|
|
62
source/tegraexplorer/fs/keys.c
Normal file
62
source/tegraexplorer/fs/keys.c
Normal file
|
@ -0,0 +1,62 @@
|
||||||
|
#include "keys.h"
|
||||||
|
#include "../../utils/types.h"
|
||||||
|
#include "../../libs/fatfs/ff.h"
|
||||||
|
#include "../../sec/se.h"
|
||||||
|
#include "../../mem/heap.h"
|
||||||
|
#include "../gfx/gfxutils.h"
|
||||||
|
#include "../../config/ini.h"
|
||||||
|
#include "../common/common.h"
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
char *getKey(const char *search, link_t *inilist){
|
||||||
|
LIST_FOREACH_ENTRY(ini_sec_t, ini_sec, inilist, link){
|
||||||
|
if (ini_sec->type == INI_CHOICE){
|
||||||
|
LIST_FOREACH_ENTRY(ini_kv_t, kv, &ini_sec->kvs, link)
|
||||||
|
{
|
||||||
|
if (!strcmp(search, kv->key))
|
||||||
|
return kv->val;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
u8 getHexSingle(const char c) {
|
||||||
|
if (c >= '0' && c <= '9')
|
||||||
|
return c - '0';
|
||||||
|
if (c >= 'a' && c <= 'f')
|
||||||
|
return c - 'a' + 10;
|
||||||
|
}
|
||||||
|
|
||||||
|
u8 *getHex(const char *in){
|
||||||
|
u32 len = strlen(in), count = 0;
|
||||||
|
u8 *out = calloc(len / 2, sizeof(u8));
|
||||||
|
|
||||||
|
for (u32 i = 0; i < len; i += 2){
|
||||||
|
out[count++] = (u8)(getHexSingle(in[i]) << 4) | (getHexSingle(in[i + 1]));
|
||||||
|
}
|
||||||
|
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
u8 *GetKey(const char *keypath, const char *keyName){
|
||||||
|
LIST_INIT(inilist);
|
||||||
|
char *key;
|
||||||
|
u8 *hex = NULL;
|
||||||
|
|
||||||
|
if (!ini_parse(&inilist, keypath, false)){
|
||||||
|
gfx_errDisplay("GetKey", ERR_INI_PARSE_FAIL, 1);
|
||||||
|
goto out_free;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((key = getKey(keyName, &inilist)) == NULL){
|
||||||
|
gfx_errDisplay("GetKey", ERR_INI_PARSE_FAIL, 2);
|
||||||
|
goto out_free;
|
||||||
|
}
|
||||||
|
|
||||||
|
hex = getHex(key);
|
||||||
|
|
||||||
|
out_free:;
|
||||||
|
list_empty(&inilist);
|
||||||
|
return hex;
|
||||||
|
}
|
4
source/tegraexplorer/fs/keys.h
Normal file
4
source/tegraexplorer/fs/keys.h
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
#pragma once
|
||||||
|
#include "../../utils/types.h"
|
||||||
|
|
||||||
|
u8 *GetKey(const char *keypath, const char *keyName);
|
46
source/tegraexplorer/fs/nca.c
Normal file
46
source/tegraexplorer/fs/nca.c
Normal file
|
@ -0,0 +1,46 @@
|
||||||
|
#include "nca.h"
|
||||||
|
#include "keys.h"
|
||||||
|
#include "../../utils/types.h"
|
||||||
|
#include "../../libs/fatfs/ff.h"
|
||||||
|
#include "../../sec/se.h"
|
||||||
|
#include "../../mem/heap.h"
|
||||||
|
#include "../gfx/gfxutils.h"
|
||||||
|
#include "../../config/ini.h"
|
||||||
|
#include "../common/common.h"
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
int SetHeaderKey(){
|
||||||
|
u8 *header_key = GetKey("sd:/switch/prod.keys", "header_key");
|
||||||
|
|
||||||
|
if (header_key == NULL)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
se_aes_key_set(4, header_key + 0x00, 0x10);
|
||||||
|
se_aes_key_set(5, header_key + 0x10, 0x10);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int GetNcaType(char *ncaPath){
|
||||||
|
FIL fp;
|
||||||
|
u32 read_bytes = 0;
|
||||||
|
|
||||||
|
if (f_open(&fp, ncaPath, FA_READ | FA_OPEN_EXISTING))
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
u8 *dec_header = (u8*)malloc(0x600);
|
||||||
|
|
||||||
|
if (f_lseek(&fp, 0x200) || f_read(&fp, dec_header, 32, &read_bytes) || read_bytes != 32){
|
||||||
|
f_close(&fp);
|
||||||
|
free(dec_header);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
se_aes_xts_crypt(5,4,0,1,dec_header + 0x200, dec_header, 32, 1);
|
||||||
|
|
||||||
|
u8 ContentType = dec_header[0x205];
|
||||||
|
|
||||||
|
f_close(&fp);
|
||||||
|
free(dec_header);
|
||||||
|
return ContentType;
|
||||||
|
}
|
4
source/tegraexplorer/fs/nca.h
Normal file
4
source/tegraexplorer/fs/nca.h
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
int GetNcaType(char *ncaPath);
|
||||||
|
int SetHeaderKey();
|
|
@ -1,4 +1,5 @@
|
||||||
#include "savesign.h"
|
#include "savesign.h"
|
||||||
|
#include "keys.h"
|
||||||
#include "../../utils/types.h"
|
#include "../../utils/types.h"
|
||||||
#include "../../libs/fatfs/ff.h"
|
#include "../../libs/fatfs/ff.h"
|
||||||
#include "../../sec/se.h"
|
#include "../../sec/se.h"
|
||||||
|
@ -62,62 +63,15 @@ out_free:;
|
||||||
return success;
|
return success;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
char *getKey(const char *search, link_t *inilist){
|
|
||||||
LIST_FOREACH_ENTRY(ini_sec_t, ini_sec, inilist, link){
|
|
||||||
if (ini_sec->type == INI_CHOICE){
|
|
||||||
LIST_FOREACH_ENTRY(ini_kv_t, kv, &ini_sec->kvs, link)
|
|
||||||
{
|
|
||||||
if (!strcmp(search, kv->key))
|
|
||||||
return kv->val;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
u8 getHexSingle(const char c) {
|
|
||||||
if (c >= '0' && c <= '9')
|
|
||||||
return c - '0';
|
|
||||||
if (c >= 'a' && c <= 'f')
|
|
||||||
return c - 'a' + 10;
|
|
||||||
}
|
|
||||||
|
|
||||||
u8 *getHex(const char *in){
|
|
||||||
u32 len = strlen(in), count = 0;
|
|
||||||
u8 *out = calloc(len / 2, sizeof(u8));
|
|
||||||
|
|
||||||
for (u32 i = 0; i < len; i += 2){
|
|
||||||
out[count++] = (u8)(getHexSingle(in[i]) << 4) | (getHexSingle(in[i + 1]));
|
|
||||||
}
|
|
||||||
|
|
||||||
return out;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool save_sign(const char *keypath, const char *savepath){
|
bool save_sign(const char *keypath, const char *savepath){
|
||||||
LIST_INIT(inilist);
|
u8 *key = GetKey(keypath, "save_mac_key");
|
||||||
char *key;
|
|
||||||
u8 *hex;
|
|
||||||
bool success = false;
|
|
||||||
|
|
||||||
if (!ini_parse(&inilist, keypath, false)){
|
if (key == NULL){
|
||||||
gfx_errDisplay("save_sign", ERR_INI_PARSE_FAIL, 1);
|
return false;
|
||||||
goto out_free;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((key = getKey("save_mac_key", &inilist)) == NULL){
|
if (!save_commit(savepath, key))
|
||||||
gfx_errDisplay("save_sign", ERR_INI_PARSE_FAIL, 2);
|
return false;
|
||||||
goto out_free;
|
|
||||||
}
|
|
||||||
|
|
||||||
hex = getHex(key);
|
return true;
|
||||||
|
|
||||||
if (!save_commit(savepath, hex))
|
|
||||||
goto out_free;
|
|
||||||
|
|
||||||
success = true;
|
|
||||||
|
|
||||||
out_free:;
|
|
||||||
list_empty(&inilist);
|
|
||||||
return success;
|
|
||||||
}
|
}
|
|
@ -60,7 +60,10 @@ void MainMenu_Tools(){
|
||||||
displaygpio();
|
displaygpio();
|
||||||
break;
|
break;
|
||||||
case TOOLS_DUMPFIRMWARE:
|
case TOOLS_DUMPFIRMWARE:
|
||||||
dumpfirmware(SYSMMC);
|
res = menu_make(fwDump_typeMenu, 4, "-- Fw Type --");
|
||||||
|
if (res >= 2)
|
||||||
|
dumpfirmware(SYSMMC, (res == 2));
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
#include "../fs/fsutils.h"
|
#include "../fs/fsutils.h"
|
||||||
#include "../../mem/heap.h"
|
#include "../../mem/heap.h"
|
||||||
#include "../utils/utils.h"
|
#include "../utils/utils.h"
|
||||||
|
#include "../fs/nca.h"
|
||||||
|
|
||||||
extern bool sd_mount();
|
extern bool sd_mount();
|
||||||
extern void sd_unmount();
|
extern void sd_unmount();
|
||||||
|
@ -93,7 +94,9 @@ void displaygpio(){
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int dumpfirmware(int mmc){
|
|
||||||
|
// bad code ahead aaaa
|
||||||
|
int dumpfirmware(int mmc, bool daybreak){
|
||||||
DIR dir;
|
DIR dir;
|
||||||
FILINFO fno;
|
FILINFO fno;
|
||||||
bool fail = false;
|
bool fail = false;
|
||||||
|
@ -107,6 +110,22 @@ int dumpfirmware(int mmc){
|
||||||
connect_mmc(mmc);
|
connect_mmc(mmc);
|
||||||
mount_mmc("SYSTEM", 2);
|
mount_mmc("SYSTEM", 2);
|
||||||
|
|
||||||
|
if (daybreak){
|
||||||
|
if (!fsutil_checkfile("sd:/switch/prod.keys")){
|
||||||
|
SWAPCOLOR(COLOR_RED);
|
||||||
|
gfx_printf("prod.keys not found.\nPress any button to exit");
|
||||||
|
hidWait();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (SetHeaderKey()){
|
||||||
|
SWAPCOLOR(COLOR_RED);
|
||||||
|
gfx_printf("Failed to find header key.\nPress any button to exit");
|
||||||
|
hidWait();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
gfx_printf("PKG1 version: %d\n", pkg1.ver);
|
gfx_printf("PKG1 version: %d\n", pkg1.ver);
|
||||||
|
|
||||||
gfx_printf("Creating folders...\n");
|
gfx_printf("Creating folders...\n");
|
||||||
|
@ -115,7 +134,24 @@ int dumpfirmware(int mmc){
|
||||||
|
|
||||||
sdbase = calloc(32 + strlen(pkg1.id), sizeof(char));
|
sdbase = calloc(32 + strlen(pkg1.id), sizeof(char));
|
||||||
sprintf(sdbase, "sd:/tegraexplorer/Firmware/%d (%s)", pkg1.ver, pkg1.id);
|
sprintf(sdbase, "sd:/tegraexplorer/Firmware/%d (%s)", pkg1.ver, pkg1.id);
|
||||||
gfx_printf("Out: %s\n", sdbase);
|
|
||||||
|
if (fsutil_checkfile(sdbase)){
|
||||||
|
SWAPCOLOR(COLOR_RED);
|
||||||
|
gfx_printf("Destination folder already exists.\nPress X to delete this folder, any other button to cancel\nPath: %s", sdbase);
|
||||||
|
|
||||||
|
Inputs *input = hidWait();
|
||||||
|
if (!input->x){
|
||||||
|
free(sdbase);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
SWAPCOLOR(COLOR_WHITE);
|
||||||
|
gfx_printf("\nDeleting folder..\n");
|
||||||
|
fsact_del_recursive(sdbase);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
gfx_printf("\rOut: %s\n", sdbase);
|
||||||
f_mkdir(sdbase);
|
f_mkdir(sdbase);
|
||||||
|
|
||||||
if ((ret = f_opendir(&dir, sysbase)))
|
if ((ret = f_opendir(&dir, sysbase)))
|
||||||
|
@ -127,16 +163,39 @@ int dumpfirmware(int mmc){
|
||||||
printerrors = 0;
|
printerrors = 0;
|
||||||
|
|
||||||
while(!f_readdir(&dir, &fno) && fno.fname[0] && !fail){
|
while(!f_readdir(&dir, &fno) && fno.fname[0] && !fail){
|
||||||
utils_copystring(fsutil_getnextloc(sdbase, fno.fname), &sdpath);
|
|
||||||
utils_copystring(fsutil_getnextloc(sysbase, fno.fname), &syspathtemp);
|
utils_copystring(fsutil_getnextloc(sysbase, fno.fname), &syspathtemp);
|
||||||
|
|
||||||
if (fno.fattrib & AM_DIR){
|
if (fno.fattrib & AM_DIR){
|
||||||
utils_copystring(fsutil_getnextloc(syspathtemp, "00"), &syspath);
|
utils_copystring(fsutil_getnextloc(syspathtemp, "00"), &syspath);
|
||||||
free(syspathtemp);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
syspath = syspathtemp;
|
syspath = syspathtemp;
|
||||||
|
|
||||||
|
if (daybreak){
|
||||||
|
u8 ContentType = GetNcaType(syspath);
|
||||||
|
|
||||||
|
if (ContentType < 0){
|
||||||
|
fail = true;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *temp;
|
||||||
|
utils_copystring(fsutil_getnextloc(sdbase, fno.fname), &temp);
|
||||||
|
|
||||||
|
if (ContentType == 0x01){
|
||||||
|
sdpath = calloc(strlen(temp) + 6, 1);
|
||||||
|
strcpy(sdpath, temp);
|
||||||
|
memcpy(sdpath + strlen(temp) - 4, ".cnmt.nca", 10);
|
||||||
|
free(temp);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
sdpath = temp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
utils_copystring(fsutil_getnextloc(sdbase, fno.fname), &sdpath);
|
||||||
|
|
||||||
|
|
||||||
ret = fsact_copy(syspath, sdpath, 0);
|
ret = fsact_copy(syspath, sdpath, 0);
|
||||||
|
|
||||||
gfx_printf("%d %s\r", ++amount, fno.fname);
|
gfx_printf("%d %s\r", ++amount, fno.fname);
|
||||||
|
@ -145,7 +204,9 @@ int dumpfirmware(int mmc){
|
||||||
fail = true;
|
fail = true;
|
||||||
|
|
||||||
free(sdpath);
|
free(sdpath);
|
||||||
free(syspath);
|
free(syspathtemp);
|
||||||
|
if (syspath != syspathtemp)
|
||||||
|
free(syspath);
|
||||||
}
|
}
|
||||||
|
|
||||||
printerrors = 1;
|
printerrors = 1;
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
#include "../../utils/types.h"
|
||||||
|
|
||||||
void displayinfo();
|
void displayinfo();
|
||||||
void displaygpio();
|
void displaygpio();
|
||||||
int format(int mode);
|
int format(int mode);
|
||||||
int dumpfirmware(int mmc);
|
int dumpfirmware(int mmc, bool daybreak);
|
Loading…
Reference in a new issue