?? packer.cpp
字號:
/* packer.cpp -- This file is part of the UPX executable compressor. Copyright (C) 1996-2007 Markus Franz Xaver Johannes Oberhumer Copyright (C) 1996-2007 Laszlo Molnar All Rights Reserved. UPX and the UCL library are free software; you can redistribute them and/or modify them under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. Markus F.X.J. Oberhumer Laszlo Molnar markus@oberhumer.com ml1050@users.sourceforge.net *///#define WANT_STL#include "conf.h"#include "file.h"#include "packer.h"#include "filter.h"#include "linker.h"#include "ui.h"/*************************************************************************//**************************************************************************/Packer::Packer(InputFile *f) : bele(NULL), fi(f), file_size(-1), ph_format(-1), ph_version(-1), uip(NULL), linker(NULL), last_patch(NULL), last_patch_len(0), last_patch_off(0){ if (fi != NULL) file_size = fi->st_size(); uip = new UiPacker(this); memset(&ph, 0, sizeof(ph));}Packer::~Packer(){ delete uip; uip = NULL; delete linker; linker = NULL;}// for PackMastervoid Packer::assertPacker() const{ assert(getFormat() > 0); assert(getFormat() <= 255); assert(getVersion() >= 11); assert(getVersion() <= 14); assert(strlen(getName()) <= 13); // info: 32 is limit for show_all_packers() in help.cpp assert(strlen(getFullName(opt)) <= 28); assert(strlen(getFullName(NULL)) <= 28); if (bele == NULL) fprintf(stderr, "%s\n", getName()); assert(bele != NULL);#if 1 Linker *l = newLinker(); if (bele != l->bele) fprintf(stderr, "%s\n", getName()); assert(bele == l->bele); delete l;#endif}/*************************************************************************// public entries called from class PackMaster**************************************************************************/void Packer::doPack(OutputFile *fo){ uip->uiPackStart(fo); pack(fo); uip->uiPackEnd(fo);}void Packer::doUnpack(OutputFile *fo){ uip->uiUnpackStart(fo); unpack(fo); uip->uiUnpackEnd(fo);}void Packer::doTest(){ uip->uiTestStart(); test(); uip->uiTestEnd();}void Packer::doList(){ uip->uiListStart(); list(); uip->uiListEnd();}void Packer::doFileInfo(){ uip->uiFileInfoStart(); fileInfo(); uip->uiFileInfoEnd();}/*************************************************************************// default actions**************************************************************************/void Packer::test(){ unpack(NULL);}void Packer::list(){ uip->uiList();}void Packer::fileInfo(){ // FIXME: subclasses should list their sections here // We also should try to get a nice layout...}bool Packer::testUnpackVersion(int version) const{ if (version != ph_version && ph_version != -1) throwCantUnpack("program has been modified; run a virus checker!"); if (!canUnpackVersion(version)) throwCantUnpack("I am not compatible with older versions of UPX"); return true;}bool Packer::testUnpackFormat(int format) const{ if (format != ph_format && ph_format != -1) throwCantUnpack("program has been modified; run a virus checker!"); return canUnpackFormat(format);}bool ph_skipVerify(const PackHeader &ph){ if (M_IS_DEFLATE(ph.method)) return false; if (M_IS_LZMA(ph.method)) return false; if (ph.level > 1) return false; return true;}/*************************************************************************// compress - wrap call to low-level upx_compress()**************************************************************************/bool Packer::compress(upx_bytep i_ptr, unsigned i_len, upx_bytep o_ptr, const upx_compress_config_t *cconf_parm){ ph.u_len = i_len; ph.c_len = 0; assert(ph.level >= 1); assert(ph.level <= 10); // Avoid too many progress bar updates. 64 is s->bar_len in ui.cpp. unsigned step = (ph.u_len < 64*1024) ? 0 : ph.u_len / 64; // save current checksums ph.saved_u_adler = ph.u_adler; ph.saved_c_adler = ph.c_adler; // update checksum of uncompressed data ph.u_adler = upx_adler32(i_ptr, ph.u_len, ph.u_adler); // set compression paramters upx_compress_config_t cconf; cconf.reset(); if (cconf_parm) cconf = *cconf_parm; // cconf options if (M_IS_NRV2B(ph.method) || M_IS_NRV2D(ph.method) || M_IS_NRV2E(ph.method)) { if (opt->crp.crp_ucl.c_flags != -1) cconf.conf_ucl.c_flags = opt->crp.crp_ucl.c_flags; if (opt->crp.crp_ucl.p_level != -1) cconf.conf_ucl.p_level = opt->crp.crp_ucl.p_level; if (opt->crp.crp_ucl.h_level != -1) cconf.conf_ucl.h_level = opt->crp.crp_ucl.h_level; if (opt->crp.crp_ucl.max_offset != UINT_MAX && opt->crp.crp_ucl.max_offset < cconf.conf_ucl.max_offset) cconf.conf_ucl.max_offset = opt->crp.crp_ucl.max_offset; if (opt->crp.crp_ucl.max_match != UINT_MAX && opt->crp.crp_ucl.max_match < cconf.conf_ucl.max_match) cconf.conf_ucl.max_match = opt->crp.crp_ucl.max_match;#if defined(WITH_NRV) if (ph.level >= 7 || (ph.level >= 4 && ph.u_len >= 512*1024)) step = 0;#endif } if (M_IS_LZMA(ph.method)) { oassign(cconf.conf_lzma.pos_bits, opt->crp.crp_lzma.pos_bits); oassign(cconf.conf_lzma.lit_pos_bits, opt->crp.crp_lzma.lit_pos_bits); oassign(cconf.conf_lzma.lit_context_bits, opt->crp.crp_lzma.lit_context_bits); oassign(cconf.conf_lzma.dict_size, opt->crp.crp_lzma.dict_size); oassign(cconf.conf_lzma.num_fast_bytes, opt->crp.crp_lzma.num_fast_bytes); } if (M_IS_DEFLATE(ph.method)) { oassign(cconf.conf_zlib.mem_level, opt->crp.crp_zlib.mem_level); oassign(cconf.conf_zlib.window_bits, opt->crp.crp_zlib.window_bits); oassign(cconf.conf_zlib.strategy, opt->crp.crp_zlib.strategy); } if (uip->ui_pass >= 0) uip->ui_pass++; uip->startCallback(ph.u_len, step, uip->ui_pass, uip->ui_total_passes); uip->firstCallback(); //OutputFile::dump("data.raw", in, ph.u_len); // compress int r = upx_compress(i_ptr, ph.u_len, o_ptr, &ph.c_len, uip->getCallback(), ph.method, ph.level, &cconf, &ph.compress_result); //uip->finalCallback(ph.u_len, ph.c_len); uip->endCallback(); if (r == UPX_E_OUT_OF_MEMORY) throwOutOfMemoryException(); if (r != UPX_E_OK) throwInternalError("compression failed"); if (M_IS_NRV2B(ph.method) || M_IS_NRV2D(ph.method) || M_IS_NRV2E(ph.method)) { const ucl_uint *res = ph.compress_result.result_ucl.result; //ph.min_offset_found = res[0]; ph.max_offset_found = res[1]; //ph.min_match_found = res[2]; ph.max_match_found = res[3]; //ph.min_run_found = res[4]; ph.max_run_found = res[5]; ph.first_offset_found = res[6]; //ph.same_match_offsets_found = res[7]; if (cconf_parm) { assert(cconf.conf_ucl.max_offset == 0 || cconf.conf_ucl.max_offset >= ph.max_offset_found); assert(cconf.conf_ucl.max_match == 0 || cconf.conf_ucl.max_match >= ph.max_match_found); } } //printf("\nPacker::compress: %d/%d: %7d -> %7d\n", ph.method, ph.level, ph.u_len, ph.c_len); if (!checkCompressionRatio(ph.u_len, ph.c_len)) return false; // return in any case if not compressible if (ph.c_len >= ph.u_len) return false; // update checksum of compressed data ph.c_adler = upx_adler32(o_ptr, ph.c_len, ph.c_adler); // Decompress and verify. Skip this when using the fastest level. if (!ph_skipVerify(ph)) { // decompress unsigned new_len = ph.u_len; r = upx_decompress(o_ptr, ph.c_len, i_ptr, &new_len, ph.method, &ph.compress_result); if (r == UPX_E_OUT_OF_MEMORY) throwOutOfMemoryException(); //printf("%d %d: %d %d %d\n", ph.method, r, ph.c_len, ph.u_len, new_len); if (r != UPX_E_OK) throwInternalError("decompression failed"); if (new_len != ph.u_len) throwInternalError("decompression failed (size error)"); // verify decompression if (ph.u_adler != upx_adler32(i_ptr, ph.u_len, ph.saved_u_adler)) throwInternalError("decompression failed (checksum error)"); } return true;}#if 0bool Packer::compress(upx_bytep in, upx_bytep out, const upx_compress_config_t *cconf){ return ph_compress(ph, in, out, cconf);}#endifbool Packer::checkDefaultCompressionRatio(unsigned u_len, unsigned c_len) const{ assert((int)u_len > 0); assert((int)c_len > 0); if (c_len >= u_len) return false; unsigned gain = u_len - c_len; if (gain < 512) // need at least 512 bytes gain return false;#if 1 if (gain >= 4096) // ok if we have 4096 bytes gain return true; if (gain >= u_len / 16) // ok if we have 6.25% gain return true; return false;#else return true;#endif}bool Packer::checkCompressionRatio(unsigned u_len, unsigned c_len) const{ return checkDefaultCompressionRatio(u_len, c_len);}bool Packer::checkFinalCompressionRatio(const OutputFile *fo) const{ const unsigned u_len = file_size; const unsigned c_len = fo->getBytesWritten(); return checkDefaultCompressionRatio(u_len, c_len);}/*************************************************************************// decompress**************************************************************************/void ph_decompress(PackHeader &ph, const upx_bytep in, upx_bytep out, bool verify_checksum, Filter *ft){ unsigned adler; // verify checksum of compressed data if (verify_checksum) { adler = upx_adler32(in, ph.c_len, ph.saved_c_adler); if (adler != ph.c_adler) throwChecksumError(); } // decompress unsigned new_len = ph.u_len; int r = upx_decompress(in, ph.c_len, out, &new_len, ph.method, &ph.compress_result); if (r == UPX_E_OUT_OF_MEMORY) throwOutOfMemoryException(); if (r != UPX_E_OK || new_len != ph.u_len) throwCompressedDataViolation(); // verify checksum of decompressed data if (verify_checksum) { if (ft) ft->unfilter(out, ph.u_len); adler = upx_adler32(out, ph.u_len, ph.saved_u_adler); if (adler != ph.u_adler) throwChecksumError(); }}void Packer::decompress(const upx_bytep in, upx_bytep out, bool verify_checksum, Filter *ft){ ph_decompress(ph, in, out, verify_checksum, ft);}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -