コード例 #1
0
ファイル: p_unix.cpp プロジェクト: tfauck/upx
int PackUnix::canUnpack()
{
    int const small = 32 + sizeof(overlay_offset);
    // Allow zero-filled last page, for Mac OS X code signing.
    int bufsize = 2*4096 + 2*small +1;
    if (bufsize > fi->st_size())
        bufsize = fi->st_size();
    MemBuffer buf(bufsize);

    fi->seek(-(off_t)bufsize, SEEK_END);
    fi->readx(buf, bufsize);
    int i = bufsize;
    while (i > small && 0 == buf[--i]) { }
    i -= small;
    // allow incompressible extents
    if (i < 0 || !getPackHeader(buf + i, bufsize - i, true))
        return false;

    int l = ph.buf_offset + ph.getPackHeaderSize();
    if (l < 0 || l + 4 > bufsize)
        throwCantUnpack("file corrupted");
    overlay_offset = get_te32(buf + i + l);
    if ((off_t)overlay_offset >= file_size)
        throwCantUnpack("file corrupted");

    return true;
}
コード例 #2
0
int PackTos::canUnpack()
{
    if (!readFileHeader())
        return false;
    if (!readPackHeader(768))
        return false;
    // check header as set by packer
    if ((ih.fh_text & 3) != 0 || (ih.fh_data & 3) != 0 || (ih.fh_bss & 3) != 0
        || ih.fh_sym != 0 || ih.fh_reserved != 0 || ih.fh_reloc > 1)
        throwCantUnpack("program header damaged");
    // generic check
    if (!checkFileHeader())
        throwCantUnpack("unsupported header flags");
    return true;
}
コード例 #3
0
ファイル: packhead.cpp プロジェクト: QuocHuy7a10/Arianrhod
int PackHeader::getPackHeaderSize() const
{
    if (format < 0 || version < 0)
        throwInternalError("getPackHeaderSize");

    int n = 0;
    if (version <= 3)
        n = 24;
    else if (version <= 9)
    {
        if (format == UPX_F_DOS_COM || format == UPX_F_DOS_SYS)
            n = 20;
        else if (format == UPX_F_DOS_EXE || format == UPX_F_DOS_EXEH)
            n = 25;
        else
            n = 28;
    }
    else
    {
        if (format == UPX_F_DOS_COM || format == UPX_F_DOS_SYS)
            n = 22;
        else if (format == UPX_F_DOS_EXE || format == UPX_F_DOS_EXEH)
            n = 27;
        else
            n = 32;
    }
    if (n < 20)
        throwCantUnpack("unknown header version");
    return n;
}
コード例 #4
0
ファイル: p_com.cpp プロジェクト: BiteFoo/UPX-Visual-Studio
void PackCom::unpack(OutputFile *fo)
{
    ibuf.alloc(file_size);
    obuf.allocForUncompression(ph.u_len);

    // read whole file
    fi->seek(0,SEEK_SET);
    fi->readx(ibuf,file_size);

    // get compressed data offset
    int e_len = ph.buf_offset + ph.getPackHeaderSize();
    if (file_size <= e_len + (off_t)ph.c_len)
        throwCantUnpack("file damaged");

    // decompress
    decompress(ibuf+e_len,obuf);

    // unfilter
    Filter ft(ph.level);
    ft.init(ph.filter, getCallTrickOffset());
    ft.unfilter(obuf,ph.u_len);

    // write decompressed file
    if (fo)
        fo->write(obuf,ph.u_len);
}
コード例 #5
0
ファイル: p_vmlinz.cpp プロジェクト: IngwiePhoenix/drag0n-src
void PackVmlinuzI386::unpack(OutputFile *fo)
{
    // no uncompression support for this format, so that
    // it is possible to remove the original deflate code (>10 KiB)

    // FIXME: but we could write the uncompressed "vmlinux" image

    ibuf.alloc(ph.c_len);
    obuf.allocForUncompression(ph.u_len);

    fi->seek(setup_size + ph.buf_offset + ph.getPackHeaderSize(), SEEK_SET);
    fi->readx(ibuf, ph.c_len);

    // decompress
    decompress(ibuf, obuf);

    // unfilter
    Filter ft(ph.level);
    ft.init(ph.filter, physical_start);
    ft.cto = (unsigned char) ph.filter_cto;
    ft.unfilter(obuf, ph.u_len);

    // write decompressed file
    if (fo)
    {
        throwCantUnpack("build a new kernel instead :-)");
        //fo->write(obuf, ph.u_len);
    }
}
コード例 #6
0
ファイル: p_unix.cpp プロジェクト: sincoder/upx
int PackUnix::canUnpack()
{
    upx_byte buf[sizeof(overlay_offset) + 32];
    const int bufsize = sizeof(buf);

    fi->seek(-bufsize, SEEK_END);
    fi->readx(buf, bufsize);
    if (!getPackHeader(buf, bufsize, true))  // allow incompressible extents
        return false;

    int l = ph.buf_offset + ph.getPackHeaderSize();
    if (l < 0 || l + 4 > bufsize)
        throwCantUnpack("file corrupted");
    overlay_offset = get_te32(buf+l);
    if ((off_t)overlay_offset >= file_size)
        throwCantUnpack("file corrupted");

    return true;
}
コード例 #7
0
ファイル: p_armpe.cpp プロジェクト: BiteFoo/UPX-Visual-Studio
static const
#include "stub/arm.v4a-wince.pe.h"
static const
#include "stub/arm.v4t-wince.pe.h"

#define IDSIZE(x)       ih.ddirs[x].size
#define IDADDR(x)       ih.ddirs[x].vaddr
#define ODSIZE(x)       oh.ddirs[x].size
#define ODADDR(x)       oh.ddirs[x].vaddr

#define isdll           ((ih.flags & DLL_FLAG) != 0)

#define FILLVAL         0

/*************************************************************************
//
**************************************************************************/

#if defined(__BORLANDC__)
#  undef strcpy
#  define strcpy(a,b)   strcpy((char *)(a),(const char *)(b))
#endif

#if (__ACC_CXX_HAVE_PLACEMENT_DELETE) || defined(__DJGPP__)
#include "bptr.h"
#define IPTR(type, var)         BoundedPtr<type> var(ibuf, ibuf.getSize())
#define OPTR(type, var)         BoundedPtr<type> var(obuf, obuf.getSize())
#define IPTR_I(type, var, v)    BoundedPtr<type> var(ibuf, ibuf.getSize(), v)
#define OPTR_I(type, var, v)    BoundedPtr<type> var(obuf, obuf.getSize(), v)
#define IPTR_C(type, var, v)    const BoundedPtr<type> var(ibuf, ibuf.getSize(), v)
#define OPTR_C(type, var, v)    const BoundedPtr<type> var(obuf, obuf.getSize(), v)
#else
#define IPTR(type, var)         type* var = 0
#define OPTR(type, var)         type* var = 0
#define IPTR_I(type, var, v)    type* var = (v)
#define OPTR_I(type, var, v)    type* var = (v)
#define IPTR_C(type, var, v)    type* const var = (v)
#define OPTR_C(type, var, v)    type* const var = (v)
#endif

static void xcheck(const void *p, size_t plen, const void *b, size_t blen)
{
    const char *pp = (const char *) p;
    const char *bb = (const char *) b;
    if (pp < bb || pp > bb + blen || pp + plen > bb + blen)
        throwCantUnpack("pointer out of range; take care!");
}
コード例 #8
0
ファイル: packhead.cpp プロジェクト: QuocHuy7a10/Arianrhod
bool PackHeader::fillPackHeader(const upx_bytep buf, int blen)
{
    int boff = find_le32(buf, blen, UPX_MAGIC_LE32);
    if (boff < 0)
        return false;

    if (boff + 8 <= 0 || boff + 8 > blen)
        throwCantUnpack("header corrupted 1");

    const upx_bytep p = buf + boff;

    version = p[4];
    format = p[5];
    method = p[6];
    level = p[7];
    filter_cto = 0;

    const int size = getPackHeaderSize();
    if (boff + size <= 0 || boff + size > blen)
        throwCantUnpack("header corrupted 2");

    //
    // decode the new variable length header
    //

    int off_filter = 0;
    if (format < 128)
    {
        u_adler = get_le32(p+8);
        c_adler = get_le32(p+12);
        if (format == UPX_F_DOS_COM || format == UPX_F_DOS_SYS)
        {
            u_len = get_le16(p+16);
            c_len = get_le16(p+18);
            u_file_size = u_len;
            off_filter = 20;
        }
        else if (format == UPX_F_DOS_EXE || format == UPX_F_DOS_EXEH)
        {
            u_len = get_le24(p+16);
            c_len = get_le24(p+19);
            u_file_size = get_le24(p+22);
            off_filter = 25;
        }
        else
        {
            u_len = get_le32(p+16);
            c_len = get_le32(p+20);
            u_file_size = get_le32(p+24);
            off_filter = 28;
            filter_cto = p[29];
            n_mru = p[30] ? 1 + p[30] : 0;
        }
    }
    else
    {
        u_len = get_be32(p+8);
        c_len = get_be32(p+12);
        u_adler = get_be32(p+16);
        c_adler = get_be32(p+20);
        u_file_size = get_be32(p+24);
        off_filter = 28;
        filter_cto = p[29];
        n_mru = p[30] ? 1 + p[30] : 0;
    }

    if (version >= 10)
        filter = p[off_filter];
    else if ((level & 128) == 0)
        filter = 0;
    else
    {
        // convert old flags to new filter id
        level &= 127;
        if (format == UPX_F_DOS_COM || format == UPX_F_DOS_SYS)
            filter = 0x06;
        else
            filter = 0x26;
    }
    level &= 15;

    //
    // now some checks
    //

    if (version == 0xff)
        throwCantUnpack("cannot unpack UPX ;-)");

    // check header_checksum
    if (version > 9)
        if (p[size - 1] != get_packheader_checksum(p, size - 1))
            throwCantUnpack("header corrupted 3");

    //
    // success
    //

    this->buf_offset = boff;
    return true;
}
コード例 #9
0
ファイル: p_lx_interp.cpp プロジェクト: Distrotech/upx
void PackLinuxElf32x86interp::unpack(OutputFile *fo)
{
#define MAX_INTERP_HDR 512
    union {
        unsigned char buf[MAX_INTERP_HDR];
        //struct { Elf32_Ehdr ehdr; Elf32_Phdr phdr; } e;
    } u;
    Elf32_Ehdr *const ehdr = (Elf32_Ehdr *) u.buf;
    Elf32_Phdr const *phdr = (Elf32_Phdr *) (u.buf + sizeof(*ehdr));

    unsigned szb_info = sizeof(b_info);
    {
        fi->seek(0, SEEK_SET);
        fi->readx(u.buf, MAX_INTERP_HDR);
        unsigned const e_entry = get_te32(&ehdr->e_entry);
        if (e_entry < 0x401180) { /* old style, 8-byte b_info */
            szb_info = 2*sizeof(unsigned);
        }
    }

    fi->seek(overlay_offset, SEEK_SET);
    p_info hbuf;
    fi->readx(&hbuf, sizeof(hbuf));
    unsigned orig_file_size = get_te32(&hbuf.p_filesize);
    blocksize = get_te32(&hbuf.p_blocksize);
    if (file_size > (off_t)orig_file_size || blocksize > orig_file_size)
        throwCantUnpack("file header corrupted");

    ibuf.alloc(blocksize + OVERHEAD);
    b_info bhdr; memset(&bhdr, 0, sizeof(bhdr));
    fi->readx(&bhdr, szb_info);
    ph.u_len = get_te32(&bhdr.sz_unc);
    ph.c_len = get_te32(&bhdr.sz_cpr);
    ph.filter_cto = bhdr.b_cto8;

    // Uncompress Ehdr and Phdrs.
    fi->readx(ibuf, ph.c_len);
    decompress(ibuf, (upx_byte *)ehdr, false);

    unsigned total_in = 0;
    unsigned total_out = 0;
    unsigned c_adler = upx_adler32(NULL, 0);
    unsigned u_adler = upx_adler32(NULL, 0);
    off_t ptload0hi=0, ptload1lo=0, ptload1sz=0;

    // decompress PT_LOAD
    bool first_PF_X = true;
    fi->seek(- (off_t) (szb_info + ph.c_len), SEEK_CUR);
    for (unsigned j=0; j < ehdr->e_phnum; ++phdr, ++j) {
        if (PT_LOAD==phdr->p_type) {
            if (0==ptload0hi) {
                ptload0hi = phdr->p_filesz + phdr->p_offset;
            }
            else if (0==ptload1lo) {
                ptload1lo = phdr->p_offset;
                ptload1sz = phdr->p_filesz;
            }
            if (fo)
                fo->seek(phdr->p_offset, SEEK_SET);
            if (Elf32_Phdr::PF_X & phdr->p_flags) {
                unpackExtent(phdr->p_filesz, fo, total_in, total_out,
                    c_adler, u_adler, first_PF_X, szb_info);
                first_PF_X = false;
            }
            else {
                unpackExtent(phdr->p_filesz, fo, total_in, total_out,
                    c_adler, u_adler, false, szb_info);
            }
        }
    }

    if (0!=ptload1sz && ptload0hi < ptload1lo) {  // alignment hole?
        if (fo)
            fo->seek(ptload0hi, SEEK_SET);
        unpackExtent(ptload1lo - ptload0hi, fo, total_in, total_out,
            c_adler, u_adler, false, szb_info);
    }
    if (total_out != orig_file_size) {  // non-PT_LOAD stuff
        if (fo)
            fo->seek(0, SEEK_END);
        unpackExtent(orig_file_size - total_out, fo, total_in, total_out,
            c_adler, u_adler, false, szb_info);
    }

    // check for end-of-file
    fi->readx(&bhdr, szb_info);
    unsigned const sz_unc = ph.u_len = get_te32(&bhdr.sz_unc);

    if (sz_unc == 0) { // uncompressed size 0 -> EOF
        // note: magic is always stored le32
        unsigned const sz_cpr = get_le32(&bhdr.sz_cpr);
        if (sz_cpr != UPX_MAGIC_LE32)  // sz_cpr must be h->magic
            throwCompressedDataViolation();
    }
    else { // extra bytes after end?
        throwCompressedDataViolation();
    }

    // update header with totals
    ph.c_len = total_in;
    ph.u_len = total_out;

    // all bytes must be written
    if (total_out != orig_file_size)
        throwEOFException();

    // finally test the checksums
    if (ph.c_adler != c_adler || ph.u_adler != u_adler)
        throwChecksumError();
#undef MAX_INTERP_HDR
}
コード例 #10
0
ファイル: p_unix.cpp プロジェクト: tfauck/upx
void PackUnix::unpack(OutputFile *fo)
{
    unsigned const szb_info = sizeof(b_info);

    unsigned c_adler = upx_adler32(NULL, 0);
    unsigned u_adler = upx_adler32(NULL, 0);

    // defaults for ph.version == 8
    unsigned orig_file_size = 0;
    blocksize = 512 * 1024;

    fi->seek(overlay_offset, SEEK_SET);
    if (ph.version > 8)
    {
        p_info hbuf;
        fi->readx(&hbuf, sizeof(hbuf));
        orig_file_size = get_te32(&hbuf.p_filesize);
        blocksize = get_te32(&hbuf.p_blocksize);

        if (file_size > (off_t)orig_file_size || blocksize > orig_file_size)
            throwCantUnpack("file header corrupted");
    }
    else
    {
        // skip 4 bytes (program id)
        fi->seek(4, SEEK_CUR);
    }

    if ((int)(blocksize + OVERHEAD) < 0)
        throwCantUnpack("blocksize corrupted");
    ibuf.alloc(blocksize + OVERHEAD);

    // decompress blocks
    unsigned total_in = 0;
    unsigned total_out = 0;
    b_info bhdr; memset(&bhdr, 0, sizeof(bhdr));
    for (;;)
    {
#define buf ibuf
        int i;
        unsigned sz_unc, sz_cpr;

        fi->readx(&bhdr, szb_info);
        ph.u_len = sz_unc = get_te32(&bhdr.sz_unc);
        ph.c_len = sz_cpr = get_te32(&bhdr.sz_cpr);

        if (sz_unc == 0)                   // uncompressed size 0 -> EOF
        {
            // note: must reload sz_cpr as magic is always stored le32
            sz_cpr = get_le32(&bhdr.sz_cpr);
            if (sz_cpr != UPX_MAGIC_LE32)  // sz_cpr must be h->magic
                throwCompressedDataViolation();
            break;
        }
        if (sz_unc <= 0 || sz_cpr <= 0)
            throwCompressedDataViolation();
        if (sz_cpr > sz_unc || sz_unc > blocksize)
            throwCompressedDataViolation();

        i = blocksize + OVERHEAD - sz_cpr;
        if (i < 0)
            throwCantUnpack("corrupt b_info");
        fi->readx(buf+i, sz_cpr);
        // update checksum of compressed data
        c_adler = upx_adler32(buf + i, sz_cpr, c_adler);
        // decompress
        if (sz_cpr < sz_unc) {
            decompress(buf+i, buf, false);
            if (0!=bhdr.b_ftid) {
                Filter ft(ph.level);
                ft.init(bhdr.b_ftid);
                ft.cto = bhdr.b_cto8;
                ft.unfilter(buf, sz_unc);
            }
            i = 0;
        }
        // update checksum of uncompressed data
        u_adler = upx_adler32(buf + i, sz_unc, u_adler);
        total_in  += sz_cpr;
        total_out += sz_unc;
        // write block
        if (fo)
            fo->write(buf + i, sz_unc);
#undef buf
    }

    // update header with totals
    ph.c_len = total_in;
    ph.u_len = total_out;

    // all bytes must be written
    if (ph.version > 8 && total_out != orig_file_size)
        throwEOFException();

    // finally test the checksums
    if (ph.c_adler != c_adler || ph.u_adler != u_adler)
        throwChecksumError();
}
コード例 #11
0
ファイル: p_unix.cpp プロジェクト: tfauck/upx
void PackUnix::unpackExtent(unsigned wanted, OutputFile *fo,
    unsigned &total_in, unsigned &total_out,
    unsigned &c_adler, unsigned &u_adler,
    bool first_PF_X, unsigned szb_info
)
{
    b_info hdr; memset(&hdr, 0, sizeof(hdr));
    while (wanted) {
        fi->readx(&hdr, szb_info);
        int const sz_unc = ph.u_len = get_te32(&hdr.sz_unc);
        int const sz_cpr = ph.c_len = get_te32(&hdr.sz_cpr);
        ph.filter_cto = hdr.b_cto8;

        if (sz_unc == 0) { // must never happen while 0!=wanted
            throwCantUnpack("corrupt b_info");
            break;
        }
        if (sz_unc <= 0 || sz_cpr <= 0)
            throwCantUnpack("corrupt b_info");
        if (sz_cpr > sz_unc || sz_unc > (int)blocksize)
            throwCantUnpack("corrupt b_info");

        int j = blocksize + OVERHEAD - sz_cpr;
        fi->readx(ibuf+j, sz_cpr);
        // update checksum of compressed data
        c_adler = upx_adler32(ibuf + j, sz_cpr, c_adler);
        // decompress
        if (sz_cpr < sz_unc)
        {
            decompress(ibuf+j, ibuf, false);
            if (12==szb_info) { // modern per-block filter
                if (hdr.b_ftid) {
                    Filter ft(ph.level);  // FIXME: ph.level for b_info?
                    ft.init(hdr.b_ftid, 0);
                    ft.cto = hdr.b_cto8;
                    ft.unfilter(ibuf, sz_unc);
                }
            }
            else { // ancient per-file filter
                if (first_PF_X) { // Elf32_Ehdr is never filtered
                    first_PF_X = false;  // but everything else might be
                }
                else if (ph.filter) {
                    Filter ft(ph.level);
                    ft.init(ph.filter, 0);
                    ft.cto = (unsigned char) ph.filter_cto;
                    ft.unfilter(ibuf, sz_unc);
                }
            }
            j = 0;
        }
        // update checksum of uncompressed data
        u_adler = upx_adler32(ibuf + j, sz_unc, u_adler);
        total_in  += sz_cpr;
        total_out += sz_unc;
        // write block
        if (fo)
            fo->write(ibuf + j, sz_unc);
        if (wanted < (unsigned)sz_unc)
            throwCantUnpack("corrupt b_info");
        wanted -= sz_unc;
    }
}
コード例 #12
0
ファイル: p_armpe.cpp プロジェクト: BiteFoo/UPX-Visual-Studio
int PackArmPe::canUnpack()
{
    if (!readFileHeader() || (ih.cpu != 0x1c0 && ih.cpu != 0x1c2))
        return false;

    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);
    if (ih.objects < 3)
        return -1;
    bool is_packed = ((ih.objects == 3 || ih.objects == 4) &&
                      (IDSIZE(15) || ih.entry > isection[1].vaddr));
    bool found_ph = false;
    if (memcmp(isection[0].name,"UPX",3) == 0)
    {
        // current version
        fi->seek(isection[1].rawdataptr - 64, SEEK_SET);
        found_ph = readPackHeader(1024);
        if (!found_ph)
        {
            // old versions
            fi->seek(isection[2].rawdataptr, SEEK_SET);
            found_ph = readPackHeader(1024);
        }
    }
    if (is_packed && found_ph)
        return true;
    if (!is_packed && !found_ph)
        return -1;
    if (is_packed && ih.entry < isection[2].vaddr)
    {
        unsigned char buf[256];
        bool x = false;

        memset(buf, 0, sizeof(buf));
        try {
            fi->seek(ih.entry - isection[1].vaddr + isection[1].rawdataptr, SEEK_SET);
            fi->read(buf, sizeof(buf));

            // FIXME this is for x86
            static const unsigned char magic[] = "\x8b\x1e\x83\xee\xfc\x11\xdb";
            // mov ebx, [esi];    sub esi, -4;    adc ebx,ebx

            int offset = find(buf, sizeof(buf), magic, 7);
            if (offset >= 0 && find(buf + offset + 1, sizeof(buf) - offset - 1, magic, 7) >= 0)
                x = true;
        } catch (...) {
            //x = true;
        }
        if (x)
            throwCantUnpack("file is modified/hacked/protected; take care!!!");
        else
            throwCantUnpack("file is possibly modified/hacked/protected; take care!");
        return false;   // not reached
    }

    // FIXME: what should we say here ?
    //throwCantUnpack("file is possibly modified/hacked/protected; take care!");
    return false;
}
コード例 #13
0
ファイル: p_armpe.cpp プロジェクト: BiteFoo/UPX-Visual-Studio
static void xcheck(size_t poff, size_t plen, const void *b, size_t blen)
{
    ACC_UNUSED(b);
    if (poff > blen || poff + plen > blen)
        throwCantUnpack("pointer out of range; take care!");
}