Kovter is a click-fraud malware famous from the unconventional tricks used for persistence. It hides malicious modules in PowerShell scripts as well as in registry keys to make detection and analysis difficult. In this post we will take a deep dive into the techniques used by it's latest samples to see all the elements and how they cooperate together.
- 49a748e9f2d98ba92b5af8f680bef7f2 - original executable
- 78c622b295114aa0004b2a8cba8df371 - original executable
Behavioral analysisAuthors of Kovter put a lot of effort in making their malware stealth and hard to detect. During the initial assessment of some of the Kovter samples we could notice that it is signed by valid Comodo certificate (it got revoked later):
After the sample gets deployed, Kovter runs PowerShell and install itself in the system
Observing it via Process Explorer we can find the command passed to PowerShell. It's purpose is to execute a code stored in an environment variable (names are random, new on each run), i.e:
Content of the variable is a base64 encoded PowerShell script:
After that initialization phase, we can see PowerShell deploying regsrv32.exe (via which Kovter runs it's modules):
Examining the network activity we can notice many new connections with the regsrv32.exe that are appearing and disappearing:
We can expect that it is related with the click-fraud activity, performed by the malware.
UnpackingKovter comes packed by a crypter/FUD. After unpacking it we get the loader that is another PE file. It comes with a binary data in the resources:
Content of the resource is a next PE file, encrypted and compressed with aPLib (we can easily recognize the algorithm by the typical way in which it modified MZ header):
During the execution, this unpacked PE file is loaded into an newly allocated, continuous area in the memory (without dividing content into sections). The original (host) sample loads all the necessary DLLs and applies relocations on the new module. Then, the execution is redirected there (see below):
Payload's Entry Point:
This executable turns out to be a final stage, containing the core malicious functions. Looking at it's strings (that are not obfuscated) we can find that this is the module responsible for further steps of infection - writing the registry keys, dropping malicious scripts etc. The easiest way to proceed with the analysis would be to dump the payload and analyze it as a separate entity. However, authors of the malware added some tricks in order to prevent this executable from running independently. When we dump the unpacked payload and try to run it, it will crash:
Analyzing the point of crashing, we can see the reason - trying to read unaccessible memory:
As we can see in the above code, sample reads it's own headers and find the end of the mapped module (ImageBase + VirtualSize). Then it tries to read from the address that is exactly after it. In case if the sample was loaded via the host application, this address is accessible and the content is filled with appropriate value - see the example below:
The read value points to the address where some content has been written - including the path to the current sample:
However, it doesn't work if the sample was executed independently. That's why we encounter the crash. Anyways, the dump can be very useful for the static analysis.
PersistenceKovter achieves persistence by adding a Run key in the Windows Registry. Access to this key via regedit is restricted:
But using Sysinternals‘s tool – autoruns still we can see where it leads:
It refers to the link that leads to a batch script, running a dropped file of an unknown format:
This file with the extension .d7e6b has unreadable content and it doesn't make much sense until we notice how it is opened. Kovter's executable, during the installation process, registered in the Windows Registry a special way to run this type of files.
Added extension .d7e6b is handled by a newly defined command df01:
That command is defined in another registry key (...\df01\shell\open\command):
Content of the script:
jATFuw4="wQfAd"; ZF3=new ActiveXObject("WScript.Shell"); XZs6HOl="uE6"; gdV5K2=ZF3.RegRead("HKCU\\software\\nsem\\tnxm"); a0ZRS="gBz"; eval(gdV5K2); CcsujQ6="N61cuVbU";It refers to other dropped registry keys, saved under a different path (names are different for different samples - in the current sample it is: "HKCU\software\nsem"):
Inside the variable tnxm another obfuscated script is embedded:
The script contains simple obfuscation - variables have meaningless names and some unused strings are added in between to create a noise. After renaming variables and removing junk the same code looks much more readable:
The hex_string contains hexadecimal representation of an encrypted code. It is processed by the following two loops. First loop converts it from the text representation into a binary. Second one - performs XOR decryption (the XOR key is random, generated newly on each run). Then, the result is executed by eval function.
Decrypted content: https://gist.github.com/hasherezade/184b23a2a98831061fc4b18473078542#file-txnm_deobfuscated_decoded2-ps1 The base64 content is the same like the one we encountered during behavioral analysis - (it was set in in the environment variable).
After decoding it turns out to be a PowerShell Script:
It's role is to load and execute the code hidden in the variable $sc32. It contains position-independent 32bit code (it will be referred as a shellcode). Content is loaded to the newly allocated memory page and executed in a new thread. Pointer to the allocated memory is passed to the thread as a parameter (it is very important, because this address is further used for resolving pointers to variables).
Below you can see the beginning of this code, converted to binary:
Every shellcode must be self-sufficient in loading all the required imports. For this purpose, this one uses a trick known from from ReflectiveLoader and shellcodes generated by Metasploit platform. At the beginning of the execution it tries to get the handle of kernel32.dll. To achieve this goal, it enumerates all the loaded modules, calculates checksums of their names and compares them with the hardcoded checksum (0x6A4ABC5B). Similarly, it uses checksums to get handles to the functions inside the kernel32.dll.
With their help, it loads other necessary modules and functions, i.e advapi32.dll:
Then, uses them to open registry keys dropped during installation.
In the analyzed samples the read registry paths are appropriately:
- sample#1: HKCU\software\nsem -> zorsuhg
- sample #2: HKCU\software\wuuu -> vfkhxfak
Note, that if you try to export this key, it will appear very shot, because it's preview will be cut on the first zero byte - it's not the full length! Example:
The value that was stored in the registry is read into the memory and decrypted (also in this case, the encryption key is random, newly generated on each run of the installer):
It turns out to be a PE file (the same payload that was loaded before - by the loader executable):
Just like at the first execution, all the dependencies of the payload are resolved by the external loader (this time it is inside the shellcode). Then, execution is redirected there:
That's how the original module has been redeployed. Now, Kovter can continue with it's mission.
ConclusionThanks to the techniques employed by Kovter, no executable needs to be dropped on the disk - that's why is known as "fileless". Even the file to which the initial link leaded does not contain any code to be executed. Instead, it is used just for the flow obfuscation. Running it, in reality leads to running the code stored in the registry, that is sufficient to unpack and re-run the real payload.
Persistence used by this malware is creatively designed and exceptional in comparison to most of the malware. Not only it is scattered into several layers, but also obfuscated at every stage and containing tricks that slow down the analysis process.
Summary of the elements used for the persistenceKovter's persistence is composed of various tiny elements that executes each other, sometimes in an indirect way, like:
- Run key in the registry
- batch script running the file with a new extension
- PowerShell script with Base64
- PowerShell script decoding and running the shellcode
- shellcode reading the dropped registry key, unpacking the PE file from it and loading it in the memory
This was a guest post written by Hasherezade, an independent researcher and programmer with a strong interest in InfoSec. She loves going in details about malware and sharing threat information with the community. Check her out on Twitter @hasherezade and her personal blog: https://hshrzd.wordpress.com.