static void build_info_hdr(void) { // TODO: figure all those values out :-) u8 *p; memset(info_hdr, 0, sizeof info_hdr); p = info_hdr; wbe32(p + 0x00, 3); wbe32(p + 0x04, 1); wbe64(p + 0x08, 1); // package type wbe64(p + 0x10, version); wbe64(p + 0x18, pkg_real_size - 0x80); wbe64(p + 0x20, pkg_files_size); wbe64(p + 0x28, 0); // XXX: ??? wbe64(p + 0x30, 0); wbe64(p + 0x38, 0); p += 0x40; wbe64(p + 0x00, 3); wbe64(p + 0x08, 0x40); wbe64(p + 0x10, 0); wbe64(p + 0x18, pkg_real_size - 0x80); wbe64(p + 0x20, 0); wbe64(p + 0x28, 1); wbe64(p + 0x30, 0); wbe64(p + 0x38, 0); }
static void build_info_hdr(void) { u32 app_type; memset(info_header, 0, sizeof info_header); switch (type) { case KEY_LV0: app_type = 1; break; case KEY_LV1: app_type = 2; break; case KEY_LV2: app_type = 3; break; case KEY_APP: app_type = 4; break; case KEY_ISO: app_type = 5; break; case KEY_LDR: app_type = 6; break; default: fail("something that should never fail failed."); } wbe64(info_header + 0x00, auth_id); wbe32(info_header + 0x08, vendor_id); wbe32(info_header + 0x0c, app_type); wbe64(info_header + 0x10, version); // version 1.0.0 }
static void build_sec_hdr(void) { u32 i; u8 *ptr; sec_header_size = ehdr.e_phnum * 0x20; sec_header = malloc(sec_header_size); memset(sec_header, 0, sec_header_size); for (i = 0; i < ehdr.e_phnum; i++) { ptr = sec_header + i * 0x20; wbe64(ptr + 0x00, phdr[i].p_off + header_size); wbe64(ptr + 0x08, phdr[i].p_filesz); wbe32(ptr + 0x10, 1); // not compressed wbe32(ptr + 0x14, 0); // unknown wbe32(ptr + 0x18, 0); // unknown if (phdr[i].p_type == 1) wbe32(ptr + 0x1c, 1); // encrypted LOAD phdr else wbe32(ptr + 0x1c, 0); // no loadable phdr } }
static void build_pkg_hdr(void) { u8 *p; u32 i; pkg_hdr_size = 0x10 + n_files * 0x30; pkg_hdr = malloc(pkg_hdr_size); if (pkg_hdr == NULL) fail("out of memory"); memset(pkg_hdr, 0, pkg_hdr_size); p = pkg_hdr; wbe32(p + 0x00, 1); // magic wbe32(p + 0x04, n_files); wbe32(p + 0x08, pkg_hdr_size + pkg_size); p += 0x10; for (i = 0; i < n_files; i++) { wbe64(p + 0x00, files[i].offset + pkg_hdr_size); wbe64(p + 0x08, files[i].size); strncpy((char *)(p + 0x10), files[i].name, 0x20); p += 0x30; } }
static void build_hdr(void) { u8 *p; u32 i; u64 file_size; file_size = files[n_files - 1].offset + files[n_files - 1].size; hdr_size = 0x10 + n_files * 0x30; hdr = malloc(hdr_size); if (hdr == NULL) fail("out of memory"); memset(hdr, 0, hdr_size); p = hdr; wbe32(p + 0x00, 1); // magic wbe32(p + 0x04, n_files); wbe64(p + 0x08, hdr_size + file_size); p += 0x10; for (i = 0; i < n_files; i++) { wbe64(p + 0x00, files[i].offset + hdr_size); wbe64(p + 0x08, files[i].size); strncpy((char *)(p + 0x10), files[i].name, 0x20); p += 0x30; } }
void hmac_final(hmac_ctx *ctx, unsigned char *hmac) { int i; unsigned char hash[0x14]; SHA1Result(&ctx->hash_ctx); // this sha1 implementation is buggy, needs to switch endian for(i=0; i<5; ++i) { wbe32(hash + 4*i, ctx->hash_ctx.Message_Digest[i]); } for(i=0; i<0x40; ++i) ctx->key[i] ^= 0x36^0x5c; // opad SHA1Reset(&ctx->hash_ctx); SHA1Input(&ctx->hash_ctx,ctx->key,0x40); SHA1Input(&ctx->hash_ctx,hash,0x14); SHA1Result(&ctx->hash_ctx); for(i=0; i<5; ++i) { wbe32(hash + 4*i, ctx->hash_ctx.Message_Digest[i]); } memcpy(hmac, hash, 20); }
// func for building the SCE hdr (for SPP) int build_spp_sce_hdr(sce_header_t* pSceHdr, u64 ContentSizeOriginal) { sce_header_t* pSce_Header = NULL; int retval = -1; // validate input params if (pSceHdr == NULL) goto exit; // populate the SCE-HDR fields for PKG build pSce_Header = (sce_header_t*)pSceHdr; memset(pSceHdr, 0, sizeof(sce_header_t)); wbe32((u8*)&pSce_Header->magic, SCE_HEADER_MAGIC); // magic wbe32((u8*)&pSce_Header->version, SCE_HEADER_VERSION_2); // version wbe16((u8*)&pSce_Header->key_revision, KEY_REVISION_0); // key revision wbe16((u8*)&pSce_Header->header_type, SCE_HEADER_TYPE_SPP); // SCE header type; pkg wbe32((u8*)&pSce_Header->metadata_offset, 0); // meta offset wbe64((u8*)&pSce_Header->header_len, sizeof(sce_header_t) + sizeof(SPP_META_HDR)); // header len wbe64((u8*)&pSce_Header->data_len, ContentSizeOriginal); // status success retval = STATUS_SUCCESS; exit: return retval; }
static void build_ctrl_hdr(void) { memset(ctrl_header, 0, sizeof ctrl_header); wbe32(ctrl_header + 0x00, 1); // type: control flags wbe32(ctrl_header + 0x04, 0x30); // length // flags are all zero here wbe32(ctrl_header + 0x30, 2); // type: digest wbe32(ctrl_header + 0x34, 0x40); // length }
static void build_sce_hdr(void) { memset(sce_hdr, 0, sizeof sce_hdr); wbe32(sce_hdr + 0x00, 0x53434500); // magic wbe32(sce_hdr + 0x04, 2); // version wbe16(sce_hdr + 0x08, 0); // dunno, sdk type? wbe16(sce_hdr + 0x0a, 3); // SCE header type; pkg wbe32(sce_hdr + 0x0c, 0); // meta offset wbe64(sce_hdr + 0x10, sizeof sce_hdr + sizeof meta_hdr); wbe64(sce_hdr + 0x18, 0x80 + pkg_real_size); }
static void slot_checksum(u8 *x) { u32 i; u32 sum, nsum; sum = 0; for (i = 0; i < 0x0a8c; i++) sum += x[i]; nsum = -(sum + 0x0a8c); wbe32(x + 0x0a8c, sum); wbe32(x + 0x0a90, nsum); }
static void build_sce_hdr(void) { memset(sce_header, 0, sizeof sce_header); wbe32(sce_header + 0x00, 0x53434500); // magic wbe32(sce_header + 0x04, 2); // version wbe16(sce_header + 0x08, sdk_type); // dunno, sdk type? wbe16(sce_header + 0x0a, 1); // SCE header type; self wbe32(sce_header + 0x0c, meta_offset); wbe64(sce_header + 0x10, header_size); wbe64(sce_header + 0x18, round_up(elf_size, ALIGNMENT)); wbe64(sce_header + 0x20, 3); // dunno, has to be 3 wbe64(sce_header + 0x28, info_offset); wbe64(sce_header + 0x30, elf_offset); wbe64(sce_header + 0x38, phdr_offset); wbe64(sce_header + 0x40, shdr_offset); wbe64(sce_header + 0x48, sec_offset); wbe64(sce_header + 0x50, version_offset); wbe64(sce_header + 0x58, ctrl_offset); wbe64(sce_header + 0x60, 0x70); // ctrl size }
static void build_meta_hdr(void) { u32 i; u8 *ptr; meta_header_size = 0x80 + ehdr.e_phnum * (0x30 + 0x20 + 0x60) + 0x30; meta_header = malloc(meta_header_size); memset(meta_header, 0, meta_header_size); ptr = meta_header + 0x20; // aes keys for meta encryption get_rand(ptr, 0x10); get_rand(ptr + 0x20, 0x10); ptr += 0x40; // area covered by the signature wbe64(ptr + 0x00, meta_offset + meta_header_size - 0x30); wbe32(ptr + 0x08, 1); wbe32(ptr + 0x0c, ehdr.e_phnum); // number of encrypted headers wbe32(ptr + 0x10, ehdr.e_phnum * 8); // number of keys/hashes required wbe32(ptr + 0x14, meta_header_size / 0x10); ptr += 0x20; // add encrypted phdr information for (i = 0; i < ehdr.e_phnum; i++) { if (phdr[i].p_type == 1) meta_add_load(ptr, i); else meta_add_phdr(ptr, i); ptr += 0x30; } // add keys/ivs and hmac keys get_rand(ptr, ehdr.e_phnum * 8 * 0x10); }
static void meta_add_phdr(u8 *ptr, u32 i) { wbe64(ptr + 0x00, phdr[i].p_off + header_size); wbe64(ptr + 0x08, phdr[i].p_filesz); // unknown wbe32(ptr + 0x10, 2); wbe32(ptr + 0x14, i); // phdr index maybe? wbe32(ptr + 0x18, 2); wbe32(ptr + 0x1c, i*8); // sha index wbe32(ptr + 0x20, 1); // not encpryted wbe32(ptr + 0x24, 0xffffffff); // no key wbe32(ptr + 0x28, 0xffffffff); // no iv wbe32(ptr + 0x2c, 1); // not compressed }
static void meta_add_load(u8 *ptr, u32 i) { wbe64(ptr + 0x00, phdr[i].p_off + header_size); wbe64(ptr + 0x08, phdr[i].p_filesz); // unknown wbe32(ptr + 0x10, 2); wbe32(ptr + 0x14, i); // phdr index maybe? wbe32(ptr + 0x18, 2); wbe32(ptr + 0x1c, i*8); // sha index wbe32(ptr + 0x20, 3); // phdr is encrypted wbe32(ptr + 0x24, (i*8) + 6); // key index wbe32(ptr + 0x28, (i*8) + 7); // iv index wbe32(ptr + 0x2c, 1); // not compressed }
void fs_hmac_data(const unsigned char *data, int uid, const unsigned char *name, int entry_n, int x3, short blk, unsigned char *hmac) { int i,j; unsigned char extra[0x40]; memset(extra,0,0x40); wbe32(extra, uid); memcpy(extra+4,name,12); wbe16(extra + 0x12, blk); wbe32(extra + 0x14, entry_n); wbe32(extra + 0x18, x3); // fprintf(stderr,"extra (%s): \nX ",name); // for(i=0;i<0x20;++i){ // fprintf(stderr,"%02X ",extra[i]); // if(!((i+1)&0xf)) fprintf(stderr,"\nX "); // } fs_hmac_generic(data,0x4000,extra,0x40,hmac); }
static void meta_add_load(u8 *ptr, u32 i) { wbe64(ptr + 0x00, phdr_map[i].offset); wbe64(ptr + 0x08, phdr_map[i].size); // unknown wbe32(ptr + 0x10, 2); wbe32(ptr + 0x14, i); // phdr index maybe? wbe32(ptr + 0x18, 2); wbe32(ptr + 0x1c, i*8); // sha index wbe32(ptr + 0x20, 3); // phdr is encrypted wbe32(ptr + 0x24, (i*8) + 6); // key index wbe32(ptr + 0x28, (i*8) + 7); // iv index if (phdr_map[i].compressed == 1) wbe32(ptr + 0x2c, 2); else wbe32(ptr + 0x2c, 1); }
static void check_elf(void) { u8 bfr[0x48]; u64 elf_offset; u64 phdr_offset; u64 shdr_offset; u64 phdr_offset_new; u64 shdr_offset_new; u64 shstrtab_offset; u16 n_phdr; u16 n_shdr; const char shstrtab[] = ".unknown\0\0"; fseek(out, 0, SEEK_SET); fread(bfr, 4, 1, out); if (memcmp(bfr, "\7fELF", 4) == 0) return; elf_offset = be64(self + 0x30); phdr_offset = be64(self + 0x38) - elf_offset; shdr_offset = be64(self + 0x40) - elf_offset; if (arch64) { fseek(out, 0x48, SEEK_SET); phdr_offset_new = 0x48; fseek(out, 0, SEEK_END); shdr_offset_new = ftell(out); n_phdr = be16(elf + 0x38); n_shdr = be16(elf + 0x3c); shstrtab_offset = shdr_offset_new + n_shdr * 0x40; remove_shnames(shdr_offset, n_shdr, shstrtab_offset, sizeof shstrtab); fseek(out, phdr_offset_new, SEEK_SET); fwrite(elf + phdr_offset, 0x38, n_phdr, out); fseek(out, shdr_offset_new, SEEK_SET); fwrite(elf + shdr_offset, 0x40, n_shdr, out); wbe64(elf + 0x20, phdr_offset_new); wbe64(elf + 0x28, shdr_offset_new); fseek(out, SEEK_SET, 0); fwrite(elf, 0x48, 1, out); fseek(out, shstrtab_offset, SEEK_SET); fwrite(shstrtab, sizeof shstrtab, 1, out); } else { fseek(out, 0x34, SEEK_SET); phdr_offset_new = 0x34; fseek(out, 0, SEEK_END); shdr_offset_new = ftell(out); n_phdr = be16(elf + 0x2c); n_shdr = be16(elf + 0x30); shstrtab_offset = shdr_offset_new + n_shdr * 0x40; remove_shnames(shdr_offset, n_shdr, shstrtab_offset, sizeof shstrtab); fseek(out, phdr_offset_new, SEEK_SET); fwrite(elf + phdr_offset, 0x20, n_phdr, out); fseek(out, shdr_offset_new, SEEK_SET); fwrite(elf + shdr_offset, 0x28, n_shdr, out); wbe32(elf + 0x1c, phdr_offset_new); wbe32(elf + 0x20, shdr_offset_new); fseek(out, SEEK_SET, 0); fwrite(elf, 0x34, 1, out); fseek(out, shstrtab_offset, SEEK_SET); fwrite(shstrtab, sizeof shstrtab, 1, out); } }
static void build_meta_hdr(void) { u8 *ptr; memset(meta_hdr, 0, sizeof sce_hdr); ptr = meta_hdr; // keys for metadata encryptiomn get_rand(ptr, 0x10); get_rand(ptr + 0x20, 0x10); ptr += 0x40; // area covered by the signature wbe64(ptr + 0x00, sizeof sce_hdr + sizeof meta_hdr - 0x30); wbe32(ptr + 0x0c, 3); // number of encrypted headers wbe32(ptr + 0x10, 3 * 8); // number of keys/hashes required ptr += 0x20; // first info header wbe64(ptr + 0x00, 0x2c0); // offset wbe64(ptr + 0x08, 0x40); // size wbe32(ptr + 0x10, 1); // unknown wbe32(ptr + 0x14, 1); // index wbe32(ptr + 0x18, 2); // unknown again wbe32(ptr + 0x1c, 0); // sha index wbe32(ptr + 0x20, 1); // no encryption wbe32(ptr + 0x24, 0xffffffff); // key index wbe32(ptr + 0x28, 0xffffffff); // iv index wbe32(ptr + 0x2c, 0x1); // no compression ptr += 0x30; // second info header wbe64(ptr + 0x00, 0x300); // offset wbe64(ptr + 0x08, 0x40); // size wbe32(ptr + 0x10, 2); // unknown wbe32(ptr + 0x14, 2); // index wbe32(ptr + 0x18, 2); // unknown again wbe32(ptr + 0x1c, 8); // sha index wbe32(ptr + 0x20, 1); // no encryption wbe32(ptr + 0x24, 0xffffffff); // key index wbe32(ptr + 0x28, 0xffffffff); // iv index wbe32(ptr + 0x2c, 0x1); // no compression ptr += 0x30; // package files wbe64(ptr + 0x00, 0x340); // offset wbe64(ptr + 0x08, pkg_files_size); wbe32(ptr + 0x10, 3); // unknown wbe32(ptr + 0x14, 3); // index wbe32(ptr + 0x18, 2); // unknown again wbe32(ptr + 0x1c, 16); // sha index wbe32(ptr + 0x20, 3); // encrypted wbe32(ptr + 0x24, 22); // key index wbe32(ptr + 0x28, 23); // iv index wbe32(ptr + 0x2c, 2); // compressed ptr += 0x30; // add keys/ivs and hmac keys get_rand(ptr, 3 * 8 * 0x10); }
void elf_write_shdr(int arch64, u8 *shdr, struct elf_shdr *s) { if (arch64) { wbe32(shdr + 0*4, s->sh_name); wbe32(shdr + 1*4, s->sh_type); wbe64(shdr + 2*4, s->sh_flags); wbe64(shdr + 2*4 + 1*8, s->sh_addr); wbe64(shdr + 2*4 + 2*8, s->sh_offset); wbe64(shdr + 2*4 + 3*8, s->sh_size); wbe32(shdr + 2*4 + 4*8, s->sh_link); wbe32(shdr + 3*4 + 4*8, s->sh_info); wbe64(shdr + 4*4 + 4*8, s->sh_addralign); wbe64(shdr + 4*4 + 5*8, s->sh_entsize); } else { wbe32(shdr + 0*4, s->sh_name); wbe32(shdr + 1*4, s->sh_type); wbe32(shdr + 2*4, s->sh_flags); wbe32(shdr + 3*4, s->sh_addr); wbe32(shdr + 4*4, s->sh_offset); wbe32(shdr + 5*4, s->sh_size); wbe32(shdr + 6*4, s->sh_link); wbe32(shdr + 7*4, s->sh_info); wbe32(shdr + 8*4, s->sh_addralign); wbe32(shdr + 9*4, s->sh_entsize); } }
static void build_version_hdr(void) { memset(version_header, 0, sizeof version_header); wbe32(version_header, 1); wbe32(version_header + 0x08, 0x10); }
static void dol2elf(char *inname, char *outname) { u8 dolheader[0x100]; u8 elfheader[0x400] = {0}; u8 segheader[0x400] = {0}; u8 secheader[0x400] = {0}; u8 strings[0x400] = "\0.strtab"; u32 str_offset = 9; struct section section[19]; FILE *in, *out; u32 n_text, n_data, n_total; u32 entry; u32 elf_offset; u32 i; u8 *p; in = fopen(inname, "rb"); fread(dolheader, 1, sizeof dolheader, in); elf_offset = 0x1000; // 7 text, 11 data for (i = 0; i < 18; i++) { section[i].offset = be32(dolheader + 4*i); section[i].addr = be32(dolheader + 0x48 + 4*i); section[i].size = be32(dolheader + 0x90 + 4*i); section[i].elf_offset = elf_offset; elf_offset += -(-section[i].size & -0x100); } // bss section[18].offset = 0; section[18].addr = be32(dolheader + 0xd8); section[18].size = be32(dolheader + 0xdc); section[18].elf_offset = elf_offset; entry = be32(dolheader + 0xe0); n_text = 0; for (i = 0; i < 7; i++) if (section[i].size) { sprintf(strings + str_offset, ".text.%d", n_text); section[i].str_offset = str_offset; str_offset += 8; n_text++; } n_data = 0; for ( ; i < 18; i++) if (section[i].size) { sprintf(strings + str_offset, ".data.%d", n_data); section[i].str_offset = str_offset; str_offset += i < 16 ? 8 : 9; n_data++; } n_total = n_text + n_data; if (section[18].size) { sprintf(strings + str_offset, ".bss"); section[i].str_offset = str_offset; str_offset += 5; n_total++; } printf("%d text sections, %d data sections, %d total (includes bss)\n", n_text, n_data, n_total); printf("entry point = %08x\n", entry); memset(elfheader, 0, sizeof elfheader); elfheader[0] = 0x7f; elfheader[1] = 0x45; elfheader[2] = 0x4c; elfheader[3] = 0x46; elfheader[4] = 0x01; elfheader[5] = 0x02; elfheader[6] = 0x01; wbe16(elfheader + 0x10, 2); wbe16(elfheader + 0x12, 0x14); wbe32(elfheader + 0x14, 1); wbe32(elfheader + 0x18, entry); wbe32(elfheader + 0x1c, 0x400); wbe32(elfheader + 0x20, 0x800); wbe32(elfheader + 0x24, 0); wbe16(elfheader + 0x28, 0x34); wbe16(elfheader + 0x2a, 0x20); wbe16(elfheader + 0x2c, n_total); wbe16(elfheader + 0x2e, 0x28); wbe16(elfheader + 0x30, n_total + 2); wbe16(elfheader + 0x32, 1); p = segheader; for (i = 0; i < 19; i++) if (section[i].size) { wbe32(p + 0x00, 1); wbe32(p + 0x04, section[i].elf_offset); wbe32(p + 0x08, section[i].addr); wbe32(p + 0x0c, section[i].addr); wbe32(p + 0x10, i == 18 ? 0 : section[i].size); wbe32(p + 0x14, section[i].size); wbe32(p + 0x18, i < 7 ? 5 : 6); wbe32(p + 0x1c, 0x20); p += 0x20; } p = secheader + 0x28; wbe32(p + 0x00, 1); wbe32(p + 0x04, 3); wbe32(p + 0x08, 0); wbe32(p + 0x0c, 0); wbe32(p + 0x10, 0xc00); wbe32(p + 0x14, 0x400); wbe32(p + 0x18, 0); wbe32(p + 0x1c, 0); wbe32(p + 0x20, 1); wbe32(p + 0x24, 0); p += 0x28; for (i = 0; i < 19; i++) if (section[i].size) { wbe32(p + 0x00, section[i].str_offset); wbe32(p + 0x04, i == 18 ? 8 : 1); wbe32(p + 0x08, i < 7 ? 6 : 3); wbe32(p + 0x0c, section[i].addr); wbe32(p + 0x10, section[i].elf_offset); wbe32(p + 0x14, section[i].size); wbe32(p + 0x18, 0); wbe32(p + 0x1c, 0); wbe32(p + 0x20, 0x20); wbe32(p + 0x24, 0); p += 0x28; } out = fopen(outname, "wb"); fwrite(elfheader, 1, sizeof elfheader, out); fwrite(segheader, 1, sizeof segheader, out); fwrite(secheader, 1, sizeof secheader, out); fwrite(strings, 1, sizeof strings, out); for (i = 0; i < 19; i++) if (section[i].size) { p = malloc(section[i].size); fseek(in, section[i].offset, SEEK_SET); fread(p, 1, section[i].size, in); fseek(out, section[i].elf_offset, SEEK_SET); fwrite(p, 1, section[i].size, out); free(p); } fclose(out); fclose(in); }
void setup_context() { // setup stack pointer _ctx.reg[1][0] = 0x3FFD0; _ctx.reg[1][1] = 0x0; _ctx.reg[1][2] = 0x0; _ctx.reg[1][3] = 0x0; wbe32(_ctx.ls + 0x7060, 0x32000600); TextureBlobHeader* header = (TextureBlobHeader*)src_data; TextureBlobChunk* chunks = (TextureBlobChunk*)(header + 1); wbe32(_ctx.ls + 0x3BE40, be16((u8*)&header->type)); wbe32(_ctx.ls + 0x3BE44, be16((u8*)&header->quality)); wbe32(_ctx.ls + 0x3BE48, (u32)src_data + be32((u8*)&chunks[0].offset)); wbe32(_ctx.ls + 0x3BE4C, be32((u8*)&chunks[0].compressed_size)); wbe32(_ctx.ls + 0x3BE50, (u32)dst_data); wbe32(_ctx.ls + 0x3BE54, be32((u8*)&chunks[0].decompressed_size)); wbe32(_ctx.ls + 0x3BE58, be16((u8*)&chunks[0].num_batches)); wbe32(_ctx.ls + 0x3BE5C, be16((u8*)&header->width)); wbe32(_ctx.ls + 0x3BE60, be16((u8*)&header->height)); wbe32(_ctx.ls + 0x3BE64, be32((u8*)&header->unk_0x0C)); wbe32(_ctx.ls + 0x3BE68, be32((u8*)&header->unk_0x10)); wbe32(_ctx.ls + 0x3BE6C, be32((u8*)&header->unk_0x14)); wbe32(_ctx.ls + 0x3BE70, be32((u8*)&header->unk_0x18)); wbe32(_ctx.ls + 0x3BE74, be32((u8*)&header->unk_0x1C)); wbe32(_ctx.ls + 0x3BE78, be32((u8*)&header->unk_0x20)); wbe32(_ctx.ls + 0x3BE7C, 0); wbe32(_ctx.ls + 0x3BE80, 0); wbe32(_ctx.ls + 0x3BE84, 0); wbe32(_ctx.ls + 0x3BE8C, 0); }
// func for building the SPP_META_HDR int build_spp_meta_hdr(SPP_META_HDR* pMetaHdr, u64 ContentSizeOriginal) { u8 *ptr = NULL; metadata_info_t* pMetaDataInfoHeader = NULL; metadata_header_t* pMetaDataHeader = NULL; metadata_section_header_t* pMetaSectionHeader = NULL; int retval = -1; // validate input params if (pMetaHdr == NULL) goto exit; memset(pMetaHdr, 0, sizeof(SPP_META_HDR)); ptr = (u8*)pMetaHdr; pMetaDataInfoHeader = (metadata_info_t*)ptr; // setup the "metadata" random generated keys get_rand((u8*)&pMetaDataInfoHeader->key, sizeof(pMetaDataInfoHeader->key)); get_rand((u8*)&pMetaDataInfoHeader->iv, sizeof(pMetaDataInfoHeader->iv)); ptr += sizeof(metadata_info_t); // area covered by the signature pMetaDataHeader = (metadata_header_t*)ptr; wbe64((u8*)&pMetaDataHeader->sig_input_length, sizeof(sce_header_t) + sizeof(SPP_META_HDR) - sizeof(metadata_section_header_t )); wbe32((u8*)&pMetaDataHeader->unknown_0, 1); wbe32((u8*)&pMetaDataHeader->section_count, 2); // number of encrypted headers wbe32((u8*)&pMetaDataHeader->key_count, (2 * 8)); // number of keys/hashes required ++++++ ptr += sizeof(metadata_header_t); // (size 0x20) // first info header pMetaSectionHeader = (metadata_section_header_t*)ptr; wbe64((u8*)&pMetaSectionHeader->data_offset, 0x200); // offset //SIZE_SPP_HDR wbe64((u8*)&pMetaSectionHeader->data_size, 0x20); // size wbe32((u8*)&pMetaSectionHeader->type, METADATA_SECTION_TYPE_SHDR); // type wbe32((u8*)&pMetaSectionHeader->index, 1); // index wbe32((u8*)&pMetaSectionHeader->hashed, METADATA_SECTION_HASHED); // hashed wbe32((u8*)&pMetaSectionHeader->sha1_index, 0); // sha index wbe32((u8*)&pMetaSectionHeader->encrypted, METADATA_SECTION_NOT_ENCRYPTED);// no encryption wbe32((u8*)&pMetaSectionHeader->key_index, 0xffffffff); // key index wbe32((u8*)&pMetaSectionHeader->iv_index, 0xffffffff); // iv index wbe32((u8*)&pMetaSectionHeader->compressed, METADATA_SECTION_NOT_COMPRESSED);// no compression ptr += sizeof(metadata_section_header_t); // second info header pMetaSectionHeader = (metadata_section_header_t*)ptr; wbe64((u8*)&pMetaSectionHeader->data_offset, 0x220); // offset wbe64((u8*)&pMetaSectionHeader->data_size, ContentSizeOriginal - 0x20);// size wbe32((u8*)&pMetaSectionHeader->type, METADATA_SECTION_TYPE_PHDR); // type wbe32((u8*)&pMetaSectionHeader->index, 2); // index wbe32((u8*)&pMetaSectionHeader->hashed, METADATA_SECTION_HASHED); // hashed wbe32((u8*)&pMetaSectionHeader->sha1_index, 8); // sha index wbe32((u8*)&pMetaSectionHeader->encrypted, METADATA_SECTION_ENCRYPTED);// no encryption wbe32((u8*)&pMetaSectionHeader->key_index, 0); // key index wbe32((u8*)&pMetaSectionHeader->iv_index, 1); // iv index wbe32((u8*)&pMetaSectionHeader->compressed, METADATA_SECTION_NOT_COMPRESSED);// no compression ptr += sizeof(metadata_section_header_t); // add keys/ivs and hmac keys get_rand(ptr, 2 * 8 * 0x10); // status success retval = STATUS_SUCCESS; exit: return retval; }
int main(int argc, char *argv[]) { u32 done; memset(&_ctx, 0x00, sizeof _ctx); ctx = &_ctx; parse_args(argc, argv); #if 0 u64 local_ptr; local_ptr = 0xdead0000dead0000ULL; ctx->reg[3][0] = (u32)(local_ptr >> 32); ctx->reg[3][1] = (u32)local_ptr; ctx->reg[4][0] = 0xdead0000; ctx->reg[4][1] = 0xdead0000; #endif ctx->ls = (u8*)malloc(LS_SIZE); if (ctx->ls == NULL) fail("Unable to allocate local storage."); memset(ctx->ls, 0, LS_SIZE); #if 0 wbe64(ctx->ls + 0x3f000, 0x100000000ULL); wbe32(ctx->ls + 0x3f008, 0x10000); wbe32(ctx->ls + 0x3e000, 0xff); #endif if (gdb_port < 0) { ctx->paused = 0; } else { gdb_init(gdb_port); ctx->paused = 1; gdb_signal(SIGABRT); } elf_load(elf_path); setup_context(); done = 0; while(done == 0) { if (ctx->paused == 0 || ctx->paused == 2) done = emulate(); // data watchpoints if (done == 2) { ctx->paused = 0; gdb_signal(SIGTRAP); done = 0; } if (done != 0) { printf("emulated() returned, sending SIGSEGV to gdb stub\n"); ctx->paused = 1; done = gdb_signal(SIGSEGV); } if (done != 0) { #ifdef STOP_DUMP_REGS dump_regs(); #endif #ifdef STOP_DUMP_LS dump_ls(); #endif } //if (ctx->paused == 1) gdb_handle_events(); } printf("emulate() returned. we're done!\n"); dump_ls(); free(ctx->ls); gdb_deinit(); return 0; }