Recently there was an IE 0day (CVE-2014-0322) used for hanging horses. Although this vulnerability exists in IE, in order to achieve successful exploitation, the sample also uses flash as an aid to break through various protection measures. The combination of IE and flash brings some challenges to analysis. I have never analyzed such a combination before. I just took this opportunity to analyze it in detail, sort out the documents, and exchange and learn together. In case of any errors, please criticize and correct them.
The content of this article includes:
1. Analysis of the entire exploit process.
2. Cause of the vulnerability.
3. Use flash uint vector to bypass DEP/ASLR.
4. the ROP fragment in the sample.
5. Sample shellcode behavior.
1. samples used in this article
The sample used in this article contains three files.
Index.html (that is, the html file, formerly called what I forgot) Tope.swf
Erido.jpg
These files can be searched on the Internet. I will not give them here.
2. Entry Point
The entire attack entry point is index.html, which will try to load Tope.swf:
1 <embedsrc?tope.swf width = 10 height = 10> </embed> 3.Tope.swf loading and heap spray
When Tope.swf is being optimized, we will first try to get erido.jpg from the server"
1 2 3 4 _ local1.url = "Erido.jpg"; this. l. dataFormat = URLLoaderDataFormat. BINARY; this. l. addEventListener (Event. COMPLETE, this. e_xx); this. l. load (_ local1 );
Then we try to allocate a large number of flash uint vector objects for heap spray. Each vector contains 1022 (0x3fe) elements. Because each vector object contains an 8-byte header, the actual memory size occupied by each object is 0x1000 bytes (0x3fe * 4 + 8 ). This part of spray requires about 400 mb of memory.
1 this. s = newVector.
At the same time, Tope.swf will also spray a small amount of flash object vector, which stores the reference of the same flash. media. Sound object:
1 2 3 4 5 6 7 8 while (_ local2 <0x0400) {this. ss [_ local2] = newVector. <Object> (_ local9); _ local3 = 0; while (_ local3 <_ local9) {this. ss [_ local2] [_ local3] = this. snd; _ local3 ++ ;}; _ local2 ++ ;};
After heap spray is completed, the "puIHa3" function in index.html will be called through ExternalInterface in flash.
4. use-after-free vulnerability and inc-by-one magic
The puIHa3 function will attempt to trigger a CVE-2014-0322 vulnerability, which is a user-after-free leak of a CMarkup object
Holes. There have been a lot of analysis on the vulnerability principles on the Internet. Here is a simple introduction:
1 2 3 4 5 6 7 vara = document. getElementsByTagName ("script"); varb = a [0]; B. onpropertychange = fun; 5 handler function varc = document. createElement ('select'); c = B. appendChild (c); // set "onpropertychange" for the script node // create a "select" Node // attach the newly created select node to the script node
When appendChild is called, MSHTML! CElement: Var_appendChild is called. A new
The CMarkup object of will be created:
1 2 MSHTML! CDoc: CreateMarkupFromInfo + 0x0000017f MSHTML! CDoc: CreateMarkupWithElement + 0x0000008a MSHTML! CElement: GetDOMInsertPosition + 0x000001c0 MSHTML! CElement: InsertBeforeHelper + 0x0000007e MSHTML! CElement: InsertBeforeHelper + 0x000000e5 MSHTML! CElement: InsertBefore + 0x00000036 MSHTML! CElement: Var_appendChild + 0x000000cb
Then appendChild continues to run and comes here:
1 2 MSHTML! CMarkup: Export yelemententertree + 0x1df call CElement: HandleTextChange (bool)
The call of this function will eventually trigger the onpropertychange event, so the previously registered callback function will be called, and a line of code in the callback function will trigger DOM release, resulting in the release of the CMarkup object:
1 this. outerHTML = this. outerHTML // frees the DOM thus frees the CMarkup Object
After the CMarkup object is released, the sample immediately tries to release the memory position:
1 2 3 for (a = 0; a <arrLen; ++ a) {g_arr [a]. title = d. substring (0, d. length );}
The above code allocates a series of string objects to implement the station position.
After CMarkup is released and occupied, the program continues to run and comes here:
1 2 3 4 5 6 7 8 9 10 CMarkup: UpdateMarkupContentsVersion (void ). text: 637C943E. text: 637C943E mov eax, [edx + 7Ch] inc eax. text: 637C9441 inc eax. text: 637C9442 or eax, 80000000 h. text: 637C9447 mov [edx + 7Ch], eax. text: 637C944A mov eax, [edx + 0ACh]. text: 637C9450 test eax, eax. text: 637C9452 jz1_loc_637c9457. text: 637C9454 inc dword ptr [eax + 10 h]
Here, the CMarkup object has been released and positioned. When running inc dword ptr [eax + 10 h,
Eax + 10 h is already set to 0x1a1b2000 (can be set to any value), so this command will increase the data at 1a1b2000 by 1.
The effect of this vulnerability is summarized as follows: one byte of any address can be added to + 1.
So how can we relate the effect of this arbitrary address data + 1 with exploit? What is the memory data at 0x1a1b2000?
We can still remember that tope.swf initially spray a large number of uint vectors into the memory. In fact, if spray is successful, the address 0x1a1b2000 will point to the size field of a vector.
Let's take a look at the layout of the uint vector in the memory:
The Uint vector contains an 8-byte header, where four bytes are length fields.
Let's see if the memory data at 1a1b2000 is like this:
1 2 3 0: 006> dd 1a1b2000 1a1b2000 000003fe 08c24000 deadbee1 00000000 1a1b2010 1a1b2000 1a1b2000 00000000 00000000
We can see that the dword Value at 1a1b2000 is 0x3fe, which is the length of the uint vector of spray at the beginning. After executing the inc dword ptr [eax + 10 h] command, the memory is:
1 2 3 0: 006> dd 1a1b2000 1a1b2000 000003ff 08c24000 deadbee1 00000000 1a1b2010 1a1b2000 1a1b2000 00000000 00000000
What does this mean? To put it simply:
We first define a uint vector with the size of 0x3fe, and then increase the length field in its memory through the vulnerability, so that when we access this uint vector again in the flash script, the flash library mistakenly assumes that the length of the vector is greater than 0x3fe. So we can implement cross-border read/write to this vector.
After modifying the length field of the vector, the html task is completed. Next, return to flash to continue the task.
5. Any memory read/write and ROP
After returning to flash, the sample will first try to find the modified vector, which we call "V1 ". Then execute
Statement:
V1 [0 x 3Fe] = 1073741808;
Obviously, the subscript is out of the range (because its length is 0x3fe when V1 is defined ). As a result, a dword is written into the dword. Since these vectors are continuously allocated in spray, this 1073741808 actually covers the length field of a vector under V1. We call this vector "V2 ".
Because V1 has a memory address of 0x1a1b2000, the starting address of V2 is 0x1a1b3000 (each vector occupies 0 × 1000 bytes). Let's take a look at the memory data of V2.
1 2 3 0: 006> dd 1a1b3000 1a1b3000 3ffffff0 08c24000 deadbee1 00000000 1a1b3010 1a1b2000 1a1b2000 00000000 00000000
We can see that the V2 length field has been tampered with into a very large value 0x3ffffff0 (1073741808 ). In this case, we can perform any read/write operations on the entire memory. So far, "arbitrary address plus one" is successfully converted into "arbitrary address read/write ".
For DEP protection, the sample begins to construct the ROP. Using the read/write function of any address, it searches for the drop command and function in the memory space of the process, and uses the command in ntdll for the drop operation ., Here we will talk about the basic search process. For details, you can read the code by yourself.
Flash. media. sound object pointer-> flash. media. sound object virtual function table-> flash Module Base Address-> flash module import table-> kernel32 function address-> kernel32 base address-> kernel32 import table-> ntdll function address-> ntdll base Address-> (ZwProtectVirtualMemory address and [xchgeax, esp; ret;] command address)
Then, the sample will overwrite the virtual function table of a flash. media. Sound object, and then call its function to redirect the control flow to the drop object:
Flash! IAEModule_AEModule_PutKernel + 0 × 212712:
66769ae2 ff5070 call dword ptr [eax + 70 h]
Ds: 0023: 1a1b3170 = 77a646a8
6. Drop operation
This drop operation is quite simple, with only two steps:
Step 1:
1 77a646a8 94 xchg eax, esp // reset the stack pointer
Step 2:
1 ntdll! ZwProtectVirtualMemory (1a1b3000, 1000, PAGE_EXECUTE_READWRITE)
The first drop command points the stack pointer to a controllable memory. The second command changes the shellcode attribute of the second stage to executable, and then returns the shellcode of the second stage.
7. shellcode of the Second Stage
The shellcode start address of the second stage is 1a1b311c.
Here, the virtual table of the overwritten flash. media. Sound object is restored, and the API address is searched. When an API is called, the inline-hook check is performed, and the hook directly skips the first five Bytes:
What shellcode does in the second stage is as follows:
1. decode the data contained in “erido.jpg. The algorithm is as follows: foreach byte B in buffer:
If B! = 0 & B! = 0 × 95: B ^ = 0 × 95
2. Drop two PES: % TEMP % \ sqlrene1_txt % TEMP % \ stream.exe
3. Call LoadLibrary to load sqlrene1_txt
4. Return the flash code
8. Summary
Although the vulnerability exists in IE, The flash vector is used to achieve the breakthrough of DEP/ASLR. This method is very common to implement advanced exploit by modifying the array and string length through vulnerabilities, exploit appears in software supporting scripts such as IE, pdf, flash, java, firefox, chrome, and safari.
We recommend that you read xiaobo's article in detail:
Http://www.fireeye.com/blog/technical/cyber-exploits/2013/10/aslr-bypass-apocalypse-in-lately zero-day-exploits.html