Ubuntu 10.04 LTS
wget https://github.com/mudongliang/source-packages/raw/master/CVE-2006-4182/clamav-0.88.2.tar.gz
tar -xvf clamav-0.88.2.tar.gz
cd clamav-0.88.2
./configure
make
sudo make install
/usr/local/bin/clamscan 28348.exe
Clam Anti-Virus ClamAV 0.88.x - UPX Compressed PE File Heap Buffer Overflow
Clam Anti-Virus ClamAV UPX Compressed PE File Heap Buffer Overflow Vulnerability
Remote exploitation of a heap overflow vulnerability could allow execution of arbitrary code or cause denial of service.
Vulnerability exists in pefromupx() function, that is used to buil Win32 PE file from UPX packed file.
The vulnerable code is:
libclamav/upx.c:
------------
int pefromupx (char *src, char *dst, uint32_t *dsize, uint32_t ep, uint32_t
upx0, uint32_t upx1, uint32_t magic)
{
char *imports, *sections, *pehdr, *newbuf;
int sectcnt, upd=1;
uint32_t realstuffsz;
uint32_t foffset=0xd0+0xf8;
imports = dst + cli_readint32(src + ep - upx1 + magic);
realstuffsz = imports-dst;
if (realstuffsz >= *dsize ) {
cli_dbgmsg("UPX: wrong realstuff size - giving up rebuild\n");
return 0;
}
....
OK first we check that realstuffsz is not larger than dsize.
....
foffset+=0x28*sectcnt;
if (!CLI_ISCONTAINED(dst, *dsize, sections, 0x28*sectcnt)) {
cli_dbgmsg("UPX: Not enough space for all sects - giving up rebuild\n");
return 0;
}
....
Now we check that we have enough space for section headers.
....
for (upd = 0; upd <sectcnt ; upd++) {
uint32_t vsize=cli_readint32(sections+8)-1;
uint32_t rsize=cli_readint32(sections+16);
uint32_t urva=cli_readint32(sections+12);
.....
cli_writeint32(sections+8, vsize);
cli_writeint32(sections+20, foffset);
foffset+=rsize;
sections+=0x28;
}
....
Now, we add to foffset rsize value of all sections and we DON`T check that we have enough space in *dst.
....
/* CBA restoring the imports they'll look different from the originals
anyway... */
/* ...and yeap i miss the icon too :P */
memcpy(dst, newbuf, foffset);
*dsize = foffset;
free(newbuf);
cli_dbgmsg("UPX: PE structure rebuilt from compressed file\n");
return 1;
}
....
And there is our heap overflow. We copy from newbuf to dst pointer foffset bytes, but we don`t check that foffset > *dsize.