fillPackHeader: revise and add yet more checks
https://github.com/upx/upx/issues/414 https://github.com/upx/upx/pull/415 revised modified: packhead.cpp
This commit is contained in:
parent
7c105d7af5
commit
c3466f579c
@ -58,12 +58,14 @@ static unsigned char get_packheader_checksum(const upx_bytep buf, int len) {
|
|||||||
//
|
//
|
||||||
**************************************************************************/
|
**************************************************************************/
|
||||||
|
|
||||||
|
// Returns the size that will be generated based on version and format,
|
||||||
|
// not necessarily the size that actually is present in spoofed input.
|
||||||
int PackHeader::getPackHeaderSize() const {
|
int PackHeader::getPackHeaderSize() const {
|
||||||
if (format < 0 || version < 0)
|
if (format < 0 || version < 0)
|
||||||
throwInternalError("getPackHeaderSize");
|
throwInternalError("getPackHeaderSize");
|
||||||
|
|
||||||
int n = 0;
|
int n = 0;
|
||||||
if (version <= 3)
|
if (version <= 3) // Note: covers (version <= 0)
|
||||||
n = 24;
|
n = 24;
|
||||||
else if (version <= 9) {
|
else if (version <= 9) {
|
||||||
if (format == UPX_F_DOS_COM || format == UPX_F_DOS_SYS)
|
if (format == UPX_F_DOS_COM || format == UPX_F_DOS_SYS)
|
||||||
@ -170,11 +172,11 @@ bool PackHeader::fillPackHeader(const upx_bytep buf, int blen) {
|
|||||||
if (boff < 0)
|
if (boff < 0)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (boff + 8 <= 0 || boff + 8 > blen)
|
const upx_bytep const p = buf + boff;
|
||||||
|
unsigned const headway = blen - boff; // bytes remaining in buf
|
||||||
|
|
||||||
|
if (headway < (1+ 7))
|
||||||
throwCantUnpack("header corrupted 1");
|
throwCantUnpack("header corrupted 1");
|
||||||
|
|
||||||
const upx_bytep p = buf + boff;
|
|
||||||
|
|
||||||
version = p[4];
|
version = p[4];
|
||||||
format = p[5];
|
format = p[5];
|
||||||
method = p[6];
|
method = p[6];
|
||||||
@ -192,20 +194,20 @@ bool PackHeader::fillPackHeader(const upx_bytep buf, int blen) {
|
|||||||
snprintf(msg, sizeof(msg), "unknown format %d", format);
|
snprintf(msg, sizeof(msg), "unknown format %d", format);
|
||||||
throwCantUnpack(msg);
|
throwCantUnpack(msg);
|
||||||
}
|
}
|
||||||
const int size = getPackHeaderSize();
|
|
||||||
if (boff + size <= 0 || boff + size > blen)
|
|
||||||
throwCantUnpack("header corrupted 2");
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// decode the new variable length header
|
// decode the new variable length header
|
||||||
//
|
//
|
||||||
|
|
||||||
int off_filter = 0;
|
unsigned off_filter = 0;
|
||||||
if (format < 128) {
|
if (format < 128) {
|
||||||
|
if (headway < 16) {
|
||||||
|
throwCantUnpack("header corrupted 2");
|
||||||
|
}
|
||||||
u_adler = get_le32(p + 8);
|
u_adler = get_le32(p + 8);
|
||||||
c_adler = get_le32(p + 12);
|
c_adler = get_le32(p + 12);
|
||||||
if (format == UPX_F_DOS_COM || format == UPX_F_DOS_SYS) {
|
if (format == UPX_F_DOS_COM || format == UPX_F_DOS_SYS) {
|
||||||
if (size < 21) {
|
if (headway < 20) {
|
||||||
throwCantUnpack("header corrupted 5");
|
throwCantUnpack("header corrupted 5");
|
||||||
}
|
}
|
||||||
u_len = get_le16(p + 16);
|
u_len = get_le16(p + 16);
|
||||||
@ -213,7 +215,7 @@ bool PackHeader::fillPackHeader(const upx_bytep buf, int blen) {
|
|||||||
u_file_size = u_len;
|
u_file_size = u_len;
|
||||||
off_filter = 20;
|
off_filter = 20;
|
||||||
} else if (format == UPX_F_DOS_EXE || format == UPX_F_DOS_EXEH) {
|
} else if (format == UPX_F_DOS_EXE || format == UPX_F_DOS_EXEH) {
|
||||||
if (size < 26) {
|
if (headway < 25) {
|
||||||
throwCantUnpack("header corrupted 6");
|
throwCantUnpack("header corrupted 6");
|
||||||
}
|
}
|
||||||
u_len = get_le24(p + 16);
|
u_len = get_le24(p + 16);
|
||||||
@ -221,7 +223,7 @@ bool PackHeader::fillPackHeader(const upx_bytep buf, int blen) {
|
|||||||
u_file_size = get_le24(p + 22);
|
u_file_size = get_le24(p + 22);
|
||||||
off_filter = 25;
|
off_filter = 25;
|
||||||
} else {
|
} else {
|
||||||
if (size < 31) {
|
if (headway < (3+ 28)) {
|
||||||
throwCantUnpack("header corrupted 7");
|
throwCantUnpack("header corrupted 7");
|
||||||
}
|
}
|
||||||
u_len = get_le32(p + 16);
|
u_len = get_le32(p + 16);
|
||||||
@ -232,7 +234,7 @@ bool PackHeader::fillPackHeader(const upx_bytep buf, int blen) {
|
|||||||
n_mru = p[30] ? 1 + p[30] : 0;
|
n_mru = p[30] ? 1 + p[30] : 0;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (size < 31) {
|
if (headway < (3+ 28)) {
|
||||||
throwCantUnpack("header corrupted 8");
|
throwCantUnpack("header corrupted 8");
|
||||||
}
|
}
|
||||||
u_len = get_be32(p + 8);
|
u_len = get_be32(p + 8);
|
||||||
@ -245,8 +247,12 @@ bool PackHeader::fillPackHeader(const upx_bytep buf, int blen) {
|
|||||||
n_mru = p[30] ? 1 + p[30] : 0;
|
n_mru = p[30] ? 1 + p[30] : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (version >= 10)
|
if (version >= 10) {
|
||||||
|
if (headway < (1+ off_filter)) {
|
||||||
|
throwCantUnpack("header corrupted 9");
|
||||||
|
}
|
||||||
filter = p[off_filter];
|
filter = p[off_filter];
|
||||||
|
}
|
||||||
else if ((level & 128) == 0)
|
else if ((level & 128) == 0)
|
||||||
filter = 0;
|
filter = 0;
|
||||||
else {
|
else {
|
||||||
@ -267,9 +273,12 @@ bool PackHeader::fillPackHeader(const upx_bytep buf, int blen) {
|
|||||||
throwCantUnpack("cannot unpack UPX ;-)");
|
throwCantUnpack("cannot unpack UPX ;-)");
|
||||||
|
|
||||||
// check header_checksum
|
// check header_checksum
|
||||||
if (version > 9)
|
if (version > 9) {
|
||||||
if (p[size - 1] != get_packheader_checksum(p, size - 1))
|
unsigned const size = getPackHeaderSize(); // expected; based on format and version
|
||||||
|
if (size < headway
|
||||||
|
|| p[size - 1] != get_packheader_checksum(p, size - 1))
|
||||||
throwCantUnpack("header corrupted 3");
|
throwCantUnpack("header corrupted 3");
|
||||||
|
}
|
||||||
|
|
||||||
if (c_len < 2 || u_len < 2 || !mem_size_valid_bytes(c_len) || !mem_size_valid_bytes(u_len))
|
if (c_len < 2 || u_len < 2 || !mem_size_valid_bytes(c_len) || !mem_size_valid_bytes(u_len))
|
||||||
throwCantUnpack("header corrupted 4");
|
throwCantUnpack("header corrupted 4");
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user