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

📄 p_w32pe.cpp

📁 UPX 源代码
💻 CPP
📖 第 1 页 / 共 3 页
字号:
        // 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;}/*************************************************************************// Load Configuration handling**************************************************************************/void PackW32Pe::processLoadConf(Interval *iv) // pass 1{    if (IDSIZE(PEDIR_LOADCONF) == 0)        return;    const unsigned lcaddr = IDADDR(PEDIR_LOADCONF);    const upx_byte * const loadconf = ibuf + lcaddr;    soloadconf = get_le32(loadconf);    if (soloadconf == 0)        return;    if (soloadconf > 256)        throwCantPack("size of Load Configuration directory unexpected");    // if there were relocation entries referring to the load config table    // then we need them for the copy of the table too    unsigned pos,type;    Reloc rel(ibuf + IDADDR(PEDIR_RELOC), IDSIZE(PEDIR_RELOC));    while (rel.next(pos, type))        if (pos >= lcaddr && pos < lcaddr + soloadconf)        {            iv->add(pos - lcaddr, type);            // printf("loadconf reloc detected: %x\n", pos);        }    oloadconf = new upx_byte[soloadconf];    memcpy(oloadconf, loadconf, soloadconf);}void PackW32Pe::processLoadConf(Reloc *rel, const Interval *iv,                                unsigned newaddr) // pass2{    // now we have the address of the new load config table    // so we can create the new relocation entries    for (unsigned ic = 0; ic < iv->ivnum; ic++)    {        rel->add(iv->ivarr[ic].start + newaddr, iv->ivarr[ic].len);        //printf("loadconf reloc added: %x %d\n",        //       iv->ivarr[ic].start + newaddr, iv->ivarr[ic].len);    }}/*************************************************************************// pack**************************************************************************/bool PackW32Pe::canPack(){    if (!readFileHeader() || ih.cpu < 0x14c || ih.cpu > 0x150)        return false;    return true;}void PackW32Pe::buildLoader(const Filter *ft){    // recompute tlsindex (see pack() below)    unsigned tmp_tlsindex = tlsindex;    const unsigned oam1 = ih.objectalign - 1;    const unsigned newvsize = (ph.u_len + rvamin + ph.overlap_overhead + oam1) &~ oam1;    if (tlsindex && ((newvsize - ph.c_len - 1024 + oam1) &~ oam1) > tlsindex + 4)        tmp_tlsindex = 0;    // prepare loader    initLoader(stub_i386_win32_pe, sizeof(stub_i386_win32_pe), 2);    addLoader(isdll ? "PEISDLL1" : "",              "PEMAIN01",              icondir_count > 1 ? (icondir_count == 2 ? "PEICONS1" : "PEICONS2") : "",              tmp_tlsindex ? "PETLSHAK" : "",              "PEMAIN02",              ph.first_offset_found == 1 ? "PEMAIN03" : "",              getDecompressorSections(),              /*multipass ? "PEMULTIP" :  */  "",              "PEMAIN10",              NULL             );    if (ft->id)    {        const unsigned texv = ih.codebase - rvamin;        assert(ft->calls > 0);        addLoader(texv ? "PECTTPOS" : "PECTTNUL",NULL);        addFilter32(ft->id);    }    if (soimport)        addLoader("PEIMPORT",                  importbyordinal ? "PEIBYORD" : "",                  kernel32ordinal ? "PEK32ORD" : "",                  importbyordinal ? "PEIMORD1" : "",                  "PEIMPOR2",                  isdll ? "PEIERDLL" : "PEIEREXE",                  "PEIMDONE",                  NULL                 );    if (sorelocs)    {        addLoader(soimport == 0 || soimport + cimports != crelocs ? "PERELOC1" : "PERELOC2",                  "PERELOC3,RELOC320",                  big_relocs ? "REL32BIG" : "",                  "RELOC32J",                  NULL                 );        //FIXME: the following should be moved out of the above if        addLoader(big_relocs&6 ? "PERLOHI0" : "",                  big_relocs&4 ? "PERELLO0" : "",                  big_relocs&2 ? "PERELHI0" : "",                  NULL                 );    }    if (use_dep_hack)        addLoader("PEDEPHAK", NULL);    addLoader("PEMAIN20", NULL);    if (use_clear_dirty_stack)        addLoader("CLEARSTACK", NULL);    addLoader("PEMAIN21", NULL);    addLoader(ih.entry ? "PEDOJUMP" : "PERETURN",              "IDENTSTR,UPX1HEAD",              NULL             );}void PackW32Pe::pack(OutputFile *fo){    // FIXME: we need to think about better support for --exact    if (opt->exact)        throwCantPackExact();    const unsigned objs = ih.objects;    isection = new pe_section_t[objs];    fi->seek(pe_offset+sizeof(ih),SEEK_SET);    fi->readx(isection,sizeof(pe_section_t)*objs);    rvamin = isection[0].vaddr;    infoHeader("[Processing %s, format %s, %d sections]", fn_basename(fi->getName()), getName(), objs);    // check the PE header    // FIXME: add more checks    if (!opt->force && (           (ih.cpu < 0x14c || ih.cpu > 0x150)        || (ih.opthdrsize != 0xe0)        || ((ih.flags & EXECUTABLE) == 0)        || (ih.subsystem != 2 && ih.subsystem != 3            && ih.subsystem != 1 && ih.subsystem != 9)        || (ih.entry == 0 && !isdll)        || (ih.ddirsentries != 16)        || IDSIZE(PEDIR_EXCEPTION) // is this used on i386?//        || IDSIZE(PEDIR_COPYRIGHT)       ))        throwCantPack("unexpected value in PE header (try --force)");    if (ih.subsystem == 9)        throwCantPack("x86/wince files are not yet supported");    if (IDSIZE(PEDIR_SEC))        IDSIZE(PEDIR_SEC) = IDADDR(PEDIR_SEC) = 0;    if (IDSIZE(PEDIR_COMRT))        throwCantPack(".NET files (win32/net) are not yet supported");    if (isdll)        opt->win32_pe.strip_relocs = false;    else if (opt->win32_pe.strip_relocs < 0)        opt->win32_pe.strip_relocs = (ih.imagebase >= 0x400000);    if (opt->win32_pe.strip_relocs)    {        if (ih.imagebase < 0x400000)            throwCantPack("--strip-relocs is not allowed when imagebase < 0x400000");        else            ih.flags |= RELOCS_STRIPPED;    }    if (memcmp(isection[0].name,"UPX",3) == 0)        throwAlreadyPackedByUPX();    if (!opt->force && IDSIZE(15))        throwCantPack("file is possibly packed/protected (try --force)");    if (ih.entry && ih.entry < rvamin)        throwCantPack("run a virus scanner on this file!");    if (!opt->force && ih.subsystem == 1)        throwCantPack("subsystem 'native' is not supported (try --force)");    if (ih.filealign < 0x200)        throwCantPack("filealign < 0x200 is not yet supported");    handleStub(fi,fo,pe_offset);    const unsigned usize = ih.imagesize;    const unsigned xtrasize = UPX_MAX(ih.datasize, 65536u) + IDSIZE(PEDIR_IMPORT) + IDSIZE(PEDIR_BOUNDIM) + IDSIZE(PEDIR_IAT) + IDSIZE(PEDIR_DELAYIMP) + IDSIZE(PEDIR_RELOC);    ibuf.alloc(usize + xtrasize);    // BOUND IMPORT support. FIXME: is this ok?    fi->seek(0,SEEK_SET);    fi->readx(ibuf,isection[0].rawdataptr);    Interval holes(ibuf);    unsigned ic,jc,overlaystart = 0;    ibuf.clear(0, usize);    for (ic = jc = 0; ic < objs; ic++)    {        if (isection[ic].rawdataptr && overlaystart < isection[ic].rawdataptr + isection[ic].size)            overlaystart = ALIGN_UP(isection[ic].rawdataptr + isection[ic].size,ih.filealign);        if (isection[ic].vsize == 0)            isection[ic].vsize = isection[ic].size;        if ((isection[ic].flags & PEFL_BSS) || isection[ic].rawdataptr == 0            || (isection[ic].flags & PEFL_INFO))        {            holes.add(isection[ic].vaddr,isection[ic].vsize);            continue;        }        if (isection[ic].vaddr + isection[ic].size > usize)            throwCantPack("section size problem");        if (!isrtm && ((isection[ic].flags & (PEFL_WRITE|PEFL_SHARED))            == (PEFL_WRITE|PEFL_SHARED)))            if (!opt->force)                throwCantPack("writeable shared sections not supported (try --force)");        if (jc && isection[ic].rawdataptr - jc > ih.filealign)            throwCantPack("superfluous data between sections");        fi->seek(isection[ic].rawdataptr,SEEK_SET);        jc = isection[ic].size;        if (jc > isection[ic].vsize)            jc = isection[ic].vsize;        if (isection[ic].vsize == 0) // hack for some tricky programs - may this break other progs?            jc = isection[ic].vsize = isection[ic].size;        if (isection[ic].vaddr + jc > ibuf.getSize())            throwInternalError("buffer too small 1");        fi->readx(ibuf + isection[ic].vaddr,jc);        jc += isection[ic].rawdataptr;    }    // check for NeoLite    if (find(ibuf + ih.entry, 64+7, "NeoLite", 7) >= 0)        throwCantPack("file is already compressed with another packer");    unsigned overlay = file_size - stripDebug(overlaystart);    if (overlay >= (unsigned) file_size)    {#if 0        if (overlay < file_size + ih.filealign)            overlay = 0;        else if (!opt->force)            throwNotCompressible("overlay problem (try --force)");#endif        overlay = 0;    }    checkOverlay(overlay);    Resource res;    Interval tlsiv(ibuf);    Interval loadconfiv(ibuf);    Export xport((char*)(unsigned char*)ibuf);    const unsigned dllstrings = processImports();    processTls(&tlsiv); // call before processRelocs!!    processLoadConf(&loadconfiv);    processResources(&res);    processExports(&xport);    processRelocs();    //OutputFile::dump("x1", ibuf, usize);    // some checks for broken linkers - disable filter if necessary    bool allow_filter = true;    if (ih.codebase == ih.database        || ih.codebase + ih.codesize > ih.imagesize        || (isection[virta2objnum(ih.codebase,isection,objs)].flags & PEFL_CODE) == 0)        allow_filter = false;    const unsigned oam1 = ih.objectalign - 1;    // FIXME: disabled: the uncompressor would not allocate enough memory    //objs = tryremove(IDADDR(PEDIR_RELOC),objs);    // FIXME: if the last object has a bss then this won't work    // newvsize = (isection[objs-1].vaddr + isection[objs-1].size + oam1) &~ oam1;    // temporary solution:    unsigned newvsize = (isection[objs-1].vaddr + isection[objs-1].vsize + oam1) &~ oam1;    //fprintf(stderr,"newvsize=%x objs=%d\n",newvsize,objs);    if (newvsize + soimport + sorelocs > ibuf.getSize())         throwInternalError("buffer too small 2");    memcpy(ibuf+newvsize,oimport,soimport);    memcpy(ibuf+newvsize+soimport,orelocs,sorelocs);    cimports = newvsize - rvamin;   // rva of preprocessed imports    crelocs = cimports + soimport;  // rva of preprocessed fixups    ph.u_len = newvsize + soimport + sorelocs;    // some extra data for uncompression support    unsigned s = 0;    upx_byte * const p1 = ibuf + ph.u_len;    memcpy(p1 + s,&ih,sizeof (ih));    s += sizeof (ih);    memcpy(p1 + s,isection,ih.objects * sizeof(*isection));    s += ih.objects * sizeof(*isection);    if (soimport)    {        set_le32(p1 + s,cimports);        set_le32(p1 + s + 4,dllstrings);        s += 8;    }    if (sorelocs)    {        set_le32(p1 + s,crelocs);        p1[s + 4] = (unsigned char) (big_relocs & 6);        s += 5;    }    if (soresources)    {        set_le16(p1 + s,icondir_count);        s += 2;    }    // end of extra data    set_le32(p1 + s,ptr_diff(p1,ibuf) - rvamin);    s += 4;    ph.u_len += s;    obuf.allocForCompression(ph.u_len);    // prepare packheader    ph.u_len -= rvamin;    // prepare filter    Filter ft(ph.level);    ft.buf_len = ih.codesize;    ft.addvalue = ih.codebase - rvamin;    // compress    int filter_strategy = allow_filter ? 0 : -3;    // disable filters for files with broken headers    if (ih.codebase + ih.codesize > ph.u_len)    {        ft.buf_len = 1;        filter_strategy = -3;    }    compressWithFilters(&ft, 2048, NULL_cconf, filter_strategy,                        ih.codebase, rvamin, 0, NULL, 0);// info: see buildLoader()    newvsize = (ph.u_len + rvamin + ph.overlap_overhead + oam1) &~ oam1;    if (tlsindex && ((newvsize - ph.c_len - 1024 + oam1) &~ oam1) > tlsindex + 4)        tlsindex = 0;    int identsize = 0;    const unsigned codesize = getLoaderSection("IDENTSTR",&identsize);    assert(identsize > 0);    getLoaderSection("UPX1HEAD",(int*)&ic);    identsize += ic;    pe_section_t osection[3];    // section 0 : bss    //         1 : [ident + header] + packed_data + unpacker + tls + loadconf    //         2 : not compressed data    // section 2 should start with the resource data, because lots of lame    // windoze codes assume that resources starts on the beginning of a section    // note: there should be no data in section 2 which needs fixup    // identsplit - number of ident + (upx header) bytes to put into the PE header    int identsplit = pe_offset + sizeof(osection) + sizeof(oh);    if ((identsplit & 0x1ff) == 0)        identsplit = 0;    else if (((identsplit + identsize) ^ identsplit) < 0x200)        identsplit = identsize;    else        identsplit = ALIGN_GAP(identsplit, 0x200);    ic = identsize - identsplit;    const unsigned c_len = ((ph.c_len + ic) & 15) == 0 ? ph.c_len : ph.c_len + 16 - ((ph.c_len + ic) & 15);    obuf.clear(ph.c_len, c_len - ph.c_len);    const unsigned s1size = ALIGN_UP(ic + c_len + codesize,4u) + sotls + soloadconf;    const unsigned s1addr = (newvsize - (ic + c_len) + oam1) &~ oam1;    const unsigned ncsection = (s1addr + s1size + oam1) &~ oam1;    const unsigned upxsection = s1addr + ic + c_len;    const unsigned myimport = ncsection + soresources - rvamin;    // patch loader    linker->defineSymbol("original_entry", ih.entry);    if (use_dep_hack)    {        // This works around a "protection" introduced in MSVCRT80, which        // works like this:        // When the compiler detects that it would link in some code from its        // C runtime library which references some data in a read only        // section then it compiles in a runtime check whether that data is        // still in a read only section by looking at the pe header of the        // file. If this check fails the runtime does "interesting" things        // like not running the floating point initialization code - the result        // is an R6002 runtime error.        // These supposed to be read only addresses are covered by the sections        // UPX0 & UPX1 in the compressed files, so we have to patch the PE header        // in the memory. And the page on which the PE header is stored is read        // only so we must make it rw, fix the flags (i.e. clear        // PEFL_WRITE of osection[x].flags), and make it ro again.

⌨️ 快捷键说明

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