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

📄 p_exe.cpp

📁 UPX 源代码
💻 CPP
📖 第 1 页 / 共 2 页
字号:
}/*************************************************************************//**************************************************************************/void PackExe::pack(OutputFile *fo){    unsigned ic;    if (ih.relocs > MAXRELOCS)        throwCantPack("too many relocations");    checkOverlay(ih_overlay);    // alloc buffers    relocsize = RSFCRI + 4*ih.relocs;    ibuf.alloc(ih_imagesize+16+relocsize+2);    obuf.allocForCompression(ih_imagesize+16+relocsize+2);    // read image    fi->seek(ih.headsize16*16,SEEK_SET);    fi->readx(ibuf,ih_imagesize);    checkAlreadyPacked(ibuf, UPX_MIN(ih_imagesize, 127u));    device_driver = get_le32(ibuf) == 0xffffffffu;    // relocations    has_9a = false;    upx_byte *w = ibuf + ih_imagesize;    if (ih.relocs)    {        upx_byte *wr = w + RSFCRI;        fi->seek(ih.relocoffs,SEEK_SET);        fi->readx(wr,4*ih.relocs);        for (ic = 0; ic < ih.relocs; ic++)        {            unsigned jc = get_le32(wr+4*ic);            set_le32(wr+4*ic, ((jc>>16)*16+(jc&0xffff)) & 0xfffff);        }        qsort(wr,ih.relocs,4,le32_compare);        relocsize = optimize_relocs(ibuf, ih_imagesize, wr, ih.relocs, w, &has_9a);        set_le16(w+relocsize, relocsize+2);        relocsize += 2;        if (relocsize > MAXRELOCS)            throwCantPack("too many relocations");#if 0        upx_byte out[9*relocsize/8+1024];        unsigned in_len = relocsize;        unsigned out_len = 0;        ucl_nrv2b_99_compress(w, in_len, out, &out_len, NULL, 9, NULL, NULL);        printf("reloc compress: %d -> %d\n", in_len, out_len);#endif    }    else    {        relocsize = 0;    }    // prepare packheader    ph.u_len = ih_imagesize + relocsize;    // prepare filter    Filter ft(ph.level);    // compress (max_match = 8192)    upx_compress_config_t cconf; cconf.reset();    cconf.conf_ucl.max_match = MAXMATCH;    cconf.conf_lzma.max_num_probs = 1846 + (768 << 4); // ushort: ~28KB stack    compressWithFilters(&ft, 32, &cconf);    if (M_IS_NRV2B(ph.method) || M_IS_NRV2D(ph.method) || M_IS_NRV2E(ph.method))        if (ph.max_run_found + ph.max_match_found > 0x8000)            throwCantPack("decompressor limit exceeded, send a bugreport");#ifdef TESTING    if (opt->debug.debug_level)    {        printf("image+relocs %d -> %d\n",ih_imagesize+relocsize,ph.c_len);        printf("offsets: %d - %d\nmatches: %d - %d\nruns: %d - %d\n",               0/*ph.min_offset_found*/,ph.max_offset_found,               0/*ph.min_match_found*/,ph.max_match_found,               0/*ph.min_run_found*/,ph.max_run_found);    }#endif    int flag = fillExeHeader(&oh);    const unsigned lsize = getLoaderSize();    MemBuffer loader(lsize);    memcpy(loader,getLoader(),lsize);    //OutputFile::dump("xxloader.dat", loader, lsize);    // patch loader    const unsigned packedsize = ph.c_len;    const unsigned e_len = getLoaderSectionStart("EXECUTPO");    const unsigned d_len = lsize - e_len;    assert((e_len&15) == 0);    const unsigned copysize = (1+packedsize+d_len) & ~1;    const unsigned firstcopy = copysize%0x10000 ? copysize%0x10000 : 0x10000;    // set oh.min & oh.max    ic = ih.min*16 + ih_imagesize;    if (ic < oh.ss*16u + oh.sp)        ic = oh.ss*16u + oh.sp;    oh.min = (ic - (packedsize + lsize)) / 16;    ic = oh.min + (ih.max - ih.min);    oh.max = ic < 0xffff && ih.max != 0xffff ? ic : 0xffff;    // set extra info    unsigned char extra_info[9];    unsigned eisize = 0;    if (oh.ss != ih.ss)    {        set_le16(extra_info+eisize,ih.ss);        eisize += 2;        assert((flag & SS) != 0);   // set in fillExeHeader()    }    if (oh.sp != ih.sp)    {        set_le16(extra_info+eisize,ih.sp);        eisize += 2;        assert((flag & SP) != 0);   // set in fillExeHeader()    }    if (ih.min != oh.min)    {        set_le16(extra_info+eisize,ih.min);        eisize += 2;        flag |= MINMEM;    }    if (ih.max != oh.max)    {        set_le16(extra_info+eisize,ih.max);        eisize += 2;        flag |= MAXMEM;    }    extra_info[eisize++] = (unsigned char) flag;    if (M_IS_NRV2B(ph.method) || M_IS_NRV2D(ph.method) || M_IS_NRV2E(ph.method))        linker->defineSymbol("bx_magic", 0x7FFF + 0x10 * ((packedsize & 15) + 1));    unsigned decompressor_entry = 1 + (packedsize & 15);    if (M_IS_LZMA(ph.method))        decompressor_entry = 0x10;    linker->defineSymbol("decompressor_entry", decompressor_entry);    // patch loader    if (flag & USEJUMP)    {        // I use a relocation entry to set the original cs        unsigned n = getLoaderSectionStart("EXEJUMPF") + 1;        n += packedsize + 2;        oh.relocs = 1;        oh.firstreloc = (n & 0xf) + ((n >> 4) << 16);    }    else    {        oh.relocs = 0;        oh.firstreloc = ih.cs * 0x10000 + ih.ip;    }    // g++ 3.1 does not like the following line...//    oh.relocoffs = offsetof(exe_header_t, firstreloc);    oh.relocoffs = ptr_diff(&oh.firstreloc, &oh);    linker->defineSymbol("destination_segment", oh.ss - ph.c_len / 16 - e_len / 16);    linker->defineSymbol("source_segment", e_len / 16 + (copysize - firstcopy) / 16);    linker->defineSymbol("copy_offset", firstcopy - 2);    linker->defineSymbol("words_to_copy",firstcopy / 2);    linker->defineSymbol("exe_stack_sp", oh.sp);    linker->defineSymbol("exe_stack_ss", oh.ss);    linker->defineSymbol("interrupt", get_le16(ibuf + 8));    linker->defineSymbol("attribute", get_le16(ibuf + 4));    linker->defineSymbol("orig_strategy", get_le16(ibuf + 6));    const unsigned outputlen = sizeof(oh)+lsize+packedsize+eisize;    oh.m512 = outputlen & 511;    oh.p512 = (outputlen + 511) >> 9;    const char *exeentry = M_IS_LZMA(ph.method) ? "LZMAENTRY" : "EXEENTRY";    oh.ip = device_driver ? getLoaderSection(exeentry) - 2 : 0;    defineDecompressorSymbols();    relocateLoader();    memcpy(loader, getLoader(), lsize);    patchPackHeader(loader,e_len);//fprintf(stderr,"\ne_len=%x d_len=%x c_len=%x oo=%x ulen=%x destp=%x copys=%x images=%x",e_len,d_len,packedsize,ph.overlap_overhead,ph.u_len,destpara,copysize,ih_imagesize);    // write header + write loader + compressed file#ifdef TESTING    if (opt->debug.debug_level)        printf("\n%d %d %d %d\n",(int)sizeof(oh),e_len,packedsize,d_len);#endif    fo->write(&oh,sizeof(oh));    fo->write(loader,e_len);            // entry    fo->write(obuf,packedsize);    fo->write(loader+e_len,d_len);      // decompressor    fo->write(extra_info,eisize);    assert(eisize <= 9);#if 0    printf("%-13s: program hdr  : %8ld bytes\n", getName(), (long) sizeof(oh));    printf("%-13s: entry        : %8ld bytes\n", getName(), (long) e_len);    printf("%-13s: compressed   : %8ld bytes\n", getName(), (long) packedsize);    printf("%-13s: decompressor : %8ld bytes\n", getName(), (long) d_len);    printf("%-13s: extra info   : %8ld bytes\n", getName(), (long) eisize);#endif    // verify    verifyOverlappingDecompression();    // copy the overlay    copyOverlay(fo, ih_overlay, &obuf);//fprintf (stderr,"%x %x\n",relocsize,ph.u_len);    // finally check the compression ratio    if (!checkFinalCompressionRatio(fo))        throwNotCompressible();}/*************************************************************************//**************************************************************************/int PackExe::canUnpack(){    if (!readFileHeader())        return false;    const off_t off = ih.headsize16 * 16;    fi->seek(off, SEEK_SET);    bool b = readPackHeader(4096);    return b && (off + (off_t) ph.c_len <= file_size);}/*************************************************************************//**************************************************************************/void PackExe::unpack(OutputFile *fo){    ibuf.alloc(file_size);    obuf.allocForUncompression(ph.u_len);    // read the file    fi->seek(ih.headsize16*16,SEEK_SET);    fi->readx(ibuf,ih_imagesize);    // get compressed data offset    unsigned e_len = ph.buf_offset + ph.getPackHeaderSize();    if (ih_imagesize <= e_len + ph.c_len)        throwCantUnpack("file damaged");    checkOverlay(ih_overlay);    // decompress    decompress(ibuf+e_len,obuf);    unsigned imagesize = ih_imagesize;    imagesize--;    const unsigned char flag = ibuf[imagesize];    unsigned relocn = 0;    upx_byte *relocs = obuf + ph.u_len;    MemBuffer wrkmem;    if (!(flag & NORELOC))    {        relocs -= get_le16(obuf+ph.u_len-2);        ph.u_len -= 2;        wrkmem.alloc(4*MAXRELOCS);        unsigned es = 0, ones = get_le16(relocs);        const unsigned seghi = get_le16(relocs+2);        const upx_byte *p = relocs + 4;        while (ones)        {            unsigned di = get_le16(p);            es += get_le16(p+2);            bool dorel = true;            for (p += 4; ones && di < 0x10000; p++)            {                if (dorel)                {                    set_le16(wrkmem+4*relocn,di);                    set_le16(wrkmem+2+4*relocn++,es);                    //printf ("%x\n",es*16+di);                }                dorel = true;                if (*p == 0)                {                    const upx_byte *q;                    for (q = obuf+es*16+di; !(*q == 0x9a && get_le16(q+3) <= seghi); q++)                        ;                    di = ptr_diff(q, obuf+es*16) + 3;                }                else if (*p == 1)                {                    di += 254;                    if (di < 0x10000)                        ones--;                    dorel = false;                }                else                    di += *p;            }        }    }    // fill new exe header    memset(&oh,0,sizeof(oh));    oh.ident = 'M' + 'Z'*256;    if (relocn)    {        oh.relocs = relocn;        while (relocn & 3)            set_le32(wrkmem+4*relocn++,0);    }    unsigned outputlen = ptr_diff(relocs, obuf) + sizeof(oh) + relocn*4;    oh.m512 = outputlen & 511;    oh.p512 = (outputlen + 511) >> 9;    oh.headsize16 = 2+relocn/4;    oh.max = ih.max;    oh.min = ih.min;    oh.sp = ih.sp;    oh.ss = ih.ss;    if (flag & MAXMEM)        { imagesize -= 2; oh.max = get_le16(ibuf+imagesize); }    if (flag & MINMEM)        { imagesize -= 2; oh.min = get_le16(ibuf+imagesize); }    if (flag & SP)        { imagesize -= 2; oh.sp = get_le16(ibuf+imagesize); }    if (flag & SS)        { imagesize -= 2; oh.ss = get_le16(ibuf+imagesize); }    unsigned ip = (flag & USEJUMP) ? get_le32(ibuf+imagesize-4) : (unsigned) ih.firstreloc;    oh.ip = ip & 0xffff;    oh.cs = ip >> 16;    oh.relocoffs = sizeof(oh);    oh.firstreloc = 0;    if (!fo)        return;    // write header + relocations + uncompressed file    fo->write(&oh,sizeof(oh));    if (relocn)        fo->write(wrkmem,relocn*4);    fo->write(obuf, ptr_diff(relocs, obuf));    // copy the overlay    copyOverlay(fo, ih_overlay, &obuf);}Linker* PackExe::newLinker() const{    return new ElfLinkerX86();}/*memory layout at decompression time===================================normal exe----------a, at load time(e - copying code, C - compressed data, d - decompressor+relocator, x - not specified, U - uncompressed code+data, R uncompressed relocation)eeCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCdddd^ CS:0                                       ^ SS:0b, after copyingxxxxxxxxxxxxxxxCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCdddd^ES:DI=0       ^ DS:SI=0                     ^ CS=SS, IP in range 0..0xfc, after uncompressionUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUURRdddd                                           ^ ES:DIdevice driver-------------the file has 2 entry points, CS:0 in device driver mode, andCS:exe_as_device_entry in normal mode. the code in section DEVICEENTRYsets up the same environment for section EXEENTRY, as it would see in normalexecution mode.lzma uncompression for normal exes----------------------------------(n - nrv2b uncompressor, l - nrv2b compressed lzma + relocator code)a, at load timenneelllCCCCCCCCCCCCCCCCCCCCCCCCC^ CS:0                                       ^ SS:0b, after nrv2bnneelllCCCCCCCCCCCCCCCCCCCCCCCCC             dddd^ CS:0                                       ^ SS:0x10after this, normal ee code runslzma + device driver--------------------(D - device driver adapter)a, at load timeDDnneelllCCCCCCCCCCCCCCCCCCCCCCCCC*//*vi:ts=4:et*/

⌨️ 快捷键说明

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