mirror of
https://github.com/d0k3/GodMode9.git
synced 2025-06-26 13:42:47 +00:00
Improved encdecTitlekeys.bin / seeddb.bin builder
This commit is contained in:
parent
cabe185016
commit
3d7ac49f87
@ -1,5 +1,6 @@
|
|||||||
#include "ncch.h"
|
#include "ncch.h"
|
||||||
#include "support.h"
|
#include "support.h"
|
||||||
|
#include "disadiff.h"
|
||||||
#include "keydb.h"
|
#include "keydb.h"
|
||||||
#include "aes.h"
|
#include "aes.h"
|
||||||
#include "sha.h"
|
#include "sha.h"
|
||||||
@ -64,11 +65,10 @@ u32 GetNcchSeed(u8* seed, NcchHeader* ncch) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// setup a large enough buffer
|
// setup a large enough buffer
|
||||||
u8* buffer = (u8*) malloc(max(STD_BUFFER_SIZE, SEEDSAVE_MAX_ENTRIES*(8+16)*2));
|
u8* buffer = (u8*) malloc(max(STD_BUFFER_SIZE, SEEDSAVE_AREA_SIZE));
|
||||||
if (!buffer) return 1;
|
if (!buffer) return 1;
|
||||||
|
|
||||||
// try to grab the seed from NAND database
|
// try to grab the seed from NAND database
|
||||||
const u32 seed_offset[2] = {SEEDSAVE_AREA_OFFSETS};
|
|
||||||
const char* nand_drv[] = {"1:", "4:"}; // SysNAND and EmuNAND
|
const char* nand_drv[] = {"1:", "4:"}; // SysNAND and EmuNAND
|
||||||
for (u32 i = 0; i < countof(nand_drv); i++) {
|
for (u32 i = 0; i < countof(nand_drv); i++) {
|
||||||
UINT btr = 0;
|
UINT btr = 0;
|
||||||
@ -90,37 +90,21 @@ u32 GetNcchSeed(u8* seed, NcchHeader* ncch) {
|
|||||||
nand_drv[i], sha256sum[0], sha256sum[1], sha256sum[2], sha256sum[3]);
|
nand_drv[i], sha256sum[0], sha256sum[1], sha256sum[2], sha256sum[3]);
|
||||||
|
|
||||||
// check seedsave for seed
|
// check seedsave for seed
|
||||||
u8* seeddb[2];
|
u8* seeddb = buffer;
|
||||||
seeddb[0] = buffer;
|
if (ReadDisaDiffIvfcLvl4(path, NULL, SEEDSAVE_AREA_OFFSET, SEEDSAVE_AREA_SIZE, seeddb) != SEEDSAVE_AREA_SIZE)
|
||||||
seeddb[1] = buffer + (SEEDSAVE_MAX_ENTRIES*(8+16));
|
|
||||||
if (f_open(&file, path, FA_READ | FA_OPEN_EXISTING) != FR_OK)
|
|
||||||
continue;
|
continue;
|
||||||
f_read(&file, seeddb[0], 0x200, &btr);
|
|
||||||
u32 p_active = (getle32(seeddb[0] + 0x168)) ? 1 : 0;
|
|
||||||
|
|
||||||
// read both partitions
|
|
||||||
for (u32 p = 0; p < 2; p++) {
|
|
||||||
f_lseek(&file, seed_offset[(p + p_active) % 2]);
|
|
||||||
f_read(&file, seeddb[p], SEEDSAVE_MAX_ENTRIES*(8+16), &btr);
|
|
||||||
}
|
|
||||||
|
|
||||||
// search for the seed
|
// search for the seed
|
||||||
for (u32 p = 0; p < 2; p++) {
|
for (u32 s = 0; s < SEEDSAVE_MAX_ENTRIES; s++) {
|
||||||
for (u32 s = 0; s < SEEDSAVE_MAX_ENTRIES; s++) {
|
if (titleId != getle64(seeddb + (s*8))) continue;
|
||||||
if (titleId != getle64(seeddb[p] + (s*8))) continue;
|
memcpy(lseed, seeddb + (SEEDSAVE_MAX_ENTRIES*8) + (s*16), 16);
|
||||||
for (u32 p0 = 0; p0 < 2; p0++) {
|
sha_quick(sha256sum, lseed, 16 + 8, SHA256_MODE);
|
||||||
memcpy(lseed, seeddb[(p+p0)%2] + (SEEDSAVE_MAX_ENTRIES*8) + (s*16), 16);
|
if (hash_seed == sha256sum[0]) {
|
||||||
sha_quick(sha256sum, lseed, 16 + 8, SHA256_MODE);
|
memcpy(seed, lseed, 16);
|
||||||
if (hash_seed == sha256sum[0]) {
|
free(buffer);
|
||||||
memcpy(seed, lseed, 16);
|
return 0; // found!
|
||||||
f_close(&file);
|
|
||||||
free(buffer);
|
|
||||||
return 0; // found!
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
f_close(&file);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// not found -> try seeddb.bin
|
// not found -> try seeddb.bin
|
||||||
|
@ -20,8 +20,9 @@
|
|||||||
#define SEEDDB_NAME "seeddb.bin"
|
#define SEEDDB_NAME "seeddb.bin"
|
||||||
#define SEEDDB_SIZE(sdb) (16 + ((sdb)->n_entries * sizeof(SeedInfoEntry)))
|
#define SEEDDB_SIZE(sdb) (16 + ((sdb)->n_entries * sizeof(SeedInfoEntry)))
|
||||||
|
|
||||||
#define SEEDSAVE_AREA_OFFSETS 0x7000, 0x5C000
|
|
||||||
#define SEEDSAVE_MAX_ENTRIES 2000
|
#define SEEDSAVE_MAX_ENTRIES 2000
|
||||||
|
#define SEEDSAVE_AREA_OFFSET 0x4000
|
||||||
|
#define SEEDSAVE_AREA_SIZE (SEEDSAVE_MAX_ENTRIES * (8+16))
|
||||||
|
|
||||||
// wrapper defines
|
// wrapper defines
|
||||||
#define DecryptNcch(data, offset, size, ncch, exefs) CryptNcch(data, offset, size, ncch, exefs, NCCH_NOCRYPTO)
|
#define DecryptNcch(data, offset, size, ncch, exefs) CryptNcch(data, offset, size, ncch, exefs, NCCH_NOCRYPTO)
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
#include "ticketdb.h"
|
#include "ticketdb.h"
|
||||||
|
#include "disadiff.h"
|
||||||
#include "support.h"
|
#include "support.h"
|
||||||
#include "aes.h"
|
#include "aes.h"
|
||||||
#include "ff.h"
|
#include "ff.h"
|
||||||
@ -64,29 +65,25 @@ Ticket* TicketFromTickDbChunk(u8* chunk, u8* title_id, bool legit_pls) {
|
|||||||
|
|
||||||
u32 FindTicket(Ticket* ticket, u8* title_id, bool force_legit, bool emunand) {
|
u32 FindTicket(Ticket* ticket, u8* title_id, bool force_legit, bool emunand) {
|
||||||
const char* path_db = TICKDB_PATH(emunand); // EmuNAND / SysNAND
|
const char* path_db = TICKDB_PATH(emunand); // EmuNAND / SysNAND
|
||||||
const u32 area_offsets[] = { TICKDB_AREA_OFFSETS };
|
u8* data = (u8*) malloc(TICKDB_AREA_SIZE);
|
||||||
u8 data[0x400];
|
if (!data) return 1;
|
||||||
FIL file;
|
|
||||||
UINT btr;
|
|
||||||
|
|
||||||
// parse file, sector by sector
|
// read and decode ticket.db DIFF partition
|
||||||
if (f_open(&file, path_db, FA_READ | FA_OPEN_EXISTING) != FR_OK)
|
if (ReadDisaDiffIvfcLvl4(path_db, NULL, TICKDB_AREA_OFFSET, TICKDB_AREA_SIZE, data) != TICKDB_AREA_SIZE) {
|
||||||
|
free(data);
|
||||||
return 1;
|
return 1;
|
||||||
bool found = false;
|
|
||||||
for (u32 p = 0; p < 2; p++) {
|
|
||||||
u32 area_offset = area_offsets[p];
|
|
||||||
for (u32 i = 0; !found && (i < TICKDB_AREA_SIZE); i += 0x200) {
|
|
||||||
f_lseek(&file, area_offset + i);
|
|
||||||
if ((f_read(&file, data, 0x400, &btr) != FR_OK) || (btr != 0x400)) break;
|
|
||||||
Ticket* tick = TicketFromTickDbChunk(data, title_id, force_legit);
|
|
||||||
if (!tick) continue;
|
|
||||||
memcpy(ticket, tick, sizeof(Ticket));
|
|
||||||
found = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
f_close(&file);
|
|
||||||
|
|
||||||
|
// parse the decoded data for a ticket
|
||||||
|
bool found = false;
|
||||||
|
for (u32 i = 0; !found && (i < TICKDB_AREA_SIZE + 0x400); i += 0x200) {
|
||||||
|
Ticket* tick = TicketFromTickDbChunk(data + i, title_id, force_legit);
|
||||||
|
if (!tick) continue;
|
||||||
|
memcpy(ticket, tick, sizeof(Ticket));
|
||||||
|
found = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
free(data);
|
||||||
return (found) ? 0 : 1;
|
return (found) ? 0 : 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -7,9 +7,10 @@
|
|||||||
#define TIKDB_NAME_DEC "decTitleKeys.bin"
|
#define TIKDB_NAME_DEC "decTitleKeys.bin"
|
||||||
#define TIKDB_SIZE(tdb) (16 + ((tdb)->n_entries * sizeof(TitleKeyEntry)))
|
#define TIKDB_SIZE(tdb) (16 + ((tdb)->n_entries * sizeof(TitleKeyEntry)))
|
||||||
|
|
||||||
#define TICKDB_PATH(emu) ((emu) ? "4:/dbs/ticket.db" : "1:/dbs/ticket.db") // EmuNAND / SysNAND
|
#define TICKDB_PATH(emu) ((emu) ? "4:/dbs/ticket.db" : "1:/dbs/ticket.db") // EmuNAND / SysNAND
|
||||||
#define TICKDB_AREA_OFFSETS 0x0137F000, 0x001C0C00 // second partition is more likely to be in use
|
#define TICKDB_AREA_OFFSET 0xA1C00 // offset inside the decoded DIFF partition
|
||||||
#define TICKDB_AREA_SIZE 0x00180000 // the actual area size is around 0x0010C600
|
#define TICKDB_AREA_RAW 0x0137F000, 0x001C0C00 // raw offsets inside the file
|
||||||
|
#define TICKDB_AREA_SIZE 0x00500000 // 5MB, arbitrary (around 1MB is realistic)
|
||||||
|
|
||||||
#define TICKDB_MAGIC 0x44, 0x49, 0x46, 0x46, 0x00, 0x00, 0x03, 0x00, \
|
#define TICKDB_MAGIC 0x44, 0x49, 0x46, 0x46, 0x00, 0x00, 0x03, 0x00, \
|
||||||
0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
|
0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
#include "gameutil.h"
|
#include "gameutil.h"
|
||||||
|
#include "disadiff.h"
|
||||||
#include "game.h"
|
#include "game.h"
|
||||||
#include "hid.h"
|
#include "hid.h"
|
||||||
#include "ui.h"
|
#include "ui.h"
|
||||||
@ -1881,39 +1882,23 @@ u32 BuildTitleKeyInfo(const char* path, bool dec, bool dump) {
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
} else if (filetype & SYS_TICKDB) {
|
} else if (filetype & SYS_TICKDB) {
|
||||||
const u32 area_offsets[] = { TICKDB_AREA_OFFSETS };
|
u8* data = (u8*) malloc(TICKDB_AREA_SIZE);
|
||||||
FIL file;
|
if (!data) return 1;
|
||||||
|
|
||||||
if (fvx_open(&file, path, FA_READ | FA_OPEN_EXISTING) != FR_OK) return 1;
|
// read and decode ticket.db DIFF partition
|
||||||
u8* data = (u8*) malloc(STD_BUFFER_SIZE);
|
if (ReadDisaDiffIvfcLvl4(path_in, NULL, TICKDB_AREA_OFFSET, TICKDB_AREA_SIZE, data) != TICKDB_AREA_SIZE) {
|
||||||
if (!data) {
|
free(data);
|
||||||
fvx_close(&file);
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// parse file, sector by sector
|
// parse the decoded data for valid tickets
|
||||||
for (u32 p = 0; p < sizeof(area_offsets) / sizeof(u32); p++) {
|
for (u32 i = 0; i < TICKDB_AREA_SIZE + 0x400; i += 0x200) {
|
||||||
fvx_lseek(&file, area_offsets[p]);
|
Ticket* ticket = TicketFromTickDbChunk(data + i, NULL, true);
|
||||||
fvx_sync(&file);
|
if (!ticket || (ticket->commonkey_idx >= 2) || !getbe64(ticket->ticket_id)) continue;
|
||||||
for (u32 i = 0; i < TICKDB_AREA_SIZE; i += (STD_BUFFER_SIZE - 0x200)) {
|
if (TIKDB_SIZE(tik_info) + 32 > STD_BUFFER_SIZE) break; // no error message
|
||||||
u32 read_bytes = min(STD_BUFFER_SIZE, TICKDB_AREA_SIZE - i);
|
AddTicketToInfo(tik_info, ticket, dec); // ignore result
|
||||||
|
|
||||||
if (fvx_read(&file, data, read_bytes, NULL) != FR_OK) {
|
|
||||||
fvx_close(&file);
|
|
||||||
free(data);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (u8* ptr = data; ptr + 0x400 < data + read_bytes; ptr += 0x200) {
|
|
||||||
Ticket* ticket = TicketFromTickDbChunk(ptr, NULL, true);
|
|
||||||
if (!ticket || (ticket->commonkey_idx >= 2) || !getbe64(ticket->ticket_id)) continue;
|
|
||||||
if (TIKDB_SIZE(tik_info) + 32 > STD_BUFFER_SIZE) break; // no error message
|
|
||||||
AddTicketToInfo(tik_info, ticket, dec); // ignore result
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fvx_close(&file);
|
|
||||||
free(data);
|
free(data);
|
||||||
} else if (filetype & BIN_TIKDB) {
|
} else if (filetype & BIN_TIKDB) {
|
||||||
TitleKeysInfo* tik_info_merge = (TitleKeysInfo*) malloc(STD_BUFFER_SIZE);
|
TitleKeysInfo* tik_info_merge = (TitleKeysInfo*) malloc(STD_BUFFER_SIZE);
|
||||||
@ -2017,32 +2002,22 @@ u32 BuildSeedInfo(const char* path, bool dump) {
|
|||||||
|
|
||||||
free(seed_info_merge);
|
free(seed_info_merge);
|
||||||
} else if (inputtype == 2) { // seed system save input
|
} else if (inputtype == 2) { // seed system save input
|
||||||
static const u32 seed_offset[2] = {SEEDSAVE_AREA_OFFSETS};
|
u8* seedsave = (u8*) malloc(SEEDSAVE_AREA_SIZE);
|
||||||
u8* seedsave = (u8*) malloc(SEEDSAVE_MAX_ENTRIES*(8+16));
|
|
||||||
if (!seedsave) return 1;
|
if (!seedsave) return 1;
|
||||||
|
|
||||||
if (fvx_qread(path_in, seedsave, 0, 0x200, NULL) != FR_OK) {
|
if (ReadDisaDiffIvfcLvl4(path_in, NULL, SEEDSAVE_AREA_OFFSET, SEEDSAVE_AREA_SIZE, seedsave) != SEEDSAVE_AREA_SIZE) {
|
||||||
free(seedsave);
|
free(seedsave);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 p_active = (getle32(seedsave + 0x168)) ? 1 : 0;
|
SeedInfoEntry seed = { 0 };
|
||||||
for (u32 p = 0; p < 2; p++) {
|
for (u32 s = 0; s < SEEDSAVE_MAX_ENTRIES; s++) {
|
||||||
SeedInfoEntry seed = { 0 };
|
seed.titleId = getle64(seedsave + (s*8));
|
||||||
|
memcpy(seed.seed, seedsave + (SEEDSAVE_MAX_ENTRIES*8) + (s*16), 16);
|
||||||
if (fvx_qread(path_in, seedsave, seed_offset[(p + p_active) % 2], SEEDSAVE_MAX_ENTRIES*(8+16), NULL) != FR_OK) {
|
if (((seed.titleId >> 32) != 0x00040000) ||
|
||||||
free(seedsave);
|
(!getle64(seed.seed) && !getle64(seed.seed + 8))) continue;
|
||||||
return 1;
|
if (SEEDDB_SIZE(seed_info) + 32 > STD_BUFFER_SIZE) break; // no error message
|
||||||
}
|
AddSeedToDb(seed_info, &seed); // ignore result
|
||||||
|
|
||||||
for (u32 s = 0; s < SEEDSAVE_MAX_ENTRIES; s++) {
|
|
||||||
seed.titleId = getle64(seedsave + (s*8));
|
|
||||||
memcpy(seed.seed, seedsave + (SEEDSAVE_MAX_ENTRIES*8) + (s*16), 16);
|
|
||||||
if (((seed.titleId >> 32) != 0x00040000) ||
|
|
||||||
(!getle64(seed.seed) && !getle64(seed.seed + 8))) continue;
|
|
||||||
if (SEEDDB_SIZE(seed_info) + 32 > STD_BUFFER_SIZE) break; // no error message
|
|
||||||
AddSeedToDb(seed_info, &seed); // ignore result
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
free(seedsave);
|
free(seedsave);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user