Esempio n. 1
0
    const unsigned origstart = get_le32(obuf+ph.u_len-8);

    // unfilter
    if (ph.filter)
    {
        Filter ft(ph.level);
        ft.init(ph.filter, 0);
        ft.cto = (unsigned char) ph.filter_cto;
        if (ph.version < 11)
            ft.cto = (unsigned char) (get_le32(obuf+ph.u_len-12) >> 24);
        ft.unfilter(obuf, ptr_diff(relocs, obuf));
    }

    // decode relocations
    MemBuffer wrkmem;
    unsigned relocn = unoptimizeReloc32(&relocs,obuf,&wrkmem,1);
    for (unsigned ic = 0; ic < relocn; ic++)
        set_le32(wrkmem+ic*4,get_le32(wrkmem+ic*4)+4);

    memcpy(&oh,&ih,sizeof(oh));
    oh.imagesize = osize;
    oh.entry = origstart;
    oh.relocsize = relocn*4;

    const unsigned overlay = file_size - adam_offset - ih.imagesize
        - ih.relocsize - sizeof(ih);
    checkOverlay(overlay);

    // write decompressed file
    if (fo)
    {
Esempio n. 2
0
void PackWcle::decodeFixups()
{
    upx_byte *p = oimage + soimage;

    iimage.dealloc();

    MemBuffer tmpbuf;
    unsigned fixupn = unoptimizeReloc32(&p,oimage,&tmpbuf,1);

    MemBuffer wrkmem(8*fixupn+8);
    unsigned ic,jc,o,r;
    for (ic=0; ic<fixupn; ic++)
    {
        jc=get_le32(tmpbuf+4*ic);
        set_le32(wrkmem+ic*8,jc);
        o = soobject_table;
        r = get_le32(oimage+jc);
        virt2rela(oobject_table,&o,&r);
        set_le32(wrkmem+ic*8+4,OOT(o-1,my_base_address));
        set_le32(oimage+jc,r);
    }
    set_le32(wrkmem+ic*8,0xFFFFFFFF);     // end of 32-bit offset fixups
    tmpbuf.dealloc();

    // selector fixups and self-relative fixups
    const upx_byte *selector_fixups = p;
    const upx_byte *selfrel_fixups = p;

    while (*selfrel_fixups != 0xC3)
        selfrel_fixups += 9;
    selfrel_fixups++;
    unsigned selectlen = ptr_diff(selfrel_fixups, selector_fixups)/9;

    ofixups = New(upx_byte, fixupn*9+1000+selectlen*5);
    upx_bytep fp = ofixups;

    for (ic = 1, jc = 0; ic <= opages; ic++)
    {
        // self relative fixups
        while ((r = get_le32(selfrel_fixups))/mps == ic-1)
        {
            fp[0] = 8;
            set_le16(fp+2,r & (mps-1));
            o = 4+get_le32(oimage+r);
            set_le32(oimage+r,0);
            r += o;
            o = soobject_table;
            virt2rela(oobject_table,&o,&r);
            fp[4] = (unsigned char) o;
            set_le32(fp+5,r);
            fp[1] = (unsigned char) (r > 0xFFFF ? 0x10 : 0);
            fp += fp[1] ? 9 : 7;
            selfrel_fixups += 4;
            dputc('r',stdout);
        }
        // selector fixups
        while (selectlen && (r = get_le32(selector_fixups+5))/mps == ic-1)
        {
            fp[0] = 2;
            fp[1] = 0;
            set_le16(fp+2,r & (mps-1));
            unsigned x = selector_fixups[1] > 0xD0 ? oh.init_ss_object : oh.init_cs_object;
            fp[4] = (unsigned char) x;
            fp += 5;
            selector_fixups += 9;
            selectlen--;
            dputc('s',stdout);
        }
        // 32 bit offset fixups
        while (get_le32(wrkmem+4*jc) < ic*mps)
        {
            if (jc > 1 && ((get_le32(wrkmem+4*(jc-2))+3) & (mps-1)) < 3) // cross page fixup?
            {
                r = get_le32(oimage+get_le32(wrkmem+4*(jc-2)));
                fp[0] = 7;
                fp[1] = (unsigned char) (r > 0xFFFF ? 0x10 : 0);
                set_le16(fp+2,get_le32(wrkmem+4*(jc-2)) | ~3);
                set_le32(fp+5,r);
                o = soobject_table;
                r = get_le32(wrkmem+4*(jc-1));
                virt2rela(oobject_table,&o,&r);
                fp[4] = (unsigned char) o;
                fp += fp[1] ? 9 : 7;
                dputc('0',stdout);
            }
            o = soobject_table;
            r = get_le32(wrkmem+4*(jc+1));
            virt2rela(oobject_table,&o,&r);
            r = get_le32(oimage+get_le32(wrkmem+4*jc));
            fp[0] = 7;
            fp[1] = (unsigned char) (r > 0xFFFF ? 0x10 : 0);
            set_le16(fp+2,get_le32(wrkmem+4*jc) & (mps-1));
            fp[4] = (unsigned char) o;
            set_le32(fp+5,r);
            fp += fp[1] ? 9 : 7;
            jc += 2;
        }
        set_le32(ofpage_table+ic,ptr_diff(fp,ofixups));
    }
    for (ic=0; ic < FIXUP_EXTRA; ic++)
        *fp++ = 0;
    sofixups = ptr_diff(fp, ofixups);
}