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

📄 packer.cpp

📁 UPX 源代码
💻 CPP
📖 第 1 页 / 共 4 页
字号:
/*************************************************************************// overlapping decompression**************************************************************************/bool ph_testOverlappingDecompression(const PackHeader &ph,                                     const upx_bytep buf,                                     const upx_bytep tbuf,                                     unsigned overlap_overhead){    if (ph.c_len >= ph.u_len)        return false;    assert((int) overlap_overhead >= 0);    assert((int) (ph.u_len + overlap_overhead) >= 0);    // Because upx_test_overlap() does not use the asm_fast decompressor    // we must account for extra 3 bytes that asm_fast does use,    // or else we may fail at runtime decompression.    unsigned extra = 0;    if (M_IS_NRV2B(ph.method) || M_IS_NRV2D(ph.method) || M_IS_NRV2E(ph.method))        extra = 3;    if (overlap_overhead <= 4 + extra)  // don't waste time here        return false;    overlap_overhead -= extra;    unsigned src_off = ph.u_len + overlap_overhead - ph.c_len;    unsigned new_len = ph.u_len;    int r = upx_test_overlap(buf - src_off, tbuf,                             src_off, ph.c_len, &new_len,                             ph.method, &ph.compress_result);    if (r == UPX_E_OUT_OF_MEMORY)        throwOutOfMemoryException();    return (r == UPX_E_OK && new_len == ph.u_len);}bool Packer::testOverlappingDecompression(const upx_bytep buf, const upx_bytep tbuf,                                          unsigned overlap_overhead) const{    return ph_testOverlappingDecompression(ph, buf, tbuf, overlap_overhead);}void Packer::verifyOverlappingDecompression(Filter *ft){    assert(ph.c_len < ph.u_len);    assert((int)ph.overlap_overhead > 0);    // Idea:    //   obuf[] was allocated with MemBuffer::allocForCompression(), and    //   its contents are no longer needed, i.e. the compressed data    //   must have been already written.    //   We now can perform a real overlapping decompression and    //   verify the checksum.    //    // Note:    //   This verify is just because of complete paranoia that there    //   could be a hidden bug in the upx_test_overlap implementation,    //   and it should not be necessary at all.    //    // See also:    //   Filter::verifyUnfilter()    if (ph_skipVerify(ph))        return;    unsigned offset = (ph.u_len + ph.overlap_overhead) - ph.c_len;    if (offset + ph.c_len > obuf.getSize())        return;    memmove(obuf + offset, obuf, ph.c_len);    decompress(obuf + offset, obuf, true, ft);    obuf.checkState();}void Packer::verifyOverlappingDecompression(upx_bytep o_ptr, unsigned o_size, Filter *ft){    assert(ph.c_len < ph.u_len);    assert((int)ph.overlap_overhead > 0);    if (ph_skipVerify(ph))        return;    unsigned offset = (ph.u_len + ph.overlap_overhead) - ph.c_len;    if (offset + ph.c_len > o_size)        return;    memmove(o_ptr + offset, o_ptr, ph.c_len);    decompress(o_ptr + offset, o_ptr, true, ft);}/*************************************************************************// Find overhead for in-place decompression in an heuristic way// (using a binary search). Return 0 on error.//// To speed up things://   - you can pass the range of an acceptable interval (so that//     we can succeed early)//   - you can enforce an upper_limit (so that we can fail early)**************************************************************************/unsigned Packer::findOverlapOverhead(const upx_bytep buf,                                     const upx_bytep tbuf,                                     unsigned range,                                     unsigned upper_limit) const{    assert((int) range >= 0);    // prepare to deal with very pessimistic values    unsigned low = 1;    unsigned high = UPX_MIN(ph.u_len + 512, upper_limit);    // but be optimistic for first try (speedup)    unsigned m = UPX_MIN(16u, high);    //    unsigned overhead = 0;    unsigned nr = 0;          // statistics    while (high >= low)    {        assert(m >= low); assert(m <= high);        assert(m < overhead || overhead == 0);        nr++;        bool success = testOverlappingDecompression(buf, tbuf, m);        //printf("testOverlapOverhead(%d): %d %d: %d -> %d\n", nr, low, high, m, (int)success);        if (success)        {            overhead = m;            // Succeed early if m lies in [low .. low+range-1], i.e. if            // if the range of the current interval is <= range.            //   if (m <= low + range - 1)            //   if (m <  low + range)            if (m - low < range)                    // avoid underflow                break;            high = m - 1;        }        else            low = m + 1;        ////m = (low + high) / 2;        m = (low & high) + ((low ^ high) >> 1);     // avoid overflow    }    //printf("findOverlapOverhead: %d (%d tries)\n", overhead, nr);    if (overhead == 0)        throwInternalError("this is an oo bug");    UNUSED(nr);    return overhead;}/*************************************************************************// file i/o utils**************************************************************************/void Packer::handleStub(InputFile *fif, OutputFile *fo, long size){    if (fo)    {        if (size > 0)        {            // copy stub from exe            info("Copying original stub: %ld bytes", size);            ByteArray(stub, size);            fif->seek(0,SEEK_SET);            fif->readx(stub,size);            fo->write(stub,size);        }        else        {            // no stub        }    }}void Packer::checkOverlay(unsigned overlay){    if ((int)overlay < 0 || (off_t)overlay > file_size)        throw OverlayException("invalid overlay size; file is possibly corrupt");    if (overlay == 0)        return;    info("Found overlay: %d bytes", overlay);    if (opt->overlay == opt->SKIP_OVERLAY)        throw OverlayException("file has overlay -- skipped; try '--overlay=copy'");}void Packer::copyOverlay(OutputFile *fo, unsigned overlay,                         MemBuffer *buf,                         bool do_seek){    assert((int)overlay >= 0);    assert((off_t)overlay < file_size);    buf->checkState();    if (!fo || overlay == 0)        return;    if (opt->overlay != opt->COPY_OVERLAY)    {        assert(opt->overlay == opt->STRIP_OVERLAY);        infoWarning("stripping overlay: %d bytes", overlay);        return;    }    info("Copying overlay: %d bytes", overlay);    if (do_seek)        fi->seek(-(off_t)overlay, SEEK_END);    // get buffer size, align to improve i/o speed    unsigned buf_size = buf->getSize();    if (buf_size > 65536)        buf_size = ALIGN_DOWN(buf_size, 4096u);    assert((int)buf_size > 0);    do {        unsigned len = overlay < buf_size ? overlay : buf_size;        fi->readx(buf, len);        fo->write(buf, len);        overlay -= len;    } while (overlay > 0);    buf->checkState();}// Create a pseudo-unique program id.unsigned Packer::getRandomId() const{    if (opt->debug.disable_random_id)        return 0x01020304;    unsigned id = 0;#if 0 && defined(__unix__)    // Don't consume precious bytes from /dev/urandom.    int fd = open("/dev/urandom", O_RDONLY);    if (fd < 0)        fd = open("/dev/random", O_RDONLY);    if (fd >= 0)    {        if (read(fd, &id, 4) != 4)            id = 0;        close(fd);    }#endif    while (id == 0)    {#if !defined(HAVE_GETTIMEOFDAY) || defined(__DJGPP__)        id ^= (unsigned) time(NULL);        id ^= ((unsigned) clock()) << 12;#else        struct timeval tv;        gettimeofday(&tv, 0);        id ^= (unsigned) tv.tv_sec;        id ^= ((unsigned) tv.tv_usec) << 12;  // shift into high-bits#endif#if defined(HAVE_GETPID)        id ^= (unsigned) getpid();#endif        id ^= (unsigned) fi->st.st_ino;        id ^= (unsigned) fi->st.st_atime;        id ^= (unsigned) rand();    }    return id;}/*************************************************************************// packheader util**************************************************************************/// this is called directly after the constructor from class PackMastervoid Packer::initPackHeader(){    memset(&ph, 0, sizeof(ph));    ph.version = getVersion();    ph.format = getFormat();    ph.method = M_NONE;    ph.level = -1;    ph.u_adler = ph.c_adler = ph.saved_u_adler = ph.saved_c_adler = upx_adler32(NULL,0);    ph.buf_offset = -1;    ph.u_file_size = file_size;}// this is called directly after canPack() from class PackMastervoid Packer::updatePackHeader(){    assert(opt->cmd == CMD_COMPRESS);    //    const int *m = getCompressionMethods(opt->method, opt->level);    ph.method = m[0];    ph.level = opt->level;    if (ph.level < 0)        ph.level = file_size < 512*1024 ? 8 : 7;    //    assert(isValidCompressionMethod(ph.method));    assert(1 <= ph.level && ph.level <= 10);}// FIXME: remove patchPackHeader() and fold into relocateLoader();//   then make linker->relocate() private (friend Packer)int Packer::patchPackHeader(void *b, int blen){    assert(isValidFilter(ph.filter));    const int size = ph.getPackHeaderSize();    if (linker->findSection("UPX1HEAD", false))        assert(size == linker->getSectionSize("UPX1HEAD"));    int boff = find_le32(b, blen, UPX_MAGIC_LE32);    checkPatch(b, blen, boff, size);    unsigned char *p = (unsigned char *)b + boff;    ph.putPackHeader(p);    return boff;}bool Packer::getPackHeader(void *b, int blen, bool allow_incompressible){    if (!ph.fillPackHeader((unsigned char *)b, blen))        return false;    if (ph.version > getVersion())        throwCantUnpack("need a newer version of UPX");    // Some formats might be able to unpack old versions because    // their implementation hasn't changed. Ask them.    if (opt->cmd != CMD_FILEINFO)        if (!testUnpackVersion(ph.version))            return false;    if (ph.c_len > ph.u_len        || (ph.c_len == ph.u_len && !allow_incompressible)        || (off_t)ph.c_len >= file_size        || ph.version <= 0 || ph.version >= 0xff)        throwCantUnpack("header corrupted");    else if ((off_t)ph.u_len > ph.u_file_size)    {#if 0        // FIXME: does this check make sense w.r.t. overlays ???        if (ph.format == UPX_F_W32_PE || ph.format == UPX_F_DOS_EXE)            // may get longer            ((void)0);        else            throwCantUnpack("header size corrupted");#endif    }    if (!isValidCompressionMethod(ph.method))        throwCantUnpack("unknown compression method (try a newer version of UPX)");    // Some formats might be able to unpack "subformats". Ask them.    if (!testUnpackFormat(ph.format))        return false;    return true;}bool Packer::readPackHeader(int len, bool allow_incompressible){    assert((int)len > 0);    MemBuffer buf(len);    len = fi->read(buf, len);    if (len <= 0)        return false;    return getPackHeader(buf, len, allow_incompressible);}void Packer::checkAlreadyPacked(const void *b, int blen){    int boff = find_le32(b, blen, UPX_MAGIC_LE32);    if (boff < 0)        return;    // FIXME: could add some more checks to verify that this    //   is a real PackHeader, e.g.    //    //PackHeader tmp;    //if (!tmp.fillPackHeader((unsigned char *)b + boff, blen - boff))    //    return;    //    // This also would require that the buffer in 'b' holds    // the full PackHeader, and not only the 4 magic bytes.    throwAlreadyPacked();}/*************************************************************************// patch util for loader**************************************************************************/

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -