Friday, 17 July 2015

Kovter analysis [part 1]


Fileless malware has been gaining increased attention in the malware forensics community as of late. Accordingly, I have been paying particular attention to indicators and forensic analysis of threats such as Poweliks. These malware variants typically leverage the Windows registry to maintain persistence, and they avoid leaving executable files on disk.  I recently had an encounter with one such malware family - Kovter.

Kovter was originally discovered as a particularly nasty type of ransomware, but has recently been adapted to instead cash in via ad/click fraud.

In the sections below I will walk through some basic static analysis of one such sample.  Additional analysis of later stages of this malware will follow in another writeup.

In case you want to follow along, the sample being analysed in this discussion is: 6ca41538ae9c25b259e6fcfce565b89b (many thanks to Kafeine for the sample).

Initial Infection

Upon execution of the initial infector, several checks are performed to look for security tools such as Fiddler and Wireshark, as well as for standard indicators of virtual environments (registry keys common to VirtualBox, Sandboxie, and VMware). If none are found, the malware proceeds to create a random looking registry key (using hex chars) under HKCU\Software and HKLM\Software.  Within this parent key are six values which are also named using apparently random hex characters. These registry values and their parent key appear to be named in a deterministic manner, likely generated on characteristics of the victim system (such as product id, guid, etc).  One of these registry values contains obfuscated javascript which ultimately unpacks and executes shellcode.  This shellcode is responsible for decrypting the data stored in a second registry value and executing it.  Interestingly, the encryption key for this activity appears to be generated uniquely upon execution of the initial infection binary.

Fileless Persistence

After initial infection, the run key shown below in Figure 1 will be present.

Figure 1: Run key

This run key makes use of the mshta.exe application to execute a few simple javascript commands. Deobfuscated, this became (in the case under examination):
y=new ActiveXObject("WScript.Shell"); 

*Note that this particular malware will write to both HKLM and HKCU if it is able.  The content written is identical in either case.

 Taking a look at the HKCU\Software\2efd7e07 key revealed the following:

Figure  2: HKCU\Software\2efd7e07 key content
The run key ultimately ran a javascript eval() command on the contents of registry value 7b5fa1aa. A closer look at this particular value revealed the block shown in Figure 3:

Figure 3: Obfuscated javascript block
Some quick JSDetox'ing and variable renaming yielded the following:

Figure 4: Deobfuscated javascript
The content of the encodedBlock variable was snipped to aid in readability; and the ultimate goal of this javascript code is to xor decode the content of this variable.  The last stage is to eval() it, and the actual decoded version of encodedBlock looks like this:

Figure 5: Script to execute
Again I have truncated some content to ease reading.  In this case there is a large base64 block which is being converted and then executed via powershell.exe. Naturally this base64 decoded text is just a powershell script. Figure 6 below depicts the version I cleaned up to a readable state.

Figure 6: Powershell script to launch shellcode
Variable $sc32 in the powershell script contains (unsurprisingly) shellcode to be executed from memory. The method of invocation follows a pretty standard execution flow including calls to VirtualAlloc using PAGE_READWRITE_EXECUTE permission and then CreateThread invoking the shellcode as a function from a (now) executable memory page.  Note also that it passes the memory address of the shellcode to itself as a parameter.

Shellcode Analysis


Once the shellcode is loaded, the overall actions are pretty standard, with a couple of interesting exceptions.

Overall steps:
  1. Locate Kernel32.dll using hashing on the BaseDLLName member of the InMemoryOrderModuleList for the current process thread.
  2. Locate the offsets for LoadLibraryA, GetProcAddress, VirtualAlloc, and ExitProcess via ordinal lookups
  3. Load advapi32.dll and then do an ordinal lookup for RegOpenKeyExA, RegQueryValueExA
Things get interesting at this point. With each execution of the initial infector, a unique registry key name is chosen to store the various values shown above in figure 2. In the excerpt below you can see that the shellcode we have extracted (from the $sc32 variable in Figure 6) is actually referencing a location at offset 0xAD8 from its base address, and this location holds a string equal to the name of the registry key it was ultimately being stored in:

Figure 7: Loading the string variable matching the registry key
This suggests that the shellcode is modified during initial infection to correctly reference the registry values it will eventually be stored in.

Figure 8: Reference to randomly generated key
Before continuing from step 3 above, we have to locate a particular (also randomly named) registry value located within this key, and this one is also explicitly named within the shellcode:

Figure 9: Registry value which contains next stage, encrypted shellcode
  1. Load the content of this registry key (HKCU\Software\2efd7e07\fecae03a in our example) into memory.  
Again, we find more evidence that the shellcode has been patched during initial infection, as this registry data is actually an RC4 encrypted executable. The length of the RC4 key, as well as the key itself are pulled directly from the shellcode, and these values are unique for each execution of the initial infector*:

Figure 10: RC4 key length

Figure 11: RC4 key

This key is then copied (using an included 'memcpy' function) to a local variable for later use:

Figure 12: copy RC4 key to local variable
Continuing on, we see the shellcode decrypt the data from the fecae03a registry value and unpack it for execution.  To round out the shellcode execution steps:
  1. Decrypt the executable and perform required memory mapping (headers, copying sections to correct addresses, apply any relocs, etc.)
  2. Call the newly mapped file.
In a follow-up post I will walk through analysis of the running payload. Until then, feel free to contact me with any questions or comments.

* Note: not only do the encryption key and length change each time the initial infector is run, but if the registry key is deleted, a watchdog process reinserts the values immediately - and each time the data is reinserted, the encryption key is modified.