CVE-2012-0158: RTF/OLE/CFBF/PE

Since support for the RTF file format has been added very recently with the version 0.9.4 of the Profiler, it’s a good idea to test it against real malware. I downloaded a pack of RTFs from contagiodump.blogspot.com and as I promised in the last post chose a more recent vulnerability: CVE-2012-0158. The reason why I picked a certain RTF from the pack is because most of the RTFs were automatically recognized and analyzed by the Profiler, while the following sample offers us a chance for some nice interactive analysis.

Unidentifed RTF

The first problem as you can see from the screenshot is that the RTF is not being automatically identified as such. That is because the signature is incomplete: the last two letters are missing. The next version of the Profiler will improve the detection in this regard. However, we can easily load it as RTF ourselves.

RTF foreign data

The RTF contains a lot of foreign data (meaning data which is not part of the RTF itself). Looking at the pattern an educate guess would be that it’s an encrypted payload.

The OLE stream contained in the RTF is flagged as containing possible shellcode. The Profiler detects it correctly. However, it’s actually the object embedded in the OLE stream which contains the shellcode. But wait, there’s no embedded object visible. This is because the extraction of the object failed, since the format of the OLE stream (which is undocumented) is different than usual. This is not a problem, we can just as easily load the object ourselves as the signature is easily recognizable.

Embedded CFBF

This last step was not strictly necessary, since we had already a detected shellcode in the OLE stream, but it increases the completeness of the analysis.

Since this is the header of the OLE stream:

Another educated guess would be that this is the component affected by the vulnerability. Let’s go back to the detected shellcode.

Detected shellcode

The initial instructions make sense and the following ones not. Let’s take a closer look.

This portion of code is easily recognizable as being a decryption loop for the code that follows. This is usually implemented to avoid detection. Didn’t work this time.

Let’s select the encrypted shellcode.

Encrypted shellcode

And decrypt it with the xor filter. We can confirm the correctness of the decryption by adding the ‘disasm/x86‘ filter.

Decrypted shellcode disasm

Back to the decrypted bytes, we use the script presented in the previous post to create an executable from the shellcode.

Shellcode to executable

A quick analysis with the help of the debugger.

The debugger was necessary only to check which APIs are retrieved by the shellcode and from there static analysis was easy. To sum up the shellcode decrypts two files, an executable and a doc file, executes the first directly and opens the second with the same program which is executing the shellcode.

From the shellcode we can retrieve the ranges of the encrypted payloads:

Embedded payloads

Now we can open the encrypted payloads and apply the simple decryption code.

Payload decryption

We save the decrypted payloads to disk. In the near future this won’t be necessary as such a filter will be easily created and used to load files inside the workspace of the Profiler itself.

We can use the safe text preview of Word Documents in the Profiler to view the text of the document opened by the shellcode.

DOC preview

From the text it seems to be directed at something gov: “My Esteemed Colleagues; Members of the Board of Governors of the Indian Business Chamber in Vietnam”.

The reason for opening the second document is clearly that the instance of the original program which ran the shellcode would’ve crashed and was therefore terminated cleanly with ExitProcess by the shellcode itself. Spawning a second instance with a clean document doesn’t make the user suspicious, from his point of view he just opened a document and a document has indeed been opened.

The executable is not protected by any means and so it’s just a matter of opening it with IDA Pro and spend a few hours understanding the whole code. But that’s beyond the scope of this demonstration.

Leave a Reply

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