GDI+ – ‘gdiplus.dll’ CreateDashedPath Integer Overflow

  • 作者: Abysssec
    日期: 2011-07-18
  • 类别:
    平台:
  • 来源:https://www.exploit-db.com/exploits/17544/
  • Abysssec Research
    
    1) Advisory information
    
    Title :GDI+ CreateDashedPath Integer overflow in
    gdiplus.dll
    Discovery :Nicolas july from vupen
    Analysis:Abysssec.com
    Vendor:http://www.microsoft.com
    Impact:High
    Contact :info[at] abysssec.com
    Twitter : @abysssec
    CVE : CVE-2011-0041
    
    
    2) Vulnerable version
    Gdiplus.dll 5.2.6001.22319
    
    3) Vulnerability information
    
    Class
    1-Integer overflow
    Impact
    
    Successfully exploiting this issue allows remote attackers to execute
    arbitrary code in the context of vulnerable application or cause
    denial-of-service conditions.
    
    Remotely Exploitable
    Yes
    Locally Exploitable
    Yes
    
    4) Vulnerabilities detail
    
    The vulnerability exists in gdiplus!GpPath::CreateDashedPath function of
    gdiplus.dll that is responsible for bitmap drawing and other 2d graphic
    rendering.
    EMF+ file is one of the image file format that is rendered by the
    library. And the vulnerability is based on some floating point
    calculation of an EMF+ path object.
    We made the following proof of concept to trigger the issues and it will
    be explained more:
    A little taste of file format we simply put a EMF_COMMENT record (id =
    0x00000046) and embed and emf+ geraphic object ( id = 0x00004008 ) .
    For simplicity we ripped out a valid graphic object from another file
    and started to play with it. The record have two important area that we
    highlighted them in the above picture.
    
    Here is the faulty code:
    .text:4ECFCBAD loc_4ECFCBAD:
    .text:4ECFCBAD mov eax, esi
    .text:4ECFCBAF shl eax, 3
    .text:4ECFCBB2 cmp [ebp+lpMem], 0
    .text:4ECFCBB6 pusheax ; dwBytes
    .text:4ECFCBB7 jzshort loc_4ECFCBCE
    .text:4ECFCBB9 push[ebp+lpMem] ; lpMem
    .text:4ECFCBBC callGpRealloc(x,x)
    .text:4ECFCBC1 testeax, eax
    .text:4ECFCBC3 jzloc_4ECFCCDB
    .text:4ECFCBC9 mov [ebp+lpMem], eax
    .text:4ECFCBCC jmp short loc_4ECFCBDE
    .text:4ECFCBCE ;
    ---------------------------------------------------------------------------
    .text:4ECFCBCE
    .text:4ECFCBCE loc_4ECFCBCE:
    .text:4ECFCBCE callGpMalloc(x)
    .text:4ECFCBD3 testeax, eax
    .text:4ECFCBD5 mov [ebp+lpMem], eax
    .text:4ECFCBD8 jzloc_4ECFCCDB
    
    The above code uses the eax register as arguments to the GpMalloc
    function. GpMalloc is simply a gdi version of heapAlloc function. The
    value of eax register is based on various floating point calculation
    that is not simple to examine at first look.But I traced the value of
    eax register and it seems the calculations are based on our values
    mentioned earlear in the file.
    And it doesn�t bound checked well, by changing the path value tricky it
    is possible when the �shr 	eax, 3� instruction multiply the value by 8
    we get an integer overflow and in turn a faulty heap allocation.
    I dynamically traced the values with my proof of concept file. Eax
    register is equall to eax + [ebp-38] * 10 and as there are a lot of
    values and calculations before that, for better consideration
    I made the following diagram:
    
    
    It took a lot of time explanation of all of the variables above but, the
    important one is the GpPath object that is in the code a clone of the
    object is made to later be manipulated for drawings.
    
    .text:4ECFC9D9 loc_4ECFC9D9: ; CODE XREF:
    GpPath::CreateDashedPath(DpPen const *,GpMatrix const
    *,float,float,float,int)+1AAj
    .text:4ECFC9D9 fld dword ptr [esi+eax*4]
    .text:4ECFC9DC fmul[ebp+arg_0]
    .text:4ECFC9DF fstpdword ptr [esi+eax*4]
    .text:4ECFC9E2 inc eax
    .text:4ECFC9E3 cmp eax, [ebp+arg_4]
    .text:4ECFC9E6 jlshort loc_4ECFC9D9
    .text:4ECFC9E8
    .text:4ECFC9E8 loc_4ECFC9E8:
    .text:4ECFC9E8 mov ecx, [ebp+var_18] ; Src
    .text:4ECFC9EB callGpPath::Clone(void)
    .text:4ECFC9F0 mov edi, eax
    .text:4ECFC9F2 testedi, edi
    .text:4ECFC9F4 jzloc_4ECFCDBA
    .text:4ECFC9FA mov eax, [edi]
    .text:4ECFC9FC mov ecx, edi
    .text:4ECFC9FE calldword ptr [eax+4]
    
    After calling the clone, it checks whether it is a valid clone or not at
    address 4ECFC9FE.
    The offset +34h of the object contains a pointer to our 4byte path
    object values.
    
    0:000> dd ecx
    0e03ca504ec67e58 68745031 00000000 00000000
    0e03ca600e03ca74 0e03ca74 00000010 00000010
    0e03ca7000000002 00000100 00000000 00000000
    0e03ca8000000000 0e03ca98 0e03ca98 00000010
    0e03ca9000000010 00000002 449a8eab 458ac500
    0e03caa0449a8eab 4e0000fe 00000000 00000000
    0e03cab000000000 00000000 00000000 00000000
    0e03cac000000000 00000000 00000000 00000000
    
    Our floating point values in the file format:
    0e03ca98449a8eab 458ac500 449a8eab 4e0000fe
    0e03caa800000000 00000000 00000000 00000000
    
    But there are some modifications on our values before we get the faulty
    code. First after the clone is performed GpPath::Flatten function made
    some changes
    to our values based on a transform matrix in the file. So this is cause
    of the highlighted 6 DWORDs in the file.���
    
    .text:4ECFC9FE calldword ptr [eax+4]
    .text:4ECFCA01 testeax, eax
    .text:4ECFCA03 jzloc_4ECFCDBA
    .text:4ECFCA09 fld ds:flt_4ECB80FC
    .text:4ECFCA0F pushecx ; float
    .text:4ECFCA10 lea eax, [ebp+var_F8]
    .text:4ECFCA16 fstp[esp+108h+var_108]
    .text:4ECFCA19 pusheax ; int
    .text:4ECFCA1A mov ecx, edi
    .text:4ECFCA1C callGpPath::Flatten(GpMatrix const
    *,float)
    .text:4ECFCA21 cmp [ebp+var_2C], 0
    
    Flattened GpPath object values:
    0:000> dd poi(edi+34)
    0e03cd18449a7eab 458ac100 449a7eab 4e0000fd
    0e03cd2800000000 00000000 00000000 00000000
    
    And after that our changed GpPath object is sent to
    calculateGradiantArray and some array of floating point values are made
    based on its calculation.
    There are many other default floating point values has effects on the
    value of the overflowing size for GpMalloc that are not so interesting
    and I�ve just shown them on the diagram.
    After the calculation integer wrapped, the heap allocated by the
    gpMalloc function is not big enough to hold our data. So in next uses of
    the wrapped allocated heap the corruption occurs.
    But it seems there is not a straight way of exploiting such heap
    corruptions using a standalone file. .
    
     feel free to contact us at : info [at] abysssec.com
    
    PoC link : http://abysssec.com/files/GDI_PoC.zip
    PoC Mirror : https://gitlab.com/exploit-database/exploitdb-bin-sploits/-/raw/main/bin-sploits/17544.zip (GDI_PoC.zip)