Archived Blog
IE7 Zero Day Technical Analysis
12.15.2008 - 11:07 AMA. JavaScript heap spray code and x86 shellcode
B. The XML/SPAN tag vulnerability
A. JavaScript heap spray code and x86 shellcode
Here we can see the first part of the attack from the script point of view:
B. The XML/SPAN tag vulnerability
Let's move on to the second part: the exploit and the trigger. Here we can see the attacker add XML/SPAN tags:2) Advanced shellcode
The shellcode used by the Zero Day is rather interesting. The ending payload is quite similar to any normal shellcode (download a file and execute it), but it also has some peculiarities.
Before it does anything fancy, the shellcode starts to allocate memory using the GlobalAlloc function. It allocates 0x2000 bytes onto the heap, and the shellcode makes a copy of itself onto the heap. Let's see what happens next.
2.1 - Hooks
The shellcode hooks a few Windows functions, such as UnhandledExceptionFilter, LdrShutdownThread, and the like. We had never seen public shellcode hooking Windows functions before, so this was a surprise. We were expecting a very simple download and execute shellcode.
In order to hook them, it uses the VirtualProtect function with the PAGE_EXECUTE_READWRITE parameter. By default, Windows functions are write-protected. Therefore, you need to change the rights in order to modify them. After the write access is enabled, the first instructions are overwritten, in order to install the hook. The injected code redirects the hooked functions to special handling routines. These routines are part of the shellcode, obviously. Once the function is patched, the PAGE rights are set back to their original value.
Here you can see the call to VirtualProtect:
After the rights have been modified, this piece of code is responsible for installing the hook:
This is the first hooked function, UnhandledExceptionFilter, after it has been patched:
If we follow the redirection code, we end up here:
Basically, if the UnhandledExceptionFilter function is executed, it returns 0x80040111. Two other functions are patched, including LdrShutdownThread.
2.2 - Checks for hooks
The shellcode also checks some of the API functions it is planning to call. In fact, it checks to see if those functions have been hooked already (possibly by some sandboxing product or any sort of monitoring program). As you can see below, one of the checked API functions is CreateProcessA:
This piece of code is looking to see whether the API function has been detoured. If the function has been patched, the shellcode executes embedded instructions, and then skips the first 5 bytes of the API and resumes execution from there. Basically, this technique is used to bypass the hooks that could have been inserted in the API function. It's also checking for nops (0x90) right after the first byte of the detour (0xE8 or 0xE9).
2.3 - UrlDownloadToCache
The shellcode also uses UrlDownloadToCache rather than the infamous UrlDownloadToFile. This is most likely done to escape any products that are monitoring or hooking this function, in order to log the URLs of the payload. This is a cheap attempt to bypass protection, and it probably works.
2.4 - CreateProcessA
In order to execute the downloaded file, it executes cmd /c. This is typical and nothing really exciting.
2.5 - LdrShutDownThread
As mentioned earlier, a few hooks are made by the shellcode. The LdrShutdownThread hook counts both processes and windows, and its EnumWindow CallBack is looking for the IEFrame class using the GetClassNameA API function. We haven't yet looked into the details, but this could be used to check whether the shellcode is being executed from the IE context, and not from some other applications (such as shellcode2exe).
2.6 - shdocvw ordinal 101
For this one, we are not quite sure about its goal. We have a few hypotheses, but the parameters used are not matching. Indeed, it's pushing EBX four times, and EBX is 0. This function is supposed to take only two different parameters. While researching, the only references we could find to that function were bugs in Wine and similar projects. One of our guesses was that it could be anti-Wine code, but we haven't tested this theory yet. We have some other ideas about it, but if you know for sure, you are invited to email us and share your thoughts.
2.7 - Last words on the shellcode
The shellcode is doing a few other things, but most of it is quite standard for shellcode. The most surprising pieces were the actual hook checks and the hooking function. This shellcode has its own GetProcAddress-like function, and it is using HASH to find which function it has to resolve. Typical shellcode.
Security Researchers: Jun Zhang and Nicolas Brulez