static void build_header(void) { u32 i; memset(hdr, 0, sizeof hdr); memcpy(hdr, "SCEUF\0\0\0", 8); wbe64(hdr + 0x08, 1); wbe64(hdr + 0x10, 0xf411); wbe64(hdr + 0x18, n_files); wbe64(hdr + 0x20, 0x50 + n_files * 0x40); wbe64(hdr + 0x28, data_size); for (i = 0; i < n_files; i++) { wbe64(hdr + 0x30 + 0x20 * i + 0x00, files[i].id); wbe64(hdr + 0x30 + 0x20 * i + 0x08, files[i].offset); wbe64(hdr + 0x30 + 0x20 * i + 0x10, files[i].len); wbe64(hdr + 0x30 + 0x20 * i + 0x18, 0); wbe64(hdr + 0x30 + 0x20 * n_files + 0x20 * i, i); calc_hmac(files[i].ptr, files[i].len, hdr + 0x30 + 0x20 * n_files + 0x20 * i + 0x08); } calc_hmac(hdr, 0x30 + 0x40 * n_files, hdr + 0x30 + 0x40 * n_files); }
void aes128ctr(u8 *key, u8 *iv, u8 *in, u64 len, u8 *out) { AES_KEY k; u32 i; u8 ctr[16]; u64 tmp; memset(ctr, 0, 16); memset(&k, 0, sizeof k); AES_set_encrypt_key(key, 128, &k); for (i = 0; i < len; i++) { if ((i & 0xf) == 0) { AES_encrypt(iv, ctr, &k); // increase nonce tmp = be64(iv + 8) + 1; wbe64(iv + 8, tmp); if (tmp == 0) wbe64(iv, be64(iv) + 1); } *out++ = *in++ ^ ctr[i & 0x0f]; } }
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_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_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; } }
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; } }
// 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_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); }
int paged_file_seek (PagedFile *f, u64 offset) { u32 pos; if (!f->reader) return -1; pos = offset % 0x10; offset &= ~0xF; if (offset + pos > f->page_pos && offset + pos < f->page_pos + f->size) { f->pos = offset + pos - f->page_pos; return f->page_pos + f->pos; } if (f->crypt != PAGED_FILE_CRYPT_NONE) { /* TODO: support other crypto */ if (f->crypt == PAGED_FILE_CRYPT_AES_128_CBC || f->crypt == PAGED_FILE_CRYPT_AES_256_CBC) { if (offset >= 0x10) { fseek (f->fd, offset - 0x10, SEEK_SET); if (fread (f->iv, 1, 0x10, f->fd) != 1) return -1; } } else if (f->crypt == PAGED_FILE_CRYPT_AES_128_CTR) { s64 seek_diff = (signed) (offset - (f->page_pos + f->size)) / 0x10; u64 tmp = be64(f->iv + 8) + seek_diff; if (seek_diff > 0 && tmp < be64 (f->iv + 8)) wbe64(f->iv, be64(f->iv) + 1); else if (seek_diff < 0 && tmp > be64 (f->iv + 8)) wbe64(f->iv, be64(f->iv) - 1); wbe64(f->iv + 8, tmp); } else if (f->crypt == PAGED_FILE_CRYPT_CUSTOM) { if (!f->crypt_cb (f, PAGED_FILE_CRYPT_SEEK, NULL, offset, f->crypt_cb_data)) return -1; } } fseek (f->fd, offset, SEEK_SET); f->size = 0; f->page_pos = ftell (f->fd); paged_file_read_new_page (f); f->pos = pos; return f->page_pos; }
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 }
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); }
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); }
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); } }
// main function to do the spkg decrypt/unpackage int do_spp_decrypt(char* pInPath, char* pOutPath, char* pKeyName) { u8* pMySpp = NULL; u64 dec_size = 0; u64 hdr_len = 0; uint32_t dwBytesRead = 0; sce_header_t* pSceHdr = NULL; int retval = -1; // validate input params if ( (pInPath == NULL) || (pOutPath == NULL) ) goto exit; // read the spp file into a buffer (alloc a new buffer) if ( ReadFileToBuffer(pInPath,(uint8_t**)&pMySpp, 0x00, &dwBytesRead, TRUE) != STATUS_SUCCESS ) { printf("failed to read in file:%s, exiting...\n", pInPath); goto exit; } /// Unpackage the "PKG" types /// if ( decrypt_spp(pMySpp, &dec_size, pKeyName) != STATUS_SUCCESS ) { printf("\n!!ERROR!! FAILED to decrypt SPP file:%s\n\n", pInPath); goto exit; } // setup the SCE header pSceHdr = (sce_header_t*)pMySpp;//SIZE_SPKG_HDR wbe64((u8*)&hdr_len, pSceHdr->header_len); // write the decrypted file to disk if ( WriteBufferToFile(pOutPath, (pMySpp+hdr_len), (uint32_t)dec_size, FALSE, 0, NULL) != STATUS_SUCCESS ) { printf("failed to write to file:%s, exiting...\n", pOutPath); goto exit; } // status success retval = STATUS_SUCCESS; exit: // free the alloc'd memory if (pMySpp != NULL) free(pMySpp); return retval; }
static void decrypt_debug_pkg(void) { u8 key[0x40]; u8 bfr[0x1c]; u64 i; memset(key, 0, sizeof key); memcpy(key, pkg + 0x60, 8); memcpy(key + 0x08, pkg + 0x60, 8); memcpy(key + 0x10, pkg + 0x60 + 0x08, 8); memcpy(key + 0x18, pkg + 0x60 + 0x08, 8); sha1(key, sizeof key, bfr); for (i = 0; i < size; i++) { if (i != 0 && (i % 16) == 0) { wbe64(key + 0x38, be64(key + 0x38) + 1); sha1(key, sizeof key, bfr); } pkg[offset + i] ^= bfr[i & 0xf]; } }
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 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 }
// 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; }
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_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); }
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; }