Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <stdio.h>
- // iQue Player ticket structure dumper
- // by Riley/RoL, based on research by emoose
- #include <stdint.h>
- #include <stdbool.h>
- #include <stddef.h>
- #include <string.h>
- typedef struct _TICKET {
- uint32_t unk_0[2];
- uint32_t unk_8; // always 1?
- uint32_t content_length;
- uint32_t unk_10; // 1 for sysarea ticket and 0 for game
- uint8_t unkbuf[0x34];
- uint32_t unk_44; // 0 for sysarea ticket and 2 for game
- uint32_t certs_offset; // only filled in in a sysarea ticket
- uint32_t flags; // access rights, maybe? seen 0xfffffff in one sysarea tik
- uint32_t unk_50; // always 0?
- char cert_name[0x40];
- uint32_t content_id; // this is stored in hex but only makes sense in decimal.
- // it cannot be higher than 99999999.
- // the last two digits appear to be used as a version number.
- // if the third-to-last digit is 9 then this is a manual.
- uint8_t unk_94[0x10]; // hash of decrypted content, maybe?
- uint8_t signature[0x100];
- } TICKET;
- bool is_little_endian() {
- uint8_t test[2] = {1,0};
- return ( *(uint16_t*) ( test ) == 1 );
- }
- void swap_endianness(uint32_t* var) {
- uint8_t* var8 = (uint8_t*)var;
- uint8_t temp[4] = { var8[3], var8[2], var8[1], var8[0] };
- *var = *(uint32_t*)temp;
- }
- void read_ticket(FILE* f,TICKET* tik) {
- fread(tik,sizeof(TICKET),1,f);
- uint32_t* tik32 = (uint32_t*)tik;
- if (is_little_endian()) {
- for (int i = 0; i < 5; i++) swap_endianness(&tik32[i]);
- for (int i = 0; i < 4; i++) swap_endianness(&tik32[i + (offsetof(TICKET,unk_44) / 4)]);
- swap_endianness(&tik32[offsetof(TICKET,content_id) / 4]);
- }
- }
- // prints a hexdump of a buffer
- void prtbuf(char* name,void* buf,size_t length) {
- printf("\n%s: ...\n",name);
- uint8_t* ptr = (uint8_t*)buf;
- size_t i = 0;
- for (; i < length; i++) {
- printf("%02x ",ptr[i]);
- if ((i & 0xf) == 0xf) printf("\n");
- }
- if ((i & 0xf) != 0xf) printf("\n");
- printf("\n");
- }
- size_t num_tickets = 1;
- void dump_ticket(TICKET* tik) {
- printf("ticket %d ...:\n",num_tickets);
- printf(" unk_0: %08x %08x\n",tik->unk_0[0],tik->unk_0[1]);
- printf(" unk_8: %08x\n",tik->unk_8);
- printf("content_length: %d\n",tik->content_length);
- printf(" unk_10: %08x\n",tik->unk_10);
- prtbuf(" unkbuf", tik->unkbuf,sizeof(tik->unkbuf));
- printf(" unk_44: %08x\n",tik->unk_44);
- printf(" certs_offset: %08x\n",tik->certs_offset);
- printf(" flags: %08x\n",tik->flags);
- printf(" unk_50: %08x\n",tik->unk_50);
- printf(" cert_name: %s\n",tik->cert_name);
- printf(" content_id: %d\n",tik->content_id);
- prtbuf(" unk_94", tik->unk_94,sizeof(tik->unk_94));
- prtbuf(" signature", tik->signature,sizeof(tik->signature));
- num_tickets++;
- }
- void check_raw_ticket(FILE* f) {
- TICKET tik;
- read_ticket(f,&tik);
- dump_ticket(&tik);
- }
- void check_ticketsys_entry(FILE* f) {
- fseek(f,0x2800,SEEK_CUR);
- check_raw_ticket(f);
- }
- void check_ticket_sys(FILE* f,size_t num_tickets) {
- for (size_t i = 0; i < num_tickets; i++) {
- fseek(f,i*0x2b4c + sizeof(uint32_t),SEEK_SET);
- check_ticketsys_entry(f);
- }
- }
- void check_sksa(FILE* f) {
- TICKET tik;
- // check the first ticket
- fseek(f,0x10000,SEEK_SET);
- read_ticket(f,&tik);
- dump_ticket(&tik);
- // is there a second?
- fseek(f,0x14000 + tik.content_length + offsetof(TICKET,cert_name),SEEK_SET);
- char cert_ca[5];
- memset(cert_ca,0,sizeof(cert_ca));
- fread(cert_ca,4,1,f);
- if (!strcmp(cert_ca,"Root")) {
- fseek(f,0x14000 + tik.content_length,SEEK_SET);
- check_raw_ticket(f);
- }
- }
- void check_file(char* path) {
- FILE* f = fopen(path,"rb");
- if (f == NULL) return;
- // is this a system area?
- uint32_t first_u32;
- fread(&first_u32,sizeof(uint32_t),1,f);
- if (is_little_endian()) swap_endianness(&first_u32);
- if (first_u32 == 0x965b0414) {
- check_sksa(f);
- } else {
- // perhaps this is a ticket.sys?
- fseek(f,0x44,SEEK_SET);
- char cam_magic[4];
- memset(cam_magic,0,sizeof(cam_magic));
- fread(cam_magic,3,1,f);
- if ((!strcmp(cam_magic,"CAM")) && (first_u32 < 0x1000)) { // just an arbitrary number to compare against...
- check_ticket_sys(f,first_u32);
- } else {
- // maybe a ticket.sys entry?
- fseek(f,0x40,SEEK_SET);
- memset(cam_magic,0,sizeof(cam_magic));
- fread(cam_magic,3,1,f);
- if (!strcmp(cam_magic,"CAM")) {
- fseek(f,0,SEEK_SET);
- check_ticketsys_entry(f);
- } else {
- // how about a raw ticket?
- fseek(f,offsetof(TICKET,cert_name),SEEK_SET);
- char cert_ca[5];
- memset(cert_ca,0,sizeof(cert_ca));
- fread(cert_ca,4,1,f);
- if (!strcmp(cert_ca,"Root")) {
- fseek(f,0,SEEK_SET);
- check_raw_ticket(f);
- }
- }
- }
- }
- fclose(f);
- }
- int main(int argc,char** argv) {
- if (argc < 2) return -1;
- for (int i = 1; i < argc; i++) {
- check_file(argv[i]);
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement