📄 p_wcle.cpp
字号:
ph.u_len = isize; // prepare filter [already done] // compress upx_compress_config_t cconf; cconf.reset(); cconf.conf_lzma.max_num_probs = 1846 + (768 << 4); // ushort: ~28KB stack compressWithFilters(ibuf, isize, oimage + RESERVED, ibuf + ft->addvalue, ft->buf_len, NULL, 0, ft, 512, &cconf, 0); ibuf.dealloc(); soimage = ph.c_len; while (soimage & 3) oimage[RESERVED + soimage++] = 0;}void PackWcle::pack(OutputFile *fo){ handleStub(fo); if (ih.byte_order || ih.word_order || ih.exe_format_level || ih.cpu_type < 2 || ih.cpu_type > 5 || ih.target_os != 1 || ih.module_type != 0x200 || ih.object_iterate_data_map_offset || ih.resource_entries || ih.module_directives_entries || ih.imported_modules_count || ih.object_table_entries > 255) throwCantPack("watcom/le: unexpected value in header"); readObjectTable(); readPageMap(); readResidentNames(); readEntryTable(); readFixupPageTable(); readFixups(); readImage(); readNonResidentNames();// if (find_le32(iimage,20,get_le32("UPX ")) >= 0) if (find_le32(iimage,UPX_MIN(soimage,256u),UPX_MAGIC_LE32) >= 0) throwAlreadyPacked(); if (ih.init_ss_object != objects) throwCantPack("the stack is not in the last object"); preprocessFixups(); const unsigned text_size = IOT(ih.init_cs_object-1,npages) * mps; const unsigned text_vaddr = IOT(ih.init_cs_object-1,my_base_address); // attach some useful data at the end of preprocessed fixups ifixups[sofixups++] = (unsigned char) ih.automatic_data_object; unsigned ic = objects*sizeof(*iobject_table); memcpy(ifixups+sofixups,iobject_desc,ic); iobject_desc.dealloc(); sofixups += ic; set_le32(ifixups+sofixups,ih.init_esp_offset+IOT(ih.init_ss_object-1,my_base_address)); // old stack pointer set_le32(ifixups+sofixups+4,ih.init_eip_offset+text_vaddr); // real entry point set_le32(ifixups+sofixups+8,mps*pages); // virtual address of unpacked relocations ifixups[sofixups+12] = (unsigned char) (unsigned) objects; sofixups += 13; // prepare filter Filter ft(ph.level); ft.buf_len = text_size; ft.addvalue = text_vaddr; // compress encodeImage(&ft); const unsigned lsize = getLoaderSize(); neweip = getLoaderSection("WCLEMAIN"); int e_len = getLoaderSectionStart("WCLECUTP"); const unsigned d_len = lsize - e_len; assert(e_len > 0 && e_len < RESERVED); memmove(oimage+e_len,oimage+RESERVED,soimage); soimage += lsize; opages = (soimage+mps-1)/mps; oh.bytes_on_last_page = soimage%mps; encodeObjectTable(); encodeFixups(); encodeFixupPageTable(); encodePageMap(); encodeEntryTable(); encodeResidentNames(); encodeNonResidentNames(); // patch loader ic = (OOT(0,virtual_size) - d_len) &~ 15; assert(ic > ((ph.u_len + ph.overlap_overhead + 31) &~ 15)); linker->defineSymbol("WCLECUTP", ic); linker->defineSymbol("original_entry", ih.init_eip_offset + text_vaddr); linker->defineSymbol("original_stack", ih.init_esp_offset + IOT(ih.init_ss_object - 1, my_base_address)); linker->defineSymbol("start_of_relocs", mps*pages); defineDecompressorSymbols(); defineFilterSymbols(&ft); linker->defineSymbol("filter_buffer_start", text_vaddr); unsigned jpos = (((ph.c_len + 3) &~ 3) + d_len + 3) / 4; linker->defineSymbol("words_to_copy", jpos); linker->defineSymbol("copy_dest", ((ic + d_len + 3) &~ 3) - 4); linker->defineSymbol("copy_source", e_len + jpos * 4 - 4); relocateLoader(); MemBuffer loader(lsize); memcpy(loader, getLoader(), lsize); patchPackHeader(loader, lsize); memcpy(oimage, loader, e_len); memcpy(oimage + soimage - d_len, loader + e_len, d_len); writeFile(fo, opt->watcom_le.le); // verify verifyOverlappingDecompression(oimage + e_len, oimage.getSize() - e_len); // copy the overlay const unsigned overlaystart = ih.data_pages_offset + exe_offset + getImageSize(); const unsigned overlay = file_size - overlaystart - ih.non_resident_name_table_length; checkOverlay(overlay); copyOverlay(fo, overlay, &oimage); // finally check the compression ratio if (!checkFinalCompressionRatio(fo)) throwNotCompressible();}/*************************************************************************//**************************************************************************/void PackWcle::decodeFixups(){ upx_byte *p = oimage + soimage; iimage.dealloc(); MemBuffer tmpbuf; unsigned fixupn = unoptimizeReloc32(&p,oimage,&tmpbuf,1); MemBuffer wrkmem(8*fixupn+8); unsigned ic,jc,o,r; for (ic=0; ic<fixupn; ic++) { jc=get_le32(tmpbuf+4*ic); set_le32(wrkmem+ic*8,jc); o = soobject_table; r = get_le32(oimage+jc); virt2rela(oobject_table,&o,&r); set_le32(wrkmem+ic*8+4,OOT(o-1,my_base_address)); set_le32(oimage+jc,r); } set_le32(wrkmem+ic*8,0xFFFFFFFF); // end of 32-bit offset fixups tmpbuf.dealloc(); // selector fixups and self-relative fixups const upx_byte *selector_fixups = p; const upx_byte *selfrel_fixups = p; while (*selfrel_fixups != 0xC3) selfrel_fixups += 9; selfrel_fixups++; unsigned selectlen = ptr_diff(selfrel_fixups, selector_fixups)/9; ofixups = new upx_byte[fixupn*9+1000+selectlen*5]; upx_bytep fp = ofixups; for (ic = 1, jc = 0; ic <= opages; ic++) { // self relative fixups while ((r = get_le32(selfrel_fixups))/mps == ic-1) { fp[0] = 8; set_le16(fp+2,r & (mps-1)); o = 4+get_le32(oimage+r); set_le32(oimage+r,0); r += o; o = soobject_table; virt2rela(oobject_table,&o,&r); fp[4] = (unsigned char) o; set_le32(fp+5,r); fp[1] = (unsigned char) (r > 0xFFFF ? 0x10 : 0); fp += fp[1] ? 9 : 7; selfrel_fixups += 4; dputc('r',stdout); } // selector fixups while (selectlen && (r = get_le32(selector_fixups+5))/mps == ic-1) { fp[0] = 2; fp[1] = 0; set_le16(fp+2,r & (mps-1)); unsigned x = selector_fixups[1] > 0xD0 ? oh.init_ss_object : oh.init_cs_object; fp[4] = (unsigned char) x; fp += 5; selector_fixups += 9; selectlen--; dputc('s',stdout); } // 32 bit offset fixups while (get_le32(wrkmem+4*jc) < ic*mps) { if (ic > 1 && ((get_le32(wrkmem+4*(jc-2))+3) & (mps-1)) < 3) // cross page fixup? { r = get_le32(oimage+get_le32(wrkmem+4*(jc-2))); fp[0] = 7; fp[1] = (unsigned char) (r > 0xFFFF ? 0x10 : 0); set_le16(fp+2,get_le32(wrkmem+4*(jc-2)) | ~3); set_le32(fp+5,r); o = soobject_table; r = get_le32(wrkmem+4*(jc-1)); virt2rela(oobject_table,&o,&r); fp[4] = (unsigned char) o; fp += fp[1] ? 9 : 7; dputc('0',stdout); } o = soobject_table; r = get_le32(wrkmem+4*(jc+1)); virt2rela(oobject_table,&o,&r); r = get_le32(oimage+get_le32(wrkmem+4*jc)); fp[0] = 7; fp[1] = (unsigned char) (r > 0xFFFF ? 0x10 : 0); set_le16(fp+2,get_le32(wrkmem+4*jc) & (mps-1)); fp[4] = (unsigned char) o; set_le32(fp+5,r); fp += fp[1] ? 9 : 7; jc += 2; } set_le32(ofpage_table+ic,ptr_diff(fp,ofixups)); } for (ic=0; ic < FIXUP_EXTRA; ic++) *fp++ = 0; sofixups = ptr_diff(fp, ofixups);}void PackWcle::decodeFixupPageTable(){ ofpage_table = new unsigned[sofpage_table = 1 + opages]; set_le32(ofpage_table,0); // the rest of ofpage_table is filled by decodeFixups()}void PackWcle::decodeObjectTable(){ soobject_table = oimage[ph.u_len - 1]; oobject_table = new le_object_table_entry_t[soobject_table]; unsigned jc, ic = soobject_table * sizeof(*oobject_table); const unsigned extradata = ph.version == 10 ? 17 : 13; memcpy(oobject_table,oimage + ph.u_len - extradata - ic,ic); if (ph.version >= 12) oh.automatic_data_object = oimage[ph.u_len - ic - 14]; for (ic = jc = 0; ic < soobject_table; ic++) { OOT(ic,my_base_address) = jc; jc += (OOT(ic,virtual_size)+mps-1) &~ (mps-1); } // restore original cs:eip & ss:esp ic = soobject_table; jc = get_le32(oimage + ph.u_len - (ph.version < 11 ? 13 : 9)); virt2rela(oobject_table,&ic,&jc); oh.init_cs_object = ic; oh.init_eip_offset = jc; ic = soobject_table; if (ph.version < 10) jc = ih.init_esp_offset; else jc = get_le32(oimage + ph.u_len - (ph.version == 10 ? 17 : 13)); virt2rela(oobject_table,&ic,&jc); oh.init_ss_object = ic; oh.init_esp_offset = jc;}void PackWcle::decodeImage(){ oimage.allocForUncompression(ph.u_len); decompress(iimage + ph.buf_offset + ph.getPackHeaderSize(),oimage); soimage = get_le32(oimage + ph.u_len - 5); opages = soimage / mps; oh.memory_page_size = mps;}void PackWcle::decodeEntryTable(){ unsigned count,object,n,r; upx_byte *p = ientries; n = 0; while (*p) { count = *p; n += count; if (p[1] == 0) // unused bundle p += 2; else if (p[1] == 3) // 32-bit offset bundle { object = get_le16(p+2); if (object != 1) throwCantUnpack("corrupted entry found"); object = soobject_table; r = get_le32(p+5); virt2rela(oobject_table,&object,&r); set_le16(p+2,object--); p += 4; for (; count; count--, p += 5) set_le32(p+1,get_le32(p+1) - OOT(object,my_base_address)); } else throwCantUnpack("unsupported bundle type in entry table"); } //if (Opt_debug) printf("\n%d entries decoded.\n",n); soentries = ptr_diff(p, ientries) + 1; oentries = ientries; ientries = NULL;}int PackWcle::canUnpack(){ if (!LeFile::readFileHeader()) return false; fi->seek(exe_offset + ih.data_pages_offset, SEEK_SET); // FIXME: 1024 could be too large for some files //int len = 1024; int len = UPX_MIN(getImageSize(), 256u); return readPackHeader(len) ? 1 : -1;}void PackWcle::virt2rela(const le_object_table_entry_t *entr,unsigned *objn,unsigned *addr){ for (; *objn > 1; objn[0]--) { if (entr[*objn-1].my_base_address > *addr) continue; *addr -= entr[*objn-1].my_base_address; break; }}/*************************************************************************//**************************************************************************/void PackWcle::unpack(OutputFile *fo){ handleStub(fo); readObjectTable(); iobject_desc.dealloc(); readPageMap(); readResidentNames(); readEntryTable(); readFixupPageTable(); readFixups(); readImage(); readNonResidentNames(); decodeImage(); decodeObjectTable(); // unfilter if (ph.filter) { const unsigned text_size = OOT(oh.init_cs_object-1,npages) * mps; const unsigned text_vaddr = OOT(oh.init_cs_object-1,my_base_address); Filter ft(ph.level); ft.init(ph.filter, text_vaddr); ft.cto = (unsigned char) (ph.version < 11 ? (get_le32(oimage+ph.u_len-9) >> 24) : ph.filter_cto); ft.unfilter(oimage+text_vaddr, text_size); } decodeFixupPageTable(); decodeFixups(); decodeEntryTable(); decodePageMap(); decodeResidentNames(); decodeNonResidentNames(); for (unsigned ic = 0; ic < soobject_table; ic++) OOT(ic,my_base_address) = 0; while (oimage[soimage-1] == 0) soimage--; oh.bytes_on_last_page = soimage % mps; // write decompressed file if (fo) writeFile(fo, opt->watcom_le.le); // copy the overlay const unsigned overlaystart = ih.data_pages_offset + exe_offset + getImageSize(); const unsigned overlay = file_size - overlaystart - ih.non_resident_name_table_length; checkOverlay(overlay); copyOverlay(fo, overlay, &oimage);}/*vi:ts=4:et*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -