Menu

(Tutorial) How to Understanding UPX Work

2010-06-14
2013-05-23
  • ian Anindya

    ian Anindya - 2010-06-14

    I don't have programmer background, But I need to learn about how UPX work. Someone tell me by UPX source code I will understand about how UPX work but I don't. I don't know about programmer langugae.
    Could Member in here help me to make tutorial about it?

    Thanks,
    Ian911

     
  • ian Anindya

    ian Anindya - 2010-06-26

    Hi,

    Please help to give me understanding about script below. Is it should be copied/write into *.cpp file?

    Thanks,
    Ian

    /*************************************************************************
    // simple checksum for the header itself (since version 10)
    **************************************************************************/

    static unsigned char get_packheader_checksum(const upx_bytep buf, int len)
    {
    assert(get_le32(buf) == UPX_MAGIC_LE32);
    //printf("1 %d\n", len);
    buf += 4;
    len -= 4;
    unsigned c = 0;
    while (len- > 0)
    c += *buf++;
    c %= 251;
    //printf("2 %d\n", c);
    return (unsigned char) c;
    }

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

    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;
    }

    /*************************************************************************
    // see stub/header.ash
    **************************************************************************/

    void PackHeader::putPackHeader(upx_bytep p)
    {
    assert(get_le32(p) == UPX_MAGIC_LE32);
    if (get_le32(p+4) != UPX_MAGIC2_LE32)
    {
    //fprintf(stderr, "MAGIC2_LE32: %x %x\n", get_le32(p+4), UPX_MAGIC2_LE32);
    throwBadLoader();
    }

    int size = 0;
    int old_chksum = 0;

    // the new variable length header
    if (format < 128)
    {
    if (format == UPX_F_DOS_COM || format == UPX_F_DOS_SYS)
    {
    size = 22;
    old_chksum = get_packheader_checksum(p, size - 1);
    set_le16(p+16,u_len);
    set_le16(p+18,c_len);
    p = (unsigned char) filter;
    }
    else if (format == UPX_F_DOS_EXE)
    {
    size = 27;
    old_chksum = get_packheader_checksum(p, size - 1);
    set_le24(p+16,u_len);
    set_le24(p+19,c_len);
    set_le24(p+22,u_file_size);
    p = (unsigned char) filter;
    }
    else if (format == UPX_F_DOS_EXEH)
    {
    throwInternalError("invalid format";
    }
    else
    {
    size = 32;
    old_chksum = get_packheader_checksum(p, size - 1);
    set_le32(p+16,u_len);
    set_le32(p+20,c_len);
    set_le32(p+24,u_file_size);
    p = (unsigned char) filter;
    p = (unsigned char) filter_cto;
    assert(n_mru == 0 || (n_mru >= 2 && n_mru <= 256));
    p = (unsigned char) (n_mru ? n_mru - 1 : 0);
    }
    set_le32(p+8,u_adler);
    set_le32(p+12,c_adler);
    }
    else
    {
    size = 32;
    old_chksum = get_packheader_checksum(p, size - 1);
    set_be32(p+8,u_len);
    set_be32(p+12,c_len);
    set_be32(p+16,u_adler);
    set_be32(p+20,c_adler);
    set_be32(p+24,u_file_size);
    p = (unsigned char) filter;
    p = (unsigned char) filter_cto;
    assert(n_mru == 0 || (n_mru >= 2 && n_mru <= 256));
    p = (unsigned char) (n_mru ? n_mru - 1 : 0);
    }

    p = (unsigned char) version;
    p = (unsigned char) format;
    p = (unsigned char) method;
    p = (unsigned char) level;

    // header_checksum
    assert(size == getPackHeaderSize());
    // check old header_checksum
    if (p != 0)
    {
    if (p != old_chksum)
    {
    //printf("old_checksum: %d %d\n", p, old_chksum);
    throwBadLoader();
    }
    }
    // store new header_checksum
    p = get_packheader_checksum(p, size - 1);
    }

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

    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;
    format = p;
    method = p;
    level = p;
    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;
    n_mru = p ? 1 + p : 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;
    n_mru = p ? 1 + p : 0;
    }

    if (version >= 10)
    filter = p;
    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 != get_packheader_checksum(p, size - 1))
    throwCantUnpack("header corrupted 3");

    //
    // success
    //

    this->buf_offset = boff;
    return true;
    }

     
  • dos386

    dos386 - 2010-06-30

    > I don't have programmer background, But I need to learn about how UPX work.

    It compresses the EXE data and adds a stub that decompresses it at loading.

    > Someone tell me by UPX source code I will understand about how
    > UPX work but I don't. I don't know about programmer langugae.

    UPX source code is not for beginners, sorry (NO, I can't understand/compile it either).

     
  • Pras

    Pras - 2011-12-15

    "I don't have programmer background, But I need to learn about how UPX work. Someone tell me by UPX source code I will understand about how UPX work but I don't. I don't know about programmer langugae."

    What do you want to understand more about? You can google for file compression - data compression - executable compression etc to learn more about data redundancy and overall compression. To find out more about the settings in UPX - basically there's only one that you really need unless you know what you're doing - set in advanced EXACT (byte-identical decompression). Otherwise it's just a trade-off between time and compression amount.

    "Could Member in here help me to make tutorial about it?"

    I'd be happy to help you if you have more of a specific idea of what you want to do. It would be nice to just start by listing all the available commands and inviting people here to post descriptions of their function.

     

Log in to post a comment.