Overflow.pl Security Advisory #6
Clam AntiVirus Win32-UPX Heap Overflow
Vendor: Clam AntiVirus
Affected version: Prior to 0.88.4
Vendor status: Fixed version released (0.88.4)
Author: Damian Put <pucik@overflow.pl>
URL: http://www.overflow.pl/adv/clamav_upx_heap.txt
Date: 09.08.2006
1. Background
"Clam AntiVirus is a GPL anti-virus toolkit for UNIX. The main purpose of th=
is
software is the integration with mail servers (attachment scanning). =20
The package
provides a flexible and scalable multi-threaded daemon, a command line =20
scanner,
and a tool for automatic updating via Internet. The programs are based on a
shared library distributed with the Clam AntiVirus package, which you can us=
e
with your own software. Most importantly, the virus database is kept =20
up to date"
http://www.clamav.net
2. Description
Remote exploitation of a heap overflow vulnerability could allow execution o=
f
arbitrary code or cause denial of service.
Vulnerability exists in pefromupx() function, that is used to buil =20
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=3D1;
uint32_t realstuffsz;
uint32_t foffset=3D0xd0+0xf8;
imports =3D dst + cli_readint32(src + ep - upx1 + magic);
realstuffsz =3D imports-dst;
if (realstuffsz >=3D *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+=3D0x28*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 =3D 0; upd <sectcnt ; upd++) {
uint32_t vsize=3Dcli_readint32(sections+8)-1;
uint32_t rsize=3Dcli_readint32(sections+16);
uint32_t urva=3Dcli_readint32(sections+12);
.....
cli_writeint32(sections+8, vsize);
cli_writeint32(sections+20, foffset);
foffset+=3Drsize;
sections+=3D0x28;
}
.....
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 =3D 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.
3. PoC
The example of crafted upx file: http://overflow.pl/poc/clamav_upx_heap.exe
[pucik@overflow UPX]$ clamscan clamav_upx_heap.exe
*** glibc detected *** double free or corruption (out): 0x08bcbbc0 ***
Przerwane (core dumped)
You can control value of foffset changing "SizeOfRawData" of section 1.

Likes:
![[Overflow.pl] Clam AntiVirus Win32-UPX Heap Overflow](https://www.webhostingtalk.nl/images/WHT_rd/misc/dT.png)
Quote