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_filemenu[];
|
||||
|
||||
extern menu_entry fwDump_typeMenu[];
|
|
@ -93,3 +93,10 @@ menu_entry mmcmenu_filemenu[] = {
|
|||
{"\nBack", COLOR_WHITE, {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}}
|
||||
};
|
|
@ -219,9 +219,6 @@ int dump_biskeys(){
|
|||
//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;
|
||||
strcpy(pkg1inf.id, pkg1_id->id);
|
||||
return 0;
|
||||
|
|
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 "keys.h"
|
||||
#include "../../utils/types.h"
|
||||
#include "../../libs/fatfs/ff.h"
|
||||
#include "../../sec/se.h"
|
||||
|
@ -62,62 +63,15 @@ out_free:;
|
|||
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){
|
||||
LIST_INIT(inilist);
|
||||
char *key;
|
||||
u8 *hex;
|
||||
bool success = false;
|
||||
u8 *key = GetKey(keypath, "save_mac_key");
|
||||
|
||||
if (!ini_parse(&inilist, keypath, false)){
|
||||
gfx_errDisplay("save_sign", ERR_INI_PARSE_FAIL, 1);
|
||||
goto out_free;
|
||||
if (key == NULL){
|
||||
return false;
|
||||
}
|
||||
|
||||
if ((key = getKey("save_mac_key", &inilist)) == NULL){
|
||||
gfx_errDisplay("save_sign", ERR_INI_PARSE_FAIL, 2);
|
||||
goto out_free;
|
||||
}
|
||||
if (!save_commit(savepath, key))
|
||||
return false;
|
||||
|
||||
hex = getHex(key);
|
||||
|
||||
if (!save_commit(savepath, hex))
|
||||
goto out_free;
|
||||
|
||||
success = true;
|
||||
|
||||
out_free:;
|
||||
list_empty(&inilist);
|
||||
return success;
|
||||
return true;
|
||||
}
|
|
@ -60,7 +60,10 @@ void MainMenu_Tools(){
|
|||
displaygpio();
|
||||
break;
|
||||
case TOOLS_DUMPFIRMWARE:
|
||||
dumpfirmware(SYSMMC);
|
||||
res = menu_make(fwDump_typeMenu, 4, "-- Fw Type --");
|
||||
if (res >= 2)
|
||||
dumpfirmware(SYSMMC, (res == 2));
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
#include "../fs/fsutils.h"
|
||||
#include "../../mem/heap.h"
|
||||
#include "../utils/utils.h"
|
||||
#include "../fs/nca.h"
|
||||
|
||||
extern bool sd_mount();
|
||||
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;
|
||||
FILINFO fno;
|
||||
bool fail = false;
|
||||
|
@ -107,6 +110,22 @@ int dumpfirmware(int mmc){
|
|||
connect_mmc(mmc);
|
||||
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("Creating folders...\n");
|
||||
|
@ -115,7 +134,24 @@ int dumpfirmware(int mmc){
|
|||
|
||||
sdbase = calloc(32 + strlen(pkg1.id), sizeof(char));
|
||||
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);
|
||||
|
||||
if ((ret = f_opendir(&dir, sysbase)))
|
||||
|
@ -127,16 +163,39 @@ int dumpfirmware(int mmc){
|
|||
printerrors = 0;
|
||||
|
||||
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);
|
||||
|
||||
if (fno.fattrib & AM_DIR){
|
||||
utils_copystring(fsutil_getnextloc(syspathtemp, "00"), &syspath);
|
||||
free(syspathtemp);
|
||||
}
|
||||
else
|
||||
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);
|
||||
|
||||
gfx_printf("%d %s\r", ++amount, fno.fname);
|
||||
|
@ -145,6 +204,8 @@ int dumpfirmware(int mmc){
|
|||
fail = true;
|
||||
|
||||
free(sdpath);
|
||||
free(syspathtemp);
|
||||
if (syspath != syspathtemp)
|
||||
free(syspath);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
#pragma once
|
||||
#include "../../utils/types.h"
|
||||
|
||||
void displayinfo();
|
||||
void displaygpio();
|
||||
int format(int mode);
|
||||
int dumpfirmware(int mmc);
|
||||
int dumpfirmware(int mmc, bool daybreak);
|
Loading…
Reference in a new issue