Talos Vulnerability Report

TALOS-2016-0127

GMER Path Length Code Execution Vulnerability

November 3, 2016
CVE Number

CVE-2016-4289

Summary

A stack based buffer overflow vulnerability exists in the method receiving data from SysTreeView32 control of the GMER application. A specially created long path can lead to a buffer overflow on the stack resulting in code execution. An attacker needs to create path longer than 99 characters to trigger this vulnerability.

Tested Versions

GMER 2.1.19357

Product URLs

http://www.gmer.net/

CVSSv3 Score

CVSS:3.0/AV:L/AC:L/PR:N/UI:R/S:U/C:N/I:N/A:H/E:P/RC:C
CVSSv3 Calculator: https://www.first.org/cvss/calculator/3.0

Details

Gmer can be used to detect and delete hidden files and folders. We can use this functionality by choosing the “Files” tab in the GMER application. Folders are presented there in the SysTreeView32 control. A directory name longer than 99 characters causes a stack based buffer overflow in the function resposible for receiving data from this control item. Let’s take a look at a vulnerable function and its surroundings.

sub_463880 proc near

var_DC= dword ptr -0DCh
this= dword ptr -0D8h
var_D4= dword ptr -0D4h
directoryName= word ptr -0D0h
var_8= dword ptr -8
hItem= dword ptr -4
arg_0= dword ptr  8
arg_4= dword ptr  0Ch

push    ebp
mov     ebp, esp
sub     esp, 220

As we can see, the previous function prepares 220 bytes for local variables.

.text:0046393D                 push    200             ; cchTextMax
.text:00463942                 lea     edx, [ebp+pszText] ;directoryName
.text:00463948                 push    edx
.text:00463949                 mov     eax, [ebp+hItem]
.text:0046394C                 push    eax
.text:0046394D                 mov     ecx, [ebp+this]
.text:00463953                 add     ecx, 272
.text:00463959                 call    TreeView_GetItem_wrapper ; <------ OVERFLOW

Here we reach the call to the wrapper function of the TreeView_GetItem macro. We are looking at a buffer of size 200 expressed in characters (third parameter), everything looks correct and the buffer should be able to accommodate 200 ANSI chars. Stepping inside this call we see the code responsible for preparing the TVITEM structure:

.text:0040AAA0 TreeView_GetItem_wrapper proc near      ; CODE XREF: sub_44CCC0+5C p
.text:0040AAA0                                         ; sub_44E150+5C p ...
.text:0040AAA0
.text:0040AAA0 var_30          = dword ptr -30h
.text:0040AAA0 tvITEM          = dword ptr -2Ch
.text:0040AAA0 var_28          = dword ptr -28h
.text:0040AAA0 var_24          = dword ptr -24h
.text:0040AAA0 var_20          = dword ptr -20h
.text:0040AAA0 var_1C          = dword ptr -1Ch
.text:0040AAA0 var_18          = dword ptr -18h
.text:0040AAA0 var_14          = dword ptr -14h
.text:0040AAA0 var_10          = dword ptr -10h
.text:0040AAA0 var_C           = dword ptr -0Ch
.text:0040AAA0 var_8           = dword ptr -8
.text:0040AAA0 var_4           = dword ptr -4
.text:0040AAA0 hItem           = dword ptr  8
.text:0040AAA0 pszText         = dword ptr  0Ch
.text:0040AAA0 cchTextMax      = dword ptr  10h
.text:0040AAA0
.text:0040AAA0                 push    ebp
.text:0040AAA1                 mov     ebp, esp
.text:0040AAA3                 sub     esp, 30h
.text:0040AAA6                 mov     [ebp+var_30], ecx
.text:0040AAA9                 mov     [ebp+tvITEM], 0
.text:0040AAB0                 xor     eax, eax
.text:0040AAB2                 mov     [ebp+var_28], eax
.text:0040AAB5                 mov     [ebp+var_24], eax
.text:0040AAB8                 mov     [ebp+var_20], eax
.text:0040AABB                 mov     [ebp+var_1C], eax
.text:0040AABE                 mov     [ebp+var_18], eax
.text:0040AAC1                 mov     [ebp+var_14], eax
.text:0040AAC4                 mov     [ebp+var_10], eax
.text:0040AAC7                 mov     [ebp+var_C], eax
.text:0040AACA                 mov     [ebp+var_8], eax
.text:0040AACD                 mov     [ebp+var_4], eax
.text:0040AAD0                 mov     [ebp+tvITEM], 1
.text:0040AAD7                 mov     ecx, [ebp+pszText]
.text:0040AADA                 mov     [ebp+var_1C], ecx
.text:0040AADD                 mov     edx, [ebp+cchTextMax]
.text:0040AAE0                 mov     [ebp+var_18], edx
.text:0040AAE3                 mov     eax, [ebp+hItem]
.text:0040AAE6                 mov     [ebp+var_28], eax
.text:0040AAE9                 lea     ecx, [ebp+tvITEM]
.text:0040AAEC                 push    ecx
.text:0040AAED                 mov     ecx, [ebp+var_30]
.text:0040AAF0                 call    sub_40AA80
.text:0040AAF5                 mov     esp, ebp
.text:0040AAF7                 pop     ebp
.text:0040AAF8                 retn    0Ch
.text:0040AAF8 TreeView_GetItem_wrapper endp

Everything starts to be clear when we get into sub_40AA80:

.text:0040AA80 sub_40AA80      proc near               ; CODE XREF: TreeView_GetItem_wrapper+50 p
.text:0040AA80
.text:0040AA80 this            = dword ptr -4
.text:0040AA80 pTVITEM         = dword ptr  8
.text:0040AA80
.text:0040AA80                 push    ebp
.text:0040AA81                 mov     ebp, esp
.text:0040AA83                 push    ecx
.text:0040AA84                 mov     [ebp+this], ecx
.text:0040AA87                 mov     eax, [ebp+pTVITEM]
.text:0040AA8A                 push    eax
.text:0040AA8B                 push    0
.text:0040AA8D                 push    113Eh
.text:0040AA92                 mov     ecx, [ebp+this]
.text:0040AA95                 call    SendMessageA_to_SysTreeView32
.text:0040AA9A                 mov     esp, ebp
.text:0040AA9C                 pop     ebp
.text:0040AA9D                 retn    4
.text:0040AA9D sub_40AA80      endp

Another wrapper, this time on SendMessageA. We see here 3 parameters pushed on the stack for the SendMessageA api and the handle to SysTreeView32 is pushed inside the wrapper. Let’s jump over the wrapper code to the API call and see all the parameters pushed onto the stack:

00139430   004013B0  /CALL to SendMessageA from unpacked.004013AA
00139434   00010C02  |hWnd = 10C02
00139438   0000113E  |Message = MSG(113E)
0013943C   00000000  |wParam = 0
00139440   00139470  \lParam = 139470

Structure
Address    Name                              Type      Value       Hex Dump
00139470   _mask                             DWORD     00000001
00139474   hItem                             DWORD     001AE710
00139478   state                             DWORD     00000000
0013947C   stateMask                         DWORD     00000000
00139480   pszText                           DWORD     001394BC
00139484   cchTextMax                        DWORD     000000C8
00139488   iImage                            DWORD     00000000
0013948C   iSelectedImage                    DWORD     00000000
00139490   cChildren                         DWORD     00000000
00139494   lParam                            DWORD     00000000

Now the most interesting parameter for our purposes is a Message and its value 113E. Resolving this hexadecimal value to a more understandable form we get TVM_GETITEMW. While the author used the SendMessage version for ANSI, the number of signs passed to TVITEM cchTextMax value means now that our buffer is able to accommodate 200 UNICODE characters. This incorrect size value allows an attacker to overflow the buffer and gain code execution.

Proof of Concept

python:

import os
os.mkdir("C:\\" + "A"*100);

Mitigation

The buffer that accommodates data from a SysTreeView32 control should be declared as wchar_t buffer to accommodate Unicode characters. Additionally, its size should be increased to 256 * sizeof(wchar_t) to be able to receive the entire directory name.

Timeline

2016-06-01 - Discovery
2016-06-10 - Reported
2016-11-03 - Released

Credit

Discovered by Marcin Icewall Noga of Cisco Talos.