/* * Return the working directory for the current buffer, terminated * with a '/'. First, try to extract it from the current buffer's * filename. If that fails, use global cwd. */ int getbufcwd(char *path, size_t plen) { char cwd[NFILEN]; if (plen == 0) return (FALSE); if (globalwd == FALSE && curbp->b_cwd[0] != '\0') { (void)strlcpy(path, curbp->b_cwd, plen); } else { if (getcwdir(cwd, sizeof(cwd)) == FALSE) goto error; (void)strlcpy(path, cwd, plen); } return (TRUE); error: path[0] = '\0'; return (FALSE); }
error_t fshelp_start_translator (fshelp_open_fn_t underlying_open_fn, void *cookie, char *name, char *argz, int argz_len, int timeout, fsys_t *control) { mach_port_t ports[INIT_PORT_MAX]; mach_port_t fds[STDERR_FILENO + 1]; int ints[INIT_INT_MAX]; int i; error_t err; for (i = 0; i < INIT_PORT_MAX; i++) ports[i] = MACH_PORT_NULL; for (i = 0; i < STDERR_FILENO + 1; i++) fds[i] = MACH_PORT_NULL; memset (ints, 0, INIT_INT_MAX * sizeof(int)); ports[INIT_PORT_CWDIR] = getcwdir (); ports[INIT_PORT_CRDIR] = getcrdir (); ports[INIT_PORT_AUTH] = getauth (); fds[STDERR_FILENO] = getdport (STDERR_FILENO); err = fshelp_start_translator_long (underlying_open_fn, cookie, name, argz, argz_len, fds, MACH_MSG_TYPE_COPY_SEND, STDERR_FILENO + 1, ports, MACH_MSG_TYPE_COPY_SEND, INIT_PORT_MAX, ints, INIT_INT_MAX, geteuid (), timeout, control); for (i = 0; i < INIT_PORT_MAX; i++) mach_port_deallocate (mach_task_self (), ports[i]); for (i = 0; i <= STDERR_FILENO; i++) mach_port_deallocate (mach_task_self (), fds[i]); return err; }
int main(int argc, char *argv[]) { app_title(); //Argument Checks if(argc < 3){ printf("[!] Not Enough Arguments\n"); help(argv[0]); return 1; } if(argc > 3){ printf("[!] Too Many Arguments\n"); help(argv[0]); return 1; } //Storing Current Working Directory char cwd[1024]; if (getcwdir(cwd, sizeof(cwd)) == NULL){ printf("[!] Could not store Current Working Directory\n"); return IO_FAIL; } //Changing to CDN Content Directory chdir(argv[1]); //Processing TIK FILE *tik = fopen("cetk","rb"); if(tik == NULL){ printf("[!] Could not open 'tik'\n"); return IO_FAIL; } TIK_CONTEXT tik_context = process_tik(tik); //Processing TMD FILE *tmd = fopen("tmd","rb"); if(tmd == NULL){ printf("[!] Could not open 'tmd'\n"); return IO_FAIL; } TMD_CONTEXT tmd_context = process_tmd(tmd); //Error Checking if(tik_context.result != 0 || tmd_context.result != 0){ printf("[!] Input files could not be processed successfully\n"); free(tmd_context.content_struct); free(tmd_context.content); fclose(tik); fclose(tmd); return FILE_PROCESS_FAIL; } //TID comparison check if(check_tid(tik_context.title_id,tmd_context.title_id) != TRUE){ printf("[!] Caution, Ticket and TMD Title IDs do not match\n"); printf("[!] CETK Title ID: "); u8_hex_print_be(tik_context.title_id,0x8); printf("\n"); printf("[!] TMD Title ID: "); u8_hex_print_be(tmd_context.title_id,0x8); printf("\n"); } //Title Version comparison if(tik_context.title_version != tmd_context.title_version){ printf("[!] Caution, Ticket and TMD Title Versions do not match\n"); printf("[!] CETK Title Ver: %d\n",tik_context.title_version); printf("[!] TMD Title Ver: %d\n",tmd_context.title_version); } //Returning to Original Working Directory chdir(cwd); //Opening Output file FILE *output = fopen(argv[2],"wb"); if(output == NULL){ printf("[!] Could not create '%s'\n",argv[2]); return IO_FAIL; } int result = generate_cia(tmd_context,tik_context,output); if(result != 0){ printf("[!] Failed to Generate %s\n",argv[2]); remove(argv[2]); } else printf("[*] %s Generated Sucessfully\n",argv[2]); return 0; }
int main(int argc, char *argv[]) { if(argc < 2) { printf("[!] Invalid Arguments (Not Enough Arguments)\n"); help(argv[0]); return 1; } int mode = -1; // Deciding Mode of Operation for(int i = 1; i < argc; i++) { if(strcmp(argv[i],"-g") == 0 || strcmp(argv[i],"--genxor") == 0) { mode = gen_xorpad; break; } else if(strcmp(argv[i],"-d") == 0 || strcmp(argv[i],"--decrypt") == 0) { mode = dec_icondata; break; } else if(strcmp(argv[i],"-t") == 0 || strcmp(argv[i],"--disp_tid") == 0) { mode = read_cache_dat; break; } else if(strcmp(argv[i],"-o") == 0 || strncmp(argv[i],"--dec_list=",11) == 0) { mode = read_cache_dat; break; } } if(mode == -1) { printf("[!] Invalid Arguments (No Mode Specified)\n"); help(argv[0]); return 1; } if(mode == read_cache_dat) { return ReadCacheDat(argc,argv); } // Getting Current Working Directory char CWD[1024]; memset(CWD,0,1024); getcwdir(CWD,1024); // Getting Data from args s32 pre_existing_icons = -1; s32 icons_to_crypt = -1; char *xor_dir = NULL; char *dec_icn_dir = NULL; char *cacheD_path = NULL; char xor_abs_dir[1024]; memset(xor_abs_dir,0,1024); char dec_icn_abs_dir[1024]; memset(dec_icn_abs_dir,0,1024); for(int i = 1; i < argc; i++) { if(strcmp(argv[i],"-i") == 0 && dec_icn_dir == NULL && i < argc-1) { dec_icn_dir = argv[i+1]; } else if(strncmp(argv[i],"--decdata=",10) == 0 && dec_icn_dir == NULL) { dec_icn_dir = (char*)(argv[i]+10); } else if(strcmp(argv[i],"-x") == 0 && xor_dir == NULL && i < argc-1) { xor_dir = argv[i+1]; } else if(strncmp(argv[i],"--xorpaddir=",12) == 0 && xor_dir == NULL) { xor_dir = (char*)(argv[i]+12); } else if(strcmp(argv[i],"-c") == 0 && cacheD_path == NULL && i < argc-1) { cacheD_path = argv[i+1]; } else if(strncmp(argv[i],"--iconcache=",12) == 0 && cacheD_path == NULL) { cacheD_path = (char*)(argv[i]+12); } else if(strcmp(argv[i],"-0") == 0 && pre_existing_icons == -1 && i < argc-1) { pre_existing_icons = strtoul(argv[i+1],NULL,10); } else if(strncmp(argv[i],"--unused_slots=",15) == 0 && pre_existing_icons == -1) { pre_existing_icons = strtoul((argv[i]+15),NULL,10); } else if(strcmp(argv[i],"-1") == 0 && icons_to_crypt == -1 && i < argc-1) { icons_to_crypt = strtoul(argv[i+1],NULL,10); } else if(strncmp(argv[i],"--num_decrypt=",14) == 0 && icons_to_crypt == -1) { icons_to_crypt = strtoul((argv[i]+14),NULL,10); } } // Sorting out bad input if(pre_existing_icons < 0 || pre_existing_icons > 360) { printf("[!] Invalid input or no input, for option '-0'/'--unused_slots='\n"); help(argv[0]); return 1; } if(icons_to_crypt < 1 || icons_to_crypt > 360) { printf("[!] Invalid input or no input, for option '-1'/'--num_decrypt='\n"); help(argv[0]); return 1; } if(dec_icn_dir == NULL) { printf("[!] No Plaintext Icon directory was specified\n"); help(argv[0]); return 1; } if(xor_dir == NULL) { printf("[!] No XOR pad Directory was specified\n"); help(argv[0]); return 1; } if(cacheD_path == NULL) { printf("[!] No Encryption Icon Cache was specified\n"); help(argv[0]); return 1; } // Opening Icon Cache File FILE *cacheD = fopen(cacheD_path,"rb"); if(cacheD == NULL) { printf("[!] Failed to open '%s'\n",cacheD_path); return 1; } // Allocating Buffers u8 *DecIconData = malloc(SMDH_SIZE); u8 *EncIconData = malloc(SMDH_SIZE); u8 *XORpad = malloc(SMDH_SIZE); if(DecIconData == NULL || EncIconData == NULL || XORpad == NULL) { printf("[!] Memory Error\n"); return 1; } // Getting Absolute Dir Paths for Icon Dir and XOR pad DIR if(mode == gen_xorpad) makedir(xor_dir); else if(mode == dec_icondata) makedir(dec_icn_dir); chdir(xor_dir); getcwdir(xor_abs_dir,1024); chdir(CWD); chdir(dec_icn_dir); getcwdir(dec_icn_abs_dir,1024); chdir(CWD); // Informing the user what the program will do if(mode == gen_xorpad) printf("[+] Generating XOR pad(s)\n"); else if(mode == dec_icondata) printf("[+] Decrypting Icon Data\n"); // Init File Pointers / Arrays / Values FILE *dec_icon_fp = NULL; FILE *xor_pad_fp = NULL; char deciconfile[100]; char xorfile[100]; u32 enc_icon_pos = 0; for(int i = pre_existing_icons; i < (pre_existing_icons+icons_to_crypt); i++) { enc_icon_pos = CACHE_EXTDATA_OFFSET + SMDH_SIZE*i; // Getting File Names memset(&deciconfile,0,100); memset(&xorfile,0,100); sprintf(deciconfile,"icon_%d.icn",i); sprintf(xorfile,"icon_%d.xor",i); // Getting Enc Icon ReadFile_64(EncIconData,SMDH_SIZE,enc_icon_pos,cacheD); // Getting File Pointers and Storing Data if(mode == gen_xorpad) { chdir(dec_icn_abs_dir); dec_icon_fp = fopen(deciconfile,"rb"); if(dec_icon_fp == NULL) { printf("[!] Failed To Open '%s'\n",deciconfile); return 1; } chdir(xor_abs_dir); xor_pad_fp = fopen(xorfile,"wb"); if(xor_pad_fp == NULL) { printf("[!] Failed To Create '%s'\n",xorfile); return 1; } // Storing Dec Icon ReadFile_64(DecIconData,SMDH_SIZE,0,dec_icon_fp); int icon_check = CheckDecIcon(DecIconData); if(icon_check == BAD_ICON) printf("[!] Caution '%s' does not appear to be an icon file, '%s' may be invalid\n",deciconfile,xorfile); } else if(mode == dec_icondata) { chdir(dec_icn_abs_dir); dec_icon_fp = fopen(deciconfile,"wb"); if(dec_icon_fp == NULL) { printf("[!] Failed To Create '%s'\n",deciconfile); return 1; } chdir(xor_abs_dir); xor_pad_fp = fopen(xorfile,"rb"); if(xor_pad_fp == NULL) { printf("[!] Failed To Open '%s'\n",xorfile); return 1; } // Storing XOR pad ReadFile_64(XORpad,SMDH_SIZE,0,xor_pad_fp); } // Perform XOR crypto if(mode == gen_xorpad) xor_file(XORpad, DecIconData, EncIconData, SMDH_SIZE); else if(mode == dec_icondata) { xor_file(DecIconData, XORpad, EncIconData, SMDH_SIZE); int icon_check = CheckDecIcon(DecIconData); if(icon_check == BAD_ICON) printf("[!] '%s' does not appear to have decrypted properly\n",deciconfile); } // Writing Output to File if(mode == gen_xorpad) WriteBuffer(XORpad, SMDH_SIZE, 0, xor_pad_fp); else if(mode == dec_icondata) WriteBuffer(DecIconData, SMDH_SIZE, 0, dec_icon_fp); fclose(dec_icon_fp); fclose(xor_pad_fp); } // Freeing Buffers and Icon Cache File Pointer free(EncIconData); free(DecIconData); free(XORpad); fclose(cacheD); printf("[*] Done\n"); return 0; }
int main(int argc, char *argv[]) { if(argc < 2){ help(argv[0]); return 1; } int action = 0; int i = 1; while(!action){ if(i == argc) break; if(strcmp(argv[i],"-i") == 0 || strncmp(argv[i],"--image=",8) == 0) action = image; if(strcmp(argv[i],"-d") == 0 || strncmp(argv[i],"--FSdir=",8) == 0) action = fs; if(strcmp(argv[i],"-g") == 0 || strncmp(argv[i],"--genextdata=",13) == 0) action = generate; i++; } if(action == 0){ printf("[!] Nothing to do\n"); help(argv[0]); return ARG_ERROR; } if(action == image){ ExtdataContext *extdata = malloc(sizeof(ExtdataContext)); InitaliseExtdataContext(extdata); char *input = NULL; char *output = NULL; int DB_Mode = -1; u8 Extract = False; extdata->PrintInfo = False; extdata->Verbose = False; extdata->OverrideActiveDIFI = False; u8 result = 0; for(i = 1; i < argc; i++){ if(strcmp(argv[i],"-i") == 0 && input == NULL && i < argc-1){ input = argv[i+1]; } else if(strncmp(argv[i],"--image=",8) == 0 && input == NULL){ input = (char*)(argv[i]+8); } else if(strcmp(argv[i],"-x") == 0 && output == NULL && i < argc-1 && Extract == False){ Extract = True; output = argv[i+1]; } else if(strncmp(argv[i],"--extract=",10) == 0 && output == NULL && Extract == False){ Extract = True; output = (char*)(argv[i]+10); } else if(strcmp(argv[i],"-a") == 0 && i < argc-1){ extdata->OverrideActiveDIFI = True; extdata->DIFIPartition = strtol(argv[i+1],NULL,10); } else if(strncmp(argv[i],"--forcedifi=",12) == 0){ extdata->OverrideActiveDIFI = True; extdata->DIFIPartition = strtol((argv[i]+12),NULL,10); } else if(strcmp(argv[i],"-p") == 0 || strcmp(argv[i],"--info") == 0){ extdata->PrintInfo = True; } else if(strcmp(argv[i],"-v") == 0 || strcmp(argv[i],"--verbose") == 0){ extdata->Verbose = True; } else if(strcmp(argv[i],"-l") == 0 || strcmp(argv[i],"--listDB") == 0){ DB_Mode = DB_Normal; } else if(strcmp(argv[i],"-0") == 0 || strcmp(argv[i],"--listTID") == 0){ DB_Mode = DB_ByTID; } } if(input == NULL){ printf("[!] No input extdata image was specified\n"); FreeExtdataContext(extdata); help(argv[0]); return ARG_ERROR; } if(Extract == False && extdata->PrintInfo == False && extdata->Verbose == False && DB_Mode == -1){ printf("[!] Nothing to do\n"); FreeExtdataContext(extdata); help(argv[0]); return ARG_ERROR; } if(extdata->OverrideActiveDIFI && extdata->DIFIPartition != 0 && extdata->DIFIPartition != 1){ printf("[!] Invalid DIFI partition: %d\n",extdata->DIFIPartition); FreeExtdataContext(extdata); help(argv[0]); return ARG_ERROR; } FILE *fp = fopen(input,"rb"); if(fp == NULL){ printf("[!] Failed to open '%s'\n",input); FreeExtdataContext(extdata); return IO_ERROR; } fclose(fp); extdata->extdata.size = GetFileSize_u64(input); extdata->extdata.buffer = malloc(extdata->extdata.size); if(extdata->extdata.buffer == NULL){ printf("[!] Failed to allocate memory for extdata image\n"); FreeExtdataContext(extdata); return MEM_ERROR; } fp = fopen(input,"rb"); ReadFile_64(extdata->extdata.buffer,extdata->extdata.size,0,fp); fclose(fp); result = GetExtdataContext(extdata); if(result != 0){ printf("[!] Failed to interprete extdata image (%d)\n",result); FreeExtdataContext(extdata); return 1; } if(extdata->Files.Count > 0){ u8* embedded_data = extdata->extdata.buffer + extdata->Files.Data[0].offset; // Extracting Data if(extdata->Files.Count == 1 && Extract){ fp = fopen(output,"wb"); if(fp == NULL){ printf("[!] Failed to create '%s'\n",output); FreeExtdataContext(extdata); return IO_ERROR; } if(extdata->Verbose) printf("[+] Writing data to '%s'\n",output); WriteBuffer(embedded_data,extdata->Files.Data[0].size,0,fp); fclose(fp); } // Displaying DB... if possible if(DB_Mode >= 0){ if(extdata->ExtdataType == RawIVFC && extdata->Files.Count == 1 && IsTitleDB(embedded_data)){ result = ProcessTitleDB(embedded_data,DB_Mode); if(result){ printf("[!] Failed to read DB (%d)\n",result); } } else{ printf("[!] No valid Title Database in extdata\n"); } } } else{ printf("[!] No data exists embedded in extdata\n"); } FreeExtdataContext(extdata); } else if(action == fs){ VSXEContext *vsxe_ctx = malloc(sizeof(VSXEContext)); ExtdataContext *vsxe = malloc(sizeof(ExtdataContext)); char *input = NULL; char *output = NULL; char cwd[IO_PATH_LEN]; char VSXE_image_path[IO_PATH_LEN]; memset(vsxe_ctx,0,sizeof(VSXEContext)); memset(&cwd,0,IO_PATH_LEN); memset(&VSXE_image_path,0,IO_PATH_LEN); memset(vsxe,0,sizeof(ExtdataContext)); if(getcwdir(cwd,IO_PATH_LEN) == NULL){ printf("[!] Could not store Current Working Directory\n"); return IO_ERROR; } for(i = 1; i < argc; i++){ if(strcmp(argv[i],"-d") == 0 && input == NULL && i < argc-1){ input = argv[i+1]; } else if(strncmp(argv[i],"--FSdir=",8) == 0 && input == NULL){ input = (char*)(argv[i]+8); } else if(strcmp(argv[i],"-x") == 0 && output == NULL && i < argc-1){ vsxe_ctx->Flags[vsxe_extract] = True; output = argv[i+1]; } else if(strncmp(argv[i],"--extractFS=",12) == 0 && output == NULL){ vsxe_ctx->Flags[vsxe_extract] = True; output = (char*)(argv[i]+12); } else if(strcmp(argv[i],"-s") == 0 || strcmp(argv[i],"--showFS") == 0){ vsxe_ctx->Flags[vsxe_show_fs] = True; } else if(strcmp(argv[i],"-v") == 0 || strcmp(argv[i],"--verbose") == 0){ vsxe_ctx->Flags[vsxe_verbose] = True; } else if(strcmp(argv[i],"-f") == 0 || strcmp(argv[i],"--FStable") == 0){ vsxe_ctx->Flags[vsxe_fstable] = True; } else if(strcmp(argv[i],"-a") == 0 && i < argc-1){ vsxe->OverrideActiveDIFI = True; vsxe->DIFIPartition = strtol(argv[i+1],NULL,10); } else if(strncmp(argv[i],"--forcedifi=",12) == 0){ vsxe->OverrideActiveDIFI = True; vsxe->DIFIPartition = strtol((argv[i]+12),NULL,10); } } if(input == NULL){ printf("[!] No Extdata FS directory was specified\n"); free(vsxe_ctx); FreeExtdataContext(vsxe); return ARG_ERROR; } if(vsxe_ctx->Flags[vsxe_extract] && output == NULL){ printf("[!] No Output directory was specified\n"); free(vsxe_ctx); FreeExtdataContext(vsxe); return ARG_ERROR; } if(vsxe_ctx->Flags[vsxe_show_fs] == False && vsxe_ctx->Flags[vsxe_extract] == False && vsxe_ctx->Flags[vsxe_fstable] == False){ printf("[!] Nothing to do\n"); free(vsxe_ctx); FreeExtdataContext(vsxe); return ARG_ERROR; } #ifdef _WIN32 vsxe_ctx->platform = WIN_32; #else vsxe_ctx->platform = UNIX; #endif // Storing Input Directory vsxe_ctx->input = malloc(IO_PATH_LEN); if(vsxe_ctx->input == NULL){ printf("[!] Failed to allocate memory for input path\n"); free(vsxe_ctx); FreeExtdataContext(vsxe); return MEM_ERROR; } chdir(input); if(getcwdir(vsxe_ctx->input,IO_PATH_LEN) == NULL){ printf("[!] Could not store input Directory\n"); free(vsxe_ctx->input); free(vsxe_ctx); FreeExtdataContext(vsxe); return IO_ERROR; } chdir(cwd); // Storing Output Directory vsxe_ctx->output = malloc(IO_PATH_LEN); if(vsxe_ctx->output == NULL){ printf("[!] Failed to allocate memory for output path\n"); free(vsxe_ctx->input); free(vsxe_ctx); FreeExtdataContext(vsxe); return MEM_ERROR; } chdir(output); if(getcwdir(vsxe_ctx->output,IO_PATH_LEN) == NULL){ printf("[!] Could not store output Directory\n"); free(vsxe_ctx->input); free(vsxe_ctx->output); free(vsxe_ctx); FreeExtdataContext(vsxe); return IO_ERROR; } chdir(cwd); // Getting path to VSXE FS Image sprintf(VSXE_image_path,"%s%c00000001.dec",vsxe_ctx->input,vsxe_ctx->platform); FILE *fp = fopen(VSXE_image_path,"rb"); if(fp == NULL){ printf("[!] Could not open '%s'\n",VSXE_image_path); free(vsxe_ctx->input); free(vsxe_ctx->output); free(vsxe_ctx); FreeExtdataContext(vsxe); return IO_ERROR; } fclose(fp); vsxe->extdata.size = GetFileSize_u64(VSXE_image_path); vsxe->extdata.buffer = malloc(vsxe->extdata.size); if(vsxe->extdata.buffer == NULL){ printf("[!] Failed to allocate memory for VSXE FST Image\n"); free(vsxe_ctx->input); free(vsxe_ctx->output); free(vsxe_ctx); FreeExtdataContext(vsxe); return MEM_ERROR; } // Getting VSXE FST Image fp = fopen(VSXE_image_path,"rb"); ReadFile_64(vsxe->extdata.buffer,vsxe->extdata.size,0,fp); fclose(fp); u8 result = GetExtdataContext(vsxe); if(result){ printf("[!] Failed to obtain VSXE FST from image '%s' (%d)\n",VSXE_image_path,result); free(vsxe_ctx->input); free(vsxe_ctx->output); free(vsxe_ctx); FreeExtdataContext(vsxe); return result; } if(vsxe->Files.Count > 0){ u8 *vsxe_offset = vsxe->extdata.buffer + vsxe->Files.Data[0].offset; if(vsxe->ExtdataType == RawIVFC && vsxe->Files.Count == 1 && IsVSXEFileSystem(vsxe_offset)){ vsxe_ctx->vsxe = vsxe_offset; result = ProcessExtData_FS(vsxe_ctx); if(result){ printf("[!] Failed to read VSXE FST (%d)\n",result); } } else{ printf("[!] No valid VSXE FST exists in '%s'\n",output); } } else{ printf("[!] No data exists embedded in extdata\n"); } free(vsxe_ctx->input); free(vsxe_ctx->output); free(vsxe_ctx); FreeExtdataContext(vsxe); } else if(action == generate){ // Extdata Gen COMPONENT_STRUCT sourcedata; memset(&sourcedata,0,sizeof(COMPONENT_STRUCT)); COMPONENT_STRUCT outdata; memset(&outdata,0,sizeof(COMPONENT_STRUCT)); char *input = NULL; char *output = NULL; char *extdatatype = NULL; u32 activeDIFI = 0; u8 type = 0; u8 Verbose = False; u8 UniqueExtdataID[8]; memset(&UniqueExtdataID,0,8); u8 GenMAC = False; for(i = 1; i < argc; i++){ if(strcmp(argv[i],"-1") == 0 || strcmp(argv[i],"-2") == 0 || strncmp(argv[i],"--keyX=",6) == 0 || strncmp(argv[i],"--keyY=",6) == 0){ GenMAC = True; } else if(strcmp(argv[i],"-g") == 0 && input == NULL && i < argc-1){ input = argv[i+1]; } else if(strncmp(argv[i],"--genextdata=",13) == 0 && input == NULL){ input = (char*)(argv[i]+13); } else if(strcmp(argv[i],"-o") == 0 && output == NULL && i < argc-1){ output = argv[i+1]; } else if(strncmp(argv[i],"--outimage=",11) == 0 && output == NULL){ output = (char*)(argv[i]+11); } else if(strcmp(argv[i],"-t") == 0 && extdatatype == NULL && i < argc-1){ extdatatype = argv[i+1]; } else if(strncmp(argv[i],"--type=",7) == 0 && extdatatype == NULL){ extdatatype = (char*)(argv[i]+7); } else if(strcmp(argv[i],"-a") == 0 && i < argc-1){ activeDIFI = strtol(argv[i+1],NULL,10); } else if(strncmp(argv[i],"--activedifi=",13) == 0){ activeDIFI = strtol((argv[i]+13),NULL,10); } else if(strcmp(argv[i],"-u") == 0 && i < argc-1){ if(strlen(argv[i+1]) == 16) char_to_u8_array(UniqueExtdataID,argv[i+1],8,BE,16); else printf("[!] Invalid length for Extdata Unique ID (expected 16 hex characters)\n"); } else if(strncmp(argv[i],"--uniqueID=",11) == 0){ if(strlen((argv[i]+11)) == 16) char_to_u8_array(UniqueExtdataID,(argv[i]+11),8,BE,16); else printf("[!] Invalid length for Extdata Unique ID (expected 16 hex characters)\n"); } else if(strcmp(argv[i],"-v") == 0 || strcmp(argv[i],"--verbose") == 0){ Verbose = True; } } if(input == NULL){ printf("[!] No input image was specified\n"); help(argv[0]); return ARG_ERROR; } if(output == NULL){ printf("[!] No output extdata image was specified\n"); help(argv[0]); return ARG_ERROR; } if(extdatatype == NULL){ printf("[!] No extdata type was specified\n"); help(argv[0]); return ARG_ERROR; } // MAC Gen AESMAC_CTX *aes_ctx = malloc(sizeof(AESMAC_CTX)); memset(aes_ctx,0,sizeof(AESMAC_CTX)); u8 KeyX[0x10]; u8 KeyY[0x10]; memset(&KeyX,0,0x10); memset(&KeyY,0,0x10); aes_ctx->Verbose = Verbose; if(strcmp(extdatatype,"DATA") == 0){ type = BUILD_DATA; aes_ctx->type = mac_extdata; } else if(strcmp(extdatatype,"FS") == 0){ type = BUILD_FS; aes_ctx->type = mac_extdata; } else if(strcmp(extdatatype,"TDB") == 0){ type = BUILD_DB; aes_ctx->type = mac_title_db; } else if(strcmp(extdatatype,"IDB") == 0){ type = BUILD_DB; aes_ctx->type = mac_import_db; } if(type == 0){ printf("[!] Invalid Extdata type '%s'\n",extdatatype); help(argv[0]); free(aes_ctx); return ARG_ERROR; } if(GenMAC){ for(i = 1; i < argc; i++){ if(strcmp(argv[i],"-1") == 0 && i < argc-1){ if(strlen(argv[i+1]) == 32) char_to_u8_array(KeyX,argv[i+1],16,BE,16); else{ printf("[!] Invalid length for KeyX (expected 32 hex characters)\n"); help(argv[0]); free(aes_ctx); return ARG_ERROR; } } else if(strncmp(argv[i],"--keyX=",7) == 0){ if(strlen((argv[i]+7)) == 32) char_to_u8_array(KeyX,(argv[i]+7),16,BE,16); else{ printf("[!] Invalid length for KeyX (expected 32 hex characters)\n"); help(argv[0]); free(aes_ctx); return ARG_ERROR; } } else if(strcmp(argv[i],"-2") == 0 && i < argc-1){ if(strlen(argv[i+1]) == 32) char_to_u8_array(KeyY,argv[i+1],16,BE,16); else{ printf("[!] Invalid length for KeyY (expected 32 hex characters)\n"); help(argv[0]); free(aes_ctx); return ARG_ERROR; } } else if(strncmp(argv[i],"--keyY=",7) == 0){ if(strlen((argv[i]+7)) == 32) char_to_u8_array(KeyY,(argv[i]+7),16,BE,16); else{ printf("[!] Invalid length for KeyY (expected 32 hex characters)\n"); help(argv[0]); free(aes_ctx); return ARG_ERROR; } } else if(strcmp(argv[i],"-3") == 0 && i < argc-1){ u32_to_u8(aes_ctx->subdir_id,strtol(argv[i+1],NULL,16),BE); } else if(strncmp(argv[i],"--SubDirID=",11) == 0){ u32_to_u8(aes_ctx->subdir_id,strtol((argv[i]+11),NULL,16),BE); } else if(strcmp(argv[i],"-4") == 0 && i < argc-1){ u32_to_u8(aes_ctx->image_id,strtol(argv[i+1],NULL,16),BE); } else if(strncmp(argv[i],"--ImageID=",10) == 0){ u32_to_u8(aes_ctx->image_id,strtol((argv[i]+11),NULL,16),BE); } else if(strcmp(argv[i],"-5") == 0 || strcmp(argv[i],"--IsQuotaDat") == 0){ aes_ctx->is_quote_dat = 1; } } if(aes_ctx->is_quote_dat == 1){ memset(aes_ctx->image_id,0,4); memset(aes_ctx->subdir_id,0,4); } } //Extdata creation FILE *outfile = fopen(output,"wb"); if(outfile == NULL){ printf("[!] Failed to create '%s'\n",output); free(aes_ctx); return IO_ERROR; } FILE *infile = fopen(input,"rb"); if(infile == NULL){ printf("[!] Failed to open '%s'\n",input); free(aes_ctx); free(sourcedata.buffer); return IO_ERROR; } fclose(infile); sourcedata.size = GetFileSize_u64(input); sourcedata.buffer = malloc(sourcedata.size); if(sourcedata.buffer == NULL){ printf("[!] Failed to allocate memory to generate Extdata\n"); free(aes_ctx); return MEM_ERROR; } infile = fopen(input,"rb"); ReadFile_64(sourcedata.buffer,sourcedata.size,0,infile); fclose(infile); u8 result = CreateExtdata(&outdata,&sourcedata,type,activeDIFI,UniqueExtdataID); if(result){ free(aes_ctx); free(sourcedata.buffer); if(outdata.size > 0){ free(outdata.buffer); } return result; } if(GenMAC){ if(Verbose) printf("[+] Generating AES MAC\n"); memcpy(aes_ctx->header,(outdata.buffer+0x100),0x100); GenAESMAC(KeyX,KeyY,aes_ctx); memcpy(outdata.buffer,aes_ctx->aesmac,16); } if(Verbose) printf("[+] Writing '%s'\n",output); WriteBuffer(outdata.buffer,outdata.size,0,outfile); if(outdata.size > 0) free(outdata.buffer); if(sourcedata.size > 0)free(sourcedata.buffer); free(aes_ctx); fclose(outfile); } return 0; }