📄 p_exe.cpp
字号:
}/*************************************************************************//**************************************************************************/void PackExe::pack(OutputFile *fo){ unsigned ic; if (ih.relocs > MAXRELOCS) throwCantPack("too many relocations"); checkOverlay(ih_overlay); // alloc buffers relocsize = RSFCRI + 4*ih.relocs; ibuf.alloc(ih_imagesize+16+relocsize+2); obuf.allocForCompression(ih_imagesize+16+relocsize+2); // read image fi->seek(ih.headsize16*16,SEEK_SET); fi->readx(ibuf,ih_imagesize); checkAlreadyPacked(ibuf, UPX_MIN(ih_imagesize, 127u)); device_driver = get_le32(ibuf) == 0xffffffffu; // relocations has_9a = false; upx_byte *w = ibuf + ih_imagesize; if (ih.relocs) { upx_byte *wr = w + RSFCRI; fi->seek(ih.relocoffs,SEEK_SET); fi->readx(wr,4*ih.relocs); for (ic = 0; ic < ih.relocs; ic++) { unsigned jc = get_le32(wr+4*ic); set_le32(wr+4*ic, ((jc>>16)*16+(jc&0xffff)) & 0xfffff); } qsort(wr,ih.relocs,4,le32_compare); relocsize = optimize_relocs(ibuf, ih_imagesize, wr, ih.relocs, w, &has_9a); set_le16(w+relocsize, relocsize+2); relocsize += 2; if (relocsize > MAXRELOCS) throwCantPack("too many relocations");#if 0 upx_byte out[9*relocsize/8+1024]; unsigned in_len = relocsize; unsigned out_len = 0; ucl_nrv2b_99_compress(w, in_len, out, &out_len, NULL, 9, NULL, NULL); printf("reloc compress: %d -> %d\n", in_len, out_len);#endif } else { relocsize = 0; } // prepare packheader ph.u_len = ih_imagesize + relocsize; // prepare filter Filter ft(ph.level); // compress (max_match = 8192) upx_compress_config_t cconf; cconf.reset(); cconf.conf_ucl.max_match = MAXMATCH; cconf.conf_lzma.max_num_probs = 1846 + (768 << 4); // ushort: ~28KB stack compressWithFilters(&ft, 32, &cconf); if (M_IS_NRV2B(ph.method) || M_IS_NRV2D(ph.method) || M_IS_NRV2E(ph.method)) if (ph.max_run_found + ph.max_match_found > 0x8000) throwCantPack("decompressor limit exceeded, send a bugreport");#ifdef TESTING if (opt->debug.debug_level) { printf("image+relocs %d -> %d\n",ih_imagesize+relocsize,ph.c_len); printf("offsets: %d - %d\nmatches: %d - %d\nruns: %d - %d\n", 0/*ph.min_offset_found*/,ph.max_offset_found, 0/*ph.min_match_found*/,ph.max_match_found, 0/*ph.min_run_found*/,ph.max_run_found); }#endif int flag = fillExeHeader(&oh); const unsigned lsize = getLoaderSize(); MemBuffer loader(lsize); memcpy(loader,getLoader(),lsize); //OutputFile::dump("xxloader.dat", loader, lsize); // patch loader const unsigned packedsize = ph.c_len; const unsigned e_len = getLoaderSectionStart("EXECUTPO"); const unsigned d_len = lsize - e_len; assert((e_len&15) == 0); const unsigned copysize = (1+packedsize+d_len) & ~1; const unsigned firstcopy = copysize%0x10000 ? copysize%0x10000 : 0x10000; // set oh.min & oh.max ic = ih.min*16 + ih_imagesize; if (ic < oh.ss*16u + oh.sp) ic = oh.ss*16u + oh.sp; oh.min = (ic - (packedsize + lsize)) / 16; ic = oh.min + (ih.max - ih.min); oh.max = ic < 0xffff && ih.max != 0xffff ? ic : 0xffff; // set extra info unsigned char extra_info[9]; unsigned eisize = 0; if (oh.ss != ih.ss) { set_le16(extra_info+eisize,ih.ss); eisize += 2; assert((flag & SS) != 0); // set in fillExeHeader() } if (oh.sp != ih.sp) { set_le16(extra_info+eisize,ih.sp); eisize += 2; assert((flag & SP) != 0); // set in fillExeHeader() } if (ih.min != oh.min) { set_le16(extra_info+eisize,ih.min); eisize += 2; flag |= MINMEM; } if (ih.max != oh.max) { set_le16(extra_info+eisize,ih.max); eisize += 2; flag |= MAXMEM; } extra_info[eisize++] = (unsigned char) flag; if (M_IS_NRV2B(ph.method) || M_IS_NRV2D(ph.method) || M_IS_NRV2E(ph.method)) linker->defineSymbol("bx_magic", 0x7FFF + 0x10 * ((packedsize & 15) + 1)); unsigned decompressor_entry = 1 + (packedsize & 15); if (M_IS_LZMA(ph.method)) decompressor_entry = 0x10; linker->defineSymbol("decompressor_entry", decompressor_entry); // patch loader if (flag & USEJUMP) { // I use a relocation entry to set the original cs unsigned n = getLoaderSectionStart("EXEJUMPF") + 1; n += packedsize + 2; oh.relocs = 1; oh.firstreloc = (n & 0xf) + ((n >> 4) << 16); } else { oh.relocs = 0; oh.firstreloc = ih.cs * 0x10000 + ih.ip; } // g++ 3.1 does not like the following line...// oh.relocoffs = offsetof(exe_header_t, firstreloc); oh.relocoffs = ptr_diff(&oh.firstreloc, &oh); linker->defineSymbol("destination_segment", oh.ss - ph.c_len / 16 - e_len / 16); linker->defineSymbol("source_segment", e_len / 16 + (copysize - firstcopy) / 16); linker->defineSymbol("copy_offset", firstcopy - 2); linker->defineSymbol("words_to_copy",firstcopy / 2); linker->defineSymbol("exe_stack_sp", oh.sp); linker->defineSymbol("exe_stack_ss", oh.ss); linker->defineSymbol("interrupt", get_le16(ibuf + 8)); linker->defineSymbol("attribute", get_le16(ibuf + 4)); linker->defineSymbol("orig_strategy", get_le16(ibuf + 6)); const unsigned outputlen = sizeof(oh)+lsize+packedsize+eisize; oh.m512 = outputlen & 511; oh.p512 = (outputlen + 511) >> 9; const char *exeentry = M_IS_LZMA(ph.method) ? "LZMAENTRY" : "EXEENTRY"; oh.ip = device_driver ? getLoaderSection(exeentry) - 2 : 0; defineDecompressorSymbols(); relocateLoader(); memcpy(loader, getLoader(), lsize); patchPackHeader(loader,e_len);//fprintf(stderr,"\ne_len=%x d_len=%x c_len=%x oo=%x ulen=%x destp=%x copys=%x images=%x",e_len,d_len,packedsize,ph.overlap_overhead,ph.u_len,destpara,copysize,ih_imagesize); // write header + write loader + compressed file#ifdef TESTING if (opt->debug.debug_level) printf("\n%d %d %d %d\n",(int)sizeof(oh),e_len,packedsize,d_len);#endif fo->write(&oh,sizeof(oh)); fo->write(loader,e_len); // entry fo->write(obuf,packedsize); fo->write(loader+e_len,d_len); // decompressor fo->write(extra_info,eisize); assert(eisize <= 9);#if 0 printf("%-13s: program hdr : %8ld bytes\n", getName(), (long) sizeof(oh)); printf("%-13s: entry : %8ld bytes\n", getName(), (long) e_len); printf("%-13s: compressed : %8ld bytes\n", getName(), (long) packedsize); printf("%-13s: decompressor : %8ld bytes\n", getName(), (long) d_len); printf("%-13s: extra info : %8ld bytes\n", getName(), (long) eisize);#endif // verify verifyOverlappingDecompression(); // copy the overlay copyOverlay(fo, ih_overlay, &obuf);//fprintf (stderr,"%x %x\n",relocsize,ph.u_len); // finally check the compression ratio if (!checkFinalCompressionRatio(fo)) throwNotCompressible();}/*************************************************************************//**************************************************************************/int PackExe::canUnpack(){ if (!readFileHeader()) return false; const off_t off = ih.headsize16 * 16; fi->seek(off, SEEK_SET); bool b = readPackHeader(4096); return b && (off + (off_t) ph.c_len <= file_size);}/*************************************************************************//**************************************************************************/void PackExe::unpack(OutputFile *fo){ ibuf.alloc(file_size); obuf.allocForUncompression(ph.u_len); // read the file fi->seek(ih.headsize16*16,SEEK_SET); fi->readx(ibuf,ih_imagesize); // get compressed data offset unsigned e_len = ph.buf_offset + ph.getPackHeaderSize(); if (ih_imagesize <= e_len + ph.c_len) throwCantUnpack("file damaged"); checkOverlay(ih_overlay); // decompress decompress(ibuf+e_len,obuf); unsigned imagesize = ih_imagesize; imagesize--; const unsigned char flag = ibuf[imagesize]; unsigned relocn = 0; upx_byte *relocs = obuf + ph.u_len; MemBuffer wrkmem; if (!(flag & NORELOC)) { relocs -= get_le16(obuf+ph.u_len-2); ph.u_len -= 2; wrkmem.alloc(4*MAXRELOCS); unsigned es = 0, ones = get_le16(relocs); const unsigned seghi = get_le16(relocs+2); const upx_byte *p = relocs + 4; while (ones) { unsigned di = get_le16(p); es += get_le16(p+2); bool dorel = true; for (p += 4; ones && di < 0x10000; p++) { if (dorel) { set_le16(wrkmem+4*relocn,di); set_le16(wrkmem+2+4*relocn++,es); //printf ("%x\n",es*16+di); } dorel = true; if (*p == 0) { const upx_byte *q; for (q = obuf+es*16+di; !(*q == 0x9a && get_le16(q+3) <= seghi); q++) ; di = ptr_diff(q, obuf+es*16) + 3; } else if (*p == 1) { di += 254; if (di < 0x10000) ones--; dorel = false; } else di += *p; } } } // fill new exe header memset(&oh,0,sizeof(oh)); oh.ident = 'M' + 'Z'*256; if (relocn) { oh.relocs = relocn; while (relocn & 3) set_le32(wrkmem+4*relocn++,0); } unsigned outputlen = ptr_diff(relocs, obuf) + sizeof(oh) + relocn*4; oh.m512 = outputlen & 511; oh.p512 = (outputlen + 511) >> 9; oh.headsize16 = 2+relocn/4; oh.max = ih.max; oh.min = ih.min; oh.sp = ih.sp; oh.ss = ih.ss; if (flag & MAXMEM) { imagesize -= 2; oh.max = get_le16(ibuf+imagesize); } if (flag & MINMEM) { imagesize -= 2; oh.min = get_le16(ibuf+imagesize); } if (flag & SP) { imagesize -= 2; oh.sp = get_le16(ibuf+imagesize); } if (flag & SS) { imagesize -= 2; oh.ss = get_le16(ibuf+imagesize); } unsigned ip = (flag & USEJUMP) ? get_le32(ibuf+imagesize-4) : (unsigned) ih.firstreloc; oh.ip = ip & 0xffff; oh.cs = ip >> 16; oh.relocoffs = sizeof(oh); oh.firstreloc = 0; if (!fo) return; // write header + relocations + uncompressed file fo->write(&oh,sizeof(oh)); if (relocn) fo->write(wrkmem,relocn*4); fo->write(obuf, ptr_diff(relocs, obuf)); // copy the overlay copyOverlay(fo, ih_overlay, &obuf);}Linker* PackExe::newLinker() const{ return new ElfLinkerX86();}/*memory layout at decompression time===================================normal exe----------a, at load time(e - copying code, C - compressed data, d - decompressor+relocator, x - not specified, U - uncompressed code+data, R uncompressed relocation)eeCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCdddd^ CS:0 ^ SS:0b, after copyingxxxxxxxxxxxxxxxCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCdddd^ES:DI=0 ^ DS:SI=0 ^ CS=SS, IP in range 0..0xfc, after uncompressionUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUURRdddd ^ ES:DIdevice driver-------------the file has 2 entry points, CS:0 in device driver mode, andCS:exe_as_device_entry in normal mode. the code in section DEVICEENTRYsets up the same environment for section EXEENTRY, as it would see in normalexecution mode.lzma uncompression for normal exes----------------------------------(n - nrv2b uncompressor, l - nrv2b compressed lzma + relocator code)a, at load timenneelllCCCCCCCCCCCCCCCCCCCCCCCCC^ CS:0 ^ SS:0b, after nrv2bnneelllCCCCCCCCCCCCCCCCCCCCCCCCC dddd^ CS:0 ^ SS:0x10after this, normal ee code runslzma + device driver--------------------(D - device driver adapter)a, at load timeDDnneelllCCCCCCCCCCCCCCCCCCCCCCCCC*//*vi:ts=4:et*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -