/* calculate size of a patched file directly */ static PyObject * patchedsize(PyObject *self, PyObject *args) { long orig, start, end, len, outlen = 0, last = 0, pos = 0; Py_ssize_t patchlen; char *bin; if (!PyArg_ParseTuple(args, "ls#", &orig, &bin, &patchlen)) return NULL; while (pos >= 0 && pos < patchlen) { start = getbe32(bin + pos); end = getbe32(bin + pos + 4); len = getbe32(bin + pos + 8); if (start > end) break; /* sanity check */ pos += 12 + len; outlen += start - last; last = end; outlen += len; } if (pos != patchlen) { if (!PyErr_Occurred()) PyErr_SetString(mpatch_Error, "patch cannot be decoded"); return NULL; } outlen += orig - last; return Py_BuildValue("l", outlen); }
/* decode a binary patch into a hunk list */ static struct flist *decode(const char *bin, Py_ssize_t len) { struct flist *l; struct frag *lt; int pos = 0; /* assume worst case size, we won't have many of these lists */ l = lalloc(len / 12); if (!l) return NULL; lt = l->tail; while (pos >= 0 && pos < len) { lt->start = getbe32(bin + pos); lt->end = getbe32(bin + pos + 4); lt->len = getbe32(bin + pos + 8); if (lt->start > lt->end) break; /* sanity check */ lt->data = bin + pos + 12; pos += 12 + lt->len; lt++; } if (pos != len) { if (!PyErr_Occurred()) PyErr_SetString(mpatch_Error, "patch cannot be decoded"); lfree(l); return NULL; } l->tail = lt; return l; }
u32 IdentifyImage(const char* path) { u8 header[0x200]; FIL file; if (f_open(&file, path, FA_READ | FA_OPEN_EXISTING) != FR_OK) return 0; f_lseek(&file, 0); f_sync(&file); UINT fsize = f_size(&file); UINT bytes_read; if ((f_read(&file, header, 0x200, &bytes_read) != FR_OK) || (bytes_read != 0x200)) { f_close(&file); return 0; } f_close(&file); if ((getbe32(header + 0x100) == 0x4E435344) && (getbe64(header + 0x110) == (u64) 0x0104030301000000) && (getbe64(header + 0x108) == (u64) 0) && (fsize >= 0x8FC8000)) { return IMG_NAND; } else if (getbe16(header + 0x1FE) == 0x55AA) { // migt be FAT or MBR if ((strncmp((char*) header + 0x36, "FAT12 ", 8) == 0) || (strncmp((char*) header + 0x36, "FAT16 ", 8) == 0) || (strncmp((char*) header + 0x36, "FAT ", 8) == 0) || (strncmp((char*) header + 0x52, "FAT32 ", 8) == 0)) { return IMG_FAT; // this is an actual FAT header } else if (((getle32(header + 0x1BE + 0x8) + getle32(header + 0x1BE + 0xC)) < (fsize / 0x200)) && // check file size (getle32(header + 0x1BE + 0x8) > 0) && (getle32(header + 0x1BE + 0xC) >= 0x800) && // check first partition sanity ((header[0x1BE + 0x4] == 0x1) || (header[0x1BE + 0x4] == 0x4) || (header[0x1BE + 0x4] == 0x6) || // filesystem type (header[0x1BE + 0x4] == 0xB) || (header[0x1BE + 0x4] == 0xC) || (header[0x1BE + 0x4] == 0xE))) { return IMG_FAT; // this might be an MBR -> give it the benefit of doubt } } return 0; }
ctr_tmd_body *tmd_get_body(tmd_context *ctx) { unsigned int type = getbe32(ctx->buffer); ctr_tmd_body *body = NULL; if (type == TMD_RSA_2048_SHA256 || type == TMD_RSA_2048_SHA1) { body = (ctr_tmd_body*)(ctx->buffer + sizeof(ctr_tmd_header_2048)); } else if (type == TMD_RSA_4096_SHA256 || type == TMD_RSA_4096_SHA1) { body = (ctr_tmd_body*)(ctx->buffer + sizeof(ctr_tmd_header_4096)); } return body; }
int main(int argc, char* argv[]) { int result = 0; fprintf(stdout, "stripiosplugin - based on IOS ELF stripper - by neimod\n"); if (argc < 3 ) { fprintf(stderr,"Usage: %s <in.elf> <out.bin> [strip addr]\n", argv[0]); return -1; } FILE* fin = fopen(argv[1], "rb"); FILE* fout = fopen(argv[2], "wb"); if (fin == 0 || fout == 0) { if (fin == 0) fprintf(stderr,"ERROR opening file %s\n", argv[1]); if (fout == 0) fprintf(stderr,"ERROR opening file %s\n", argv[2]); return 1; } elfheader header; if (fread(&header, sizeof(elfheader), 1, fin) != 1) { fprintf(stderr,"ERROR reading ELF header\n"); return 1; } unsigned long elfmagicword = getbe32(&header.ident0); if (elfmagicword != 0x7F454C46) { fprintf(stderr,"ERROR not a valid ELF\n"); return 1; } unsigned long shoff = getbe32(&header.shoff); unsigned short shentsize = getbe16(&header.shentsize); unsigned short shnum = getbe16(&header.shnum); unsigned long memsz = 0, filesz = 0; unsigned long vaddr = 0, paddr = 0; //printf("shoff %lx\n", shoff); //printf("size %x\n", shentsize); //printf("entries %x\n", shnum); elfshentry* entry = new elfshentry[shnum]; fseek(fin, shoff, SEEK_SET); if (fread(entry, sizeof(elfshentry), shnum, fin) != shnum) { fprintf(stderr,"ERROR reading sections header\n"); return 1; } unsigned short i = 0; while (i < shnum) { unsigned long addr = getbe32(&entry[i].shaddr); unsigned long offset = getbe32(&entry[i].shoffset); unsigned long size = getbe32(&entry[i].shsize); if ((addr & ~0xfff) == 0x1377E000) { printf("addr:%lx - ",addr); printf("offset:%lx - ",offset); printf("size: %lx\n", size); fseek(fin, offset, SEEK_SET); char *buf = new char[size]; if (!buf) { fprintf(stderr, "Error allocating memory\n"); return 2; } fread(buf, sizeof(char), size, fin); if (fwrite(buf, sizeof(char), size, fout) != size) { fprintf(stderr, "Error writing output file\n"); return 2; } delete [] buf; } i++; } if (entry) delete[] entry; if (fout) fclose(fout); if (fin) fclose(fin); return result; }
void tmd_print(tmd_context* ctx) { unsigned int type = getbe32(ctx->buffer); ctr_tmd_header_4096* header4096 = 0; ctr_tmd_header_2048* header2048 = 0; ctr_tmd_body* body = 0; unsigned int contentcount = 0; unsigned int savesize = 0; unsigned int titlever = 0; unsigned int i; if (type == TMD_RSA_2048_SHA256 || type == TMD_RSA_2048_SHA1) { header2048 = (ctr_tmd_header_2048*)ctx->buffer; } else if (type == TMD_RSA_4096_SHA256 || type == TMD_RSA_4096_SHA1) { header4096 = (ctr_tmd_header_4096*)ctx->buffer; } else { return; } body = tmd_get_body(ctx); contentcount = getbe16(body->contentcount); savesize = getle32(body->savedatasize); titlever = getbe16(body->titleversion); fprintf(stdout, "\nTMD header:\n"); fprintf(stdout, "Signature type: %s\n", tmd_get_type_string(type)); fprintf(stdout, "Issuer: %s\n", body->issuer); fprintf(stdout, "Version: %d\n", body->version); fprintf(stdout, "CA CRL version: %d\n", body->ca_crl_version); fprintf(stdout, "Signer CRL version: %d\n", body->signer_crl_version); memdump(stdout, "System version: ", body->systemversion, 8); memdump(stdout, "Title id: ", body->titleid, 8); fprintf(stdout, "Title type: %08x\n", getbe32(body->titletype)); fprintf(stdout, "Group id: %04x\n", getbe16(body->groupid)); if(savesize < sizeKB) fprintf(stdout, "Save Size: %08x\n", savesize); else if(savesize < sizeMB) fprintf(stdout, "Save Size: %dKB (%08x)\n", savesize/sizeKB, savesize); else fprintf(stdout, "Save Size: %dMB (%08x)\n", savesize/sizeMB, savesize); fprintf(stdout, "Access rights: %08x\n", getbe32(body->accessrights)); fprintf(stdout, "Title version: %d.%d.%d (v%d)\n", (titlever >> 10) & 0x3F, (titlever >> 4) & 0x3F, titlever & 0xF, titlever); fprintf(stdout, "Content count: %04x\n", getbe16(body->contentcount)); fprintf(stdout, "Boot content: %04x\n", getbe16(body->bootcontent)); memdump(stdout, "Hash: ", body->hash, 32); fprintf(stdout, "\nTMD content info:\n"); for(i = 0; i < TMD_MAX_CONTENTS; i++) { ctr_tmd_contentinfo* info = (ctr_tmd_contentinfo*)(body->contentinfo + sizeof(ctr_tmd_contentinfo)*i); if (getbe16(info->commandcount) == 0) continue; fprintf(stdout, "Content index: %04x\n", getbe16(info->index)); fprintf(stdout, "Command count: %04x\n", getbe16(info->commandcount)); memdump(stdout, "Unknown: ", info->unk, 32); } fprintf(stdout, "\nTMD contents:\n"); for(i = 0; i < contentcount; i++) { ctr_tmd_contentchunk* chunk = (ctr_tmd_contentchunk*)(body->contentinfo + 36*64 + i*48); unsigned short type = getbe16(chunk->type); fprintf(stdout, "Content id: %08x\n", getbe32(chunk->id)); fprintf(stdout, "Content index: %04x\n", getbe16(chunk->index)); fprintf(stdout, "Content type: %04x", getbe16(chunk->type)); if (type) { fprintf(stdout, " "); if (type & 1) fprintf(stdout, "[encrypted]"); if (type & 2) fprintf(stdout, "[disc]"); if (type & 4) fprintf(stdout, "[cfm]"); if (type & 0x4000) fprintf(stdout, "[optional]"); if (type & 0x8000) fprintf(stdout, "[shared]"); } fprintf(stdout, "\n"); fprintf(stdout, "Content size: %016"PRIx64"\n", getbe64(chunk->size)); switch(ctx->content_hash_stat[i]) { case 1: memdump(stdout, "Content hash [OK]: ", chunk->hash, 32); break; case 2: memdump(stdout, "Content hash [FAIL]: ", chunk->hash, 32); break; default: memdump(stdout, "Content hash: ", chunk->hash, 32); break; } fprintf(stdout, "\n"); } }
u32 SdPadgen(u32 param) { (void) (param); // param is unused here SdInfo *info = (SdInfo*) 0x20316000; // setup AES key from SD SetupSdKeyY0x34(false, NULL); if (!DebugFileOpen("SDinfo.bin")) return 1; if (!DebugFileRead(info, 4, 0)) { FileClose(); return 1; } if (!info->n_entries || info->n_entries > MAX_ENTRIES) { FileClose(); Debug("Bad number of entries!"); return 1; } if (!DebugFileRead(info->entries, info->n_entries * sizeof(SdInfoEntry), 4)) { FileClose(); return 1; } FileClose(); Debug("Number of entries: %i", info->n_entries); for(u32 i = 0; i < info->n_entries; i++) { PadInfo padInfo = {.keyslot = 0x34, .setKeyY = 0, .size_mb = info->entries[i].size_mb, .mode = AES_CNT_CTRNAND_MODE}; memcpy(padInfo.ctr, info->entries[i].ctr, 16); memcpy(padInfo.filename, info->entries[i].filename, 180); Debug ("%2i: %s (%iMB)", i, info->entries[i].filename, info->entries[i].size_mb); if (CreatePad(&padInfo) != 0) return 1; // this can't fail anyways } return 0; } u32 SdPadgenDirect(u32 param) { (void) (param); // param is unused here SdInfo *info = (SdInfo*) 0x20316000; char basepath[256]; u8 movable_keyY[16]; if (SetupSdKeyY0x34(true, movable_keyY) != 0) return 1; // movable.sed has to be present in NAND Debug(""); if (SdFolderSelector(basepath, movable_keyY) != 0) return 1; Debug(""); if (SdInfoGen(info, basepath) != 0) return 1; if (!info->n_entries) { Debug("Nothing found in folder"); return 1; } Debug("Number of entries: %i", info->n_entries); for(u32 i = 0; i < info->n_entries; i++) { PadInfo padInfo = {.keyslot = 0x34, .setKeyY = 0, .size_mb = info->entries[i].size_mb, .mode = AES_CNT_CTRNAND_MODE}; memcpy(padInfo.ctr, info->entries[i].ctr, 16); memcpy(padInfo.filename, info->entries[i].filename, 180); Debug ("%2i: %s (%iMB)", i, info->entries[i].filename, info->entries[i].size_mb); if (CreatePad(&padInfo) != 0) return 1; // this can't fail anyways } return 0; } u32 AnyPadgen(u32 param) { (void) (param); // param is unused here AnyPadInfo *info = (AnyPadInfo*) 0x20316000; // get header if ((FileGetData("anypad.bin", info, 16, 0) != 16) || !info->n_entries || info->n_entries > MAX_ENTRIES) { Debug("Corrupt or not existing: anypad.bin"); return 1; } // get data u32 data_size = info->n_entries * sizeof(AnyPadInfoEntry); if (FileGetData("anypad.bin", (u8*) info + 16, data_size, 16) != data_size) { Debug("File is missing data: anypad.bin"); return 1; } Debug("Processing anypad.bin..."); Debug("Number of entries: %i", info->n_entries); for (u32 i = 0; i < info->n_entries; i++) { // this translates all entries to a standard padInfo struct AnyPadInfoEntry* entry = &(info->entries[i]); PadInfo padInfo = {.keyslot = entry->keyslot, .setKeyY = 0, .size_mb = 0, .size_b = entry->size_b, .mode = entry->mode}; memcpy(padInfo.filename, entry->filename, 80); memcpy(padInfo.ctr, entry->ctr, 16); // process keys if (entry->setNormalKey) setup_aeskey(entry->keyslot, entry->normalKey); if (entry->setKeyX) setup_aeskeyX(entry->keyslot, entry->keyX); if (entry->setKeyY) setup_aeskeyY(entry->keyslot, entry->keyY); use_aeskey(entry->keyslot); // process flags if (entry->flags & (AP_USE_NAND_CTR|AP_USE_SD_CTR)) { u32 ctr_add = getbe32(padInfo.ctr + 12); u8 shasum[32]; u8 cid[16]; sdmmc_get_cid((entry->flags & AP_USE_NAND_CTR) ? 1 : 0, (uint32_t*) cid); if (entry->mode == AES_CNT_TWLNAND_MODE) { sha_quick(shasum, cid, 16, SHA1_MODE); for (u32 i = 0; i < 16; i++) padInfo.ctr[i] = shasum[15-i]; } else { sha_quick(shasum, cid, 16, SHA256_MODE); memcpy(padInfo.ctr, shasum, 16); } add_ctr(padInfo.ctr, ctr_add); } // create the pad Debug ("%2i: %s (%ikB)", i, entry->filename, entry->size_b / 1024); if (CreatePad(&padInfo) != 0) return 1; // this can't fail anyways } return 0; } u32 CtrNandPadgen(u32 param) { char* filename = (param & PG_FORCESLOT4) ? "nand.fat16.slot0x04.xorpad" : "nand.fat16.xorpad"; u32 keyslot; u32 nand_size; // legacy sizes & offset, to work with Python 3DSFAT16Tool if (GetUnitPlatform() == PLATFORM_3DS) { if (param & PG_FORCESLOT4) { Debug("This is a N3DS only feature"); return 1; } keyslot = 0x4; nand_size = 758; } else { keyslot = (param & PG_FORCESLOT4) ? 0x4 : 0x5; nand_size = 1055; } Debug("Creating NAND FAT16 xorpad. Size (MB): %u", nand_size); Debug("Filename: %s", filename); PadInfo padInfo = { .keyslot = keyslot, .setKeyY = 0, .size_mb = nand_size, .mode = AES_CNT_CTRNAND_MODE }; strncpy(padInfo.filename, filename, 64); if(GetNandCtr(padInfo.ctr, 0xB930000) != 0) return 1; return CreatePad(&padInfo); } u32 TwlNandPadgen(u32 param) { (void) (param); // param is unused here PartitionInfo* twln_info = GetPartitionInfo(P_TWLN); u32 size_mb = (twln_info->size + (1024 * 1024) - 1) / (1024 * 1024); Debug("Creating TWLN FAT16 xorpad. Size (MB): %u", size_mb); Debug("Filename: twlnand.fat16.xorpad"); PadInfo padInfo = { .keyslot = twln_info->keyslot, .setKeyY = 0, .size_mb = size_mb, .filename = "twlnand.fat16.xorpad", .mode = AES_CNT_TWLNAND_MODE }; if(GetNandCtr(padInfo.ctr, twln_info->offset) != 0) return 1; return CreatePad(&padInfo); } u32 Firm0Firm1Padgen(u32 param) { (void) (param); // param is unused here PartitionInfo* firm0_info = GetPartitionInfo(P_FIRM0); PartitionInfo* firm1_info = GetPartitionInfo(P_FIRM1); u32 size_mb = (firm0_info->size + firm1_info->size + (1024 * 1024) - 1) / (1024 * 1024); Debug("Creating FIRM0FIRM1 xorpad. Size (MB): %u", size_mb); Debug("Filename: firm0firm1.xorpad"); PadInfo padInfo = { .keyslot = firm0_info->keyslot, .setKeyY = 0, .size_mb = size_mb, .filename = "firm0firm1.xorpad", .mode = AES_CNT_CTRNAND_MODE }; if(GetNandCtr(padInfo.ctr, firm0_info->offset) != 0) return 1; return CreatePad(&padInfo); }
void cia_save(cia_context* ctx, u32 type, u32 flags) { u32 offset; u32 size; u16 contentflags; u8 docrypto; filepath* path = 0; ctr_tmd_body *body; ctr_tmd_contentchunk *chunk; int i; char tmpname[255]; switch(type) { case CIATYPE_CERTS: offset = ctx->offsetcerts; size = ctx->sizecert; path = settings_get_certs_path(ctx->usersettings); break; case CIATYPE_TIK: offset = ctx->offsettik; size = ctx->sizetik; path = settings_get_tik_path(ctx->usersettings); break; case CIATYPE_TMD: offset = ctx->offsettmd; size = ctx->sizetmd; path = settings_get_tmd_path(ctx->usersettings); break; case CIATYPE_CONTENT: offset = ctx->offsetcontent; size = ctx->sizecontent; path = settings_get_content_path(ctx->usersettings); break; case CIATYPE_META: offset = ctx->offsetmeta; size = ctx->sizemeta; path = settings_get_meta_path(ctx->usersettings);; break; default: fprintf(stderr, "Error, unknown CIA type specified\n"); return; break; } if (path == 0 || path->valid == 0) return; switch(type) { case CIATYPE_CERTS: fprintf(stdout, "Saving certs to %s\n", path->pathname); break; case CIATYPE_TIK: fprintf(stdout, "Saving tik to %s\n", path->pathname); break; case CIATYPE_TMD: fprintf(stdout, "Saving tmd to %s\n", path->pathname); break; case CIATYPE_CONTENT: body = tmd_get_body(&ctx->tmd); chunk = (ctr_tmd_contentchunk*)(body->contentinfo + (sizeof(ctr_tmd_contentinfo) * TMD_MAX_CONTENTS)); for(i = 0; i < getbe16(body->contentcount); i++) { sprintf(tmpname, "%s.%04x.%08x", path->pathname, getbe16(chunk->index), getbe32(chunk->id)); fprintf(stdout, "Saving content #%04x to %s\n", getbe16(chunk->index), tmpname); contentflags = getbe16(chunk->type); docrypto = contentflags & 1 && !(flags & PlainFlag); if(docrypto) // Decrypt if needed { ctx->iv[0] = (getbe16(chunk->index) >> 8) & 0xff; ctx->iv[1] = getbe16(chunk->index) & 0xff; ctr_init_cbc_decrypt(&ctx->aes, ctx->titlekey, ctx->iv); } cia_save_blob(ctx, tmpname, offset, getbe64(chunk->size) & 0xffffffff, docrypto); offset += getbe64(chunk->size) & 0xffffffff; chunk++; } memset(ctx->iv, 0, 16); return; break; case CIATYPE_META: fprintf(stdout, "Saving meta to %s\n", path->pathname); break; } cia_save_blob(ctx, path->pathname, offset, size, 0); }
u32 DebugSeekTitleInNand(u32* offset_tmd, u32* size_tmd, u32* offset_app, u32* size_app, TitleListInfo* title_info, u32 max_cnt) { PartitionInfo* ctrnand_info = GetPartitionInfo(P_CTRNAND); u8* buffer = (u8*) 0x20316000; u32 cnt_count = 0; u32 tid_low = 0; u32 tmd_id = 0; Debug("Searching title \"%s\"...", title_info->name); Debug("Method 1: Search in title.db..."); if (SeekTitleInNandDb(&tid_low, &tmd_id, title_info) == 0) { char path[64]; sprintf(path, "TITLE %08X %08X CONTENT %08XTMD", (unsigned int) title_info->tid_high, (unsigned int) tid_low, (unsigned int) tmd_id); if (SeekFileInNand(offset_tmd, size_tmd, path, ctrnand_info) != 0) tid_low = 0; } if (!tid_low) { Debug("Method 2: Search in file system..."); for (u32 i = 0; i < 6; i++) { char path[64]; if (title_info->tid_low[i] == 0) continue; sprintf(path, "TITLE %08X %08X CONTENT ????????TMD", (unsigned int) title_info->tid_high, (unsigned int) title_info->tid_low[i]); if (SeekFileInNand(offset_tmd, size_tmd, path, ctrnand_info) == 0) { tid_low = title_info->tid_low[i]; break; } } } if (!tid_low) { Debug("Failed!"); return 1; } Debug("Found title %08X%08X", title_info->tid_high, tid_low); Debug("TMD0 found at %08X, size %ub", *offset_tmd, *size_tmd); if ((*size_tmd < 0xC4 + (0x40 * 0x24)) || (*size_tmd > 0x4000)) { Debug("TMD has bad size!"); return 1; } if (DecryptNandToMem(buffer, *offset_tmd, *size_tmd, ctrnand_info) != 0) return 1; u32 size_sig = (buffer[3] == 3) ? 0x240 : (buffer[3] == 4) ? 0x140 : (buffer[3] == 5) ? 0x80 : 0; if ((size_sig == 0) || (memcmp(buffer, "\x00\x01\x00", 3) != 0)) { Debug("Unknown signature type: %08X", getbe32(buffer)); return 1; } cnt_count = getbe16(buffer + size_sig + 0x9E); u32 size_tmd_expected = size_sig + 0xC4 + (0x40 * 0x24) + (cnt_count * 0x30); if (*size_tmd < size_tmd_expected) { Debug("TMD bad size (expected %ub)!", size_tmd_expected ); return 1; } buffer += size_sig + 0xC4 + (0x40 * 0x24); for (u32 i = 0; i < cnt_count && i < max_cnt; i++) { char path[64]; u32 cnt_id = getbe32(buffer + (0x30 * i)); if (i >= max_cnt) { Debug("APP%i was skipped", i); continue; } sprintf(path, "TITLE %08X %08X CONTENT %08XAPP", (unsigned int) title_info->tid_high, (unsigned int) tid_low, (unsigned int) cnt_id); if (SeekFileInNand(offset_app + i, size_app + i, path, ctrnand_info) != 0) { Debug("APP%i not found or fragmented!", i); return 1; } Debug("APP%i found at %08X, size %ukB", i, offset_app[i], size_app[i] / 1024); } return 0; }
int mload_elf(void *my_elf, data_elf *data_elf) { int n,m; int p; u8 *adr; u32 elf=(u32) my_elf; if(elf & 3) return -1; // aligned to 4 please! elfheader *head=(void *) elf; elfphentry *entries; if(head->ident0!=0x7F454C46) return -1; if(head->ident1!=0x01020161) return -1; if(head->ident2!=0x01000000) return -1; p=head->phoff; data_elf->start=(void *) head->entry; for(n=0; n<head->phnum; n++) { entries=(void *) (elf+p); p+=sizeof(elfphentry); if(entries->type == 4) { adr=(void *) (elf + entries->offset); if(getbe32(0)!=0) return -2; // bad info (sure) for(m=4; m < entries->memsz; m+=8) { switch(getbe32(m)) { case 0x9: data_elf->start= (void *) getbe32(m+4); break; case 0x7D: data_elf->prio= getbe32(m+4); break; case 0x7E: data_elf->size_stack= getbe32(m+4); break; case 0x7F: data_elf->stack= (void *) (getbe32(m+4)); break; } } } else if(entries->type == 1 && entries->memsz != 0 && entries->vaddr!=0) { if(mload_memset((void *) entries->vaddr, 0, entries->memsz)<0) return -1; if(mload_seek(entries->vaddr, SEEK_SET)<0) return -1; if(mload_write((void *) (elf + entries->offset), entries->filesz)<0) return -1; } } return 0; }