CHMLIB is "a library for dealing with Microsoft ITSS/CHM format files. Right now, it is a very simple library, but sufficient for dealing with all of the .chm files I've come across. Due to the fairly well-designed indexing built into this particular file format, even a small library is able to gain reasonably good performance indexing into ITSS archives".
chmlib has been found to be vulnerable to a buffer overflow, allowing attacker to execute arbitrary code.
Vulnerable Systems:
* chmlib version 0.36 and prior.
Immune Systems:
* CHM lib version 0.37 (download here)
* CHM lib version 0.37.2 (download here)
0. chm_lib.c: _chm_decompress_block(struct chmFile *h, UInt64 block,UChar **ubuffer)
1. see cmpLen and cbuffer declaration
2. call to _chm_get_cmpblock_bounds(h, block, &cmpStart, &cmpLen) to set cmpLen
3. cmpLen is used to offset write operations in cbuffer (_chm_fetch_bytes(h, cbuffer, cmpStart, cmpLen))
4. if cmpLen > h->reset_table.block_len + 6144 the buffer overflows
5. as we can supply the fd data, exploitation is possible and an attacker can execute arbitrary code.
Vulnerable code:
/* decompress the block. must have lzx_mutex. */
static Int64 _chm_decompress_block(struct chmFile *h,
UInt64 block,
UChar **ubuffer)
{
...
UChar cbuffer[h->reset_table.block_len + 6144]; /* compressed
buffer */
Int64 cmpLen; /* compressed
len */
/* get the bounds of a compressed block. return 0 on failure */
static int _chm_get_cmpblock_bounds(struct chmFile *h,
UInt64 block,
UInt64 *start,
Int64 *len)
{
UChar buffer[8], *dummy;
unsigned int remain;
/* for all but the last block, use the reset table */
if (block < h->reset_table.block_count-1)
{
Disclosure Timeline:
24.10.05 - Issue found by Sven Tantau
25.10.05 - Contacted chmlib maintainer
25.10.05 - Quick reaction with confirmation
26.10.05 - New release of chmlib and public disclosure
Vendor Status:
chmlib maintainer Jed Wing released a new version 0.37