2012-10-10
Abstract
Code injection first became popular in game cheats, where it was used to change the program’s course of execution. Wayne Low looks at a piece of malware that takes advantage of the Windows messages flaw to perform code injection.
Copyright © 2012 Virus Bulletin
Code injection first became popular in game cheats, where it was used to change the program’s course of execution. The technique has since been adapted for use in the malware world, where it is used in various ways to disguise the presence of malicious code on a machine, for example by injecting and running the code in a legitimate process.
This analysis focuses on a piece of malware found on a customer’s machine which had reportedly been infected with ransomware. Behavioural analysis showed that this malware did not behave like typical ransomware and it appeared to be an ordinary backdoor. Out of curiosity, we decided to investigate it to determine whether there were any hidden characteristics that could possibly indicate that the malware really was ransomware, as the customer claimed. Further investigation disclosed a couple of interesting details. So the story begins.
The results of the investigation are as follows:
We believe it to be the first malware found to be related to the well-known ‘Windows messaging shatter attack’, which was first discovered by Brett Moore in 2004 [1] (proof-of-concepts were available in his whitepaper [2] demonstrating how the attack worked).
This malware uses an exploitation technique to bypass Data Execution Prevention (DEP) in conjunction with the Windows shatter attack technique in order to perform code injection.
We believe the author intended to name the malware ‘sdropper32’ (Shellcode Dropper) as this term can be found in a DLL name from the image export table, IMAGE_EXPORT_DIRECTORY->Name. From now on, we will refer to the malware as Sdropper.
It is always helpful for the analyst when a malware sample comes with debug information, as it gives us hints about the malware and makes analysing it easier, even if the information is not the full symbol table of the API functions used in the code. On first looking at the debug strings from the binary, we can deduce the following information:
The programming language used by the sample
The logging information that will be sent to the malware’s command-and-control (C&C) server
The functionality of some important modules used in the sample
The error handling messages.
Based on the debug information, it is very easy to identify the main payload of this sample, but what caught our attention was the exploit string – which made us wonder what else was going on. We decided to investigate further to see if some sort of exploit was really implemented.
Our initial analysis showed that the malware didn’t use the usual memory injection method, so we first had to understand how it implements code injection.
The classic memory injection technique used by many traditional malware families will first allocate a block of memory using the VirtualAllocEx API function to hold the code instructions, which will then be written to the address space of the remote process using the WriteProcessMemory API function. Since this is a popular method [3] for writing/injecting code into a remote process, it is easily identified by anti-virus software through a Host Intrusion Prevention System (HIPS). For this reason, Sdropper utilized an alternative and intelligent method, without using any memory manipulation APIs.
First, the malware attempts to find a global file mapping object in the system, which can be found using one of the following section objects:
\BaseNamedObjects\ShimSharedMemory
\BaseNamedObjects\windows_shell_global_counters
\BaseNamedObjects\MSCTF.Shared.SFM.MIH
\BaseNamedObjects\MSCTF.Shared.SFM.AMF
\BaseNamedObjects\UrlZonesSM_Administrator
If the section object can be opened successfully for SECTION_MAP_READ and SECTION_MAP_WRITE, it will create a mapped view with protection level PAGE_READWRITE using ZwMapViewOfSection in the malware’s process address space. In my test environment, I was unable to see section objects from 2 to 4, so ZwOpenSection will return STATUS_OBJECT_NAME_NOT_FOUND if it tries to open one of these section objects.
The mapped view returned by ZwMapViewOfSection can be shared with other processes. In other words, the sample can write code and store contents in this mapped view and share it with the explorer.exe address space as well [4].
(For a larger version of the image shown in Figure 4 click here.)
As shown in Figure 4, the committed memory is marked as read-write only. How did the malware manage to execute code in this memory region? And how did the malware trigger the code written in this page? We find a clue in its export directory table:
004065A3 DownloadRunExeId
00406536 DownloadRunExeUrl
004065FC DownloadRunModId
00406676 DownloadUpdateMain
00404D4E InjectApcRoutine
00404D33 InjectNormalRoutine
00405ADB InjectedShellCodeEnd
00405A8A InjectedShellCodeStart
00406721 SendLogs
0040670C WriteConfigString
The highlighted text shows that it has a shellcode routine and its name, InjectedShellCodeStart, indicates that this shellcode will be injected somehow into the shared memory. In the next section, we will investigate how important this shellcode is in this memory injection method.
On initial execution, the malware will generate the platform-specific loader code, together with the custom shellcode mentioned in the previous section. To do so, Sdropper checks the architecture of the infected machine using IsWow64Process.
(For a larger version of the image shown in Figure 6 click here.)
While building the loader, Sdropper will simultaneously copy the code to the memory regions shared with explorer.exe.
The author wrote his own GetProcAddress function (which I refer to as _MyGetProcAddress), which has the following function prototype:
_MyGetProcAddress(HMODULE hModule, CHAR *szFuncName, BOOLEAN IsRVA)
This function is able to provide the relative virtual address, if IsRVA is set to true; otherwise, it will return the virtual address of the specified function name that is similar to GetProcAddress.
To start building the loader code, Sdropper attempts to locate the address of the shellcode from the dropper’s export table. It also needs to get the size of the shellcode by calculating the delta value between InjectedShellCodeStart and InjectedShellCodeEnd. It then resolves the following API functions, which will be called or used later in the shellcode:
CloseHandle
MapViewOfFile
OpenFileMappingA
CreateThread
SetWindowLong
The resolved API function address and shellcode are copied to the mapped view that was obtained previously. You may notice that it also gets the address of SetWindowLong, so why on earth does it use the Windows GUI API function? We will examine this further later in the article.
Figure 7 shows how the loader code looks at this point.
In order to locate the targeted shared memory address in the explorer.exe address space, Sdropper will explore all the memory regions available in the process using VirtualQueryEx. For each memory region in explorer.exe, it reads the whole memory region as a buffer using ReadProcessMemory, with the memory size obtained from MEMORY_BASIC_INFORMATION.RegionSize. It then finds the shellcode buffer using RtlCompareMemory. Once Sdropper gets the shared memory address in explorer.exe containing the shellcode, it will start building the main component in the loader code.
Figure 8. The same loader code can be found in explorer.exe shared memory and in the malware’s mapped view.
(For a larger version of the image shown in Figure 8 click here.)
One of the questions we asked earlier was: how does Sdropper execute the shellcode with only PAGE_READWRITE level protection? The answer is Return-Oriented Programming (ROP), also known as return-to-libc, which enables the loader to execute the shellcode flawlessly. The malware will create the following ROP gadgets (on x86 architecture):
Gadget 1
std;
retn;
Gadget 2
cld;
retn;
Gadget 3
pop eax;
retn;
Gadget 4
jmp eax;
Gadget 5
mov ecx, 94h;
rep movs [edi], [esi];
pop edi;
xor eax, eax;
pop esi;
pop ebp;
retn 8;
The malware author has also considered the limitations imposed by Address Space Layout Randomization (ASLR) on a potentially infected machine. When ASLR is enabled, a module will have a dynamic image base address when loaded by the operating system. This is a security mechanism designed to make exploit code development more challenging. In order to mitigate ASLR protection, Sdropper uses the following algorithm to look for the ROP gadgets among the common dynamic link libraries (DLL) loaded into explorer.exe:
Uses EnumProcessModules to get a list of module handles loaded in explorer.exe.
Reads 1,024 bytes from the starting address of the module that usually contains the PE structure information.
Makes sure the module is a valid executable by checking the MZ header and PE signature from the structure.
Goes through the section table from the structure and looks for the ‘.text’ section, which normally stores the executable code.
As checking the ‘.text’ string name alone is not enough, it also ensures that the section has the IMAGE_SCN_MEM_EXECUTE attribute, which indicates that the section can be executed as code.
If all the conditions match, it searches for the ROP gadget from the code section and retrieves its virtual address location.
The ROP gadget virtual address is then saved to the loader code.
Figure 9 shows the layout of the incomplete loader code with partial ROP gadgets set up. In the final stage, Sdropper will look for ROP gadget 4 and also hijack a function that will be used to store the shellcode contents. It chooses Ntdll!atan, probably because the function is unlikely to be used by explorer.exe as it will crash the Windows desktop, which may in turn alert the user to the malware’s existence.
Besides the ROP gadgets, Sdropper also saves the necessary parameters for WriteProcessMemory into the shared memory. Since the ROP gadget is a chain of instructions, WriteProcessMemory will be executed in the chain at some point, and will eventually write the shellcode contents to the targeted function address, followed by a return instruction that will transfer execution to the shellcode. We will discuss how the shellcode is executed in the next section.
After the ROP gadgets set-up is completed, Sdropper tries to locate the main payload address, that is, the typical malware routines such as dropping and creating files, adding and modifying registry keys, and downloading and executing additional malware components. This main payload can be found in InjectNormalRoutine, and similarly to InjectedShellcodeStart, it can be retrieved from one of the exported functions stored in the binary.
Sdropper creates an exclusive file mapping object (to store the contents of the original executable) using the object name obtained from the registry key HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Cryptography and the first 10 characters from the data stored in MachineGuid. Keep in mind that the malware will open and retrieve the same exclusive file mapping object in order to get the address of InjectNormalRoutine. This will be covered in the last section of this article.
The malware also gets and stores the original handle value of a specified Windows class object and the return value of DWL_MSGRESULT by calling the FindWindow and GetLongWindow APIs, respectively. The similar Windows GUI API functions, SetWindowLong and SendNotifyMessage, will be used in order to start the loader.
This technique is very similar to the known Windows shatter attack, which replaces the look-up table with a custom look-up table containing shellcode, as we mentioned at the beginning of this article. The malware also does a similar thing by replacing the look-up table returned by GetLongWindow with its own table containing a pointer to the loader code generated earlier.
This vulnerability is believed to be a design flaw in Windows messaging; however, a detailed description of the flaw is outside the scope of this article. Nevertheless, this is an interesting approach compared with the conventional code injection method. In the next section, we will cover how Sdropper manages to execute the shellcode located in the shared memory.
Figure 12. Routine that triggers the loader code using a similar approach to the Windows shatter attack.
(For a larger version of the image shown in Figure 12 click here.)
The final loader is ready to be executed via SetWindowLong.
When the Windows messaging API has successfully been exploited, explorer.exe will first execute the following ROP gadget instructions from the loader in sequence:
Gadget 1:
ntdll!RtlQueryAtomInAtomTable+0x110: 7c92c104 fd std 7c92c105 c3 ret
Gadget 5:
SHELL32!CFileSysBindData::GetFindData+0x10: 7c9ee84e b994000000 mov ecx,94h 7c9ee853 f3a5 rep movs dword ptr es:[edi],dword ptr [esi] 7c9ee855 5f pop edi 7c9ee856 33c0 xor eax,eax 7c9ee858 5e pop esi 7c9ee859 5d pop ebp 7c9ee85a c20800 ret 8
Gadget 2:
Explorer!CTray::_MigrateOldBrowserSettings+0xd5: 0101c2b0 fc cld 0101c2b1 c3 ret
The first gadget will set the Direction Flag (DF) of the flags register so that the data will be copied into the stack in a backwards direction. After the copy operation is completed, it will reset the DF flag. This activity can be illustrated with the following diagram:
Now the stack contains the return-oriented payload. The next thing it needs to do is to perform a stack pivot through a sequence of ‘xchg eax, esp; retn;’ instructions. The stack pivot can be found in the Ntdll!_chkstk:
ntdll!_chkstk: 001b:7c901a09 3d00100000 cmp eax,1000h 001b:7c901a0e 730e jae ntdll!_alloca_probe+0x15 (7c901a1e) 001b:7c901a10 f7d8 neg eax 001b:7c901a12 03c4 add eax,esp 001b:7c901a14 83c004 add eax,4 001b:7c901a17 8500 test dword ptr [eax],eax 001b:7c901a19 94 xchg eax,esp 001b:7c901a1a 8b00 mov eax,dword ptr [eax] 001b:7c901a1c 50 push eax 001b:7c901a1d c3 ret
This routine will adjust the stack pointer to point to the stack frame that consists of arguments required by WriteProcessMemory. This function will be executed immediately upon returning from Ntdll!_chkstk. As described earlier, the main goal for the WriteProcessMemory API call is to hijack the content in Ntdll!atan with Sdropper’s shellcode. The malware has successfully bypassed DEP when the shellcode is injected into Ntdll!atan. It will then execute the last couple of gadgets in order to pass control to the hijacked function:
Gadget 3:
Explorer!SpecialFolderList::ReadIconSize+0x2: 01013874 58 pop eax 01013875 c3 ret
Gadget 4:
Explorer!DefSubclassProc+0x27: 01002240 ffe0 jmp eax {ntdll!atan (7c901d75)}
The diagram in Figure 15 clarifies the whole roadmap of shellcode execution.
(For a larger version of the image shown in Figure 15 click here.)
Finally, we reach the shellcode. Although it does not do anything fancy like the return-oriented payload, it is an important entry point for Sdropper to achieve its goal. It first tries to open the existing malware-specific file mapping object, which as mentioned earlier, is needed to obtain the malware’s main payload. After the main payload routine has been determined, the malware passes it as a thread routine to the CreateThread API, so that the main payload is run in the process context of explorer.exe.
(For a larger version of the image shown in Figure 16 click here.)
There are a couple of tasks that Sdropper performs once the main payload is executed in the process context of explorer.exe:
It creates a mutex name, unique to every machine, based on the registry key HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Cryptography\MachineGuid. The MachineGuid data is used to form the malware’s infection marker:
Infection_Marker: {MachineGuid}gfdgfdgdfg
If no MachineGuid is found on the infected machine, it will form the following infection marker instead:
Infection_Marker: {MachineGuid}fgfdggfd
The mutex name is then combined with the infection marker, as well as the hexadecimal value of the process ID of explorer.exe:
Mutex name: Global\{Infection_Marker}{HexVal_Explorer_Pid} Example: Global\ebb80e80-143c-4014-8ca5-6b5a7894ec2agfdgfdgdfg708
The malware will also store the infection marker to the registry key, and will use the infection marker generated above to form a global infection marker:
Global_Infection_Marker: {AlphaCharacterOnlyFromMachineGuid}gfdgfdgdfg Example: ebbeccabaecagfdgfdgdfg
After the global infection marker has been determined, it will save it to the following registry key:
Key: HKEY_CURRENT_USER\Software\{GlobalInfectionMarker} Value: CurrentPath Data: Data: %COMMONAPPDATA%\{GlobalInfectcionMarker}.exe
It creates and drops a copy of itself to %COMMONAPPDATA%, using the global infection marker as the filename.
%COMMONAPPDATA%\{GlobalInfectionMarker}.exe Example: C:\Documents and Settings\All Users\Application Data\ebbeccabaecagfdgfdgdfg.exe
It then creates a start-up registry key pointing to the file %COMMONAPPDATA%\{GlobalInfectionMarker}.exe to ensure that Sdropper will survive after the system restarts:
Key: HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Run Value: {GlobalInfectionMarker} Data: Data: %COMMONAPPDATA%\{GlobalInfectcionMarker}.exe
It also determines whether it is running in the context of explorer.exe. If it is, it attempts to create two persistent threads running in explorer.exe. One of the threads is a simple protection mechanism, responsible for monitoring and protecting the dropped executable in %COMMONAPPDATA%\{GlobalInfectionMarker}.exe and its start-up registry key from being removed from the infected machine.
The other thread is responsible for establishing a connection between the malware and the C&C server. Sdropper (at this point, the client backdoor program) starts sending requests to the C&C server in order to retrieve additional commands from the attacker for execution. The botnet client will send a request to the C&C server at 10-minute intervals.
The C&C configuration information can be found in the ‘.cfg’ section of the malware binary’s sections:
The first DWORD value from this section represents the offset value to the embedded MZ, while the next DWORD value represents the size of the embedded binary file. This malware supports x64 architecture, and this embedded binary is compiled specifically for machines running on the x64 platform.
The configuration file will be saved as %COMMONAPPDATA%\{GlobalInfectionMarker}.cfg. It is locked for exclusive access by the malware, via the Windows LockFileEx API function.
The malware uses the same custom RC4 algorithm encryption scheme for the configuration file on disk and the data sent to the C&C server. The RC4 encryption/decryption key can be either:
The hostname of the C&C server, if the data is going to be sent to the remote server.
The infection marker, if the data is going to be stored on the disk.
The diagram in Figure 18 shows a few lines of code to clarify the custom RC4 algorithm (reversed from the binary):
It also performs an inline hook to the function NtResumeThread/ZwResumeThread found in explorer.exe. This results in code injection into a newly created process; however, it only targets the following processes:
explorer.exe
iexplorer.exe
firefox.exe
mozilla.exe
Inside the hook function, it will determine whether there is an associated thread handle from the newly created process. If there isn’t, it will call either the CreateRemoteThread (x86) API or RtlCreateuserThread (x64) API, with the handle of the process to execute the thread routine InjectNormalRoutine (i.e. the malware’s main payload). Otherwise, it will call the NtQueueApcThread (both x86/x64) API with the handle of the thread to start another thread routine, InjectApcRoutine. Both these routines perform a similar operation.
This is probably the first malware that takes advantage of the Windows messages flaw to perform code injection. By injecting code using this vulnerability, the malware is able to evade HIPS-based detection. This is why the author has designed the malware to execute its typical malware routines only after the flaw has successfully been exploited. However, Sdropper does unintentionally leave traces during the initial execution that can easily be used to detect the malware’s presence before it causes further havoc on the machine. Regardless of whether or not the vulnerability exploitation fails (or if the vulnerability has been patched on the machine), the malware also has an alternative approach to perform code injection by using a traditional code injection method; fortunately, this approach is not complicated and will cause an anti-virus product to issue an alert, leaving the malware nowhere to hide.
[1] Win32 Shatter Attacks. http://www.blackhat.com/presentations/bh-usa-04/bh-us-04-moore/bh-us-04-moore-up.ppt.
[2] Shattering by Example. http://www.blackhat.com/presentations/bh-usa-04/bh-us-04-moore/bh-us-04-moore-whitepaper.pdf.
[3] Dynamic Forking of Win32 EXE. http://www.security.org.sg/code/loadexe.html.
[5] Managing Memory Sections. http://msdn.microsoft.com/en-us/library/windows/hardware/ff554392(v=vs.85).aspx.