From 2a5a738765877ad3a1c347d7d36d6a54a836dd96 Mon Sep 17 00:00:00 2001 From: d0k3 Date: Tue, 20 Dec 2016 13:10:07 +0100 Subject: [PATCH] Fix ticket.db parser --- source/game/gameutil.c | 10 +++++----- source/game/ticket.c | 43 +++++++++++++++++++----------------------- source/game/ticket.h | 14 +++++++++++--- source/godmode.c | 2 +- 4 files changed, 36 insertions(+), 33 deletions(-) diff --git a/source/game/gameutil.c b/source/game/gameutil.c index d4fecb1..54d0d76 100644 --- a/source/game/gameutil.c +++ b/source/game/gameutil.c @@ -801,13 +801,13 @@ u32 BuildCiaFromTmdFile(const char* path_tmd, const char* path_cia, bool force_l Ticket* ticket = &(cia->ticket); bool src_emunand = ((*path_tmd == 'B') || (*path_tmd == '4')); if (force_legit) { - if (GetTicket(ticket, title_id, true, src_emunand) != 0) { + if (FindTicket(ticket, title_id, true, src_emunand) != 0) { ShowPrompt(false, "ID %016llX\nLegit ticket not found.", getbe64(title_id)); return 1; } } else { - if ((SearchTitleKeysBin(ticket, title_id) != 0) && - (GetTicket(ticket, title_id, false, src_emunand) == 0) && + if ((FindTitleKey(ticket, title_id) != 0) && + (FindTicket(ticket, title_id, false, src_emunand) == 0) && (getbe32(ticket->console_id) || getbe32(ticket->eshop_id))) { // if ticket found: wipe private data memset(ticket->console_id, 0, 4); // zero out console id @@ -889,7 +889,7 @@ u32 BuildCiaFromNcchFile(const char* path_ncch, const char* path_cia) { return 1; // optional stuff (proper titlekey / meta data) - SearchTitleKeysBin((&cia->ticket), title_id); + FindTitleKey((&cia->ticket), title_id); if (exthdr && (BuildCiaMeta(meta, exthdr, NULL) == 0) && (LoadExeFsFile(meta->smdh, path_ncch, 0, "icon", sizeof(meta->smdh)) == 0) && (InsertCiaMeta(path_cia, meta) == 0)) @@ -954,7 +954,7 @@ u32 BuildCiaFromNcsdFile(const char* path_ncsd, const char* path_cia) { } // optional stuff (proper titlekey / meta data) - SearchTitleKeysBin(&(cia->ticket), title_id); + FindTitleKey(&(cia->ticket), title_id); if ((BuildCiaMeta(meta, exthdr, NULL) == 0) && (LoadExeFsFile(meta->smdh, path_ncsd, NCSD_CNT0_OFFSET, "icon", sizeof(meta->smdh)) == 0) && (InsertCiaMeta(path_cia, meta) == 0)) diff --git a/source/game/ticket.c b/source/game/ticket.c index b621ab4..63f9ea6 100644 --- a/source/game/ticket.c +++ b/source/game/ticket.c @@ -70,43 +70,38 @@ u32 GetTitleKey(u8* titlekey, Ticket* ticket) { return 0; } -u32 GetTicket(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 u32 area_offsets[] = { TICKDB_AREA_OFFSETS }; - const char* path_db = emunand ? "4:/dbs/ticket.db" : "1:/dbs/ticket.db"; // EmuNAND / SysNAND u8 data[0x400]; FIL file; UINT btr; - // find active partition / offset + // parse file, sector by sector if (f_open(&file, path_db, FA_READ | FA_OPEN_EXISTING) != FR_OK) return 1; - f_lseek(&file, 0); - if (f_read(&file, data, 0x200, &btr) != FR_OK) { - f_close(&file); - return 1; - } - f_lseek(&file, (getle32(data + 0x130)) ? area_offsets[1] : area_offsets[0]); - - // parse file, sector by sector bool found = false; - for (u32 i = 0; !found && (i < TICKDB_AREA_SIZE); i++) { - Ticket* tick = (Ticket*) (data + 0x18); - if (f_read(&file, data, 0x200, &btr) != FR_OK) break; - if ((getle32(data + 0x10) == 0) || (getle32(data + 0x14) != sizeof(Ticket))) continue; - if (ValidateTicket(tick) != 0) continue; // partial ticket only - if (f_read(&file, data + 0x200, 0x200, &btr) != FR_OK) break; i++; // read the remainder of the ticket - if (memcmp(title_id, tick->title_id, 8) != 0) continue; // title id not matching - if (force_legit && (getbe64(tick->ticket_id) == 0)) continue; // legit check - memcpy(ticket, tick, sizeof(Ticket)); - found = true; - break; + for (u32 p = 0; p < 2; p++) { + u32 area_offset = area_offsets[p]; + for (u32 i = 0; !found && (i < TICKDB_AREA_SIZE); i += 0x200) { + Ticket* tick = (Ticket*) (data + 0x18); + f_lseek(&file, area_offset + i); + if ((f_read(&file, data, 0x400, &btr) != FR_OK) || (btr != 0x400)) break; + if ((getle32(data + 0x10) == 0) || (getle32(data + 0x14) != sizeof(Ticket))) continue; + if (ValidateTicket(tick) != 0) continue; // ticket not validated + if (memcmp(title_id, tick->title_id, 8) != 0) continue; // title id not matching + if (force_legit && (getbe64(tick->ticket_id) == 0)) continue; // legit check + memcpy(ticket, tick, sizeof(Ticket)); + found = true; + break; + } } - f_close(&file); + return (found) ? 0 : 1; } -u32 SearchTitleKeysBin(Ticket* ticket, u8* title_id) { +u32 FindTitleKey(Ticket* ticket, u8* title_id) { bool found = false; // search for a titlekey inside encTitleKeys.bin / decTitleKeys.bin // when found, add it to the ticket diff --git a/source/game/ticket.h b/source/game/ticket.h index c3d77c5..1b672e3 100644 --- a/source/game/ticket.h +++ b/source/game/ticket.h @@ -11,9 +11,17 @@ #define TIKDB_NAME_ENC "encTitleKeys.bin" #define TIKDB_NAME_DEC "decTitleKeys.bin" -#define TICKDB_AREA_OFFSETS 0x001C0C00, 0x0137F000 +#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_SIZE 0x00200000 // the actual area size is around 0x0010C600 +#define TICKDB_MAGIC 0x44, 0x49, 0x46, 0x46, 0x00, 0x00, 0x03, 0x00, \ + 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \ + 0x30, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \ + 0x2C, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \ + 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \ + 0x00, 0xEE, 0x37, 0x02, 0x00, 0x00, 0x00, 0x00 + // from: https://github.com/profi200/Project_CTR/blob/02159e17ee225de3f7c46ca195ff0f9ba3b3d3e4/ctrtool/tik.h#L15-L39 typedef struct { u8 sig_type[4]; @@ -47,6 +55,6 @@ typedef struct { u32 ValidateTicket(Ticket* ticket); u32 GetTitleKey(u8* titlekey, Ticket* ticket); -u32 GetTicket(Ticket* ticket, u8* title_id, bool force_legit, bool emunand); -u32 SearchTitleKeysBin(Ticket* ticket, u8* title_id); +u32 FindTicket(Ticket* ticket, u8* title_id, bool force_legit, bool emunand); +u32 FindTitleKey(Ticket* ticket, u8* title_id); u32 BuildFakeTicket(Ticket* ticket, u8* title_id); diff --git a/source/godmode.c b/source/godmode.c index e0c1655..fc52378 100644 --- a/source/godmode.c +++ b/source/godmode.c @@ -590,7 +590,7 @@ u32 FileHandlerMenu(char* current_path, u32* cursor, u32* scroll, DirStruct* cur (drvtype & DRV_FAT) && (strncmp(clipboard->entry[0].path, curr_entry->path, 256) != 0)) ? (int) ++n_opt : -1; - int searchdrv = (drvtype & DRV_SEARCH) ? ++n_opt : -1; + int searchdrv = (DriveType(current_path) & DRV_SEARCH) ? ++n_opt : -1; if (special > 0) optionstr[special-1] = (filetype == IMG_NAND ) ? "Mount as NAND image" : (filetype == IMG_FAT ) ? "Mount as FAT image" :