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

📄 pefile.cpp

📁 UPX 源代码
💻 CPP
📖 第 1 页 / 共 4 页
字号:
                return true;            if (delim2 && delim2 < delim1)                return true;            if (helper::match(iname, nname, delim1 + 1))                return true;        }        if (delim2 == NULL)            break;        keep = delim2 + 1;    }    return false;}void PeFile::processResources(Resource *res){    const unsigned vaddr = IDADDR(PEDIR_RESOURCE);    if ((soresources = IDSIZE(PEDIR_RESOURCE)) == 0)        return;    // setup default options for resource compression    if (opt->win32_pe.compress_resources < 0)        opt->win32_pe.compress_resources = true;    if (!opt->win32_pe.compress_resources)    {        opt->win32_pe.compress_icons = false;        for (int i = 0; i < RT_LAST; i++)            opt->win32_pe.compress_rt[i] = false;    }    if (opt->win32_pe.compress_rt[RT_STRING] < 0)    {        // by default, don't compress RT_STRINGs of screensavers (".scr")        opt->win32_pe.compress_rt[RT_STRING] = true;        if (fn_has_ext(fi->getName(),"scr"))            opt->win32_pe.compress_rt[RT_STRING] = false;    }    res->init(ibuf + vaddr);    for (soresources = res->dirsize(); res->next(); soresources += 4 + res->size())        ;    oresources = new upx_byte[soresources];    upx_byte *ores = oresources + res->dirsize();    char *keep_icons = NULL; // icon ids in the first icon group    unsigned iconsin1stdir = 0;    if (opt->win32_pe.compress_icons == 2)        while (res->next()) // there is no rewind() in Resource            if (res->itype() == RT_GROUP_ICON && iconsin1stdir == 0)            {                iconsin1stdir = get_le16(ibuf + res->offs() + 4);                keep_icons = new char[1 + iconsin1stdir * 9];                *keep_icons = 0;                for (unsigned ic = 0; ic < iconsin1stdir; ic++)                    snprintf(keep_icons + strlen(keep_icons), 9, "3/%u,",                             get_le16(ibuf + res->offs() + 6 + ic * 14 + 12));                if (*keep_icons)                    keep_icons[strlen(keep_icons) - 1] = 0;            }    // the icon id which should not be compressed when compress_icons == 1    unsigned first_icon_id = (unsigned) -1;    if (opt->win32_pe.compress_icons == 1)        while (res->next())            if (res->itype() == RT_GROUP_ICON && first_icon_id == (unsigned) -1)                first_icon_id = get_le16(ibuf + res->offs() + 6 + 12);    bool compress_icon = opt->win32_pe.compress_icons > 1;    bool compress_idir = opt->win32_pe.compress_icons == 3;    // some statistics    unsigned usize = 0;    unsigned csize = 0;    unsigned unum = 0;    unsigned cnum = 0;    while (res->next())    {        const unsigned rtype = res->itype();        bool do_compress = true;        if (!opt->win32_pe.compress_resources)            do_compress = false;        else if (rtype == RT_ICON)          // icon        {            if (opt->win32_pe.compress_icons == 0)                do_compress = false;            else if (opt->win32_pe.compress_icons == 1)                if ((first_icon_id == (unsigned) -1                     || first_icon_id == res->iname()))                    do_compress = compress_icon;        }        else if (rtype == RT_GROUP_ICON)    // icon directory            do_compress = compress_idir && opt->win32_pe.compress_icons;        else if (rtype > 0 && rtype < RT_LAST)            do_compress = opt->win32_pe.compress_rt[rtype] ? true : false;        if (keep_icons)            do_compress &= !match(res->itype(), res->ntype(), res->iname(),                                  res->nname(), keep_icons);        do_compress &= !match(res->itype(), res->ntype(), res->iname(),                              res->nname(), "TYPELIB,REGISTRY,16");        do_compress &= !match(res->itype(), res->ntype(), res->iname(),                              res->nname(), opt->win32_pe.keep_resource);        if (do_compress)        {            csize += res->size();            cnum++;            continue;        }        usize += res->size();        unum++;        set_le32(ores,res->offs()); // save original offset        ores += 4;        ICHECK(ibuf + res->offs(), res->size());        memcpy(ores, ibuf + res->offs(), res->size());        ibuf.fill(res->offs(), res->size(), FILLVAL);        res->newoffs() = ptr_diff(ores,oresources);        if (rtype == RT_ICON && opt->win32_pe.compress_icons == 1)            compress_icon = true;        else if (rtype == RT_GROUP_ICON)        {            if (opt->win32_pe.compress_icons == 1)            {                icondir_offset = 4 + ptr_diff(ores,oresources);                icondir_count = get_le16(oresources + icondir_offset);                set_le16(oresources + icondir_offset,1);            }            compress_idir = true;        }        ores += res->size();    }    soresources = ptr_diff(ores,oresources);    delete[] keep_icons;    if (!res->clear())    {        // The area occupied by the resource directory is not continuous        // so to still support uncompression, I can't zero this area.        // This decreases compression ratio, so FIXME somehow.        infoWarning("can't remove unneeded resource directory");    }    info("Resources: compressed %u (%u bytes), not compressed %u (%u bytes)",cnum,csize,unum,usize);}unsigned PeFile::virta2objnum(unsigned addr,pe_section_t *sect,unsigned objs){    unsigned ic;    for (ic = 0; ic < objs; ic++)    {        if (sect->vaddr <= addr && sect->vaddr + sect->vsize > addr)            return ic;        sect++;    }    //throwCantPack("virta2objnum() failed");    return ic;}unsigned PeFile::tryremove (unsigned vaddr,unsigned objs){    unsigned ic = virta2objnum(vaddr,isection,objs);    if (ic && ic == objs - 1)    {        //fprintf(stderr,"removed section: %d size: %lx\n",ic,(long)isection[ic].size);        info("removed section: %d size: 0x%lx",ic,(long)isection[ic].size);        objs--;    }    return objs;}unsigned PeFile::stripDebug(unsigned overlaystart){    if (IDADDR(PEDIR_DEBUG) == 0)        return overlaystart;    struct debug_dir_t    {        char  _[16]; // flags, time/date, version, type        LE32  size;        char  __[4]; // rva        LE32  fpos;    }    __attribute_packed;    const debug_dir_t *dd = (const debug_dir_t*) (ibuf + IDADDR(PEDIR_DEBUG));    for (unsigned ic = 0; ic < IDSIZE(PEDIR_DEBUG) / sizeof(debug_dir_t); ic++, dd++)        if (overlaystart == dd->fpos)            overlaystart += dd->size;    ibuf.fill(IDADDR(PEDIR_DEBUG), IDSIZE(PEDIR_DEBUG), FILLVAL);    return overlaystart;}/*************************************************************************// pack**************************************************************************//*************************************************************************// unpack**************************************************************************/void PeFile::rebuildRelocs(upx_byte *& extrainfo){    if (!ODADDR(PEDIR_RELOC) || !ODSIZE(PEDIR_RELOC) || (oh.flags & RELOCS_STRIPPED))        return;    if (ODSIZE(PEDIR_RELOC) == 8) // some tricky dlls use this    {        omemcpy(obuf + ODADDR(PEDIR_RELOC) - rvamin, "\x0\x0\x0\x0\x8\x0\x0\x0", 8);        return;    }    upx_byte *rdata = obuf + get_le32(extrainfo);    const upx_byte big = extrainfo[4];    extrainfo += 5;//    upx_byte *p = rdata;    OPTR_I(upx_byte, p, rdata);    MemBuffer wrkmem;    unsigned relocn = unoptimizeReloc32(&rdata,obuf,&wrkmem,1);    unsigned r16 = 0;    if (big & 6)                // 16 bit relocations    {        const LE32 *q = (LE32*) rdata;        while (*q++)            r16++;        if ((big & 6) == 6)            while (*++q)                r16++;    }    Reloc rel(relocn + r16);    if (big & 6)    {        LE32 *q = (LE32*) rdata;        while (*q)            rel.add(*q++ + rvamin,(big & 4) ? 2 : 1);        if ((big & 6) == 6)            while (*++q)                rel.add(*q + rvamin,1);        rdata = (upx_byte*) q;    }    //memset(p,0,rdata - p);    for (unsigned ic = 0; ic < relocn; ic++)    {        p = obuf + get_le32(wrkmem + 4 * ic);        set_le32(p, get_le32((unsigned char *)p) + oh.imagebase + rvamin);        rel.add(rvamin + get_le32(wrkmem + 4 * ic),3);    }    rel.finish (oxrelocs,soxrelocs);    if (opt->win32_pe.strip_relocs && !isdll)    {        obuf.clear(ODADDR(PEDIR_RELOC) - rvamin, ODSIZE(PEDIR_RELOC));        ODADDR(PEDIR_RELOC) = 0;        soxrelocs = 0;        // FIXME: try to remove the original relocation section somehow    }    else        omemcpy(obuf + ODADDR(PEDIR_RELOC) - rvamin,oxrelocs,soxrelocs);    delete [] oxrelocs; oxrelocs = NULL;    wrkmem.dealloc();    ODSIZE(PEDIR_RELOC) = soxrelocs;}void PeFile::rebuildExports(){    if (ODSIZE(PEDIR_EXPORT) == 0 || ODADDR(PEDIR_EXPORT) == IDADDR(PEDIR_EXPORT))        return; // nothing to do    opt->win32_pe.compress_exports = 0;    Export xport((char*)(unsigned char*) ibuf - isection[2].vaddr);    processExports(&xport);    processExports(&xport,ODADDR(PEDIR_EXPORT));    omemcpy(obuf + ODADDR(PEDIR_EXPORT) - rvamin,oexport,soexport);}void PeFile::rebuildTls(){    // this is an easy one : just do nothing ;-)}void PeFile::rebuildResources(upx_byte *& extrainfo){    if (ODSIZE(PEDIR_RESOURCE) == 0 || IDSIZE(PEDIR_RESOURCE) == 0)        return;    icondir_count = get_le16(extrainfo);    extrainfo += 2;    const unsigned vaddr = IDADDR(PEDIR_RESOURCE);    const upx_byte *r = ibuf - isection[ih.objects - 1].vaddr;    Resource res(r + vaddr);    while (res.next())        if (res.offs() > vaddr)        {            unsigned origoffs = get_le32(r + res.offs() - 4);            res.newoffs() = origoffs;            omemcpy(obuf + origoffs - rvamin,r + res.offs(),res.size());            if (icondir_count && res.itype() == RT_GROUP_ICON)            {                set_le16(obuf + origoffs - rvamin + 4,icondir_count);                icondir_count = 0;            }        }    upx_byte *p = res.build();    // write back when the original is zeroed    if (get_le32(obuf + ODADDR(PEDIR_RESOURCE) - rvamin + 12) == 0)        omemcpy(obuf + ODADDR(PEDIR_RESOURCE) - rvamin,p,res.dirsize());    delete [] p;}void PeFile::unpack(OutputFile *fo){    //infoHeader("[Processing %s, format %s, %d sections]", fn_basename(fi->getName()), getName(), objs);    handleStub(fi,fo,pe_offset);    const unsigned iobjs = ih.objects;    const unsigned overlay = file_size - ALIGN_UP(isection[iobjs - 1].rawdataptr                                                  + isection[iobjs - 1].size,                                                  ih.filealign);    checkOverlay(overlay);    ibuf.alloc(ph.c_len);    obuf.allocForUncompression(ph.u_len);    fi->seek(isection[1].rawdataptr - 64 + ph.buf_offset + ph.getPackHeaderSize(),SEEK_SET);    fi->readx(ibuf,ph.c_len);    // decompress    decompress(ibuf,obuf);    upx_byte *extrainfo = obuf + get_le32(obuf + ph.u_len - 4);    //upx_byte * const eistart = extrainfo;    memcpy(&oh, extrainfo, sizeof (oh));    extrainfo += sizeof (oh);    unsigned objs = oh.objects;    Array(pe_section_t, osection, objs);    memcpy(osection,extrainfo,sizeof(pe_section_t) * objs);    rvamin = osection[0].vaddr;    extrainfo += sizeof(pe_section_t) * objs;    // read the noncompressed section    ibuf.dealloc();    ibuf.alloc(isection[2].size);    fi->seek(isection[2].rawdataptr,SEEK_SET);    fi->readx(ibuf,isection[2].size);    // unfilter    if (ph.filter)    {        Filter ft(ph.level);        ft.init(ph.filter,oh.codebase - rvamin);        ft.cto = (unsigned char) ph.filter_cto;        ft.unfilter(obuf + oh.codebase - rvamin, oh.codesize);    }    rebuildImports(extrainfo);    rebuildRelocs(extrainfo);    rebuildTls();    rebuildExports();    if (iobjs == 4)    {        // read the resource section if present        ibuf.dealloc();        ibuf.alloc(isection[3].size);        fi->seek(isection[3].rawdataptr,SEEK_SET);        fi->readx(ibuf,isection[3].size);    }    rebuildResources(extrainfo);    //FIXME: this does bad things if the relocation section got removed    // during compression ...    //memset(eistart,0,extrainfo - eistart + 4);    // fill the data directory    ODADDR(PEDIR_DEBUG) = 0;    ODSIZE(PEDIR_DEBUG) = 0;    ODADDR(PEDIR_IAT) = 0;    ODSIZE(PEDIR_IAT) = 0;    ODADDR(PEDIR_BOUNDIM) = 0;    ODSIZE(PEDIR_BOUNDIM) = 0;    // oh.headersize = osection[0].rawdataptr;    // oh.headersize = ALIGN_UP(pe_offset + sizeof(oh) + sizeof(pe_section_t) * objs, oh.filealign);    oh.headersize = rvamin;    oh.chksum = 0;    // FIXME: ih.flags is checked here because of a bug in UPX 0.92    if ((opt->win32_pe.strip_relocs && !isdll) || (ih.flags & RELOCS_STRIPPED))    {        oh.flags |= RELOCS_STRIPPED;        ODADDR(PEDIR_RELOC) = 0;        ODSIZE(PEDIR_RELOC) = 0;    }    // write decompressed file    if (fo)    {        unsigned ic;        for (ic = 0; ic < objs && osection[ic].rawdataptr == 0; ic++)            ;        ibuf.dealloc();        ibuf.alloc(osection[ic].rawdataptr);        ibuf.clear();        infoHeader("[Writing uncompressed file]");        // write loader + compressed file        fo->write(&oh,sizeof(oh));        fo->write(osection,objs * sizeof(pe_section_t));        fo->write(ibuf,osection[ic].rawdataptr - fo->getBytesWritten());        for (ic = 0; ic < objs; ic++)            if (osection[ic].rawdataptr)                fo->write(obuf + osection[ic].vaddr - rvamin,ALIGN_UP(osection[ic].size,oh.filealign));        copyOverlay(fo, overlay, &obuf);    }    ibuf.dealloc();}/* extra info added to help uncompression: <ih sizeof(pe_head)> <pe_section_t objs*sizeof(pe_section_t)> <start of compressed imports 4> - optional           \ <start of the names from uncompressed imports> - opt / <start of compressed relocs 4> - optional   \ <relocation type indicator 1> - optional    / <icondir_count 2> - optional <offset of extra info 4>*//*vi:ts=4:et*/

⌨️ 快捷键说明

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