Advertisement
Guest User

Untitled

a guest
Feb 10th, 2018
95
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 4.75 KB | None | 0 0
  1. #include <stdio.h>
  2. // iQue Player ticket structure dumper
  3. // by Riley/RoL, based on research by emoose
  4.  
  5. #include <stdint.h>
  6. #include <stdbool.h>
  7. #include <stddef.h>
  8. #include <string.h>
  9.  
  10. typedef struct _TICKET {
  11.     uint32_t unk_0[2];
  12.     uint32_t unk_8; // always 1?
  13.     uint32_t content_length;
  14.     uint32_t unk_10; // 1 for sysarea ticket and 0 for game
  15.     uint8_t unkbuf[0x34];
  16.     uint32_t unk_44; // 0 for sysarea ticket and 2 for game
  17.     uint32_t certs_offset; // only filled in in a sysarea ticket
  18.     uint32_t flags; // access rights, maybe? seen 0xfffffff in one sysarea tik
  19.     uint32_t unk_50; // always 0?
  20.     char cert_name[0x40];
  21.     uint32_t content_id; // this is stored in hex but only makes sense in decimal.
  22.                          // it cannot be higher than 99999999.
  23.                          // the last two digits appear to be used as a version number.
  24.                          // if the third-to-last digit is 9 then this is a manual.
  25.     uint8_t unk_94[0x10]; // hash of decrypted content, maybe?
  26.     uint8_t signature[0x100];
  27. } TICKET;
  28.  
  29. bool is_little_endian() {
  30.     uint8_t test[2] = {1,0};
  31.     return ( *(uint16_t*) ( test ) == 1 );
  32. }
  33.  
  34. void swap_endianness(uint32_t* var) {
  35.     uint8_t* var8 = (uint8_t*)var;
  36.     uint8_t temp[4] = { var8[3], var8[2], var8[1], var8[0] };
  37.     *var = *(uint32_t*)temp;
  38. }
  39.  
  40. void read_ticket(FILE* f,TICKET* tik) {
  41.     fread(tik,sizeof(TICKET),1,f);
  42.     uint32_t* tik32 = (uint32_t*)tik;
  43.     if (is_little_endian()) {
  44.         for (int i = 0; i < 5; i++) swap_endianness(&tik32[i]);
  45.         for (int i = 0; i < 4; i++) swap_endianness(&tik32[i + (offsetof(TICKET,unk_44) / 4)]);
  46.         swap_endianness(&tik32[offsetof(TICKET,content_id) / 4]);
  47.     }
  48. }
  49.  
  50. // prints a hexdump of a buffer
  51. void prtbuf(char* name,void* buf,size_t length) {
  52.     printf("\n%s: ...\n",name);
  53.     uint8_t* ptr = (uint8_t*)buf;
  54.     size_t i = 0;
  55.     for (; i < length; i++) {
  56.         printf("%02x ",ptr[i]);
  57.         if ((i & 0xf) == 0xf) printf("\n");
  58.     }
  59.     if ((i & 0xf) != 0xf) printf("\n");
  60.     printf("\n");
  61. }
  62.  
  63. size_t num_tickets = 1;
  64.  
  65. void dump_ticket(TICKET* tik) {
  66.     printf("ticket %d ...:\n",num_tickets);
  67.     printf("         unk_0: %08x %08x\n",tik->unk_0[0],tik->unk_0[1]);
  68.     printf("         unk_8: %08x\n",tik->unk_8);
  69.     printf("content_length: %d\n",tik->content_length);
  70.     printf("        unk_10: %08x\n",tik->unk_10);
  71.     prtbuf("        unkbuf", tik->unkbuf,sizeof(tik->unkbuf));
  72.     printf("        unk_44: %08x\n",tik->unk_44);
  73.     printf("  certs_offset: %08x\n",tik->certs_offset);
  74.     printf("         flags: %08x\n",tik->flags);
  75.     printf("        unk_50: %08x\n",tik->unk_50);
  76.     printf("     cert_name: %s\n",tik->cert_name);
  77.     printf("    content_id: %d\n",tik->content_id);
  78.     prtbuf("        unk_94", tik->unk_94,sizeof(tik->unk_94));
  79.     prtbuf("     signature", tik->signature,sizeof(tik->signature));
  80.     num_tickets++;
  81. }
  82.  
  83. void check_raw_ticket(FILE* f) {
  84.     TICKET tik;
  85.     read_ticket(f,&tik);
  86.     dump_ticket(&tik);
  87. }
  88.  
  89. void check_ticketsys_entry(FILE* f) {
  90.     fseek(f,0x2800,SEEK_CUR);
  91.     check_raw_ticket(f);
  92. }
  93.  
  94. void check_ticket_sys(FILE* f,size_t num_tickets) {
  95.     for (size_t i = 0; i < num_tickets; i++) {
  96.         fseek(f,i*0x2b4c + sizeof(uint32_t),SEEK_SET);
  97.         check_ticketsys_entry(f);
  98.     }
  99. }
  100.  
  101. void check_sksa(FILE* f) {
  102.     TICKET tik;
  103.     // check the first ticket
  104.     fseek(f,0x10000,SEEK_SET);
  105.     read_ticket(f,&tik);
  106.     dump_ticket(&tik);
  107.     // is there a second?
  108.     fseek(f,0x14000 + tik.content_length + offsetof(TICKET,cert_name),SEEK_SET);
  109.     char cert_ca[5];
  110.     memset(cert_ca,0,sizeof(cert_ca));
  111.     fread(cert_ca,4,1,f);
  112.     if (!strcmp(cert_ca,"Root")) {
  113.         fseek(f,0x14000 + tik.content_length,SEEK_SET);
  114.         check_raw_ticket(f);
  115.     }
  116. }
  117.  
  118. void check_file(char* path) {
  119.     FILE* f = fopen(path,"rb");
  120.     if (f == NULL) return;
  121.     // is this a system area?
  122.     uint32_t first_u32;
  123.     fread(&first_u32,sizeof(uint32_t),1,f);
  124.     if (is_little_endian()) swap_endianness(&first_u32);
  125.     if (first_u32 == 0x965b0414) {
  126.         check_sksa(f);
  127.     } else {
  128.         // perhaps this is a ticket.sys?
  129.         fseek(f,0x44,SEEK_SET);
  130.         char cam_magic[4];
  131.         memset(cam_magic,0,sizeof(cam_magic));
  132.         fread(cam_magic,3,1,f);
  133.         if ((!strcmp(cam_magic,"CAM")) && (first_u32 < 0x1000)) { // just an arbitrary number to compare against...
  134.             check_ticket_sys(f,first_u32);
  135.         } else {
  136.             // maybe a ticket.sys entry?
  137.             fseek(f,0x40,SEEK_SET);
  138.             memset(cam_magic,0,sizeof(cam_magic));
  139.             fread(cam_magic,3,1,f);
  140.             if (!strcmp(cam_magic,"CAM")) {
  141.                 fseek(f,0,SEEK_SET);
  142.                 check_ticketsys_entry(f);
  143.             } else {
  144.                 // how about a raw ticket?
  145.                 fseek(f,offsetof(TICKET,cert_name),SEEK_SET);
  146.                 char cert_ca[5];
  147.                 memset(cert_ca,0,sizeof(cert_ca));
  148.                 fread(cert_ca,4,1,f);
  149.                 if (!strcmp(cert_ca,"Root")) {
  150.                     fseek(f,0,SEEK_SET);
  151.                     check_raw_ticket(f);
  152.                 }
  153.             }
  154.         }
  155.     }
  156.     fclose(f);
  157. }
  158.  
  159. int main(int argc,char** argv) {
  160.     if (argc < 2) return -1;
  161.     for (int i = 1; i < argc; i++) {
  162.         check_file(argv[i]);
  163.     }
  164. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement