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

📄 pefile.cpp

📁 UPX 源代码
💻 CPP
📖 第 1 页 / 共 4 页
字号:
/* pefile.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   <mfx@users.sourceforge.net>          <ml1050@users.sourceforge.net> */#include "conf.h"#include "file.h"#include "filter.h"#include "packer.h"#include "pefile.h"#define IDSIZE(x)       ih.ddirs[x].size#define IDADDR(x)       ih.ddirs[x].vaddr#define ODSIZE(x)       oh.ddirs[x].size#define ODADDR(x)       oh.ddirs[x].vaddr#define isdll           ((ih.flags & DLL_FLAG) != 0)#define FILLVAL         0/*************************************************************************//**************************************************************************/#if defined(__BORLANDC__)#  undef strcpy#  define strcpy(a,b)   strcpy((char *)(a),(const char *)(b))#endif#if (__ACC_CXX_HAVE_PLACEMENT_DELETE) || defined(__DJGPP__)#include "bptr.h"#define IPTR(type, var)         BoundedPtr<type> var(ibuf, ibuf.getSize())#define OPTR(type, var)         BoundedPtr<type> var(obuf, obuf.getSize())#define IPTR_I(type, var, v)    BoundedPtr<type> var(ibuf, ibuf.getSize(), v)#define OPTR_I(type, var, v)    BoundedPtr<type> var(obuf, obuf.getSize(), v)#define IPTR_C(type, var, v)    const BoundedPtr<type> var(ibuf, ibuf.getSize(), v)#define OPTR_C(type, var, v)    const BoundedPtr<type> var(obuf, obuf.getSize(), v)#else#define IPTR(type, var)         type* var = 0#define OPTR(type, var)         type* var = 0#define IPTR_I(type, var, v)    type* var = (v)#define OPTR_I(type, var, v)    type* var = (v)#define IPTR_C(type, var, v)    type* const var = (v)#define OPTR_C(type, var, v)    type* const var = (v)#endifstatic void xcheck(const void *p, size_t plen, const void *b, size_t blen){    const char *pp = (const char *) p;    const char *bb = (const char *) b;    if (pp < bb || pp > bb + blen || pp + plen > bb + blen)        throwCantUnpack("pointer out of range; take care!");}#if 0static void xcheck(size_t poff, size_t plen, const void *b, size_t blen){    ACC_UNUSED(b);    if (poff > blen || poff + plen > blen)        throwCantUnpack("pointer out of range; take care!");}#endif#define ICHECK(x, size)     xcheck(x, size, ibuf, ibuf.getSize())#define OCHECK(x, size)     xcheck(x, size, obuf, obuf.getSize())#define imemset(a,b,c)      ICHECK(a,c), memset(a,b,c)#define omemset(a,b,c)      OCHECK(a,c), memset(a,b,c)#define imemcpy(a,b,c)      ICHECK(a,c), memcpy(a,b,c)#define omemcpy(a,b,c)      OCHECK(a,c), memcpy(a,b,c)/*************************************************************************//**************************************************************************/PeFile::PeFile(InputFile *f) : super(f){    bele = &N_BELE_RTP::le_policy;    //printf("pe_header_t %d\n", (int) sizeof(pe_header_t));    //printf("pe_section_t %d\n", (int) sizeof(pe_section_t));    COMPILE_TIME_ASSERT(sizeof(pe_header_t) == 248)    COMPILE_TIME_ASSERT(sizeof(pe_header_t::ddirs_t) == 8)    COMPILE_TIME_ASSERT(sizeof(pe_section_t) == 40)    COMPILE_TIME_ASSERT_ALIGNED1(pe_header_t)    COMPILE_TIME_ASSERT_ALIGNED1(pe_header_t::ddirs_t)    COMPILE_TIME_ASSERT_ALIGNED1(pe_section_t)    COMPILE_TIME_ASSERT(RT_LAST == TABLESIZE(opt->win32_pe.compress_rt));    isection = NULL;    oimport = NULL;    oimpdlls = NULL;    orelocs = NULL;    oexport = NULL;    otls = NULL;    oresources = NULL;    oxrelocs = NULL;    icondir_offset = 0;    icondir_count = 0;    importbyordinal = false;    kernel32ordinal = false;    tlsindex = 0;    big_relocs = 0;    sorelocs = 0;    soxrelocs = 0;    sotls = 0;}PeFile::~PeFile(){    delete [] isection;    delete [] orelocs;    delete [] oimport;    delete [] oimpdlls;    delete [] oexport;    delete [] otls;    delete [] oresources;    delete [] oxrelocs;    //delete res;}bool PeFile::testUnpackVersion(int version) const{    if (version != ph_version && ph_version != -1)        throwCantUnpack("program has been modified; run a virus checker!");    if (!canUnpackVersion(version))        throwCantUnpack("this program is packed with an obsolete version and cannot be unpacked");    return true;}/*************************************************************************// util**************************************************************************/int PeFile::readFileHeader(){    struct exe_header_t    {        LE16 mz;        LE16 m512;        LE16 p512;        char _[18];        LE16 relocoffs;        char __[34];        LE32 nexepos;    }    __attribute_packed;    COMPILE_TIME_ASSERT(sizeof(exe_header_t) == 64);    exe_header_t h;    int ic;    pe_offset = 0;    for (ic = 0; ic < 20; ic++)    {        fi->seek(pe_offset,SEEK_SET);        fi->readx(&h,sizeof(h));        if (h.mz == 'M' + 'Z'*256) // dos exe        {            if (h.relocoffs >= 0x40)      // new format exe                pe_offset += h.nexepos;            else                pe_offset += h.p512*512+h.m512 - h.m512 ? 512 : 0;        }        else if (get_le32(&h) == 'P' + 'E'*256)            break;        else            return 0;    }    if (ic == 20)        return 0;    fi->seek(pe_offset,SEEK_SET);    fi->readx(&ih,sizeof(ih));    fi->seek(0x200,SEEK_SET);    fi->readx(&h,6);    return getFormat();}/*************************************************************************// interval handling**************************************************************************/PeFile::Interval::Interval(void *b) : capacity(0),base(b),ivarr(NULL),ivnum(0){}PeFile::Interval::~Interval(){    free(ivarr);}void PeFile::Interval::add(const void *start,unsigned len){    add(ptr_diff(start,base),len);}void PeFile::Interval::add(const void *start,const void *end){    add(ptr_diff(start,base),ptr_diff(end,start));}int __acc_cdecl_qsort PeFile::Interval::compare(const void *p1,const void *p2){    const interval *i1 = (const interval*) p1;    const interval *i2 = (const interval*) p2;    if (i1->start < i2->start) return -1;    if (i1->start > i2->start) return 1;    if (i1->len < i2->len) return 1;    if (i1->len > i2->len) return -1;    return 0;}void PeFile::Interval::add(unsigned start,unsigned len){    if (ivnum == capacity)        ivarr = (interval*) realloc(ivarr,(capacity += 15) * sizeof (interval));    ivarr[ivnum].start = start;    ivarr[ivnum++].len = len;}void PeFile::Interval::add(const Interval *iv){    for (unsigned ic = 0; ic < iv->ivnum; ic++)        add(iv->ivarr[ic].start,iv->ivarr[ic].len);}void PeFile::Interval::flatten(){    if (!ivnum)        return;    qsort(ivarr,ivnum,sizeof (interval),Interval::compare);    for (unsigned ic = 0; ic < ivnum - 1; ic++)    {        unsigned jc;        for (jc = ic + 1; jc < ivnum && ivarr[ic].start + ivarr[ic].len >= ivarr[jc].start; jc++)            if (ivarr[ic].start + ivarr[ic].len < ivarr[jc].start + ivarr[jc].len)                ivarr[ic].len = ivarr[jc].start + ivarr[jc].len - ivarr[ic].start;        if (jc > ic + 1)        {            memmove(ivarr + ic + 1, ivarr + jc,sizeof(interval) * (ivnum - jc));            ivnum -= jc - ic - 1;        }    }}void PeFile::Interval::clear(){    for (unsigned ic = 0; ic < ivnum; ic++)        memset((char*) base + ivarr[ic].start,0,ivarr[ic].len);}void PeFile::Interval::dump() const{    printf("%d intervals:\n",ivnum);    for (unsigned ic = 0; ic < ivnum; ic++)        printf("%x %x\n",ivarr[ic].start,ivarr[ic].len);}/*************************************************************************// relocation handling**************************************************************************/struct PeFile::Reloc::reloc{    LE32  pagestart;    LE32  size;}__attribute_packed;void PeFile::Reloc::newRelocPos(void *p){    rel = (reloc*) p;    rel1 = (LE16*) ((char*) p + sizeof (reloc));}PeFile::Reloc::Reloc(upx_byte *s,unsigned si) :    start(s), size(si), rel(NULL), rel1(NULL){    COMPILE_TIME_ASSERT(sizeof(reloc) == 8);    memset(counts,0,sizeof(counts));    unsigned pos,type;    while (next(pos,type))        counts[type]++;}PeFile::Reloc::Reloc(unsigned rnum) :    start(NULL), size(0), rel(NULL), rel1(NULL){    start = new upx_byte[rnum * 4 + 8192];    counts[0] = 0;}bool PeFile::Reloc::next(unsigned &pos,unsigned &type){    if (!rel)        newRelocPos(start);    if (ptr_diff(rel, start) >= (int) size || rel->pagestart == 0)        return rel = 0,false; // rewind    pos = rel->pagestart + (*rel1 & 0xfff);    type = *rel1++ >> 12;    //printf("%x %d\n",pos,type);    if (ptr_diff(rel1,rel) >= (int) rel->size)        newRelocPos(rel1);    return type == 0 ? next(pos,type) : true;}void PeFile::Reloc::add(unsigned pos,unsigned type){    set_le32(start + 1024 + 4 * counts[0]++,(pos << 4) + type);}void PeFile::Reloc::finish(upx_byte *&p,unsigned &siz){    unsigned prev = 0xffffffff;    set_le32(start + 1024 + 4 * counts[0]++,0xf0000000);    qsort(start + 1024,counts[0],4,le32_compare);    rel = (reloc*) start;    rel1 = (LE16*) rel;    for (unsigned ic = 0; ic < counts[0]; ic++)    {        unsigned pos = get_le32(start + 1024 + 4 * ic);        if ((pos ^ prev) >= 0x10000)        {            prev = pos;            *rel1 = 0;            rel->size = ALIGN_UP(ptr_diff(rel1,rel),4);            newRelocPos((char *)rel + rel->size);            rel->pagestart = (pos >> 4) &~ 0xfff;        }        *rel1++ = (pos << 12) + ((pos >> 4) & 0xfff);    }    p = start;    siz = ptr_diff(rel1,start) &~ 3;    siz -= 8;    assert(siz > 0);    start = 0; // safety}void PeFile::processRelocs(Reloc *rel) // pass2{    rel->finish(oxrelocs,soxrelocs);    if (opt->win32_pe.strip_relocs && !isdll)        soxrelocs = 0;}void PeFile::processRelocs() // pass1{    big_relocs = 0;    Reloc rel(ibuf + IDADDR(PEDIR_RELOC),IDSIZE(PEDIR_RELOC));    const unsigned *counts = rel.getcounts();    const unsigned rnum = counts[1] + counts[2] + counts[3];    if ((opt->win32_pe.strip_relocs && !isdll) || rnum == 0)    {        if (IDSIZE(PEDIR_RELOC))            ibuf.fill(IDADDR(PEDIR_RELOC), IDSIZE(PEDIR_RELOC), FILLVAL);        orelocs = new upx_byte [1];        sorelocs = 0;        return;    }    unsigned ic;    for (ic = 15; ic > 3; ic--)        if (counts[ic])            infoWarning("skipping unsupported relocation type %d (%d)",ic,counts[ic]);    LE32 *fix[4];    for (; ic; ic--)        fix[ic] = new LE32 [counts[ic]];    unsigned xcounts[4];    memset(xcounts, 0, sizeof(xcounts));    // prepare sorting    unsigned pos,type;    while (rel.next(pos,type))    {        if (pos >= ih.imagesize)            continue;           // skip out-of-bounds record        if (type < 4)            fix[type][xcounts[type]++] = pos - rvamin;    }    // remove duplicated records    for (ic = 1; ic <= 3; ic++)    {        qsort(fix[ic], xcounts[ic], 4, le32_compare);        unsigned prev = ~0;        unsigned jc = 0;        for (unsigned kc = 0; kc < xcounts[ic]; kc++)            if (fix[ic][kc] != prev)                prev = fix[ic][jc++] = fix[ic][kc];        //printf("xcounts[%u] %u->%u\n", ic, xcounts[ic], jc);        xcounts[ic] = jc;    }    // preprocess "type 3" relocation records    for (ic = 0; ic < xcounts[3]; ic++)    {        pos = fix[3][ic] + rvamin;        set_le32(ibuf + pos, get_le32(ibuf + pos) - ih.imagebase - rvamin);    }    ibuf.fill(IDADDR(PEDIR_RELOC), IDSIZE(PEDIR_RELOC), FILLVAL);    orelocs = new upx_byte [rnum * 4 + 1024];  // 1024 - safety    sorelocs = ptr_diff(optimizeReloc32((upx_byte*) fix[3], xcounts[3],                                        orelocs, ibuf + rvamin,1, &big_relocs),                        orelocs);    delete [] fix[3];    // append relocs type "LOW" then "HIGH"    for (ic = 2; ic ; ic--)    {        memcpy(orelocs + sorelocs,fix[ic],4 * xcounts[ic]);        sorelocs += 4 * xcounts[ic];        delete [] fix[ic];        set_le32(orelocs + sorelocs,0);        if (xcounts[ic])        {            sorelocs += 4;            big_relocs |= 2 * ic;

⌨️ 快捷键说明

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