This blog gives a brief description of Winnti, a malware well known for attacking german DAX companies, an introduction on how it works, other methods of how to detect Winnti and my own solution using Tycho and YARA. The script can detect Winnti injected code in a process by exploiting the malware’s behavior. The Winnti detector script is the fundament of the Winnti detective script, which will be used to extract the configuration data of the Winnti malware sample. The configuration data holds valuable information about the company that has been targeted by the sample discovered by the Winnti detector.
Winnti is injecting its code into an instance of
svchost.exe. This means by dumping the virtual memory of
each process and checking it with the specific YARA
rule one can detect if Winnti is active on the target PC.
Fortunately, dumping virtual memory of a process is really easy and
convenient with Tycho and the following will show you
how it’s done.
What Is Winnti?
The malware of the Winnti group is a remote access trojan, which is commonly called Winnti and has been around since 2009. They have successfully attacked a lot of german DAX companies, including BASF and Siemens, but are not limiting their attacks to german companies. The malware consists of two components, the trojan itself, which I will continue to call worker component, and a driver to hide its communication with C&C servers. The group fitted their trojan to the respective victims which means that there are a lot of different samples around. Because the malware would be deployed by the group themselves and therefore from a specific server, this is how a sample knows what C&C server to connect to or where in the web to find it. From an analyst point of view, who tries to run a sample this would mean that the malware would never be able to connect to C&C servers of the Winnti group as it has not been deployed from a C&C server of the group but rather from the command line of the infected PC.
How Does It Work
The malware is deployed via a
.dll and injects its code
into an instance of
svchost.exe. Most of the time Winnti
chooses the service host process that is called with arguments
-k netsvcs. This information helped me lowering the
detection times by a great margin.
The driver component checks if incoming TCP traffic starts with a
magic number. In early versions of Winnti, preferred were ports 53, 80
and 443 and the magic number was
0xdeadface but they
switched to encrypted magic numbers to improve the ability to conceal
the malware. Initially these ports (DNS, HTTP and HTTPS respectively)
were chosen as there is usually a lot of traffic on these ports,
i.e. the group hoped their malicious traffic wouldn’t surface as
If a packet with the specific magic number was found, the data is
passed to the worker component which would, in a real environment, hail
its C&C server and start to download plugins, e.g. for remote
access. This was not possible for the worker as it was deployed by me
rundll32.exe on the target PC and therefore Winnti did
not have the crucial information where its C&C servers are. But
having a live connection to C&C servers was not needed to detect the
malware with this approach.
Existing Detection Methods and Their Downsides
One way to detect Winnti is to simulate the communication to C&C servers. This has been done already with the help of an nmap script. Although the script is only able to simulate the initial handshake, it is able to trick Winnti into answering and also into sharing core information.
Though as the github repository mentions, not all samples use the same encryption key to communicate. It does allow to specify a custom key but this still means that a negative result from the script never really tells the analyst that there is no instance of Winnti running on the scanned PC as it is possible that an entirely new encryption key has been used.
Tycho Winnti Detector - Using YARA Rules on VAD Entries
As stated before, I am combining Tycho and YARA. Tycho is used to enumerate processes, dump the process’s memory, VAD (virtual address descriptor) nodes (for more information on VAD trees and nodes click here) to be more precise without ever leaving traces on the target system. And with the help of YARA, this data is scanned for malicious Winnti code by having the script load a YARA rule, which then tries to match the respective patterns to the passed data.
Tycho is especially well suited for malware analysis. This is because running the Cyberus Secure Platform on the target PC only virtualizes the CPU and therefore the system looks completely untouched and no debugger artifacts are left behind. As a result, an analyst is able to test malware in an laboratory environment to which he can connect either via GDB or the Python interface making it useful for many tools or workflows. Because the actual analysis happens on the analyst PC, almost no traces are left on the target PC and the analyst has the whole rich set of tools to his disposal.
For this approach I used the Python interface as it offers the opportunity to use loads of well-known libraries - like YARA for example.
YARA is a pattern matching tool that is mostly used to detect malware or even identify specific samples. It can be used with running processes or, as in this case, on offline data by matching rule or signature, defined by the malware analyst, to textual or binary data. The rule is a singular file, which has a syntax that resembles C code.
Adjusting for different Winnti samples is as easy as passing a YARA signature that is known to match the sample one is looking for. I have created my own YARA signature for the sample I’ve been testing this Detector with.
Winnti Detector Script
At first the
winnti_detector.py script scans the target
PC for instances of
svchost.exe and sorts them so that
processes with IDs between 900 and 999 come first. This is because, as
stated before, the samples I inspected preferably injected their code
into the svchost instance with arguments
-k netsvcs and in
all tests I ran, this instance had a PID in this range.
This list of svchost PIDs is then checked one after the other. This is done so that more promising processes are checked first to lower detection time. The processes are also halted to ensure the virtual memory remains consistent while it’s being dumped. The virtual memory of a process consists of the VAD tree, which consists of VAD nodes. Winnti can not inject code in VAD nodes that are loaded from DLLs, therefore excluding these nodes lowers the time needed for scanning by a lot. This is shown in the first code snippet.
As shown in the second code snippet, for every process, all VAD nodes
are dumped and scanned using YARA’s
.match() function. This is done until either a node is
positively matched or all nodes have been checked with negative results.
If the latter is the case, the next instance of svchost.exe is chosen in
case there are unchecked instances left.
def is_proc_infected(service, pid): with service.open_process_by_pid(pid) as proc: while not proc.is_running(): 0.5) time.sleep( proc.pause()= [o for o in proc.get_vad_list() if not vad_list ".dll")] o.filename.endswith(return any(is_node_infected(vad_node, proc) for vad_node in vad_list)
def dump_vad_node_mem(proc, start_vpn, end_vpn): = (start_vpn * 4096) start_offset = ((end_vpn + 1) * 4096) end_offset = end_offset - start_offset amount_of_bytes = proc.read_linear(start_offset, amount_of_bytes) vad_node_memory return vad_node_memory def is_node_infected(vad_node, proc): = dump_vad_node_mem(proc, vad_node.start_vpn, vad_node_memory vad_node.end_vpn)return rules.match(data=vad_node_memory)
As you can see, making use of Tycho’s built in
read_linear(), dumping the virtual memory is very
intuitive once the list of VAD nodes is formed.
The Winnti detector script is an easy way to reliably detect Winnti within minutes and fitting it for new or different versions of the malware is straight forward as all that has to be done is to update the YARA rule in the repository. The downside would be that a user has to be running the hypervisor - for more information on a Tycho setup click here. This downside is very minor though since running the hypervisor is as simple as rebooting the target PC from a specifically configured USB stick. This will boot the hypervisor first and the usual system right afterwards so that one could immediately start debugging via Tycho from a connected analyst PC.
It would also be feasible to simply always be running Cyberus Secure Platform as it has next to no impact on the actual host system. This means by always using the Cyberus Secure Platform, an analyst gains the ability to use Tycho to constantly and consistently monitor a target machine, dump its memory or as explained in this blog scan it for malicious software.
The nmap script on the other hand can be used completely remotely and it’s quite fast to be honest. It does require the user to disable the Firewall of the target PC for the time being though and, depending on the sample that might have infected the target PC, the standard encryption key the script uses could be inapplicable. This would result in a false negative outcome.
Prospect - The Tycho Winnti Detective
The Winnti group is adapting Winnti for every victim as stated before and by doing this, they specced the samples with specific configuration files. And what’s interesting with this is, that the config holds information about the victim like the companies name, very often. Extracting the config is therefore extremely attractive and since the detector is able to determine the infected svchost it should be possible to track down the config in the machines physical memory.
On the other hand, this detector can actually be used as something like an anti-virus program. It had the capability to dump process memory and applies YARA signatures, which means that by scanning the right processes with the respective signatures, any malware can be identified. The analyst only has to set the correct signature and know which process is probably infected, although checking all processes would be possible as well - it would be a lot slower than knowing what process to scan though.