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

📄 pefile.cpp

📁 UPX 源代码
💻 CPP
📖 第 1 页 / 共 4 页
字号:
        }    }    info("Relocations: original size: %u bytes, preprocessed size: %u bytes",(unsigned) IDSIZE(PEDIR_RELOC),sorelocs);}/*************************************************************************// import handling**************************************************************************/struct import_desc{    LE32  oft;      // orig first thunk    char  _[8];    LE32  dllname;    LE32  iat;      // import address table}__attribute_packed;void PeFile::processImports(unsigned myimport, unsigned iat_off) // pass 2{    COMPILE_TIME_ASSERT(sizeof(import_desc) == 20);    // adjust import data    for (import_desc *im = (import_desc*) oimpdlls; im->dllname; im++)    {        if (im->dllname < myimport)            im->dllname += myimport;        LE32 *p = (LE32*) (oimpdlls + im->iat);        im->iat += myimport;        im->oft = im->iat;        while (*p)            if ((*p++ & 0x80000000) == 0)  // import by name?                p[-1] += myimport;        im->iat = im == (import_desc*) oimpdlls ? iat_off : iat_off + 12;    }}unsigned PeFile::processImports() // pass 1{    static const unsigned char kernel32dll[] = "COREDLL.dll";    static const char llgpa[] = "\x0\x0""LoadLibraryW\x0\x0"                                "GetProcAddressA\x0\x0\x0"                                "CacheSync";    //static const char exitp[] = "ExitProcess\x0\x0\x0";    unsigned dllnum = 0;    import_desc *im = (import_desc*) (ibuf + IDADDR(PEDIR_IMPORT));    import_desc * const im_save = im;    if (IDADDR(PEDIR_IMPORT))    {        while (im->dllname)            dllnum++, im++;        im = im_save;    }    struct udll    {        const upx_byte *name;        const upx_byte *shname;        unsigned   ordinal;        unsigned   iat;        LE32       *lookupt;        unsigned   npos;        bool       isk32;        static int __acc_cdecl_qsort compare(const void *p1, const void *p2)        {            const udll *u1 = * (const udll * const *) p1;            const udll *u2 = * (const udll * const *) p2;            if (u1->isk32) return -1;            if (u2->isk32) return 1;            int rc = strcasecmp(u1->name,u2->name);            if (rc) return rc;            if (u1->ordinal) return -1;            if (u2->ordinal) return 1;            if (!u1->shname) return 1;            if (!u2->shname) return -1;            return strlen(u1->shname) - strlen(u2->shname);        }    };    // +1 for dllnum=0    Array(struct udll, dlls, dllnum+1);    Array(struct udll *, idlls, dllnum+1);    soimport = 1024; // safety    unsigned ic,k32o;    for (ic = k32o = 0; dllnum && im->dllname; ic++, im++)    {        idlls[ic] = dlls + ic;        dlls[ic].name = ibuf + im->dllname;        dlls[ic].shname = NULL;        dlls[ic].ordinal = 0;        dlls[ic].iat = im->iat;        dlls[ic].lookupt = (LE32*) (ibuf + (im->oft ? im->oft : im->iat));        dlls[ic].npos = 0;        dlls[ic].isk32 = strcasecmp(kernel32dll,dlls[ic].name) == 0;        soimport += strlen(dlls[ic].name) + 1 + 4;        for (LE32 *tarr = dlls[ic].lookupt; *tarr; tarr++)        {            if (*tarr & 0x80000000)            {                importbyordinal = true;                soimport += 2; // ordinal num: 2 bytes                dlls[ic].ordinal = *tarr & 0xffff;                //if (dlls[ic].isk32)                //    kernel32ordinal = true,k32o++;            }            else            {                unsigned len = strlen(ibuf + *tarr + 2);                soimport += len + 1;                if (dlls[ic].shname == NULL || len < strlen (dlls[ic].shname))                    dlls[ic].shname = ibuf + *tarr + 2;            }            soimport++; // separator        }    }    oimport = new upx_byte[soimport];    memset(oimport,0,soimport);    oimpdlls = new upx_byte[soimport];    memset(oimpdlls,0,soimport);    qsort(idlls,dllnum,sizeof (udll*),udll::compare);    unsigned dllnamelen = sizeof (kernel32dll);    unsigned dllnum2 = 1;    for (ic = 0; ic < dllnum; ic++)        if (!idlls[ic]->isk32 && (ic == 0 || strcasecmp(idlls[ic - 1]->name,idlls[ic]->name)))        {            dllnum2++;            dllnamelen += strlen(idlls[ic]->name) + 1;        }    //fprintf(stderr,"dllnum=%d dllnum2=%d soimport=%d\n",dllnum,dllnum2,soimport); //    info("Processing imports: %d DLLs", dllnum);    // create the new import table    im = (import_desc*) oimpdlls;    LE32 *ordinals = (LE32*) (oimpdlls + (dllnum2 + 1) * sizeof(import_desc));    LE32 *lookuptable = ordinals + 4;// + k32o + (isdll ? 0 : 1);    upx_byte *dllnames = ((upx_byte*) lookuptable) + (dllnum2 - 1) * 8;    upx_byte *importednames = dllnames + (dllnamelen &~ 1);    unsigned k32namepos = ptr_diff(dllnames,oimpdlls);    memcpy(importednames, llgpa, ALIGN_UP((unsigned) sizeof(llgpa), 2u));    strcpy(dllnames,kernel32dll);    im->dllname = k32namepos;    im->iat = ptr_diff(ordinals,oimpdlls);    *ordinals++ = ptr_diff(importednames,oimpdlls);             // LoadLibraryW    *ordinals++ = ptr_diff(importednames,oimpdlls) + 14;        // GetProcAddressA    *ordinals++ = ptr_diff(importednames,oimpdlls) + 14 + 18;   // CacheSync    dllnames += sizeof(kernel32dll);    importednames += sizeof(llgpa);    im++;    for (ic = 0; ic < dllnum; ic++)        if (idlls[ic]->isk32)        {            idlls[ic]->npos = k32namepos;            /*            if (idlls[ic]->ordinal)                for (LE32 *tarr = idlls[ic]->lookupt; *tarr; tarr++)                    if (*tarr & 0x80000000)                        *ordinals++ = *tarr;            */        }        else if (ic && strcasecmp(idlls[ic-1]->name,idlls[ic]->name) == 0)            idlls[ic]->npos = idlls[ic-1]->npos;        else        {            im->dllname = idlls[ic]->npos = ptr_diff(dllnames,oimpdlls);            im->iat = ptr_diff(lookuptable,oimpdlls);            strcpy(dllnames,idlls[ic]->name);            dllnames += strlen(idlls[ic]->name)+1;            if (idlls[ic]->ordinal)                *lookuptable = idlls[ic]->ordinal + 0x80000000;            else if (idlls[ic]->shname)            {                if (ptr_diff(importednames,oimpdlls) & 1)                    importednames--;                *lookuptable = ptr_diff(importednames,oimpdlls);                importednames += 2;                strcpy(importednames,idlls[ic]->shname);                importednames += strlen(idlls[ic]->shname) + 1;            }            lookuptable += 2;            im++;        }    soimpdlls = ALIGN_UP(ptr_diff(importednames,oimpdlls),4);    Interval names(ibuf),iats(ibuf),lookups(ibuf);    // create the preprocessed data    //ordinals -= k32o;    upx_byte *ppi = oimport;  // preprocessed imports    for (ic = 0; ic < dllnum; ic++)    {        LE32 *tarr = idlls[ic]->lookupt;        if (!*tarr)  // no imports from this dll            continue;        set_le32(ppi,idlls[ic]->npos);        set_le32(ppi+4,idlls[ic]->iat - rvamin);        ppi += 8;        for (; *tarr; tarr++)            if (*tarr & 0x80000000)            {                /*if (idlls[ic]->isk32)                {                    *ppi++ = 0xfe; // signed + odd parity                    set_le32(ppi,ptr_diff(ordinals,oimpdlls));                    ordinals++;                    ppi += 4;                }                else*/                {                    *ppi++ = 0xff;                    set_le16(ppi,*tarr & 0xffff);                    ppi += 2;                }            }            else            {                *ppi++ = 1;                unsigned len = strlen(ibuf + *tarr + 2) + 1;                memcpy(ppi,ibuf + *tarr + 2,len);                ppi += len;                names.add(*tarr,len + 2 + 1);            }        ppi++;        unsigned esize = ptr_diff((char *)tarr, (char *)idlls[ic]->lookupt);        lookups.add(idlls[ic]->lookupt,esize);        if (ptr_diff(ibuf + idlls[ic]->iat, (char *)idlls[ic]->lookupt))        {            memcpy(ibuf + idlls[ic]->iat, idlls[ic]->lookupt, esize);            iats.add(idlls[ic]->iat,esize);        }        names.add(idlls[ic]->name,strlen(idlls[ic]->name) + 1 + 1);    }    ppi += 4;    assert(ppi < oimport+soimport);    soimport = ptr_diff(ppi,oimport);    if (soimport == 4)        soimport = 0;    //OutputFile::dump("x0.imp", oimport, soimport);    //OutputFile::dump("x1.imp", oimpdlls, soimpdlls);    unsigned ilen = 0;    names.flatten();    if (names.ivnum > 1)    {        // The area occupied by the dll and imported names is not continuous        // so to still support uncompression, I can't zero the iat area.        // This decreases compression ratio, so FIXME somehow.        infoWarning("can't remove unneeded imports");        ilen += sizeof(import_desc) * dllnum;#if defined(DEBUG)        if (opt->verbose > 3)            names.dump();#endif        // do some work for the unpacker        im = im_save;        for (ic = 0; ic < dllnum; ic++, im++)        {            memset(im,FILLVAL,sizeof(*im));            im->dllname = ptr_diff(idlls[ic]->name,ibuf); // I only need this info        }    }    else    {        iats.add(im_save,sizeof(import_desc) * dllnum);        // zero unneeded data        iats.clear();        lookups.clear();    }    names.clear();    iats.add(&names);    iats.add(&lookups);    iats.flatten();    for (ic = 0; ic < iats.ivnum; ic++)        ilen += iats.ivarr[ic].len;    info("Imports: original size: %u bytes, preprocessed size: %u bytes",ilen,soimport);    return names.ivnum == 1 ? names.ivarr[0].start : 0;}/*************************************************************************// export handling**************************************************************************/PeFile::Export::Export(char *_base) : base(_base), iv(_base){    COMPILE_TIME_ASSERT(sizeof(export_dir_t) == 40);    ename = functionptrs = ordinals = NULL;    names = NULL;    memset(&edir,0,sizeof(edir));    size = 0;}PeFile::Export::~Export(){    free(ename);    delete [] functionptrs;    delete [] ordinals;    for (unsigned ic = 0; ic < edir.names + edir.functions; ic++)        free(names[ic]);    delete [] names;}void PeFile::Export::convert(unsigned eoffs,unsigned esize){    memcpy(&edir,base + eoffs,sizeof(export_dir_t));    size = sizeof(export_dir_t);    iv.add(eoffs,size);    unsigned len = strlen(base + edir.name) + 1;    ename = strdup(base + edir.name);    size += len;    iv.add(edir.name,len);    len = 4 * edir.functions;    functionptrs = new char[len + 1];    memcpy(functionptrs,base + edir.addrtable,len);    size += len;    iv.add(edir.addrtable,len);    unsigned ic;    names = new char* [edir.names + edir.functions + 1];    for (ic = 0; ic < edir.names; ic++)    {        char *n = base + get_le32(base + edir.nameptrtable + ic * 4);        len = strlen(n) + 1;        names[ic] = strdup(n);        size += len;        iv.add(get_le32(base + edir.nameptrtable + ic * 4),len);    }    iv.add(edir.nameptrtable,4 * edir.names);    size += 4 * edir.names;    LE32 *fp = (LE32*) functionptrs;    // export forwarders    for (ic = 0; ic < edir.functions; ic++)        if (fp[ic] >= eoffs && fp[ic] < eoffs + esize)        {            char *forw = base + fp[ic];            len = strlen(forw) + 1;            iv.add(forw,len);            size += len;            names[ic + edir.names] = strdup(forw);        }        else            names[ic + edir.names] = NULL;    len = 2 * edir.names;    ordinals = new char[len + 1];    memcpy(ordinals,base + edir.ordinaltable,len);    size += len;    iv.add(edir.ordinaltable,len);    iv.flatten();    if (iv.ivnum == 1)        iv.clear();#if defined(DEBUG)    else        iv.dump();#endif}void PeFile::Export::build(char *newbase, unsigned newoffs){    char * const functionp = newbase + sizeof(edir);    char * const namep = functionp + 4 * edir.functions;    char * const ordinalp = namep + 4 * edir.names;    char * const enamep = ordinalp + 2 * edir.names;    char * exports = enamep + strlen(ename) + 1;    edir.addrtable = newoffs + ptr_diff(functionp, newbase);    edir.ordinaltable = newoffs + ptr_diff(ordinalp, newbase);    memcpy(ordinalp,ordinals,2 * edir.names);    edir.name = newoffs + ptr_diff(enamep, newbase);    strcpy(enamep,ename);    edir.nameptrtable = newoffs + ptr_diff(namep, newbase);    unsigned ic;    for (ic = 0; ic < edir.names; ic++)    {        strcpy(exports,names[ic]);        set_le32(namep + 4 * ic,newoffs + ptr_diff(exports, newbase));        exports += strlen(exports) + 1;    }    memcpy(functionp,functionptrs,4 * edir.functions);    for (ic = 0; ic < edir.functions; ic++)        if (names[edir.names + ic])        {            strcpy(exports,names[edir.names + ic]);            set_le32(functionp + 4 * ic,newoffs + ptr_diff(exports, newbase));            exports += strlen(exports) + 1;        }    memcpy(newbase,&edir,sizeof(edir));    assert(exports - newbase == (int) size);}void PeFile::processExports(Export *xport) // pass1{    soexport = ALIGN_UP(IDSIZE(PEDIR_EXPORT),4);    if (soexport == 0)        return;    if (!isdll && opt->win32_pe.compress_exports)    {        infoWarning("exports compressed, --compress-exports=0 might be needed");        soexport = 0;        return;    }    xport->convert(IDADDR(PEDIR_EXPORT),IDSIZE(PEDIR_EXPORT));    soexport = ALIGN_UP(xport->getsize(), 4u);    oexport = new upx_byte[soexport];    memset(oexport, 0, soexport);}void PeFile::processExports(Export *xport,unsigned newoffs) // pass2{    if (soexport)        xport->build((char*) oexport,newoffs);}/*************************************************************************// TLS handling**************************************************************************/// thanks for theowl for providing me some docs, so that now I understand// what I'm doing here :)// 1999-10-17: this was tricky to find:// when the fixup records and the tls area are on the same page, then// the tls area is not relocated, because the relocation is done by// the virtual memory manager only for pages which are not yet loaded.// of course it was impossible to debug this ;-)

⌨️ 快捷键说明

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