After two mails to VLC security team and lack of answer I decided to public this research before any patch. Presented here vulns are not too evil (Local DoS) so making them public will not cause any damage for VLC users.
==[ Details ]==
<= VLC media player 2.0.1 contains vulnerabilities in few Demuxers:
1. voc.c – DoS via Divison by 0 2. smf.c – DoS via Infinite loop 3. au.c – DoS via Division by 0
1. Details voc.c – DoS via Divison by 0:
First scenario:
ReadBlockHeader function to handle block data type 0x9 contains the following code:
Line 304:
case 9: /* newer data block with channel number and bits resolution */
if( i_block_size < 12 )
goto corrupt;
i_block_size -= 12;
if( ( stream_Read( p_demux->s, buf, 8 ) < 8 )
|| ( stream_Read( p_demux->s, NULL, 4 ) < 4 ) )
goto corrupt;
new_fmt.audio.i_rate = GetDWLE( buf );
new_fmt.audio.i_bitspersample = buf[4];
new_fmt.audio.i_channels = buf[5];
If block header at offset 0x5 will be set to 0 then new_fmt.audio.i_channels = 0, what causes:
Line 360:
new_fmt.audio.i_bytes_per_frame = new_fmt.audio.i_channels
* (new_fmt.audio.i_bitspersample / 8);
that new_fmt.audio.i_bytes_per_frame will be set to 0 and after exit from ReadBlockHeader the following code:
Line 428:
while( ( i_offset >= p_sys->i_block_end )
&& ( p_sys->i_silence_countdown == 0 ) )
if( ReadBlockHeader( p_demux ) != VLC_SUCCESS )
return 0;
if( p_sys->i_silence_countdown == 0 )
{
i = ( p_sys->i_block_end - i_offset )
/ p_sys->fmt.audio.i_bytes_per_frame; // <- div by 0
in Demux function leads to division by zero and as an end result VLC crash.
Second scenario:
Because at the beginning in ReadBlockHeader function, structure new_fmt (es_format_t) is initialized by zero:
Line 175: es_format_Init( &new_fmt, AUDIO_ES, 0 );
therefore if type of first block will be set to different one where “normal” new_fmt structure initialization occurs e.g 0x6 then at the end of
ReadBlockHeader ,
Line 399:
if( p_sys->p_es == NULL )
{
memcpy( &p_sys->fmt, &new_fmt, sizeof( p_sys->fmt ) );
new_fmt structure initialized by 0 will be copied to p_sys->fmt which leads to division by zero after return to Demux function like in above scenario.
2. smf.c – DoS via Infinite loop
In Open function we see the following code:
Line 210:
for (;;)
{
stream_Read (stream, head, 8);
if (memcmp (head, "MTrk", 4) == 0)
break;
msg_Dbg (p_this, "skipping unknown SMF chunk");
stream_Read (stream, NULL, GetDWBE (head + 4));
}
it aim is to find „MTrk” ID chunk. But like we can also notice there is lack of checks for stream_Read function indicating that end of stream occurred.
File with malformed or without “MTrk” ID chunk will cause infinite loop and as a result VLC DoS.
3 au.c – DoS via Division by 0
Line 144:
/* init fmt */
es_format_Init( &p_sys->fmt, AUDIO_ES, 0 );
p_sys->fmt.audio.i_rate = GetDWBE( &hdr[12] );
p_sys->fmt.audio.i_channels = GetDWBE( &hdr[16] );
setting 0(DWORD) at file offset len(“.snd”)+12 => 16 we set 0 value for i_rate field. Lack of any inspection of this field and its value leads to division by zero at
Line 278:
p_sys->i_frame_length = (mtime_t)1000000 *
(mtime_t)i_samples /
(mtime_t)p_sys->fmt.audio.i_rate;
and as an end result to VLC crash.
==[ Proof of Concept ]==
1. voc.c - DoS via Divison by 0: File sample: http://samples.libav.org/voc/pcm_s16_2/nem.voc First scenario: Change offset 0x23 value from 0x02 to 0x0 Second scenario: Change offset 0x1A value from 0x060C842E to 0x06020000 2. smf.c - DoS via Infinite loop File sample: http://upload.wikimedia.org/wikipedia/commons/6/61/Drum_sample.mid Malform “MTrk” chunk ID anyhow e.g “ATrk”. 3. au.c - DoS via Division by 0 File sample: http://samples.libav.org/au/garelka.au Change offset 0x10 value from 0x00001F40 to 0x00000000