⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 packer.cpp

📁 UPX 源代码
💻 CPP
📖 第 1 页 / 共 4 页
字号:
/* 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 + -