Blob Blame History Raw
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 <tkojm@clamav.net>
+ *  Copyright (C) 2004 - 2007 Tomasz Kojm <tkojm@clamav.net>
  *			      aCaB <acab@clamav.net>
  *
  *  This program is free software; you can redistribute it and/or modify
@@ -23,11 +23,12 @@
 #endif
 
 #include <stdio.h>
+#if HAVE_STRING_H
 #include <string.h>
+#endif
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <fcntl.h>
-#include <sys/stat.h>
 #ifdef HAVE_UNISTD_H
 #include <unistd.h>
 #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].raw<headsize) headsize=exe_sections[i].raw;
-      
-	dsize = max-min+headsize-exe_sections[nsections - 1].rsz;
+	ssize = 0;
+	for(i=0 ; ; i++) {
+	    if(exe_sections[i].raw<head) 
+	        head=exe_sections[i].raw;
+	    if(i==nsections-1) break;
+	    if(ssize<exe_sections[i].rva+exe_sections[i].vsz)
+		ssize=exe_sections[i].rva+exe_sections[i].vsz;
+	}
+	if(!head || !ssize || head>ssize) 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 <acab@clamav.net>
+ *  Copyright (C) 2007 Sourcefire Inc.
+ *  Author: aCaB <acab@clamav.net>
+ *
  *  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 <stdlib.h>
-#include <string.h>
-
 #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 <string.h>
+#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) {
-    X-=*bits;
-    *eax>>=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<<fetchbits;
-	backbytes=(backbytes&0xff00)|((backbytes-31)&0xff);
-      } else {
-	/* 511b */
-	fetchbits++;
-	backbytes=1<<fetchbits;
-	backbytes-=0x9f;
+
+      BITS(2);
+      if(bits==3) { /* WORD backcopy */
+	uint8_t shifted, subbed = 31;
+	BITS(2);
+	shifted = bits + 5;
+	if(bits>=2) {
+	  shifted++;
+	  subbed += 0x80;
+	}
+	backbytes = (1<<shifted)-subbed; /* 1h, 21h, 61h, 161h */
+	BITS(shifted); /* 5, 6, 8, 9 */
+	if(error || bits == 0x1ff) break;
+	backbytes+=bits;
+	if(!CLI_ISCONTAINED(exe, exesz, ucur, 2) || !CLI_ISCONTAINED(exe, exesz, ucur-backbytes, 2)) {
+	  error=1;
+	} else {
+	  ucur[0]=*(ucur-backbytes);
+	  ucur[1]=*(ucur-backbytes+1);
+	  ucur+=2;
+	}
+	continue;
       }
-      /* 5125 */
-      if (getbits(fetchbits, &eax, &bitmap, &bits, &src, packed, psize)) return 1;
-      if ((eax&0xffff)==0x1ff) break;
-      eax&=0xffff;
-      backbytes+=eax;
-      if (!(CLI_ISCONTAINED(unpacked, usize, dst-backbytes, 2) && CLI_ISCONTAINED(unpacked, usize, dst, 2))) return 1;
-      *dst=*(dst-backbytes);
-      dst++;
-      *dst=*(dst-backbytes);
-      dst++;
-      continue;
-    }
 
-    /* 5143 - more_backbytes */      
-    oal=eax&0xff;
-    getmorestuff=1;
+      /* BLOCK backcopy */
+      saved = bits; /* cmp al, 1 / pushf */
 
-    
-    if (getbits(3, &eax, &bitmap, &bits, &src, packed, psize)) return 1;
-    if ((eax&0xff)<=3) {
-      lostbit=0;
-      if ((eax&0xff)==3) {
-	/* next_bit_or_reseed */
-	lostbit=bitmap>>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<<backbytes)-31;
+      } else if(bits==6) {
+	BITS(0x0e);
+	bits+=0x1fe1;
+      } else {
+	BITS(0x0f);
+	bits+=0x5fe1;
       }
-      eax=eax+lostbit+5;
-      /* jmp more_bb_commondock */
-    } else { /* >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<scount ; i++) {
+      cli_writeint32(structs+8, sects[i].vsz);
+      cli_writeint32(structs+12, sects[i].rva);
+      cli_writeint32(structs+16, sects[i].vsz);
+      cli_writeint32(structs+20, sects[i].rva);
+      structs+=0x28;
+    }
+    memset(structs, 0, 0x28);
+    error = cli_writen(desc, exe, exesz)!=exesz;
   }
-  memset(stuff, 0, 0x28);
-
-  return 0;
+  return error;
 }
diff -pruN clamav-0.92.1.orig/libclamav/wwunpack.h clamav-0.92.1/libclamav/wwunpack.h
--- clamav-0.92.1.orig/libclamav/wwunpack.h	2007-12-06 13:59:04.000000000 +0100
+++ clamav-0.92.1/libclamav/wwunpack.h	2008-04-24 19:37:34.000000000 +0200
@@ -20,8 +20,8 @@
 #define __WWP32_H
 
 #include "cltypes.h"
-#include "rebuildpe.h"
+#include "execs.h"
 
-int wwunpack(char *, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t, char *, uint32_t, uint16_t);
+int wwunpack(uint8_t *, uint32_t, uint8_t *, struct cli_exe_section *, uint16_t, uint32_t, int);
 
 #endif