quarta-feira, 2 de novembro de 2011

Diaries of a Vulnerability – take 3


Pray after free and use after pray.

 
Ok, I’m long overdue on this post, I know. The reason I procrastinated this so much was because the subject of this post was not important to the exploit described in the first posts of the diary, but I consider that it might be important on other exploits you might be creating. So here it is.
Let’s first review some history: the size of the exploitable “use-after-free” CObjectElement object was 0xE0. Also, the heap allocator kept all objects of the same size in the same heap sub-segment. So, all we needed to do was to fill a full segment of any other kind of object as long as it had the same size, and as soon as we tried to reuse the freed memory, an object of that memory segment would the reused. This was done with the unescape and substr javascript native functions where strings of that particular size, having content controlled by us, were allocated. But javascript strings are handled by OLE, so when we call:
 
  var size1 = (0xd8/2)-3;
  var arrSize1 = 2000;
  var obj_overwrite2 = unescape("%u0e0e");
  while(obj_overwrite2.length < size1)
    { obj_overwrite2 += obj_overwrite2; }
  obj_overwrite2 = obj_overwrite2.substr(0, size1);

 
We’re internally calling OLE:

ChildEBP RetAddr 
01a5f694 41542d59 OLEAUT32!SysAllocStringByteLen+0x28
01a5f6ac 75c1d101 IEFRAME!Detour_SysAllocStringByteLen+0x13
01a5f6c4 75c15636 jscript!PvarAllocBstrByteLen+0x2a
01a5f734 75c15ff7 jscript!JsStrSubstrCore+0x176
01a5f754 75c241e5 jscript!JsStrSubstr+0x1b
01a5f78c 75c2145c jscript!NatFncObj::Call+0x41

This is important to keep in mind because of the transformations that our strings are subjected to. These transformations were observed by Alex Sotirov in his javascript Heap Library implementation and that’s the reason of the initial calculations of the size1 variable. Divide by 2 to account for the Unicode transformation, and subtract 3 to account for the added string metadata info.

If you remember from take 2 of the diaries, I referred that a friend of mine was unable to successfully run the exploit. Well, the reason of this is that my friend was running Windows XP SP2 with Internet Explorer 8. Why is this relevant? Because of the heap allocator type used by Internet Explorer in this OS version, and the way OLE makes use of it. The old heap allocator mixes all the allocations, leaving no memory chunks separation by segmentation usage. This sounds better than LFH. But for this, we need a new approach; we need to be able to manipulate the LAL lists. What about OLE? OLE maintains a global heap variable in memory, but the heap used is the default process heap; the same as mshtml.dll uses for object allocation, so we’re safe from the OLE point of view. So, why is it still not working?

 Figure 1: OLE heap global variable.

!heap
Index   Address  Name      Debugging options enabled
  1:   00150000               
  2:   00250000               

!heap 00150000               
Index   Address  Name      Debugging options enabled
  1:   00150000
    Segment at 00150000 to 00250000 (00100000 bytes committed)
    Segment at 01dd0000 to 01ed0000 (00100000 bytes committed)
    Segment at 028a0000 to 02aa0000 (00085000 bytes committed)

CObjectElement:addr[00237278]
 CTreeNode:node[0024dc08]
 CObjectElement:addr[00237278]
 CTreeNode:node[0024d848]
 CObjectElement:addr[00237278]
 CTreeNode:node[0024db08]
 CObjectElement:addr[00237278]
 CTreeNode:node[0024dac8]
 CTreeNode:node[0024dc08]
 CTreeNode:node[0024d848]
 CTreeNode:node[0024db08]
 CTreeNode:node[0024dac8]
 String:addr[01dd6fdc]size[000000d2]
 String:addr[0023727c]size[000000d2]
 String:addr[00237364]size[000000d2]
 String:addr[0023744c]size[000000d2]
 String:addr[00237534]size[000000d2]
 String:addr[0023761c]size[000000d2]
 String:addr[00237704]size[000000d2]
 String:addr[002377ec]size[000000d2]
 String:addr[029113cc]size[000000d2]
 String:addr[0291176c]size[000000d2]
 String:addr[02911854]size[000000d2]
 String:addr[0291193c]size[000000d2]
 String:addr[02922a04]size[00000006]
...
 String:addr[01ec88cc]size[00000006]
 String:addr[01ec85cc]size[00000006]
 String:addr[001535ac]size[00000006]
 String:addr[028a09f4]size[000001e6]
 CTreeNode:node[0024d408]
 CTreeNode:node[0024d708]
 CObjectElement:addr[01ecf410]
 CTreeNode:node[0024d8c8]
 CObjectElement:addr[01ecf410]
 CObjectElement:addr[02910f40]
 CTreeNode:node[0024dc08]
 CObjectElement:addr[02910f40]

In the above (resumed) trace we’re allocating about 2000 strings, each sized 0xD8, in Windows XP, and freeing the last 500 odd strings. If you’re wondering why the size is printed 0xD2, keep reading. Notice the difference between the CObjectElement object addresses and the allocated string addresses. The CObjectElement object addresses get near but never reuse any of the string freed addresses. It looks like the approach of allocating objects of the same size as the freed object; to try to influence the LAL cache is useless. Being so, this memory fence makes it very hard for the exploitation process, as the heap spraying needs to be pretty disseminated thru the memory space. Why?
I noticed an interesting thing in my friend’s machine; the CObjectElement is 0xD8 bytes in size:

 Figure 2: Allocation of a CObjectElement in XP2

When OLE allocates a buffer for a string, it transforms the string requested size. The following calculations are done by SysAllocStringByteLen in Windows XP and by CbSysStringSize in Windows 7:

NewSize = (RequestedSize+0x15) && 0xfffffff0

 Figure 3: OLE buffer calculation in XP.

The result size that is going to be allocated by the heap manager thru OLEAUT32!APP_DATA::AllocCachedMem, must be a multiple of 16. When performing these calculations the requested size to OLE will correspond to our original object size minus 6. Applying these constraints to our two buffer sizes we get:

Size=0xE0 -> RequestSize = 0xE0-6 = 0xDA; (0xDA+0x15)&0xfffffff0 = 0xE0
Size=0xD8 -> RequestSize = 0xD8-6 = 0xD2; (0xD2+0x15)&0xfffffff0 = 0xE0

If we need to create a string sized 0xD8, we would fail to do so as the next nearest lower valid buffer size would be 0xD0. For the exploit, this is a terrible thing. In Windows Vista and above, the exploit depends on the allocation of memory chunks of the same size of our freed object, as it needs to land on the same heap sub-segment for it to control the EIP reliably. If the strings we’re creating are going to other sub-segments, all we can do is pray that whatever value goes to our freed object address may resemble one of the various heap sub-segment addresses available, filled with controlled data strings. 
 
 Figure 4: OLE buffer calculation in Windows 7.

bp oleaut32!SysAllocStringByteLen

dc esp
022ccf60  6cb0a0b7 00000000 000000d2 00000000  ...l............
022ccf70  000000d2 6cb05b0f e65b365c 022cd364  .....[.l\6[.d.,.

pt
eax=004c2c0c ebx=000000d2 ecx=779d2fe7 ..
eip=7759478e esp=022ccf48 ebp=022ccf5c ..
cs=001b  ss=0023  ds=0023  ..
OLEAUT32!SysAllocStringByteLen+0x6e:
7759478e c20800          ret     8

!heap -x 004c2c0c 
Entry     User      Heap      Segment       Size  PrevSize  Unused    Flags
-----------------------------------------------------------------------------
004c2c00  004c2c08  00400000  00484720        e8      -            8  LFH;busy
As a final example, let’s reduce the size of the string to 0xD0:

var size1 = (0xd0/2)-3;

And observe the size of the heap chunk:

String:addr[004a943c]size[000000ca]

!heap -x 004a943c
Entry     User      Heap      Segment       Size  PrevSize  Unused    Flags
-----------------------------------------------------------------------------
004a9430  004a9438  003b0000  00432610        d8      -            8  LFH;busy

We’re jumping 16 bytes, which validates our findings. Alex Sotirov also found this. If you search heapLib for allocOleaut32 function implementation, you will find this:

    // Make sure that the size is valid
    if ((size & 0xf) != 0)
        throw "Allocation size " + size + " must be a multiple of 16";

In conclusion, the symptoms are easily identified, its behavior is erratic. Sometimes it works, sometimes it doesn’t. And, as you can see, the effort for phase one exploit is much greater and unpredictable. Hence, we prefer to call it a “Use after pray” exploit instead.

Hope you enjoyed.

terça-feira, 18 de outubro de 2011

A crack in Redgate's Reflector


Above all things related to software development, those who get my warmest affection are the protection mechanisms. Almost every application out there (mainly commercial ones) have a different approach that materializes the individual vision of one programmer. Some choose commercial protection oriented software, some choose cryptography, some encode, other use math, etc. What makes them different is what makes me interested in them. This interest took me yesterday to Redgate's Reflector. But before continuing let me state the following: although I don't favor cracking, especially when a program has prices affordable by everyone like Reflector does, I believe that cracking is a necessity. Be it for validating the strength of the protections in place, be it for bypassing those protections and validate that a piece of software we just bought or downloaded it from the Internet does what it acclaims.
With that said let me tell you why I'm posting about a bypass of Redgate's Reflector protection scheme: because it just took me less than one minute to find it. Considering all the obfuscation effort that Redgate put on Reflector, this seems like they cracked open their own safety mechanisms.  Given their great work with Reflector, I think that such an error deserves a public post.

The story begins when I needed to use Reflector and it informed me that I had to buy the full version if I wanted to continue using it.


If you have been following the news, my country -Portugal- is in a huge recession, which means that we don't have money. So, as I only use Reflector a couple of times  a year, I decided to see if I could do anything to convince Reflector to work just one more time. I grabbed my second favorite debugger, Windbg, and run Reflector. As the application initialized, it started dumping some data to the debugger's output window:
 
Reflector.exe Information: 0 : Retrieving licence for .NET Reflector 7.0 {2447b2f0-fe09-4d98-8e51-93b07466303e}
Reflector.exe Information: 0 : Machine hash is local
Reflector.exe Information: 0 : Local machine hash is XXXX
Reflector.exe Information: 0 : Persisting
Reflector.exe Information: 0 : Product .NET Reflector
Reflector.exe Information: 0 : Activated False
Reflector.exe Information: 0 : Edition
Reflector.exe Information: 0 : Serial Number
Reflector.exe Information: 0 : Blob {2447b2f0-fe09-4d98-8e51-93b07466303e}
Reflector.exe Information: 0 : Hash XXXX
Reflector.exe Information: 0 : Trial Tampered
Reflector.exe Information: 0 : Expires 2011-11-13 02:59:43 UTC
Reflector.exe Information: 0 : Extended False
Reflector.exe Information: 0 : Installed 2011-10-14 02:59:43 UTC
Reflector.exe Information: 0 : First Used 2011-10-14 02:59:43 UTC
Reflector.exe Information: 0 : Last Used 2011-10-17 09:52:05 UTC
Reflector.exe Information: 0 : Stored to registry

I thought the value {2447b2f0-fe09-4d98-8e51-93b07466303e} was a curious one as it resembled a GUID. Also, the phrase "Stored to registry" seemed, hmmm... suspicious? I grabbed that value and searched the registry for it. This value was being used here:


I deleted the key from the registry and rerun Redgate's Reflector, and guess what?  The trial date was reset.

Ups!...

PS: After I found this, I searched the Internet for this trial reset hack and found that it is known for some time. But, I didn't find any reference to this leak of information by Redgate. This is the second reason why I decided to post it.

sexta-feira, 7 de outubro de 2011

Not all bugs are exploitable

Those who are, we call them vulnerabilities. Which is not the case of the bug I found in Notepad++ and it’s the subject of this post. The bug is triggered when setting the parsing Language of an opened document to "User-Defined"; exit Notepad++ while the document is still open, and then, start Notepad++. Every time Notepad++ is run it will crash with a message stating the error:



At the crash point we can observe the thread state:

k
ChildEBP RetAddr 
WARNING: Stack unwind information not available. Following frames may be wrong.
000df0d8 1001c863 SciLexer!Scintilla_DirectFunction+0x42e65
000df0f4 1001ca7b SciLexer+0x1c863
000e1090 100044fa SciLexer+0x1ca7b
000e10b8 10025c2b SciLexer+0x44fa
000e10dc 100272ec SciLexer+0x25c2b
000e1190 10029ca7 SciLexer+0x272ec
*** WARNING: Unable to verify checksum for npp.exe
*** ERROR: Module load completed but symbols could not be loaded for npp.exe
000e11a0 0047a597 SciLexer+0x29ca7
000e11c0 004811cd npp+0x7a597
000e11d4 0043b88c npp+0x811cd
000e1698 000e1688 npp+0x3b88c
000e169c 000e19ac 0xe1688
000e16a0 004d0ee8 0xe19ac
000e19ac 00400000 npp+0xd0ee8
000e19b0 00040278 npp
000e19b4 000302a8 0x40278
000e19b8 00000000 0x302a8

r
eax=00000000 ebx=00000000 ecx=00eadc40 edx=003b0608 esi=000df118 edi=00eaddf0
eip=1006cb0d esp=000def10 ebp=000df0d8 iopl=0         nv up ei pl nz na po nc
cs=001b  ss=0023  ds=0023  es=0023  fs=0038  gs=0000             efl=00010202
SciLexer!Scintilla_DirectFunction+0x42e65:
1006cb0d 8b38            mov     edi,dword ptr [eax]  ds:0023:00000000=????????

It seems that we have a null dereferenced pointer in the SciLexer module; with EAX=0, and, as there’s no null page allocated, we get a crash with access denied error. Let’s give it a look. EAX comes from ESI, so let’s see what’s there:

!address 00eaddf0
Failed to map Heaps (error 80004005)
Usage:                 
Allocation Base:        00e90000
Base Address:           00e90000
End Address:            00eb6000
Region Size:            00026000
Type:                   00020000  MEM_PRIVATE
State:                  00001000  MEM_COMMIT
Protect:                00000004  PAGE_READWRITE

!heap -x 00eaddf0
Entry     User      Heap      Segment       Size  PrevSize  Unused    Flags
-----------------------------------------------------------------------------
00eadde8  00eaddf0  003b0000  00e90000       428        58        18  busy extra fill

There’s no information of interest from the heap allocator as Notepad++ uses its own allocator. So, I started digging a little more to know if I could somehow influence this null reference to become something else more interesting from security viewpoint. Reversing some code of the application and analyzing the dump, I managed to get to some conclusions.
What is happening is that the document parsing language is saved in the session.xml file. The file is kept by Notepad++ in the AppData\Roaming\Notepad++ profile directory. This configuration file is always updated and saved when Notepad++ is closed by the user.

 
As there’s no “User-Defined” language defined, Notepad++ will allocate a language object that’s initialized with zeros by the time it is allocated. When parsing the file it will apply this empty object without verifying that there’s no valid data in it.


We got a "use an un-initialized object", and in consequence a crash. Although the object is not initialized, "sadly" it isn’t exploitable because as I said it is zeroed out on allocation.  This conclusions can be validated by doing the following:

1. Create a user defined language file. Menu View, open User-Defined dialog.
2. Name it User-Defined. 
3. Save it.


If you try now to do the same thing as described before, Notepad++ won’t crash anymore. If you go to the Language menu you will see a weird thing, there will be now two “User-Defined” items. Whichever you choose you'll get the same results, it will apply the previously defined "User-Defined" parsing language and no crash.


While the bug is not corrected by the Notepad++ developer team, you can solve this issue just by deleting the session.xml file. It will be recreated next time you start Notepad++.

Again, not all bugs are exploitable. Those who aren't remain just... bugs!

terça-feira, 4 de outubro de 2011

My new Android

I bought my first Android last weekend. It took me a while to get use to, but I managed to get a nice tour thru the whole system. I was pleasantly surprised finding that there's a lot of forensic/reversing info for it out there. But I'd like to post a list of some internal tools as a reminder for myself and for those who are starting reversing stuff on this platform:

Configuration:
getprop, setprop, monkey, pm, radiooptions, sqlite3

Debuggin:
gdbserver

Logging:
logcat, logwrapper, log, getevent

Network
iftop, netcfg, netstat, ifconfig

Files:
lsof, dexdump, strace

System:
printenv, ps, wipe, lsmod, run-as, service, svc, uptime, ssh, procrank, procmem, showmap, librank, rawbu, dumpsys, dumpstate

Media:
screencap, screenshot