int sce_decrypt_header(u8 *ptr, struct keylist *klist) { u32 meta_offset; u32 meta_len; u64 header_len; u32 i, j; u8 tmp[0x40]; int success = 0; meta_offset = be32(ptr + 0x0c); header_len = be64(ptr + 0x10); for (i = 0; i < klist->n; i++) { aes256cbc(klist->keys[i].key, klist->keys[i].iv, ptr + meta_offset + 0x20, 0x40, tmp); success = 1; for (j = 0x10; j < (0x10 + 0x10); j++) if (tmp[j] != 0) success = 0; for (j = 0x30; j < (0x30 + 0x10); j++) if (tmp[j] != 0) success = 0; if (success == 1) { memcpy(ptr + meta_offset + 0x20, tmp, 0x40); break; } } if (success != 1) return -1; printf(" Metadata key id: %s\n", klist->keys[i].id); memcpy(tmp, ptr + meta_offset + 0x40, 0x10); aes128ctr(ptr + meta_offset + 0x20, tmp, ptr + meta_offset + 0x60, 0x20, ptr + meta_offset + 0x60); meta_len = header_len - meta_offset; aes128ctr(ptr + meta_offset + 0x20, tmp, ptr + meta_offset + 0x80, meta_len - 0x80, ptr + meta_offset + 0x80); return i; }
static int decrypt_metadata(uint8_t *metadata, uint32_t metadata_size, struct keylist *klist) { uint32_t i; METADATA_INFO metadata_info; uint8_t zero[16] = {0}; for (i = 0; i < klist->n; i++) { aes256cbc(klist->keys[i].key, klist->keys[i].iv, metadata, sizeof(METADATA_INFO), (uint8_t *) &metadata_info); if (memcmp (metadata_info.key_pad, zero, 16) == 0 && memcmp (metadata_info.iv_pad, zero, 16) == 0) { memcpy(metadata, &metadata_info, sizeof(METADATA_INFO)); break; } } if (i >= klist->n) return -1; aes128ctr(metadata_info.key, metadata_info.iv, metadata + sizeof(METADATA_INFO), metadata_size - sizeof(METADATA_INFO), metadata + sizeof(METADATA_INFO)); return i; }
int sce_encrypt_header(u8 *ptr, struct key *k) { u32 meta_offset; u32 meta_len; u64 header_len; u8 iv[16]; meta_offset = be32(ptr + 0x0c); header_len = be64(ptr + 0x10); meta_len = header_len - meta_offset; memcpy(iv, ptr + meta_offset + 0x40, 0x10); aes128ctr(ptr + meta_offset + 0x20, iv, ptr + meta_offset + 0x60, meta_len - 0x60, ptr + meta_offset + 0x60); aes256cbc_enc(k->key, k->iv, ptr + meta_offset + 0x20, 0x40, ptr + meta_offset + 0x20); return 0; }
static void paged_file_crypt_internal_decrypt (PagedFile *f) { if (f->size - f->pos > 0) { if (f->crypt == PAGED_FILE_CRYPT_AES_128_CBC) { u8 iv[0x10]; memcpy (iv, f->iv, 0x10); if ((f->size - f->pos) >= 0x10) memcpy (f->iv, f->ptr + f->size - 0x10, 0x10); aes128cbc (f->key, iv, f->ptr + f->pos, f->size - f->pos, f->ptr + f->pos); } else if (f->crypt == PAGED_FILE_CRYPT_AES_256_CBC) { u8 iv[0x10]; memcpy (iv, f->iv, 0x10); if ((f->size - f->pos) >= 0x10) memcpy (f->iv, f->ptr + f->size - 0x10, 0x10); aes256cbc (f->key, iv, f->ptr + f->pos, f->size - f->pos, f->ptr + f->pos); } else if (f->crypt == PAGED_FILE_CRYPT_AES_128_CTR) { aes128ctr (f->key, f->iv, f->ptr + f->pos, f->size - f->pos, f->ptr + f->pos); } else if (f->crypt == PAGED_FILE_CRYPT_CUSTOM) { f->crypt_cb (f, PAGED_FILE_CRYPT_DECRYPT, f->ptr + f->pos, f->size - f->pos, f->crypt_cb_data); } } }
static void decrypt_retail_pkg(void) { u8 key[0x10]; u8 iv[0x10]; if (be16(pkg + 0x06) != 1) fail("invalid pkg type: %x", be16(pkg + 0x06)); if (key_get_simple("gpkg-key", key, 0x10) < 0) fail("failed to load the package key."); memcpy(iv, pkg + 0x70, 0x10); aes128ctr(key, iv, pkg + offset, size, pkg + offset); }
static void paged_file_crypt_internal_encrypt (PagedFile *f) { if (f->size > 0) { if (f->crypt == PAGED_FILE_CRYPT_AES_128_CBC) { aes128cbc_enc (f->key, f->iv, f->ptr, f->size, f->ptr); if (f->size >= 0x10) memcpy (f->iv, f->ptr + f->size - 0x10, 0x10); } else if (f->crypt == PAGED_FILE_CRYPT_AES_256_CBC) { aes256cbc_enc (f->key, f->iv, f->ptr, f->size, f->ptr); if (f->size >= 0x10) memcpy (f->iv, f->ptr + f->size - 0x10, 0x10); } else if (f->crypt == PAGED_FILE_CRYPT_AES_128_CTR) { aes128ctr (f->key, f->iv, f->ptr, f->size, f->ptr); } else if (f->crypt == PAGED_FILE_CRYPT_CUSTOM) { f->crypt_cb (f, PAGED_FILE_CRYPT_ENCRYPT, f->ptr, f->size, f->crypt_cb_data); } } }
int sce_decrypt_data(u8 *ptr) { u64 meta_offset; u32 meta_len; u32 meta_n_hdr; u64 header_len; u32 i; u64 offset; u64 size; u32 keyid; u32 ivid; u8 *tmp; u8 iv[16]; meta_offset = be32(ptr + 0x0c); header_len = be64(ptr + 0x10); meta_len = header_len - meta_offset; meta_n_hdr = be32(ptr + meta_offset + 0x60 + 0xc); for (i = 0; i < meta_n_hdr; i++) { tmp = ptr + meta_offset + 0x80 + 0x30*i; offset = be64(tmp); size = be64(tmp + 8); keyid = be32(tmp + 0x24); ivid = be32(tmp + 0x28); if (keyid == 0xffffffff || ivid == 0xffffffff) continue; memcpy(iv, ptr + meta_offset + 0x80 + 0x30 * meta_n_hdr + ivid * 0x10, 0x10); aes128ctr(ptr + meta_offset + 0x80 + 0x30 * meta_n_hdr + keyid * 0x10, iv, ptr + offset, size, ptr + offset); } return 0; }
int main(int argc, char* argv[]) { int i; u8 ecount_buf[0x10], iv[0x10]; size_t countp; int num; if(argc < 4) { printf("usage: %s input.elf output.self keytype keysuffix\n", argv[0]); return -1; } Elf64_Ehdr input_elf_header; FILE *input_elf_file = fopen(argv[1], "rb"); fseek(input_elf_file, 0, SEEK_END); int nlen = ftell(input_elf_file); fseek(input_elf_file, 0, SEEK_SET); input_elf_data = (u8*)malloc(nlen); fread(input_elf_data, 1, nlen, input_elf_file); fclose(input_elf_file); memcpy(&input_elf_header, input_elf_data, sizeof(input_elf_header)); FILE *output_self_file = fopen(argv[2], "wb"); printf("ELF header size @ %x\n", get_u16(&(input_elf_header.e_ehsize)) ); printf("%d program headers @ %64llX\n", get_u16(&(input_elf_header.e_phnum)), get_u64(&(input_elf_header.e_phoff))); printf("%d section headers @ %64llX\n", get_u16(&(input_elf_header.e_shnum)), get_u64(&(input_elf_header.e_shoff))); Self_Shdr output_self_header; memset(&output_self_header, 0, sizeof(output_self_header)); Self_Ehdr output_extended_self_header; memset(&output_extended_self_header, 0, sizeof(output_extended_self_header)); Self_Ihdr output_self_info_header; memset(&output_self_info_header, 0, sizeof(output_self_info_header)); set_u32(&(output_self_header.s_magic), 0x53434500); set_u32(&(output_self_header.s_hdrversion), 2); set_u16(&(output_self_header.s_flags), 1); set_u16(&(output_self_header.s_hdrtype), 1); // header size and file size aren't known yet set_u64(&(output_extended_self_header.e_magic), 3); set_u64(&(output_extended_self_header.e_ihoff), sizeof(Self_Shdr)+sizeof(Self_Ehdr)); set_u64(&(output_extended_self_header.e_ehoff), sizeof(Self_Shdr)+sizeof(Self_Ehdr)+sizeof(Self_Ihdr)); set_u64(&(output_extended_self_header.e_phoff), sizeof(Self_Shdr)+sizeof(Self_Ehdr)+sizeof(Self_Ihdr)+get_u64(&(input_elf_header.e_phoff))); // section header offset unknown set_u64(&(output_self_info_header.i_authid), 0x1070000500000001LL); set_u32(&(output_self_info_header.i_magic), 0x01000002); set_u32(&(output_self_info_header.i_apptype), 4); set_u64(&(output_self_info_header.i_version), 0x0003000000000000LL); // set static data int phnum = get_u16(&(input_elf_header.e_phnum)); u32 phsize = (sizeof(Elf64_Phdr)*get_u16(&(input_elf_header.e_phnum))); Self_SDKversion sdkversion; Self_Cflags cflags; memcpy(&sdkversion, sdkversion_static, sizeof(Self_SDKversion)); memcpy(&cflags, cflags_static, sizeof(Self_Cflags)); int running_size = (sizeof(output_self_header)+sizeof(output_extended_self_header)+sizeof(output_self_info_header)+sizeof(input_elf_header)+phsize+0xF)&0xFFFFFFF0; set_u64(&(output_extended_self_header.e_pmoff), running_size); running_size += phnum*sizeof(Self_PMhdr); set_u64(&(output_extended_self_header.e_svoff), running_size); running_size += sizeof(Self_SDKversion); set_u64(&(output_extended_self_header.e_cfoff), running_size); running_size += sizeof(Self_Cflags); set_u64(&(output_extended_self_header.e_cfsize), sizeof(Self_Cflags)); set_u32(&(output_self_header.s_esize), running_size - sizeof(output_self_header)); printf("running size is %X\n", running_size); int maxsection = 6; running_size += sizeof(metadata_crypt_header)+sizeof(segment_certification_header)+maxsection*(sizeof(segment_certification_segment)+sizeof(segment_certification_crypt_encrypted))+sizeof(segment_certification_sign)+sizeof(nubpadding_static); printf("running size is %X\n", running_size); set_u64(&(output_self_header.s_shsize), running_size); // init randomness gmp_randstate_t r_state; gmp_randinit_default(r_state); gmp_randseed_ui(r_state, time(NULL)); // loop through the sections segment_certification_header segment_header; memset(&segment_header, 0, sizeof(segment_header)); Self_Section first_section; Self_Section* section_ptr = &first_section; set_u64(&(segment_header.signature_offset), running_size-sizeof(segment_certification_sign)); set_u32(&(segment_header.unknown1), 1); set_u32(&(segment_header.segment_count), phnum); set_u32(&(segment_header.crypt_len), (phnum*sizeof(segment_certification_crypt_encrypted))/0x10); Elf64_Phdr* elf_segment = (Elf64_Phdr*)(&input_elf_data[get_u64(&(input_elf_header.e_phoff))]); for(i=0;i<phnum;i++) { memset(section_ptr, 0, sizeof(Self_Section)); //set_u64(&(section_ptr->enc_segment.segment_offset), get_u64(&(elf_segment->p_vaddr))); set_u64(&(section_ptr->enc_segment.segment_offset), running_size); set_u64(&(section_ptr->enc_segment.segment_size), get_u64(&(elf_segment->p_filesz))); set_u32(&(section_ptr->enc_segment.segment_crypt_flag), 2); set_u32(&(section_ptr->enc_segment.segment_sha1_index), i*8); set_u32(&(section_ptr->enc_segment.segment_erk_index), i*8+6); set_u32(&(section_ptr->enc_segment.segment_riv_index), i*8+7); set_u32(&(section_ptr->enc_segment.segment_number), i); set_u32(&(section_ptr->enc_segment.unknown2), 2); set_u32(&(section_ptr->enc_segment.unknown3), 3); set_u32(&(section_ptr->enc_segment.unknown4), 2); set_u64(&(section_ptr->pmhdr.pm_offset), running_size); set_u64(&(section_ptr->pmhdr.pm_size), get_u64(&(elf_segment->p_filesz))); set_u32(&(section_ptr->pmhdr.pm_compressed), 1); set_u32(&(section_ptr->pmhdr.pm_encrypted), 1); mpz_t riv, erk, hmac; mpz_init(riv); mpz_init(erk); mpz_init(hmac); mpz_urandomb(erk, r_state, 128); mpz_urandomb(riv, r_state, 128); mpz_urandomb(hmac, r_state, 512); mpz_export(section_ptr->crypt_segment.erk, &countp, 1, 0x10, 1, 0, erk); mpz_export(section_ptr->crypt_segment.riv, &countp, 1, 0x10, 1, 0, riv); mpz_export(section_ptr->crypt_segment.hmac, &countp, 1, 0x40, 1, 0, hmac); section_ptr->rlen = get_u64(&(elf_segment->p_filesz)); section_ptr->len = ((section_ptr->rlen)+0xF)&0xFFFFFFF0; section_ptr->data = (u8*)malloc(section_ptr->len); u32 in_data_offset = get_u64(&(elf_segment->p_offset)); // + get_u16(&(input_elf_header.e_ehsize)) + (sizeof(Elf64_Phdr)*get_u16(&(input_elf_header.e_phnum))); u8* in_data = &input_elf_data[in_data_offset]; printf("processing segment %d with len %x offset %x\n", i, section_ptr->len, in_data_offset); //hexdump((u8*)elf_segment, sizeof(Elf64_Phdr)); /*SHA_CTX c; SHA1_ghetto_init(&c, section_ptr->crypt_segment.hmac); SHA1_Update(&c, in_data, section_ptr->rlen); SHA1_ghetto_final(section_ptr->crypt_segment.sha1, &c, section_ptr->crypt_segment.hmac);*/ sha1_hmac(section_ptr->crypt_segment.hmac, in_data, section_ptr->rlen, section_ptr->crypt_segment.sha1); memset(ecount_buf, 0, 16); num=0; AES_set_encrypt_key(section_ptr->crypt_segment.erk, 128, &aes_key); memcpy(iv, section_ptr->crypt_segment.riv, 16); #ifdef NO_CRYPT memcpy(section_ptr->data, in_data, section_ptr->len); #else //AES_ctr128_encrypt(in_data, section_ptr->data, section_ptr->len, &aes_key, iv, ecount_buf, &num); aes128ctr((u8*)&aes_key, iv, in_data, section_ptr->len, section_ptr->data); #endif running_size += section_ptr->len; // next if(i != phnum-1) { section_ptr->next_section = malloc(sizeof(Self_Section)); } elf_segment += 1; // 1 is sizeof(Elf64_Phdr) section_ptr = section_ptr->next_section; } printf("segment processing done\n"); // section table offset set_u64(&(output_extended_self_header.e_shoff), running_size); // lay out the metadata u8 metadata[0x2000]; memset(metadata, 0, 0x2000); u32 metadata_len = 0; memcpy(&metadata[metadata_len], &output_self_header, sizeof(output_self_header)); metadata_len += sizeof(output_self_header); memcpy(&metadata[metadata_len], &output_extended_self_header, sizeof(output_extended_self_header)); metadata_len += sizeof(output_extended_self_header); memcpy(&metadata[metadata_len], &output_self_info_header, sizeof(output_self_info_header)); metadata_len += sizeof(output_self_info_header); memcpy(&metadata[metadata_len], &input_elf_header, sizeof(input_elf_header)); metadata_len += sizeof(input_elf_header); memcpy(&metadata[metadata_len], &input_elf_data[get_u64(&(input_elf_header.e_phoff))], phsize); metadata_len += phsize; metadata_len = (metadata_len+0xF)&0xFFFFFFF0; section_ptr = &first_section; while(section_ptr != NULL) { memcpy(&metadata[metadata_len], &(section_ptr->pmhdr), sizeof(section_ptr->pmhdr)); metadata_len += sizeof(section_ptr->pmhdr); section_ptr = section_ptr->next_section; } memcpy(&metadata[metadata_len], &sdkversion, sizeof(sdkversion)); metadata_len += sizeof(sdkversion); memcpy(&metadata[metadata_len], &cflags, sizeof(cflags)); metadata_len += sizeof(cflags); printf("top half of metadata ready\n"); // generate metadata encryption keys mpz_t bigriv, bigerk; mpz_init(bigriv); mpz_init(bigerk); mpz_urandomb(bigerk, r_state, 128); mpz_urandomb(bigriv, r_state, 128); metadata_crypt_header md_header; mpz_export(md_header.erk, &countp, 1, 0x10, 1, 0, bigerk); mpz_export(md_header.riv, &countp, 1, 0x10, 1, 0, bigriv); memcpy(&metadata[metadata_len], &md_header, sizeof(md_header)); metadata_len += sizeof(md_header); memcpy(&metadata[metadata_len], &segment_header, sizeof(segment_header)); metadata_len += sizeof(segment_header); // copy section data int csection; csection = 0; section_ptr = &first_section; while(section_ptr != NULL) { memcpy(&metadata[metadata_len], &(section_ptr->enc_segment), sizeof(section_ptr->enc_segment)); metadata_len += sizeof(section_ptr->enc_segment); section_ptr = section_ptr->next_section; if((++csection) == maxsection) break; } csection = 0; section_ptr = &first_section; while(section_ptr != NULL) { memcpy(&metadata[metadata_len], &(section_ptr->crypt_segment), sizeof(section_ptr->crypt_segment)); metadata_len += sizeof(section_ptr->crypt_segment); section_ptr = section_ptr->next_section; if((++csection) == maxsection) break; } // nubpadding time memcpy(&metadata[metadata_len], nubpadding_static, sizeof(nubpadding_static)); metadata_len += sizeof(nubpadding_static); // sign shit u8 digest[0x14]; sha1(metadata, metadata_len, digest); printf("metadata len is %X\n", metadata_len); //hexdump(metadata, metadata_len); //hexdump_nl(digest, 0x14); segment_certification_sign all_signed; memset(&all_signed, 0, sizeof(all_signed)); #ifdef GEOHOT_SIGN mpz_t n,k,da,kinv,r,cs,z; mpz_init(n); mpz_init(k); mpz_init(da); mpz_init(r); mpz_init(cs); mpz_init(z); mpz_init(kinv); mpz_import(r, 0x14, 1, 1, 0, 0, appold_R); mpz_import(n, 0x14, 1, 1, 0, 0, appold_n); mpz_import(k, 0x14, 1, 1, 0, 0, appold_K); mpz_import(da, 0x14, 1, 1, 0, 0, appold_Da); mpz_invert(kinv, k, n); mpz_import(z, 0x14, 1, 1, 0, 0, digest); mpz_mul(cs, r, da); mpz_mod(cs, cs, n); mpz_add(cs, cs, z); mpz_mod(cs, cs, n); mpz_mul(cs, cs, kinv); mpz_mod(cs, cs, n); mpz_export(all_signed.R, &countp, 1, 0x14, 1, 0, r); mpz_export(all_signed.S, &countp, 1, 0x14, 1, 0, cs); #else get_keys(argv[3], argv[4]); //ecdsa_set_curve(appnew_ctype); //ecdsa_set_pub(appnew_pub); //ecdsa_set_priv(appnew_priv); //ecdsa_sign(digest, all_signed.R, all_signed.S); #endif memcpy(&metadata[metadata_len], &all_signed, sizeof(all_signed)); metadata_len += sizeof(all_signed); // encrypt metadata int metadata_offset = get_u32(&(output_self_header.s_esize)) + sizeof(Self_Shdr); #ifndef NO_CRYPT /*memset(ecount_buf, 0, 16); num=0; AES_set_encrypt_key(&metadata[metadata_offset], 128, &aes_key); memcpy(iv, &metadata[metadata_offset+0x20], 16); //AES_ctr128_encrypt(&metadata[0x40+metadata_offset], &metadata[0x40+metadata_offset], metadata_len-metadata_offset-0x40, &aes_key, iv, ecount_buf, &num); aes128ctr(&metadata[0x20+metadata_offset], &metadata[0x40+metadata_offset], &metadata[0x60+metadata_offset], metadata_len-metadata_offset-0x60, &metadata[0x60+metadata_offset]); printf("encrypted metadata\n"); //AES_set_encrypt_key(appold_erk, 256, &aes_key); //memcpy(iv, appold_riv, 16); AES_set_encrypt_key(appnew_erk, 256, &aes_key); memcpy(iv, appnew_riv, 16); //AES_cbc_encrypt(&metadata[metadata_offset], &metadata[metadata_offset], 0x40, &aes_key, iv, AES_ENCRYPT); aes256cbc_enc(appnew_erk, appnew_riv, &metadata[metadata_offset], 0x40, &metadata[metadata_offset]); printf("encrypted keys\n");*/ //k.key = appnew_erk; //k.iv = appnew_riv; sce_encrypt_header(metadata, &ks); #endif // write the output self fwrite(metadata, 1, metadata_len, output_self_file); csection = 0; section_ptr = &first_section; while(section_ptr != 0) { printf("writing section with size %X\n", section_ptr->len); fwrite(section_ptr->data, 1, section_ptr->len, output_self_file); section_ptr = section_ptr->next_section; if((++csection) == maxsection) break; } fwrite(&input_elf_data[get_u64(&(input_elf_header.e_shoff))], sizeof(Elf64_Shdr), get_u16(&(input_elf_header.e_shnum)), output_self_file); fclose(output_self_file); }
int self_load_sections (FILE *in, SELF *self, ELF *elf, ELF_PHDR **phdr, METADATA_HEADER *metadata_header, METADATA_SECTION_HEADER **section_headers, uint8_t **keys, SELF_SECTION **sections) { uint32_t num_sections; uint32_t i; uint64_t size; uint32_t elf_size; METADATA_SECTION_HEADER *hdr; uint8_t *temp_data; size = 0; num_sections = metadata_header->section_count + 1; *sections = malloc (sizeof(SELF_SECTION) * num_sections); // ELF header for (i = 0; i < num_sections; i++) { if (i == 0) { hdr = (*section_headers); elf_size = elf->header_size + (elf->phent_size * elf->phnum); size = hdr->data_offset - self->header_len; if (size < elf_size) size = elf_size; (*sections)[i].offset = 0; (*sections)[i].size = size; (*sections)[i].data = malloc (size); fseek (in, self->header_len, SEEK_SET); if (fread ((*sections)[0].data, 1, size, in) != size) { ERROR (-6, "Couldn't read section header"); } fseek (in, self->elf_offset, SEEK_SET); if (fread ((*sections)[0].data, 1, size, in) != size) { ERROR (-6, "Couldn't read section elf"); } } else { hdr = (*section_headers) + i - 1; if (hdr->type == 2) { // phdr size = (*phdr)[hdr->program_idx].segment_size; (*sections)[i].offset = (*phdr)[hdr->program_idx].offset_in_file; } else if (hdr->type == 1) { // shdr size = (*section_headers)[i-1].data_size; (*sections)[i].offset = elf->shdr_offset; } else { (*sections)[i].offset = UINT64_MAX; printf("Section %d unkown type: %d. Skipping!\n", i, hdr->type); } (*sections)[i].size = size; (*sections)[i].data = malloc (size); temp_data = malloc (hdr->data_size); fseek (in, hdr->data_offset, SEEK_SET); if (fread (temp_data, 1, hdr->data_size, in) != hdr->data_size) { ERROR (-6, "Couldn't read section"); } // if (hdr->encrypted == 3 && self->flags != 0x8000) if (hdr->encrypted == 3) aes128ctr(*keys + 0x10 * hdr->key_idx, *keys + 0x10 * hdr->iv_idx, temp_data, hdr->data_size, temp_data); if (hdr->compressed == 2) decompress(temp_data, hdr->data_size, (*sections)[i].data, size); else memcpy ((*sections)[i].data, temp_data, size); free (temp_data); } } return num_sections; }
int sce_decrypt_header(u8 *ptr, struct keylist *klist) { u32 meta_offset; u32 meta_len; u64 header_len; u32 i, j, k; u8 tmp[0x40]; int success = 0; meta_offset = be32(ptr + 0x0c); header_len = be64(ptr + 0x10); unsigned char *erkptr; unsigned char *rivptr; for (i = 0; i < klist->n; i++) { erkptr = (unsigned char *)&klist->keys[i].key; rivptr = (unsigned char *)&klist->keys[i].iv; printf(" ERK: "); for(k=0;k<32;k++){ printf("\\x"); printf("%2.2X", *erkptr++); } printf(" RIV: "); for(k=0;k<16;k++){ printf("\\x"); printf("%2.2X", *rivptr++); } printf(" ID: %u " ,i); aes256cbc(klist->keys[i].key, klist->keys[i].iv, ptr + meta_offset + 0x20, 0x40, tmp); success = 1; for (j = 0x10; j < (0x10 + 0x10); j++) if (tmp[j] != 0) success = 0; for (j = 0x30; j < (0x30 + 0x10); j++) if (tmp[j] != 0) success = 0; if (success == 1) { memcpy(ptr + meta_offset + 0x20, tmp, 0x40); printf("...Yep!\n"); break; } if (success == 0) printf("..Nope\n"); else printf("\n"); } if (success != 1) return -1; memcpy(tmp, ptr + meta_offset + 0x40, 0x10); aes128ctr(ptr + meta_offset + 0x20, tmp, ptr + meta_offset + 0x60, 0x20, ptr + meta_offset + 0x60); meta_len = header_len - meta_offset; aes128ctr(ptr + meta_offset + 0x20, tmp, ptr + meta_offset + 0x80, meta_len - 0x80, ptr + meta_offset + 0x80); return i; }