Example #1
0
void PackTmt::pack(OutputFile *fo)
{
    big_relocs = 0;

    Packer::handleStub(fi,fo,adam_offset);

    const unsigned usize = ih.imagesize;
    const unsigned rsize = ih.relocsize;

    ibuf.alloc(usize+rsize+128);
    obuf.allocForCompression(usize+rsize+128);

    MemBuffer wrkmem;
    wrkmem.alloc(rsize+EXTRA_INFO); // relocations

    fi->seek(adam_offset+sizeof(ih),SEEK_SET);
    fi->readx(ibuf,usize);
    fi->readx(wrkmem+4,rsize);
    const unsigned overlay = file_size - fi->tell();

    if (find_le32(ibuf,128,get_le32("UPX ")) >= 0)
        throwAlreadyPacked();
    if (rsize == 0)
        throwCantPack("file is already compressed with another packer");

    checkOverlay(overlay);

    unsigned relocsize = 0;
    //if (rsize)
    {
        for (unsigned ic=4; ic<=rsize; ic+=4)
            set_le32(wrkmem+ic,get_le32(wrkmem+ic)-4);
        relocsize = ptr_diff(optimizeReloc32(wrkmem+4,rsize/4,wrkmem,ibuf,1,&big_relocs), wrkmem);
    }

    wrkmem[relocsize++] = 0;
    set_le32(wrkmem+relocsize,ih.entry); // save original entry point
    relocsize += 4;
    set_le32(wrkmem+relocsize,relocsize+4);
    relocsize += 4;
    memcpy(ibuf+usize,wrkmem,relocsize);

    // prepare packheader
    ph.u_len = usize + relocsize;
    // prepare filter
    Filter ft(ph.level);
    ft.buf_len = usize;
    // compress
    upx_compress_config_t cconf; cconf.reset();
    // limit stack size needed for runtime decompression
    cconf.conf_lzma.max_num_probs = 1846 + (768 << 4); // ushort: ~28 KiB stack
    compressWithFilters(&ft, 512, &cconf);

    const unsigned lsize = getLoaderSize();
    const unsigned s_point = getLoaderSection("TMTMAIN1");
    int e_len = getLoaderSectionStart("TMTCUTPO");
    const unsigned d_len = lsize - e_len;
    assert(e_len > 0  && s_point > 0);

    // patch loader
    linker->defineSymbol("original_entry", ih.entry);
    defineDecompressorSymbols();
    defineFilterSymbols(&ft);

    linker->defineSymbol("bytes_to_copy", ph.c_len + d_len);
    linker->defineSymbol("copy_dest", 0u - (ph.u_len + ph.overlap_overhead + d_len - 1));
    linker->defineSymbol("copy_source", ph.c_len + lsize - 1);
    //fprintf(stderr,"\nelen=%x dlen=%x copy_len=%x  copy_to=%x  oo=%x  jmp_pos=%x  ulen=%x  c_len=%x \n\n",
    //                e_len,d_len,copy_len,copy_to,ph.overlap_overhead,jmp_pos,ph.u_len,ph.c_len);

    linker->defineSymbol("TMTCUTPO", ph.u_len + ph.overlap_overhead);
    relocateLoader();

    MemBuffer loader(lsize);
    memcpy(loader,getLoader(),lsize);
    patchPackHeader(loader,e_len);

    memcpy(&oh,&ih,sizeof(oh));
    oh.imagesize = ph.c_len + lsize; // new size
    oh.entry = s_point; // new entry point
    oh.relocsize = 4;

    // write loader + compressed file
    fo->write(&oh,sizeof(oh));
    fo->write(loader,e_len);
    fo->write(obuf,ph.c_len);
    fo->write(loader+lsize-d_len,d_len); // decompressor
    char rel_entry[4];
    set_le32(rel_entry,5 + s_point);
    fo->write(rel_entry,sizeof (rel_entry));

    // verify
    verifyOverlappingDecompression();

    // copy the overlay
    copyOverlay(fo, overlay, &obuf);

    // finally check the compression ratio
    if (!checkFinalCompressionRatio(fo))
        throwNotCompressible();
}
Example #2
0
void PackWcle::preprocessFixups()
{
    big_relocs = 0;

    unsigned ic,jc;

    Array(unsigned, counts, objects+2);
    countFixups(counts);

    for (ic = jc = 0; ic < objects; ic++)
        jc += counts[ic];

    if (jc == 0)
    {
        // FIXME: implement this
        throwCantPack("files without relocations are not supported");
    }

    ByteArray(rl, jc);
    ByteArray(srf, counts[objects+0]+1);
    ByteArray(slf, counts[objects+1]+1);

    upx_byte *selector_fixups = srf;
    upx_byte *selfrel_fixups = slf;
    unsigned rc = 0;

    upx_byte *fix = ifixups;
    for (ic = jc = 0; ic < pages; ic++)
    {
        while ((unsigned)(fix - ifixups) < get_le32(ifpage_table+ic+1))
        {
            const int fixp2 = get_le16_signed(fix+2);
            unsigned value;

            switch (*fix)
            {
                case 2:       // selector fixup
                    if (fixp2 < 0)
                    {
                        // cross page selector fixup
                        dputc('S',stdout);
                        fix += 5;
                        break;
                    }
                    dputc('s',stdout);
                    memcpy(selector_fixups,"\x8C\xCB\x66\x89\x9D",5); // mov bx, cs ; mov [xxx+ebp], bx
                    if (IOT(fix[4]-1,flags) & LEOF_WRITE)
                        selector_fixups[1] = 0xDB; // ds
                    set_le32(selector_fixups+5,jc+fixp2);
                    selector_fixups += 9;
                    fix += 5;
                    break;
                case 5:       // 16-bit offset
                    if ((unsigned)fixp2 < 4096 && IOT(fix[4]-1,my_base_address) == jc)
                        dputc('6',stdout);
                    else
                        throwCantPack("unsupported 16-bit offset relocation");
                    fix += (fix[1] & 0x10) ? 9 : 7;
                    break;
                case 6:       // 16:32 pointer
                    if (fixp2 < 0)
                    {
                        // cross page pointer fixup
                        dputc('P',stdout);
                        fix += (fix[1] & 0x10) ? 9 : 7;
                        break;
                    }
                    dputc('p',stdout);
                    memcpy(iimage+jc+fixp2,fix+5,(fix[1] & 0x10) ? 4 : 2);
                    set_le32(rl+4*rc++,jc+fixp2);
                    set_le32(iimage+jc+fixp2,get_le32(iimage+jc+fixp2)+IOT(fix[4]-1,my_base_address));

                    memcpy(selector_fixups,"\x8C\xCA\x66\x89\x95",5);
                    if (IOT(fix[4]-1,flags) & LEOF_WRITE)
                        selector_fixups[1] = 0xDA; // ds
                    set_le32(selector_fixups+5,jc+fixp2+4);
                    selector_fixups += 9;
                    fix += (fix[1] & 0x10) ? 9 : 7;
                    break;
                case 7:       // 32-bit offset
                    if (fixp2 < 0)
                    {
                        fix += (fix[1] & 0x10) ? 9 : 7;
                        break;
                    }
                    //if (memcmp(iimage+jc+fixp2,fix+5,(fix[1] & 0x10) ? 4 : 2))
                    //    throwCantPack("illegal fixup offset");

                    // work around a pmwunlite bug: remove duplicated fixups
                    // FIXME: fix the other cases too
                    if (rc == 0 || get_le32(rl+4*rc-4) != jc+fixp2)
                    {
                        set_le32(rl+4*rc++,jc+fixp2);
                        set_le32(iimage+jc+fixp2,get_le32(iimage+jc+fixp2)+IOT(fix[4]-1,my_base_address));
                    }
                    fix += (fix[1] & 0x10) ? 9 : 7;
                    break;
                case 8:       // 32-bit self relative fixup
                    if (fixp2 < 0)
                    {
                        // cross page self relative fixup
                        dputc('R',stdout);
                        fix += (fix[1] & 0x10) ? 9 : 7;
                        break;
                    }
                    value = get_le32(fix+5);
                    if (fix[1] == 0)
                        value &= 0xffff;
                    set_le32(iimage+jc+fixp2,(value+IOT(fix[4]-1,my_base_address))-jc-fixp2-4);
                    set_le32(selfrel_fixups,jc+fixp2);
                    selfrel_fixups += 4;
                    dputc('r',stdout);
                    fix += (fix[1] & 0x10) ? 9 : 7;
                    break;
                default:
                    throwCantPack("unsupported fixup record");
            }
        }
        jc += mps;
    }

    // resize ifixups if it's too small
    if (sofixups < 1000)
    {
        delete[] ifixups;
        ifixups = new upx_byte[1000];
    }
    fix = optimizeReloc32 (rl,rc,ifixups,iimage,1,&big_relocs);
    has_extra_code = srf != selector_fixups;
    // FIXME: this could be removed if has_extra_code = false
    // but then we'll need a flag
    *selector_fixups++ = 0xC3; // ret
    memcpy(fix,srf,selector_fixups-srf); // copy selector fixup code
    fix += selector_fixups-srf;

    memcpy(fix,slf,selfrel_fixups-slf); // copy self-relative fixup positions
    fix += selfrel_fixups-slf;
    set_le32(fix,0xFFFFFFFFUL);
    fix += 4;

    sofixups = ptr_diff(fix, ifixups);
}