From 6f89139242b1db32c6b9f6d306018068192701fe Mon Sep 17 00:00:00 2001 From: thoger Date: Apr 25 2008 09:49:55 +0000 Subject: - Security update - backport security fixes from 0.93: CVE-2008-1100 (#442360): Upack Processing Buffer Overflow Vulnerability CVE-2008-1387 (#442525): Endless loop / hang with crafted arj CVE-2008-0314 (#442740): PeSpin Heap Overflow Vulnerability CVE-2008-1833 (#442741): PE WWPack Heap Overflow Vulnerability --- diff --git a/clamav-0.92.1-CVE-2008-0314.diff b/clamav-0.92.1-CVE-2008-0314.diff new file mode 100644 index 0000000..c8ed290 --- /dev/null +++ b/clamav-0.92.1-CVE-2008-0314.diff @@ -0,0 +1,12 @@ +diff -pruN clamav-0.92.1.orig/libclamav/spin.c clamav-0.92.1/libclamav/spin.c +--- clamav-0.92.1.orig/libclamav/spin.c 2007-12-06 13:59:04.000000000 +0100 ++++ clamav-0.92.1/libclamav/spin.c 2008-04-24 19:16:26.000000000 +0200 +@@ -419,7 +419,7 @@ int unspin(char *src, int ssize, struct + /* len = cli_readint32(ep+0x2fc8); -- Using vsizes instead */ + + for (j=0; j key32) ++ if (sections[j].rva <= key32 && key32-sections[j].rva < sections[j].vsz && CLI_ISCONTAINED(src + sections[j].raw, sections[j].rsz, src + sections[j].raw, key32 - sections[j].rva)) + break; + } + diff --git a/clamav-0.92.1-CVE-2008-1100.diff b/clamav-0.92.1-CVE-2008-1100.diff new file mode 100644 index 0000000..069627f --- /dev/null +++ b/clamav-0.92.1-CVE-2008-1100.diff @@ -0,0 +1,12 @@ +diff -pruN clamav-0.92.1.orig/libclamav/pe.c clamav-0.92.1/libclamav/pe.c +--- clamav-0.92.1.orig/libclamav/pe.c 2008-02-06 16:48:03.000000000 +0100 ++++ clamav-0.92.1/libclamav/pe.c 2008-04-24 19:19:19.000000000 +0200 +@@ -1246,7 +1246,7 @@ int cli_scanpe(int desc, cli_ctx *ctx) + + CLI_UNPSIZELIMITS("Upack", MAX(MAX(dsize, ssize), exe_sections[1].ursz)); + +- if (exe_sections[1].rva - off > dsize || exe_sections[1].rva - off > dsize - exe_sections[1].ursz || (upack && (exe_sections[2].rva - exe_sections[0].rva > dsize || exe_sections[2].rva - exe_sections[0].rva > dsize - ssize)) || ssize > dsize) { ++ if (!CLI_ISCONTAINED(0, dsize, exe_sections[1].rva - off, exe_sections[1].ursz) || (upack && !CLI_ISCONTAINED(0, dsize, exe_sections[2].rva - exe_sections[0].rva, ssize)) || ssize > dsize) { + cli_dbgmsg("Upack: probably malformed pe-header, skipping to next unpacker\n"); + break; + } diff --git a/clamav-0.92.1-CVE-2008-1387.diff b/clamav-0.92.1-CVE-2008-1387.diff new file mode 100644 index 0000000..0f33601 --- /dev/null +++ b/clamav-0.92.1-CVE-2008-1387.diff @@ -0,0 +1,326 @@ +diff -pruN clamav-0.92.1.orig/libclamav/unarj.c clamav-0.92.1/libclamav/unarj.c +--- clamav-0.92.1.orig/libclamav/unarj.c 2008-02-06 16:14:24.000000000 +0100 ++++ clamav-0.92.1/libclamav/unarj.c 2008-04-24 19:20:59.000000000 +0200 +@@ -160,6 +160,7 @@ typedef struct arj_decode_tag { + uint16_t c_table[CTABLESIZE]; + unsigned char pt_len[NPT]; + uint16_t pt_table[PTABLESIZE]; ++ int status; + } arj_decode_t; + + static int fill_buf(arj_decode_t *decode_data, int n) +@@ -170,6 +171,7 @@ static int fill_buf(arj_decode_t *decode + if (decode_data->comp_size != 0) { + decode_data->comp_size--; + if (cli_readn(decode_data->fd, &decode_data->sub_bit_buf, 1) != 1) { ++ decode_data->status = CL_EIO; + return CL_EIO; + } + } else { +@@ -228,6 +230,7 @@ static int make_table(arj_decode_t *deco + for (i = 0; (int)i < nchar; i++) { + if (bitlen[i] >= 17) { + cli_dbgmsg("UNARJ: bounds exceeded\n"); ++ decode_data->status = CL_EARJ; + return CL_EARJ; + } + count[bitlen[i]]++; +@@ -238,12 +241,14 @@ static int make_table(arj_decode_t *deco + start[i+1] = start[i] + (count[i] << (16 - i)); + } + if (start[17] != (unsigned short) (1 << 16)) { ++ decode_data->status = CL_EARJ; + return CL_EARJ; + } + + jutbits = 16 - tablebits; + if (tablebits >= 17) { + cli_dbgmsg("UNARJ: bounds exceeded\n"); ++ decode_data->status = CL_EARJ; + return CL_EARJ; + } + for (i = 1; (int)i <= tablebits; i++) { +@@ -261,6 +266,7 @@ static int make_table(arj_decode_t *deco + while (i != k) { + if (i >= tablesize) { + cli_dbgmsg("UNARJ: bounds exceeded\n"); ++ decode_data->status = CL_EARJ; + return CL_EARJ; + } + table[i++] = 0; +@@ -275,12 +281,14 @@ static int make_table(arj_decode_t *deco + } + if (len >= 17) { + cli_dbgmsg("UNARJ: bounds exceeded\n"); ++ decode_data->status = CL_EARJ; + return CL_EARJ; + } + k = start[len]; + nextcode = k + weight[len]; + if ((int)len <= tablebits) { + if (nextcode > (unsigned int) tablesize) { ++ decode_data->status = CL_EARJ; + return CL_EARJ; + } + for (i = start[len]; i < nextcode; i++) { +@@ -293,6 +301,7 @@ static int make_table(arj_decode_t *deco + if (*p == 0) { + if (avail >= (2 * NC - 1)) { + cli_dbgmsg("UNARJ: bounds exceeded\n"); ++ decode_data->status = CL_EARJ; + return CL_EARJ; + } + decode_data->right[avail] = decode_data->left[avail] = 0; +@@ -300,6 +309,7 @@ static int make_table(arj_decode_t *deco + } + if (*p >= (2 * NC - 1)) { + cli_dbgmsg("UNARJ: bounds exceeded\n"); ++ decode_data->status = CL_EARJ; + return CL_EARJ; + } + if (k & mask) { +@@ -317,7 +327,7 @@ static int make_table(arj_decode_t *deco + return CL_SUCCESS; + } + +-static void read_pt_len(arj_decode_t *decode_data, int nn, int nbit, int i_special) ++static int read_pt_len(arj_decode_t *decode_data, int nn, int nbit, int i_special) + { + int i, n; + short c; +@@ -327,7 +337,8 @@ static void read_pt_len(arj_decode_t *de + if (n == 0) { + if (nn > NPT) { + cli_dbgmsg("UNARJ: bounds exceeded\n"); +- return; ++ decode_data->status = CL_EARJ; ++ return CL_EARJ; + } + c = arj_getbits(decode_data, nbit); + for (i = 0; i < nn; i++) { +@@ -348,9 +359,15 @@ static void read_pt_len(arj_decode_t *de + } + } + fill_buf(decode_data, (c < 7) ? 3 : (int)(c - 3)); ++ if (decode_data->status != CL_SUCCESS) { ++ return decode_data->status; ++ } + decode_data->pt_len[i++] = (unsigned char) c; + if (i == i_special) { + c = arj_getbits(decode_data, 2); ++ if (decode_data->status != CL_SUCCESS) { ++ return decode_data->status; ++ } + while ((--c >= 0) && (i < NPT)) { + decode_data->pt_len[i++] = 0; + } +@@ -359,8 +376,11 @@ static void read_pt_len(arj_decode_t *de + while ((i < nn) && (i < NPT)) { + decode_data->pt_len[i++] = 0; + } +- make_table(decode_data, nn, decode_data->pt_len, 8, decode_data->pt_table, PTABLESIZE); ++ if (make_table(decode_data, nn, decode_data->pt_len, 8, decode_data->pt_table, PTABLESIZE) != CL_SUCCESS) { ++ return CL_EARJ; ++ } + } ++ return CL_SUCCESS; + } + + static int read_c_len(arj_decode_t *decode_data) +@@ -369,8 +389,14 @@ static int read_c_len(arj_decode_t *deco + unsigned short mask; + + n = arj_getbits(decode_data, CBIT); ++ if (decode_data->status != CL_SUCCESS) { ++ return decode_data->status; ++ } + if (n == 0) { + c = arj_getbits(decode_data, CBIT); ++ if (decode_data->status != CL_SUCCESS) { ++ return decode_data->status; ++ } + for (i = 0; i < NC; i++) { + decode_data->c_len[i] = 0; + } +@@ -386,6 +412,7 @@ static int read_c_len(arj_decode_t *deco + do { + if (c >= (2 * NC - 1)) { + cli_warnmsg("ERROR: bounds exceeded\n"); ++ decode_data->status = CL_EFORMAT; + return CL_EFORMAT; + } + if (decode_data->bit_buf & mask) { +@@ -398,9 +425,13 @@ static int read_c_len(arj_decode_t *deco + } + if (c >= 19) { + cli_dbgmsg("UNARJ: bounds exceeded\n"); ++ decode_data->status = CL_EARJ; + return CL_EARJ; + } + fill_buf(decode_data, (int)(decode_data->pt_len[c])); ++ if (decode_data->status != CL_SUCCESS) { ++ return decode_data->status; ++ } + if (c <= 2) { + if (c == 0) { + c = 1; +@@ -409,9 +440,13 @@ static int read_c_len(arj_decode_t *deco + } else { + c = arj_getbits(decode_data, CBIT) + 20; + } ++ if (decode_data->status != CL_SUCCESS) { ++ return decode_data->status; ++ } + while (--c >= 0) { + if (i >= NC) { + cli_warnmsg("ERROR: bounds exceeded\n"); ++ decode_data->status = CL_EFORMAT; + return CL_EFORMAT; + } + decode_data->c_len[i++] = 0; +@@ -419,6 +454,7 @@ static int read_c_len(arj_decode_t *deco + } else { + if (i >= NC) { + cli_warnmsg("ERROR: bounds exceeded\n"); ++ decode_data->status = CL_EFORMAT; + return CL_EFORMAT; + } + decode_data->c_len[i++] = (unsigned char) (c - 2); +@@ -427,7 +463,9 @@ static int read_c_len(arj_decode_t *deco + while (i < NC) { + decode_data->c_len[i++] = 0; + } +- make_table(decode_data, NC, decode_data->c_len, 12, decode_data->c_table, CTABLESIZE); ++ if (make_table(decode_data, NC, decode_data->c_len, 12, decode_data->c_table, CTABLESIZE) != CL_SUCCESS) { ++ return CL_EARJ; ++ } + } + return CL_SUCCESS; + } +@@ -450,6 +488,7 @@ static uint16_t decode_c(arj_decode_t *d + do { + if (j >= (2 * NC - 1)) { + cli_warnmsg("ERROR: bounds exceeded\n"); ++ decode_data->status = CL_EARJ; + return 0; + } + if (decode_data->bit_buf & mask) { +@@ -474,6 +513,7 @@ static uint16_t decode_p(arj_decode_t *d + do { + if (j >= (2 * NC - 1)) { + cli_warnmsg("ERROR: bounds exceeded\n"); ++ decode_data->status = CL_EARJ; + return 0; + } + if (decode_data->bit_buf & mask) { +@@ -508,8 +548,10 @@ static int decode(int fd, arj_metadata_t + decode_data.comp_size = metadata->comp_size; + ret = decode_start(&decode_data); + if (ret != CL_SUCCESS) { ++ free(decode_data.text); + return ret; + } ++ decode_data.status = CL_SUCCESS; + + while (count < metadata->orig_size) { + if ((chr = decode_c(&decode_data)) <= UCHAR_MAX) { +@@ -517,7 +559,10 @@ static int decode(int fd, arj_metadata_t + count++; + if (++out_ptr >= DDICSIZ) { + out_ptr = 0; +- write_text(metadata->ofd, decode_data.text, DDICSIZ); ++ if (write_text(metadata->ofd, decode_data.text, DDICSIZ) != CL_SUCCESS) { ++ free(decode_data.text); ++ return CL_EIO; ++ } + } + } else { + j = chr - (UCHAR_MAX + 1 - THRESHOLD); +@@ -539,7 +584,10 @@ static int decode(int fd, arj_metadata_t + decode_data.text[out_ptr] = decode_data.text[i]; + if (++out_ptr >= DDICSIZ) { + out_ptr = 0; +- write_text(metadata->ofd, decode_data.text, DDICSIZ); ++ if (write_text(metadata->ofd, decode_data.text, DDICSIZ) != CL_SUCCESS) { ++ free(decode_data.text); ++ return CL_EIO; ++ } + } + if (++i >= DDICSIZ) { + i = 0; +@@ -547,6 +595,10 @@ static int decode(int fd, arj_metadata_t + } + } + } ++ if (decode_data.status != CL_SUCCESS) { ++ free(decode_data.text); ++ return decode_data.status; ++ } + } + if (out_ptr != 0) { + write_text(metadata->ofd, decode_data.text, out_ptr); +@@ -623,21 +675,37 @@ static int decode_f(int fd, arj_metadata + return ret; + } + decode_data.getlen = decode_data.getbuf = 0; +- ++ decode_data.status = CL_SUCCESS; ++ + while (count < metadata->orig_size) { + chr = decode_len(&decode_data); ++ if (decode_data.status != CL_SUCCESS) { ++ free(decode_data.text); ++ return decode_data.status; ++ } + if (chr == 0) { + ARJ_GETBITS(dd, chr, CHAR_BIT); ++ if (decode_data.status != CL_SUCCESS) { ++ free(decode_data.text); ++ return decode_data.status; ++ } + decode_data.text[out_ptr] = (unsigned char) chr; + count++; + if (++out_ptr >= DDICSIZ) { + out_ptr = 0; +- write_text(metadata->ofd, decode_data.text, DDICSIZ); ++ if (write_text(metadata->ofd, decode_data.text, DDICSIZ) != CL_SUCCESS) { ++ free(decode_data.text); ++ return CL_EIO; ++ } + } + } else { + j = chr - 1 + THRESHOLD; + count += j; + pos = decode_ptr(&decode_data); ++ if (decode_data.status != CL_SUCCESS) { ++ free(decode_data.text); ++ return decode_data.status; ++ } + if ((i = out_ptr - pos - 1) < 0) { + i += DDICSIZ; + } +@@ -649,7 +717,10 @@ static int decode_f(int fd, arj_metadata + decode_data.text[out_ptr] = decode_data.text[i]; + if (++out_ptr >= DDICSIZ) { + out_ptr = 0; +- write_text(metadata->ofd, decode_data.text, DDICSIZ); ++ if (write_text(metadata->ofd, decode_data.text, DDICSIZ) != CL_SUCCESS) { ++ free(decode_data.text); ++ return CL_EIO; ++ } + } + if (++i >= DDICSIZ) { + i = 0; +@@ -1010,10 +1081,10 @@ int cli_unarj_extract_file(int fd, const + case 1: + case 2: + case 3: +- decode(fd, metadata); ++ ret = decode(fd, metadata); + break; + case 4: +- decode_f(fd, metadata); ++ ret = decode_f(fd, metadata); + break; + default: + ret = CL_EFORMAT; diff --git a/clamav-0.92.1-CVE-2008-1833.diff b/clamav-0.92.1-CVE-2008-1833.diff new file mode 100644 index 0000000..2c863fb --- /dev/null +++ b/clamav-0.92.1-CVE-2008-1833.diff @@ -0,0 +1,724 @@ +diff -pruN clamav-0.92.1.orig/libclamav/pe.c clamav-0.92.1/libclamav/pe.c +--- clamav-0.92.1.orig/libclamav/pe.c 2008-02-06 16:48:03.000000000 +0100 ++++ clamav-0.92.1/libclamav/pe.c 2008-04-24 19:37:34.000000000 +0200 +@@ -1,5 +1,5 @@ + /* +- * Copyright (C) 2004 - 2006 Tomasz Kojm ++ * Copyright (C) 2004 - 2007 Tomasz Kojm + * aCaB + * + * This program is free software; you can redistribute it and/or modify +@@ -23,11 +23,12 @@ + #endif + + #include ++#if HAVE_STRING_H + #include ++#endif + #include + #include + #include +-#include + #ifdef HAVE_UNISTD_H + #include + #endif +@@ -1861,106 +1862,65 @@ int cli_scanpe(int desc, cli_ctx *ctx) + CLI_UNPRESULTS("yC",(yc_decrypt(spinned, fsize, exe_sections, nsections-1, e_lfanew, ndesc)),0,(spinned,0)); + } + +- + /* WWPack */ + +- if((DCONF & PE_CONF_WWPACK) && nsections > 1 && +- exe_sections[nsections-1].raw>0x2b1 && ++ while ((DCONF & PE_CONF_WWPACK) && nsections > 1 && + vep == exe_sections[nsections - 1].rva && +- exe_sections[nsections - 1].rva + exe_sections[nsections - 1].rsz == max && + memcmp(epbuff, "\x53\x55\x8b\xe8\x33\xdb\xeb", 7) == 0 && + memcmp(epbuff+0x68, "\xe8\x00\x00\x00\x00\x58\x2d\x6d\x00\x00\x00\x50\x60\x33\xc9\x50\x58\x50\x50", 19) == 0) { +- uint32_t headsize=exe_sections[nsections - 1].raw; +- char *dest, *wwp; ++ uint32_t head = exe_sections[nsections - 1].raw; ++ uint8_t *packer; + +- for(i = 0 ; i < (unsigned int)nsections-1; i++) +- if (exe_sections[i].rawssize) break; + +- CLI_UNPSIZELIMITS("WWPack", dsize); ++ CLI_UNPSIZELIMITS("WWPack", ssize); + +- if((dest = (char *) cli_calloc(dsize, sizeof(char))) == NULL) { +- cli_dbgmsg("WWPack: Can't allocate %d bytes\n", dsize); ++ if(!(src=(char *)cli_calloc(ssize, sizeof(char)))) { + free(exe_sections); + return CL_EMEM; + } +- + lseek(desc, 0, SEEK_SET); +- if((size_t) cli_readn(desc, dest, headsize) != headsize) { +- cli_dbgmsg("WWPack: Can't read %d bytes from headers\n", headsize); +- free(dest); ++ if((size_t) cli_readn(desc, src, head) != head) { ++ cli_dbgmsg("WWPack: Can't read %d bytes from headers\n", head); ++ free(src); + free(exe_sections); + return CL_EIO; + } +- +- for(i = 0 ; i < (unsigned int)nsections-1; i++) { +- if(exe_sections[i].rsz) { +- if(!cli_seeksect(desc, &exe_sections[i]) || (unsigned int) cli_readn(desc, dest + headsize + exe_sections[i].rva - min, exe_sections[i].rsz) != exe_sections[i].rsz) { +- free(dest); +- free(exe_sections); +- return CL_EIO; +- } +- } +- } +- +- if((wwp = (char *) cli_calloc(exe_sections[nsections - 1].rsz, sizeof(char))) == NULL) { +- cli_dbgmsg("WWPack: Can't allocate %d bytes\n", exe_sections[nsections - 1].rsz); +- free(dest); ++ for(i = 0 ; i < (unsigned int)nsections-1; i++) { ++ if(!exe_sections[i].rsz) continue; ++ if(!cli_seeksect(desc, &exe_sections[i])) break; ++ if(!CLI_ISCONTAINED(src, ssize, src+exe_sections[i].rva, exe_sections[i].rsz)) break; ++ if(cli_readn(desc, src+exe_sections[i].rva, exe_sections[i].rsz)!=exe_sections[i].rsz) break; ++ } ++ if(i!=nsections-1) { ++ cli_dbgmsg("WWpack: Probably hacked/damaged file.\n"); ++ free(src); ++ break; ++ } ++ if((packer = (char *) cli_calloc(exe_sections[nsections - 1].rsz, sizeof(char))) == NULL) { ++ free(src); + free(exe_sections); + return CL_EMEM; + } +- +- if(!cli_seeksect(desc, &exe_sections[nsections - 1]) || (size_t) cli_readn(desc, wwp, exe_sections[nsections - 1].rsz) != exe_sections[nsections - 1].rsz) { ++ if(!cli_seeksect(desc, &exe_sections[nsections - 1]) || (size_t) cli_readn(desc, packer, exe_sections[nsections - 1].rsz) != exe_sections[nsections - 1].rsz) { + cli_dbgmsg("WWPack: Can't read %d bytes from wwpack sect\n", exe_sections[nsections - 1].rsz); +- free(dest); +- free(wwp); ++ free(src); ++ free(packer); + free(exe_sections); + return CL_EIO; + } + +- if (!wwunpack(dest, dsize, headsize, min, exe_sections[nsections-1].rva, e_lfanew, wwp, exe_sections[nsections - 1].rsz, nsections-1)) { +- +- free(wwp); +- +- CLI_UNPTEMP("WWPack",(dest,exe_sections,0)); +- +- if((unsigned int) write(ndesc, dest, dsize) != dsize) { +- cli_dbgmsg("WWPack: Can't write %d bytes\n", dsize); +- close(ndesc); +- free(tempfile); +- free(dest); +- free(exe_sections); +- return CL_EIO; +- } +- +- free(dest); +- if (cli_leavetemps_flag) +- cli_dbgmsg("WWPack: Unpacked and rebuilt executable saved in %s\n", tempfile); +- else +- cli_dbgmsg("WWPack: Unpacked and rebuilt executable\n"); +- +- fsync(ndesc); +- lseek(ndesc, 0, SEEK_SET); +- +- if(cli_magic_scandesc(ndesc, ctx) == CL_VIRUS) { +- free(exe_sections); +- close(ndesc); +- if(!cli_leavetemps_flag) +- unlink(tempfile); +- free(tempfile); +- return CL_VIRUS; +- } +- +- close(ndesc); +- if(!cli_leavetemps_flag) +- unlink(tempfile); +- free(tempfile); +- } else { +- free(wwp); +- free(dest); +- cli_dbgmsg("WWPpack: Decompression failed\n"); +- } ++ CLI_UNPTEMP("WWPack",(src,packer,exe_sections,0)); ++ CLI_UNPRESULTS("WWPack",(wwunpack(src, ssize, packer, exe_sections, nsections-1, e_lfanew, ndesc)),0,(src,packer,0)); ++ break; + } + + +diff -pruN clamav-0.92.1.orig/libclamav/wwunpack.c clamav-0.92.1/libclamav/wwunpack.c +--- clamav-0.92.1.orig/libclamav/wwunpack.c 2007-12-06 13:59:04.000000000 +0100 ++++ clamav-0.92.1/libclamav/wwunpack.c 2008-04-24 19:37:34.000000000 +0200 +@@ -1,6 +1,7 @@ + /* +- * Copyright (C) 2006 Sensory Networks, Inc. +- * Written by aCaB ++ * Copyright (C) 2007 Sourcefire Inc. ++ * Author: aCaB ++ * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. +@@ -16,346 +17,218 @@ + * MA 02110-1301, USA. + */ + +-/* +-** wwunpack.c +-** +-** 09/07/2k6 - Campioni del mondo!!! +-** 14/07/2k6 - RCE'ed + standalone sect unpacker +-** 15/07/2k6 - Merge started +-** 17/07/2k6 - Rebuild +-** 18/07/2k6 - Secured (well, hopefully...) +-** +-*/ +- +-/* +-** Unpacks+rebuilds WWPack32 1.20 +-** +-** Just boooooring stuff, blah. +-** +-*/ +- +- +-/* +-** TODO: +-** +-** review +-** check eax vs al +-** (check for dll's) +-** (have a look at older versions) +-** +-*/ +- +- + #if HAVE_CONFIG_H + #include "clamav-config.h" + #endif + +-#include +-#include +- + #include "cltypes.h" + #include "others.h" +-#include "wwunpack.h" +- +-#define VAALIGN(s) (((s)/0x1000+((s)%0x1000!=0))*0x1000) +-#define FIXVS(v, r) (VAALIGN((r>v)?r:v)) ++#include "execs.h" + ++#if HAVE_STRING_H ++#include ++#endif + +-static int getbitmap(uint32_t *bitmap, char **src, uint8_t *bits, char *buf, unsigned int size) { +- if (! CLI_ISCONTAINED(buf, size, *src, 4)) return 1; +- *bitmap=cli_readint32(*src); +- *src+=4; +- *bits=32; +- return 0; ++#define RESEED \ ++if (CLI_ISCONTAINED(compd, szd, ccur, 4)) { \ ++ bt = cli_readint32(ccur); \ ++ ccur+=4; \ ++} else { \ ++ cli_dbgmsg("WWPack: Out of bits\n"); \ ++ error=1; \ ++} \ ++bc = 32; ++ ++ ++#define BIT \ ++bits = bt>>31; \ ++bt<<=1; \ ++if(!--bc) { \ ++ RESEED; \ + } + +-static int getbits(uint8_t X, uint32_t *eax, uint32_t *bitmap, uint8_t *bits, char **src, char *buf, unsigned int size) { +- *eax=*bitmap>>(32-X); +- if (*bits>X) { +- *bitmap<<=X; +- *bits-=X; +- } else if (*bits>=X; +- if (getbitmap(bitmap, src, bits, buf, size)) return 1; +- *eax<<=X; +- *eax|=*bitmap>>(32-X); +- *bitmap<<=X; +- *bits-=X; +- } else { +- if (getbitmap(bitmap, src, bits, buf, size)) return 1; +- } +- return 0; ++#define BITS(N) \ ++bits = bt>>(32-(N)); \ ++if (bc>=(N)) { \ ++ bc -= (N); \ ++ bt<<=(N); \ ++ if (!bc) { \ ++ RESEED; \ ++ } \ ++} else { \ ++ if (CLI_ISCONTAINED(compd, szd, ccur, 4)) { \ ++ bt = cli_readint32(ccur); \ ++ ccur+=4; \ ++ bc += 32 - (N); \ ++ bits |= bt>>(bc); \ ++ bt <<= (32-bc); \ ++ } else { \ ++ cli_dbgmsg("WWPack: Out of bits\n"); \ ++ error=1; \ ++ } \ + } + +-static int wunpsect(char *packed, char *unpacked, unsigned int psize, unsigned int usize) { +- char *src=packed, *dst=unpacked; +- uint32_t bitmap, eax; +- uint8_t bits; +- unsigned int lostbit, getmorestuff; +- uint16_t backbytes; +- uint16_t backsize; +- uint8_t oal; +- +- if (getbitmap(&bitmap, &src, &bits, packed, psize)) return 1; +- eax=bitmap; ++int wwunpack(uint8_t *exe, uint32_t exesz, uint8_t *wwsect, struct cli_exe_section *sects, uint16_t scount, uint32_t pe, int desc) { ++ uint8_t *structs = wwsect + 0x2a1, *compd, *ccur, *unpd, *ucur, bc; ++ uint32_t src, srcend, szd, bt, bits; ++ int error=0, i; + ++ cli_dbgmsg("in wwunpack\n"); + while (1) { +- lostbit=bitmap>>31; +- bitmap<<=1; +- bits--; +- if (!lostbit && bits) { +- if (!(CLI_ISCONTAINED(packed, psize, src, 1) && CLI_ISCONTAINED(unpacked, usize, dst, 1))) return 1; +- *dst++=*src++; +- continue; +- } +- +- if (!bits) { +- if (getbitmap(&bitmap, &src, &bits, packed, psize)) return 1; +- eax=bitmap; +- if (!lostbit) { +- if (!(CLI_ISCONTAINED(packed, psize, src, 1) && CLI_ISCONTAINED(unpacked, usize, dst, 1))) return 1; +- *dst++=*src++; ++ if (!CLI_ISCONTAINED(wwsect, sects[scount].rsz, structs, 17)) { ++ cli_dbgmsg("WWPack: Array of structs out of section\n"); ++ break; ++ } ++ src = sects[scount].rva - cli_readint32(structs); /* src delta / dst delta - not used / dwords / end of src */ ++ structs+=8; ++ szd = cli_readint32(structs) * 4; ++ structs+=4; ++ srcend = cli_readint32(structs); ++ structs+=4; ++ ++ unpd = ucur = exe+src+srcend+4-szd; ++ if (!szd || !CLI_ISCONTAINED(exe, exesz, unpd, szd)) { ++ cli_dbgmsg("WWPack: Compressed data out of file\n"); ++ break; ++ } ++ cli_dbgmsg("WWP: src: %x, szd: %x, srcend: %x - %x\n", src, szd, srcend, srcend+4-szd); ++ if (!(compd = cli_malloc(szd))) break; ++ memcpy(compd, unpd, szd); ++ memset(unpd, -1, szd); /*FIXME*/ ++ ccur=compd; ++ ++ RESEED; ++ while(!error) { ++ uint32_t backbytes, backsize; ++ uint8_t saved; ++ ++ BIT; ++ if (!bits) { /* BYTE copy */ ++ if(ccur-compd>=szd || !CLI_ISCONTAINED(exe, exesz, ucur, 1)) ++ error=1; ++ else ++ *ucur++=*ccur++; + continue; + } +- } +- +- if (getbits(2, &eax, &bitmap, &bits, &src, packed, psize)) return 1; +- +- if ((eax&0xff)>=3) { +- /* 50ff - two_bytes */ +- uint8_t fetchbits; +- +- if (getbits(2, &eax, &bitmap, &bits, &src, packed, psize)) return 1; +- fetchbits=(eax&0xff)+5; +- eax--; +- if ((int16_t)(eax&0xffff)<=0) { +- /* 5113 */ +- backbytes=1<=2) { ++ shifted++; ++ subbed += 0x80; ++ } ++ backbytes = (1<>31; +- bitmap<<=1; +- bits--; +- if (!bits) { +- if (getbitmap(&bitmap, &src, &bits, packed, psize)) return 1; ++ BITS(3); ++ if (bits<6) { ++ backbytes = bits; ++ switch(bits) { ++ case 4: /* 10,11 */ ++ backbytes++; ++ case 3: /* 8,9 */ ++ BIT; ++ backbytes+=bits; ++ case 0: case 1: case 2: /* 5,6,7 */ ++ backbytes+=5; ++ break; ++ case 5: /* 12 */ ++ backbytes=12; ++ break; + } ++ BITS(backbytes); ++ bits+=(1<3 */ +- /* 5160 - more_bb_morethan3 */ +- if ((eax&0xff)==4) { +- /* next_bit_or_reseed */ +- lostbit=bitmap>>31; +- bitmap<<=1; +- bits--; +- if (!bits) { +- if (getbitmap(&bitmap, &src, &bits, packed, psize)) return 1; +- } +- eax=eax+lostbit+6; +- /* jmp more_bb_commondock */ +- } else { /* !=4 */ +- eax+=7; +- if ((eax&0xff)>=0x0d) { +- getmorestuff=0; /* jmp more_bb_PASTcommondock */ +- if ((eax&0xff)==0x0d) { +- /* 5179 */ +- if (getbits(0x0e, &eax, &bitmap, &bits, &src, packed, psize)) return 1; +- eax+=0x1fe1; ++ ++ backbytes = bits; ++ ++ /* popf / jb */ ++ if (!saved) { ++ BIT; ++ if(!bits) { ++ BIT; ++ bits+=5; ++ } else { ++ BITS(3); ++ if(bits) { ++ bits+=6; + } else { +- /* 516c */ +- if (getbits(0x0f, &eax, &bitmap, &bits, &src, packed, psize)) return 1; +- eax+=0x5fe1; ++ BITS(4); ++ if(bits) { ++ bits+=13; ++ } else { ++ uint8_t cnt = 4; ++ uint16_t shifted = 0x0d; ++ ++ do { ++ if(cnt==7) { cnt = 0x0e; shifted = 0; break; } ++ shifted=((shifted+2)<<1)-1; ++ BIT; ++ cnt++; ++ } while(!bits); ++ BITS(cnt); ++ bits+=shifted; ++ } + } +- /* jmp more_bb_PASTcommondock */ +- } /* al >= 0d */ +- } /* al != 4 */ +- } /* >3 */ +- +- if (getmorestuff) { +- /* 5192 - more_bb_commondock */ +- uint16_t bk=(1<<(eax&0xff))-0x1f; +- if (getbits((eax&0xff), &eax, &bitmap, &bits, &src, packed, psize)) return 1; +- eax+=bk; +- } +- +- /* 51a7 - more_bb_pastcommondock */ +- eax&=0xffff; +- backbytes=eax; +- backsize=3+(oal!=1); +- +- if (oal<1) { /* overrides backsize */ +- /* 51bb - more_bb_again */ +- +- /* next_bit_or_reseed */ +- lostbit=bitmap>>31; +- bitmap<<=1; +- bits--; +- if (!bits) { +- if (getbitmap(&bitmap, &src, &bits, packed, psize)) return 1; +- } +- if (!lostbit) { +- /* 51c2 */ +- /* next_bit_or_reseed */ +- lostbit=bitmap>>31; +- bitmap<<=1; +- bits--; +- if (!bits) { +- if (getbitmap(&bitmap, &src, &bits, packed, psize)) return 1; + } +- eax=5+lostbit; +- /* jmp setsize_and_backcopy */ ++ backsize = bits; + } else { +- /* 51ce - more_bb_again_and_again */ +- if (getbits(3, &eax, &bitmap, &bits, &src, packed, psize)) return 1; +- if (eax&0xff) { +- /* 51e6 */ +- eax+=6; +- /* jmp setsize_and_backcopy */ +- } else { +- if (getbits(4, &eax, &bitmap, &bits, &src, packed, psize)) return 1; +- if (eax&0xff) { +- /* 51e4 */ +- eax+=7+6; +- /* jmp setsize_and_backcopy */ +- } else { +- /* 51ea - OMGWTF */ +- uint8_t c=4; +- uint16_t d=0x0d; +- +- while ( 1 ) { +- if (c!=7){ +- d+=2; +- d<<=1; +- d--; +- +- /* next_bit_or_reseed */ +- lostbit=bitmap>>31; +- bitmap<<=1; +- bits--; +- if (!bits) { +- if (getbitmap(&bitmap, &src, &bits, packed, psize)) return 1; +- } +- c++; +- if (!lostbit) continue; +- if (getbits(c, &eax, &bitmap, &bits, &src, packed, psize)) return 1; +- d+=eax&0xff; +- eax&=0xffffff00; +- eax|=d&0xff; +- } else { +- if (getbits(14, &eax, &bitmap, &bits, &src, packed, psize)) return 1; +- } +- break; +- } /* while */ +- } /* OMGWTF */ +- } /* eax&0xff */ +- } /* lostbit */ +- /* 521b - setsize_and_backcopy */ +- backsize=eax&0xffff; +- } +- +- /* 521e - backcopy */ +- if (!(CLI_ISCONTAINED(unpacked, usize, dst-backbytes, backsize) && CLI_ISCONTAINED(unpacked, usize, dst, backsize))) return 1; +- while(backsize--){ +- *dst=*(dst-backbytes); +- dst++; +- } +- +- } /* while true */ +- +- return 0; +-} +- +-int wwunpack(char *exe, uint32_t exesz, uint32_t headsize, uint32_t min, uint32_t wwprva, uint32_t e_lfanew, char *wwp, uint32_t wwpsz, uint16_t sects) { +- char *stuff=wwp+0x2a1, *packed, *unpacked; +- uint32_t rva, csize; +- +- cli_dbgmsg("in wwunpack\n"); +- ++ backsize = saved+2; ++ } + +- while(1) { +- if (!CLI_ISCONTAINED(wwp, wwpsz, stuff, 17)) { +- cli_dbgmsg("WWPack: next chunk out ouf file, giving up.\n"); +- return 1; +- } +- if ((csize=cli_readint32(stuff+8)*4)!=(uint32_t)cli_readint32(stuff+12)+4) { +- cli_dbgmsg("WWPack: inconsistent/hacked data, go figure!\n"); +- return 1; +- } +- rva = wwprva-cli_readint32(stuff); +- if((packed = (char *) cli_calloc(csize, sizeof(char))) == NULL) { +- cli_dbgmsg("WWPack: Can't allocate %d bytes\n", csize); +- return 1; +- } +- unpacked=exe+headsize+rva-min; +- if (!CLI_ISCONTAINED(exe, exesz, unpacked, csize)) { +- free(packed); +- cli_dbgmsg("WWPack: packed data out of bounds, giving up.\n"); +- return 1; ++ if(!CLI_ISCONTAINED(exe, exesz, ucur, backsize) || !CLI_ISCONTAINED(exe, exesz, ucur-backbytes, backsize)) error=1; ++ while(backsize--) { ++ *ucur=*(ucur-backbytes); ++ ucur++; ++ } + } +- memcpy(packed, unpacked, csize); +- if (wunpsect(packed, unpacked, csize, exesz-(unpacked-exe))) { +- free(packed); +- cli_dbgmsg("WWPack: unpacking failed.\n"); +- return 1; ++ free(compd); ++ if(error) { ++ cli_dbgmsg("WWPack: decompression error\n"); ++ break; + } +- free(packed); +- if (!stuff[16]) break; +- stuff+=17; ++ if (error || !*structs++) break; + } + +- stuff=exe+e_lfanew; +- stuff[6]=sects&0xff; +- stuff[7]=sects>>8; +- +- csize=cli_readint32(wwp+0x295)+wwprva+0x299; +- cli_dbgmsg("WWPack: found OEP @%x\n", csize); +- cli_writeint32(stuff+0x28, csize); +- +- csize=cli_readint32(stuff+0x50)-VAALIGN(wwpsz); +- cli_writeint32(stuff+0x50, csize); +- +- +- stuff+=0x18+(cli_readint32(stuff+0x14)&0xffff); +- while (sects--) { +- uint32_t v=cli_readint32(stuff+8); +- uint32_t r=cli_readint32(stuff+16); +- csize=FIXVS(v, r); +- cli_writeint32(stuff+8, csize); +- cli_writeint32(stuff+16, csize); +- cli_writeint32(stuff+20, cli_readint32(stuff+12)-min+headsize); +- stuff+=0x28; ++ if(!error) { ++ exe[pe+6]=(uint8_t)scount; ++ exe[pe+7]=(uint8_t)(scount>>8); ++ cli_writeint32(&exe[pe+0x28], cli_readint32(wwsect+0x295)+sects[scount].rva+0x299); ++ cli_writeint32(&exe[pe+0x50], cli_readint32(&exe[pe+0x50])-sects[scount].vsz); ++ ++ structs = &exe[0xffff&cli_readint32(&exe[pe+0x14])+pe+0x18]; ++ for(i=0 ; i/dev/null || : %changelog +* Thu Apr 24 2008 Tomas Hoger - 0.92.1-2 +- Security update - backport security fixes from 0.93: + CVE-2008-1100 (#442360): Upack Processing Buffer Overflow Vulnerability + CVE-2008-1387 (#442525): Endless loop / hang with crafted arj + CVE-2008-0314 (#442740): PeSpin Heap Overflow Vulnerability + CVE-2008-1833 (#442741): PE WWPack Heap Overflow Vulnerability + * Mon Feb 11 2008 Enrico Scholz - 0.92.1-1 - updated to 0.92.1