Taking this into account, we first tried to locate the execution of different exploits in the equipment’s GUI. Some crash of the /bin/sslvpnd process helps to identify a few, but as explained in the article (and tested), the vulnerability can be exploited without crashing the /bin/sslvpnd process.
In order to obtain interesting traces, two approaches were used:
1) Use of the exploit to take control of the equipment in order to collect system evidence and RAM:
This step will not be detailed here. However, it is important to note that the exploitation of the CVE allows the entire device to be compromised, without leaving any trace on the disk, and allows the attacker to modify any evidence if he wishes. Likewise, we will not go into the various ways of setting up persistence.
2) Use of the equipment command line interpreter:
We tried that way because it fits with our test environment, you may access these logs in a different way.
# Set up the logs on your prompt
CLI > diagnose debug enable
# Set up the configuration
diagnose debug application sslvpn 0xflag_you_want_in_hexa
The configurations set up to identify the first traces of CVE execution are the following
It has to be noted that we found evidence of the execution on both configurations. Thus, the Log level at « Debug » (0x00000080) may not be necessary to detect the exploit.
Short analysis
Below is an extract of the executions that can be found on the test environment with the 2nd collection approach.
This summary is not an exhaustive analysis, but it does highlight a few patterns.
32-bit environment
The 1st step which appears is the step to obtain the salt. As explained in the blog, salt is a random value created by the server, which can be retrieved by issuing a GET request to /remote/info.
The second request that appears /remote/hostcheck_validate corresponds to the set up of the heap.
At the very beginning of the following capture, we noticed the /remote/error request, which is a way found to force the reallocation of the buffer for the HTTP response, in order for « out » to take its place in the heap. « out » is then allocated on the top of the SSL structure.
Next, the following requests are related to the « xorverflow » which rewrites the SSL structure. It is important to note that, depending on the payload used, the volume of these requests may vary in the logs. This means that depending on the opponent you are looking for, the behavior can vary in the logs:
Standard threat actor: For overflow to be optimal and functional, these requests need to be sent at extremely short intervals. The timing of these requests is therefore more important than their volume (from a forensics/detection perspective).
Advanced Threat Actor: If the heap is set up correctly, there is no need to send successive requests. The rewriting of the SSL structure can be perfectly spaced out over time.
One step that is specific to the CVE-2023-27997 exploitation on 32bit is the queries that are made to the web page that echoes back some inputs. It is these requests that we found in the last section of the screen.
The URL is not described here (as in the original blog), but it should be noted that different approaches (or URL requested) may work.
64-bit environment
The 64-bit environment broadly follows the same logic when we look only at the existing traces. First, the salt is retrieved and the /remote/saml/logout that appears after corresponds to the set up of the heap.
As expected, a rewriting of the SSL structure follows with a lot of requests for this payload (364 requests).
Note: I would like to emphasize once again the existence of certain payloads that could, for example, be successful with just 5 requests. Here, the sequence of requests is therefore the point to pay attention to, not the number of requests.
We also noted the presence of the « enc » variable in the request /remote/hostcheck_validate?enc=value, which is targeted in this vulnerability. However, this value is truncated. The hexadecimal value displayed corresponds to the value of the seed. The seed value generally starts with « 0x00 » and must be 8 hexadecimal character long. No trace of payloads has been identified with this approach.
The « enc » variable is encrypted with a keystream generated from a constant, a value provided by the server (the salt, which changes at runtime), and a value provided by the attacker (the seed). As a result, you cannot always « decrypt » the payload, as if the main sslvpnd process had crashed, the salt would have changed.
Conclusion
In addition to the « blue teamers » elements mentioned in the original blog, it is possible to identify the execution of the CVE-2023-27997 in our test environment. From a defensive point of view, the first thing to remember is to apply the editor’s patch.
If you need to carry out a forensic analysis, in the hope that the integrity of evidence has been preserved, we advise the following:
Do not rely solely on the application crash of the /bin/sslvpnd process;
Take an interest in the sequencing of the requests used in the logs;
Question the presence of /remote/logincheck and /remote/hostcheck_validate requests;
Investigate the presence of HTTP requests containing the variable « enc » and do not forget the possibility for the attacker to use the POST request;
And most importantly, stay proactive in monitoring the news concerning the investigation of this CVE. This leaflet may be incomplete. Additions and adjustments will be made as real cases come to light.
We’ll describe here the bug and the exploitation process on two architectures, along with a few pointers for blue teamers.
The bug
The bug is located on the web interface that allows users to authenticate to the VPN. This interface is, by design, internet-facing. If we hit the path /remote/hostcheck_validate, we can send an HTTP parameter named enc, through GET or POST. The parameter, which does not seem to be much used now, seems to be an old way for Fortigate to forward HTTP parameters across requests.
The enc parameter is a structure containing a seed, size (2 bytes) and data. Both size and data are encrypted.
The seed, stored as 8 hexadecimal characters, is used to compute the first state of a XOR keystream:
salt is a random value created by the server, which can be retrieved by issuing a GET request to /remote/info.
The other states of the keystream are computed like so:
The keystream can be xored to the rest of the enc payload, the size and the ciphertext, to decrypt them. It is sent as an hexadecimal string.
The decryption method looks like this (simplified code):
int parse_enc_data(char *in)
{
int in_len = strlen(in);
int given_len;
int xored_given_len;
if(in_len & 1)
{
return 1;
}
compute_key_zero(salt, in, 8, md5); // [1] Computes key from salt, seed
out = alloc_block(*pool, (in_len >> 1) + 1); // [2] Allocate a buffer
unhex(out, in); // [2] Hexa-decode in to out
if (out[0]) // first byte of seed must be 0x00
{
ap_log_rerror((__int64)a1, 8LL, (__int64)"invalid encoding method %d\n", needs_null);
return 1;
}
// [3] Decrypt given length
xored_given_len = *((_WORD *)out + 2);
given_len = (unsigned __int8)(xored_given_len ^ md5[0]);
BYTE1(given_len) = md5[1] ^ HIBYTE(xored_given_len);
if ( inlen - 5 <= given_len ) // [4] Verify bounds
{
ap_log_rerror(a1, 8LL, "invalid enc data length: %d\n", given_len);
return 1LL;
}
// [5] Decrypt: xor every input from byte 6 (4 bytes for seed, 2 bytes for length)
p = &out[6];
if (given_len)
{
int i = 0LL;
while (i < given_len)
{
p[i] ^= md5[(i + 3) % 16];
if ((i + 3) % 16 == 0) // Current state is exhausted: compute new
{
MD5_Init(md5_ctx);
MD5_Update(md5_ctx, md5, 16LL);
MD5_Final(md5, md5_ctx);
}
++i;
}
}
out[6 + given_len] = 0; // [6] Append null byte
add_kvp_to_hashmap(a1->params, out); // [7] Process plaintext
// Allocated buffers get freed at the end of the HTTP exchange
return 0;
}
The function behaves like so:
Compute an MD5 (16 bytes), which is the first state of the key from the salt and the seed (first 8 chars of in)
Allocate a buffer of size in_len / 2 + 1, out, and hexadecimal-decoded input into it
Compute the length given by the user, given_len, by xoring the first two bytes of the payload with the first two of the key
Bound check: verify that the given length is not greater than the size of the buffer
Decrypt the whole string in place: XOR the first 14 bytes, then compute a new state
use it to XOR the 16 next bytes, and repeat.
Put a NULL byte at the end of the decrypted data
Add decrypted values to the hashmap containing HTTP input params
The bug is easy to spot: when the program checks that the given length is not greater than the length of the sent payload, it compares in_len to given_len. But while the former describes the length of the payload in hexadecimal (e.g.'41424343'), the latter describes its size in raw bytes (e.g ‘ABCD’). As a result, given_len can be twice as big as it should be.
This bug allows us to apply the decryption process to not only to the ciphertext in out, but also to the memory that comes after.
This makes for a funny bug: instead of just overwriting bytes in the heap, we get to XOR them with some MD5!
Exploit theory
The bug allows us to allocate a chunk of arbitrary size , out, and then XOR bytes after the buffer with a keystream of MD5 hashes, for which we partially control the key. We control the size of the allocated buffer, and the size of the XOR overflow. In addition, the last byte of the overflow gets nulled.
Hereafter, we name Bi the ith byte in memory, and Ki the ith byte of the keystream. Therefore, triggering the bug with a length of L applies:
We « control » the MD5 hashes because we partially control the bytes used to create the first one:
It’s easy to enforce the value of some bytes of the keystream by bruteforcing with the seed. We can’t, however, hope to control all of it.
First idea
The first thing that comes to mind, is xoring the LSB of some address to change its position. Something like this:
However, this is costly: we need to find an MD5 hash which starts with 306300000000. This hash is the hash of another one, which is the hash of another one, etc. If the distance from the hash to the pointer we want to modify is 0x1000 for instance, this would be the 256th state of the key stream. Not to hard to compute once, but to bruteforce…
Even if we manage to get such a hash, the data previous to this modified pointer would get garbled, because it’d be XORed with previous hashes, whose contents we cannot choose.
jemalloc: some allocator
As it sounded pretty hard to get anything working, we took a look at the underlying allocator, to see if there were any way to leverage the bug.
The underlying heap, jemalloc, was unknown to us at the time. We were in a hurry (understand: I ragequit when trying to make shadow work) and not looking to acquire a deep understanding of it. Here’s what we learned about it:
Heap metadata is stored independently; you can safely overflow from one chunk (region) to another
You can easily get contiguous allocations (after filling holes)
There is some kind of LIFO mechanism on allocations of the same size: freeing a chunk of size and allocating the same size yields the same pointer.
The last point actually makes the exploitation very much easier: we can allocate the buffer we overflow from, out, at the same address, repeatedly.
A powerful primitive
Triggering the bug once makes it look like a bad primitive.
However, since we can consistently allocate the out buffer at the same spot in memory, several times, the primitive becomes very good. Indeed, we know that applying the same XOR twice to a value leaves it unchanged:
If we were to trigger the bug twice, with exactly the same parameters (seed and length), and if the two out buffers were allocated at the same memory address, each byte in the overflow would get XORed twice with the same value. We’d have completely unchanged memory, except for one byte which would be set to NULL. An improvement: a way to set a byte to zero, with no side effects.
Moreover, triggering the bug twice with the same seed, only the first time setting the length of the overflow to , and the second time to, yields even better results.
On the first iteration, we would have completely messed up data until the byte at offset , which would be NULL. On the second iteration, every byte would get xored with the key twice, and thus become its old self again, except for , which would take the value of , as . Byte would become NULL. We’d have:
So, to give byte an arbitrary value , we would have to set byte to , and all other bytes would get their old value xored with twice:
So, to give byte an arbitrary value , we can just compute a keystream such that , and apply the primitive twice, once with length , and once with length .
Here’s an example: we want to set to . We compute a seed such that . This is the 8th byte of the 250th state, so . If for instance the salt is , we can use the seed to get:
We then apply the primitive with length 4999. We get the following:
We apply it a second time, with length 5000:
Improving efficiency
We can actually do better, and overwrite several bytes in a row, with one request per byte! Say we want to write ABC\0 in memory, L bytes after the overflowed buffer. We first compute a seed s0 such that KL+2s0=‘C′.
Then, we compute a seed s1 such that:
Using the primitive 4 times, we managed to write ABC in memory! This technique has, however, a huge let-off, as it messes up everything that comes before the modified memory. For the rest of the blogpost, we’ll stick to the initial technique, which requires 2 requests to set one byte.
Exploit practice
Now that we have a decent primitive, we need to find something to overwrite.
Target of choice: SSL
In 2019, Meh Chang and Orange Tsai exploited a heap overflow on the same binary, and chose to modify a structure named SSL. This kind of structure is allocated whenever a client connects to a worker process of sslvpnd, and gets destroyed when the client or the server closes the socket.
This is a perfect target for us.
First, because our primitive requires us to trigger the bug multiple times, and we need to attack a heap structure that persists accross HTTP requests.
Second, because the structure contains a callback handler, handshake_func. Due to the binary not being PIE, we can modify the value of this function pointer, and force the socket to perform an SSL handshake. From there, a standard stack pivot into whatever gets us a nodejs shell (there’s no sh!).
To setup the heap, we’d need to have an empty chunk right before some SSL structure associated with a socket we control.
Attacking on 64 bits
Our test environment was a VM running on Intel 64 bits. The SSL structure has a size of 0x1db8 bytes, so it is allocated in a 0x2000-byte region.
Right before the allocation of the SSL structure, a buffer of size 0x2000 also gets allocated, in order to store the raw HTTP request sent by the client. With an unfragmented heap, the buffer sits on top the SSL structure in memory. This is where we’d like to have out! Luckily, if a client sends a request which is larger than 0x2000 bytes, the program reallocates the buffer, leaving the region empty. As the allocator is LIFO, and we control the size of out, this makes for a very clean exploit:
Create lots of sockets to the HTTPd service (fills gaps):
SSL structures get created, contiguous to request buffers Send a huge HTTP request on the last socket, to force the buffer to be reallocated:
HTTP request buffer gets reallocated Use another socket to exploit the vulnerability; out gets allocated right where we need it:
out is allocated on top of the SSL structure As the sslvpnd binary is huge, the ROP chain is not too hard to build. It is left as an exercise to the reader.
Note: schemas greatly inspired from this one.
Attacking on 32 bits
We discovered a while later that there were Fortigate builds for 32-bit architectures, such as ARM. Our redteam target was running on such a processor. In 32 bits, the SSL structure is basically half the size as it is in 64 (it is mostly made of pointers), so it gets allocated in regions of size 0x1000. The heap setup aforementioned does not work.
We are, however, extremely lucky: in addition to the 0x2000 buffer, the program allocates a 0x1000 buffer to store… the HTTP response. Which also gets reallocated, when too big. Without too much trouble, we were able to find a web page that echoes back some input, resulting in a 32-bit exploit:
Create lots of sockets to the HTTPd service (fills gaps) Take the last connexion, and a request with a huge POST parameter The parameter gets echoed, forcing the reallocation of the HTTP response buffer Use another socket to exploit the vulnerability: the overflowed buffer gets allocated right were we need it. ROPchain left as an exercice, again.
A few notes for red teamers We’re withholding the notes until a later date.
A few notes for blue teamers We believe that providing as much details as we can on the vulnerability will allow you to better understand and protect against it.
Crash or no crash ? As with all binary exploits, a crash is possible. You might notice in your logs crashes of the /bin/sslvpnd process. However, with proper exploits, you will not detect any.
Indicators The bug is exploitable by issuing GET/POST requests to any of the two URLs: /remote/hostcheck_validate, and /remote/logincheck. Simple exploits will require several HTTP requests in quick succession to any of these URLs. It is however possible to make the exploit slower, by carefully setting up the heap.
Post-exploitation It is possible for the attacker to live exclusively in memory, without modifying anything on the disk. Although reboots might remove in-memory payloads, there are ways to attain persistence on the appliance. The best way to protect yourself is to PATCH.
Demonstration The video shows the first exploit we built, targeting x64:
During our redteam engagements, there are plenty of situations where we get an arbitrary code execution but cannot get a direct shell connection using standard reverse shell tools because of some network filtering. More importantly, we need some network pivot capabilities such as proxies or port forwarding. This led to the development of sshimpanzee a static reverse OpenSSH server which offers tunnelling mechanisms such as DNS or ICMP.
How does it work ?
Build options will not be detailed here as they are documented on sshimpanzee’s README.md. Instead, this article will give insight about how sshimpanzee works.
Building a reverse sshd
sshimpanzee brings a set of patches to OpenSSH’ssshd. Starting from a standard OpenSSH server it is fairly easy to make it « reverse ». This is due to the fact that both accept() and connect() libc calls (and syscalls) return the same type of object: fd. Thus, when initializing the network part in the listen_on_addrs() function, it is possible to remove every call to bind and listen.
The aim here is to provide basic information on the kinds of logs and other artefacts that could be generated from Cobalt Strike on a default Windows 10 host. To get a better context and understanding, we enabled Sysmon on the victim workstation, in order to get a baseline to compare with.
The tests were done with Cobalt Strike version 4.4 with the default configuration, without any kind of customization. It is important to note that Cobalt Strike allows users to change various settings (pipe names, service name, default temporary process, etc.) to customize its footprint. Depending on the Cobalt Strike settings used by the attackers, the events generated may be slightly different and detection rules may fail.
Each command was executed twice to avoid false positives, and the investigations were conducted on one of these two executions. This short analysis can be later on used as a reference to build rules to detect Cobalt Strike movements during a forensics incident response (without Sysmon or Audit Policies).
The Lab is composed of the following elements:
Windows 10 workstations with Sysmon installed,
Windows Server 2016 Domain Controller.
The different steps and tools used to extract and analyze the artefacts post compromise are:
Run DFIR-Orc to extract artefacts on the Windows 10 machine;
Analyze data using Splunk or Kibana (ELK fullstack with custom Logstash configuration).
By using DFIR-Orc and Plaso, we were able to process the most important artefacts:
Event logs (*.evtx), including PowerShell command history;
Prefetch files among other execution evidence;
NTFS artefacts, such as USNjrnl and MFT;
User and System hives (userassist, appcompatcache, etc.).
Findings Summary
A summary of the most important findings (excluding Sysmon events) is available in the timeline below. It should be noted that these events alone do not constitute evidence of the use of a Cobalt Strike beacon, and further analysis, some of which is detailed in this article, needs to be conducted to validate or not the hypothesis of remote code execution. These timelines will be detailed and explained in the following chapters.
[evtx/sec/4624] User ‘CORP.LOCAL\alice’ (S-1-5-21-1155457554-2149841727-2293290625-1108) successfully logon (type=3) from ‘192.168.56.119’ (‘-‘) (logon_id=0x000000000051bce7) with ‘-‘
jump psexec64
13:33:05.803
[evtx/sec/4624] User ‘CORP.LOCAL\alice’ (S-1-5-21-1155457554-2149841727-2293290625-1108) successfully logon (type=3) from ‘192.168.56.119’ (‘-‘) (logon_id=0x000000000051bd0a) with ‘-‘
jump psexec64
13:33:05.829
[evtx/sys/scm/7045] Service ‘4542843’ (\\DESKTOP-RI5FIO5\ADMIN$\4542843.exe) was installed by user ‘LocalSystem’ (type: user mode service, start: demand start)
[evtx/sec/4624] User ‘CORP.LOCAL\alice’ (S-1-5-21-1155457554-2149841727-2293290625-1108) successfully logon (type=3) from ‘-‘ (‘-‘) (logon_id=0x00000000005eb099) with ‘-‘
jump winrm64
13:38:11.614
[fs/usnjrnl] File ¨C10C USN_REASON_FILE_CREATE
jump winrm64
13:38:11.631
[fs/usnjrnl] File ¨C11C USN_REASON_FILE_CREATE
jump winrm64
13:38:11.964
[evtx/powershell/53504] Windows PowerShell has started an IPC listening thread on process ‘9724’ in AppDomain ‘DefaultAppDomain’
jump winrm64
13:38:13.099
[evtx/powershell/400] The PowerShell engine state hosted by application ¨C12C is changed from ‘None’ to ‘Available’.
jump winrm64
13:38:13.705
[evtx/sec/4624] User ‘CORP.LOCAL\alice’ (S-1-5-21-1155457554-2149841727-2293290625-1108) successfully logon (type=3) from ‘-‘ (‘-‘) (logon_id=0x00000000005edc9b) with ‘-‘
jump winrm64
13:38:13.828
[evtx/sec/4624] User ‘CORP.LOCAL\alice’ (S-1-5-21-1155457554-2149841727-2293290625-1108) successfully logon (type=3) from ‘-‘ (‘-‘) (logon_id=0x00000000005edd18) with ‘-‘
jump winrm64
13:38:14.362
[evtx/powershell/4104] The remote PowerShell scriptblock named ‘¨C13C’ is executed (29 blocks)
jump winrm64
13:38:19.168
[evtx/sec/4624] User ‘CORP.LOCAL\alice’ (S-1-5-21-1155457554-2149841727-2293290625-1108) successfully logon (type=3) from ‘192.168.56.119’ (‘-‘) (logon_id=0x00000000005f30a3) with ‘-‘
[evtx/sec/4624] User ‘CORP.LOCAL\alice’ (S-1-5-21-1155457554-2149841727-2293290625-1108) successfully logon (type=3) from ‘192.168.56.119’ (‘-‘) (logon_id=0x00000000008629e3) with ‘-‘
jump psexec_psh
13:45:07.755
[evtx/sys/scm/7045] Service ‘4b3d5bc’ (¨C15C) was installed by user ‘LocalSystem’ (type: user mode service, start: demand start)
[evtx/sec/4624] User ‘CORP.LOCAL\alice’ (S-1-5-21-1155457554-2149841727-2293290625-1108) successfully logon (type=3) from ‘192.168.56.119’ (‘-‘) (logon_id=0x0000000000862fb5) with ‘-‘
The Cobalt Strike jump psexec64 command allows the attacker to use the PsExec utility to execute a command or payload on a remote Windows system. When the jump psexec64 command is executed, it will use the active beacon to establish a connection to the specified Windows system, and then use the PsExec utility to run the malicious payload on the remote system. The command uses the psexec64 executable that is included in the Cobalt Strike package to run the command on x64 architectures. The Beacon type used for this test is smb.
Microsoft-Windows-Sysmon
As explained earlier, System Monitor (Sysmon) was installed on the Windows 10 workstation to have reference events on which to base our analyses. We therefore first reviewed the events recorded by Sysmon to get a baseline to compare with the extracted artefacts. The Sysmon events below have been filtered to keep the most useful ones.
Event ID 1 – Process Create
The process creation event provides extended information about a newly created process. The full command line provides context on the process execution. The ProcessGUID field is a unique value for this process across a domain to make event correlation easier.
By default, Cobalt Strike spawns a temporary process and uses rundll32.exe to inject the malicious code into it and communicate the results back to the beacon using named pipes. We can note that rundll32.exe executes without any arguments, which is very suspicious. The process chain created by the jump psexec64 command on the victim workstation is service.exe -> beacon.exe -> rundll32.exe.
Time
Description
13:33:05.883
[evtx/sysmon/1] Process created with command \\DESKTOP-RI5FIO5\ADMIN$\4542843.exe (pid: 9612) by user ‘NT AUTHORITY\SYSTEM’ via C:\Windows\System32\services.exe (pid: 596)
13:33:06.960
[evtx/sysmon/1] Process created with command C:\Windows\System32\rundll32.exe (pid: 4648) by user ‘NT AUTHORITY\SYSTEM’ via \\DESKTOP-RI5FIO5\ADMIN$\4542843.exe (pid: 9612)
Event ID 3 – Network Connection Detected
The network connection event logs TCP/UDP connections on the machine. Each connection is linked to a process through the ProcessId and ProcessGUID fields. The event also contains the source and destination host names, IP addresses, port numbers and IPv6 status.
In both of our tests, 3 connections using IPv4 are made to the victim. The first one on port 445, the second one on port 135 and the last one to a random port. Then, two IPv6 connections are recorded to port 445.
Time
Description
13:33:06.881
[evtx/sysmon/3] Tcp network connection from host – (192.168.56.119:54055) to host – (192.168.56.117:445) (pid=4)
13:33:06.884
[evtx/sysmon/3] Tcp network connection from host – (192.168.56.119:54056) to host – (192.168.56.117:135) (pid=832)
13:33:06.885
[evtx/sysmon/3] Tcp network connection from host – (192.168.56.119:54057) to host – (192.168.56.117:49692) (pid=596)
13:33:06.885
[evtx/sysmon/3] Tcp network connection from host – (fe80:0:0:0:d4bc:701f:e0a6:897d:49800) to host – (fe80:0:0:0:d4bc:701f:e0a6:897d:445) (pid=4)
13:33:06.885
[evtx/sysmon/3] Tcp network connection from host – (fe80:0:0:0:d4bc:701f:e0a6:897d:49800) to host – (fe80:0:0:0:d4bc:701f:e0a6:897d:445) (pid=4)
Event ID 7 – Image Loaded
The image loaded event logs when a module is loaded in a specific process. It indicates the process in which the module is loaded, hashes and signature information.
The libraries loaded by the beacon are not very fancy. This information will not be useful without Sysmon installed on the victim workstation.
Time
Description
13:33:05.896
[evtx/sysmon/7] Image C:\\Windows\\System32\\ntdll.dll loaded from process \\\\DESKTOP-RI5FIO5\\ADMIN$\\4542843.exe (pid=9612) with user NT AUTHORITY\SYSTEM
13:33:05.897
[evtx/sysmon/7] Image C:\\Windows\\System32\\kernel32.dll loaded from process \\\\DESKTOP-RI5FIO5\\ADMIN$\\4542843.exe (pid=9612) with user NT AUTHORITY\SYSTEM
13:33:05.899
[evtx/sysmon/7] Image C:\\Windows\\System32\\KernelBase.dll loaded from process \\\\DESKTOP-RI5FIO5\\ADMIN$\\4542843.exe (pid=9612) with user NT AUTHORITY\SYSTEM
13:33:05.902
[evtx/sysmon/7] Image C:\\Windows\\System32\\apphelp.dll loaded from process \\\\DESKTOP-RI5FIO5\\ADMIN$\\4542843.exe (pid=9612) with user NT AUTHORITY\SYSTEM
13:33:05.915
[evtx/sysmon/7] Image C:\\Windows\\System32\\advapi32.dll loaded from process ¨C53C (pid=9612) with user NT AUTHORITY\SYSTEM
13:33:05.916
[evtx/sysmon/7] Image ¨C54C loaded from process ¨C55C (pid=9612) with user NT AUTHORITY\SYSTEM
13:33:05.917
[evtx/sysmon/7] Image ¨C56C loaded from process ¨C57C (pid=9612) with user NT AUTHORITY\SYSTEM
13:33:05.918
[evtx/sysmon/7] Image ¨C58C loaded from process ¨C59C (pid=9612) with user NT AUTHORITY\SYSTEM
13:33:05.929
[evtx/sysmon/7] Image ¨C60C loaded from process ¨C61C (pid=9612) with user NT AUTHORITY\SYSTEM
Event ID 11 – File Create
File create operations are logged when a file is created or overwritten. This event is useful for monitoring autostart locations, like the Startup folder, as well as temporary and download directories, which are common places where malware is dropped during an initial infection.
A randomly named Beacon1 was created on the file system to the C:\Windows directory by the System process. The two created Prefetch files related to rundll32.exe and the Beacon will be useful to identify Cobalt Strike execution.
Time
Description
13:33:05.772
[evtx/sysmon/11] Process System (pid=4) created file C:\\Windows\\4542843.exe with user NT AUTHORITY\SYSTEM
13:33:07.009
[evtx/sysmon/11] Process C:\\Windows\\system32\\svchost.exe (pid=1860) created file C:\\Windows\\Prefetch\\4542843.EXE-B39DA9E6.pf with user NT AUTHORITY\SYSTEM
13:33:17.065
[evtx/sysmon/11] Process C:\\Windows\\system32\\svchost.exe (pid=1860) created file C:\\Windows\\Prefetch\\RUNDLL32.EXE-64292FC9.pf with user NT AUTHORITY\SYSTEM
Event ID 13 – Registry Value Set
Registry key and value create and delete operations map to this event type.
Cobalt Strike creates a service to run the Beacon as SYSTEM. So a registry key with a random name2 is created under HKLM\\System\\CurrentControlSet\\Services\\4542843 by the Services.exe executable and the ImagePath is set to the Beacon path.
Time
Description
13:33:05.866
[evtx/sysmon/13] Registry event : user NT AUTHORITY\SYSTEM process C:\\Windows\\system32\\services.exe (pid 596) has SetValue HKLM\\System\\CurrentControlSet\\Services\\4542843\\ObjectName value to LocalSystem
13:33:05.866
[evtx/sysmon/13] Registry event : user NT AUTHORITY\SYSTEM process C:\\Windows\\system32\\services.exe (pid 596) has SetValue HKLM\\System\\CurrentControlSet\\Services\\4542843\\ImagePath value to \DESKTOP-RI5FIO5\ADMIN$\4542843.exe
13:33:05.866
[evtx/sysmon/13] Registry event : user NT AUTHORITY\SYSTEM process C:\\Windows\\system32\\services.exe (pid 596) has SetValue HKLM\\System\\CurrentControlSet\\Services\\4542843\\ErrorControl value to DWORD (0x00000000)
13:33:05.866
[evtx/sysmon/13] Registry event : user NT AUTHORITY\SYSTEM process C:\\Windows\\system32\\services.exe (pid 596) has SetValue HKLM\\System\\CurrentControlSet\\Services\\4542843\\Start value to DWORD (0x00000003)
13:33:05.866
[evtx/sysmon/13] Registry event : user NT AUTHORITY\SYSTEM process C:\\Windows\\system32\\services.exe (pid 596) has SetValue ¨C82C value to DWORD (0x00000010)
13:33:07.941
[evtx/sysmon/13] Registry event : user NT AUTHORITY\SYSTEM process ¨C83C (pid 596) has SetValue ¨C84C value to DWORD (0x00000004)
13:33:07.941
[evtx/sysmon/13] Registry event : user NT AUTHORITY\SYSTEM process ¨C85C (pid 596) has SetValue ¨C86C value to DWORD (0x00000001)
Event ID 17 – Pipe Created
Pipe creation operations map to this event type.
The communication between the Beacon and the temporary process (rundll32.exe) is done using named pipes. By default, on Cobalt Strike, the pipes created by binaries use the following format \\.\pipe\MSSE-####-server. Then, the SMB Beacon creates another pipe for the communication with the C2. The default pipe format is \\msagent_##.
Time
Description
13:33:05.926
[evtx/sysmon/17] Process \\\\DESKTOP-RI5FIO5\\ADMIN$\\4542843.exe (pid=9612) created pipe \\MSSE-2716-server with user NT AUTHORITY\SYSTEM
13:33:06.988
[evtx/sysmon/17] Process C:\\Windows\\System32\\rundll32.exe (pid=4648) created pipe \\msagent_bd with user NT AUTHORITY\SYSTEM
13:33:06.955
[evtx/sysmon/18] Process \\\\DESKTOP-RI5FIO5\\ADMIN$\\4542843.exe (pid=9612) connected pipe \\MSSE-2716-server
13:33:08.961
[evtx/sysmon/18] Process System (pid=4) connected pipe \\msagent_bd
Event ID 25 – Process Tampering
Since Sysmon version 13, a new type of event is recorded, called process tampering. This event is generated when a process uses hiding techniques such as hollow or herpaderp. The injection of Cobalt Strike was successfully detected by Sysmon:
Time
Description
13:33:05.889
[evtx/sysmon/25] Process tampering detected for images \\\\DESKTOP-RI5FIO5\\ADMIN$\\4542843.exe (pid=9612) with user ‘NT AUTHORITY\SYSTEM’
Findings
Now that we have seen the events and other artefacts generated by the execution of the jump psexec64 command, let us dwell on the evidence present natively on a Windows 10 system out of the box.
Winevtx – Microsoft-Windows-Security-Auditing
Without the audit policies enabled, not many events are generated. Only two successful logons (event ID 4624) are recorded, with the logon type ‘3’ (Network), from the compromised account « CORP\alice ». If correlated, this behavior may help during the investigation to support a hypothesis. The source hostnames are not always recorded, nor is the logon process name.
Time
Description
13:33:05.769
[evtx/sec/4624] User ‘CORP.LOCAL\alice’ (S-1-5-21-1155457554-2149841727-2293290625-1108) successfully logon (type=3) from ‘192.168.56.119’ (‘-‘) (logon_id=0x000000000051bce7) with ‘-‘
13:33:05.769
[evtx/sec/4672] Special privileges assigned to ‘CORP\alice’ (S-1-5-21-1155457554-2149841727-2293290625-1108) (logon_id=0x000000000051bce7): SeSecurityPrivilege SeBackupPrivilege SeRestorePrivilege SeTakeOwnershipPrivilege SeDebugPrivilege SeSystemEnvironmentPrivilege SeLoadDriverPrivilege SeImpersonatePrivilege SeDelegateSessionUserImpersonatePrivilege
13:33:05.803
[evtx/sec/4624] User ‘CORP.LOCAL\alice’ (S-1-5-21-1155457554-2149841727-2293290625-1108) successfully logon (type=3) from ‘192.168.56.119’ (‘-‘) (logon_id=0x000000000051bd0a) with ‘-‘
13:33:05.802
[evtx/sec/4672] Special privileges assigned to ‘CORP\alice’ (S-1-5-21-1155457554-2149841727-2293290625-1108) (logon_id=0x000000000051bd0a): SeSecurityPrivilege SeBackupPrivilege SeRestorePrivilege SeTakeOwnershipPrivilege SeDebugPrivilege SeSystemEnvironmentPrivilege SeLoadDriverPrivilege SeImpersonatePrivilege SeDelegateSessionUserImpersonatePrivilege
The two network sessions (logon_type = 3) opened by user « CORP\alice » end a few moments later, just after the remote code execution.
Time
Description
13:34:46.386
[evtx/sec/4634] User logged off ‘CORP\alice’ (S-1-5-21-1155457554-2149841727-2293290625-1108) (logon_id=0x000000000051bd0a) from logon type=3
13:35:06.877
[evtx/sec/4634] User logged off ‘CORP\alice’ (S-1-5-21-1155457554-2149841727-2293290625-1108) (logon_id=0x000000000051bce7) from logon type=3
Winevtx – Service Control Manager
In that particular case, since the jump psexec64 command installs a service on the targeted host, the most useful Windows record is the event ID 7045 logged by the Service Control Manager (SCM). This event indicates that a new, randomly named2 (here 4542843) service has been installed on the system by user « LocalSystem ». The executable used by this malicious service is a strong IOC since it will be remotely accessed using the $ADMIN share. The service terminated unexpectedly a few moments later.
Time
Description
13:33:05.829
[evtx/sys/scm/7045] Service ‘4542843’ (\\DESKTOP-RI5FIO5\ADMIN$\4542843.exe) was installed by user ‘LocalSystem’ (type: user mode service, start: demand start)
13:33:07.000
[evtx/sys/scm/7034] Service ‘4542843’ terminated unexpectedly (1 times)
Prefecth – Program execution
The Prefetch files are very useful as well because the beacon has a random name1 and it is followed by proof of the execution of rundll323. It is important to mention that the presence of rundll32.exe alone is not necessarily an indication of malicious activity. However, since the beacon name is randomly set by Cobalt Strike for each execution, it is difficult to define a detection rule based on the Prefetch files.
The main IOC here is the beacon dropped in the $ADMIN share (C:\Windows\) and then executed by the malicious service. The binary itself has no entry in the MFT, but its Prefetch file and that of rundll32.exe are visible when the jump psexec64 command is executed.
In our case, since the system has been freshly installed, rundll32.exe has run for the first time and the birth of the Prefetch file can be observed in the MFT (here in both $FILE_NAME and $STANDARD_INFORMATION of the RUNDLL32.EXE-64292FC9.pf file), otherwise only its modification would be visible.
File System – USN journal
Just like the MFT, and as observed in the SysMon logs (event ID 11), the USN journal can also detect the malicious executable and its Prefetch file. The location of the beacon in the C:\Windows directory makes it easy to spot. The activity of the Prefetch file of rundll32.exe is also recorded. The C:\Windows\4542843.exe binary is deleted immediately after its execution.
The default Cobal Strike jump psexec64 command is fairly easy to detect because it creates a service with a random name2 and uses the rundll32.exe3 program without any arguments to host the payload. Even if the malicious binary is deleted immediately after its execution, the location of the beacon in the C:\Windows directory makes it even easier to spot.
Detection Rule Example
The timeline is processed using plaso (https://plaso.readthedocs.io/) on data collected with DFIR-Orc (https://dfir-orc.github.io/). The available fields and their names may vary depending on how you use log2timeline and psort.
Kibana
The various KQL queries correspond to each aspect of the conclusion stated above and can of course be grouped together. The most important is the SCM record (event ID 7045). Note that all these events occur in a short period of time. The name of the beacon can be spotted with the SCM record (event ID 7045) and then used to improve the queries on the MFT and USN journal events.
parser : "winevtx" and source_name : "Service Control Manager" and eid : 7045
parser : "winevtx" and source_name : "Microsoft-Windows-Security-Auditing" and eid : (4624 or 4672 or 4634)
parser : "usnjrnl" and message : \\Windows\\*.exe
parser : ( "prefetch" or "mft" ) and message : *RUNDLL32.EXE*
Splunk
A simple query for installed services (event ID 7045) where the service path contains the ADMIN$ substring is enough:
sigma-cli >>> sigma convert -t splunk -p sysmon ../sigma/rules/windows/builtin/system/win_cobaltstrike_service_installs.yml
Parsing Sigma rules [####################################] 100%
Provider_Name="Service Control Manager" EventID=7045 (ImagePath="*ADMIN$*" ImagePath="*.exe*" OR ImagePath="*%COMSPEC%*" ImagePath="*start*" ImagePath="*powershell*" OR ImagePath="*powershell -nop -w hidden -encodedcommand*" OR ImagePath="*SUVYIChOZXctT2JqZWN0IE5ldC5XZWJjbGllbnQpLkRvd25sb2FkU3RyaW5nKCdodHRwOi8vMTI3LjAuMC4xO*" OR ImagePath="*lFWCAoTmV3LU9iamVjdCBOZXQuV2ViY2xpZW50KS5Eb3dubG9hZFN0cmluZygnaHR0cDovLzEyNy4wLjAuMT*" OR ImagePath="*JRVggKE5ldy1PYmplY3QgTmV0LldlYmNsaWVudCkuRG93bmxvYWRTdHJpbmcoJ2h0dHA6Ly8xMjcuMC4wLjE6*")
Cobalt Strike « jump winrm64 »
The Cobalt Strike jump winrm64 command allows using the Windows Remote Management (WinRM) service to execute a command or payload on a remote Windows system. When the jump winrm64 command is executed, it will use the active beacon to establish a connection to the specified Windows system and then use the WinRM service to run the malicious payload on the remote system. The Beacon type used for this test is smb.
Microsoft-Windows-Sysmon
Event ID 1 – Process Create
The process creation event provides extended information about a newly created process. The full command line provides context on the process execution. The ProcessGUID field is a unique value for this process across a domain to make event correlation easier. The hash is a full hash of the file with the algorithms in the HashType field.
Over the period of time during which the jump winrm64 command is executed, one of the created processes is wsmprovhost.exe by the svchost.exe process. Indeed, since the jump winrm64 command uses the Windows Remote Management (WinRM) service, the wsmprovhost.exe process is started to handle the incoming connection and execute the command or payload.
Time
Description
13:38:10.192
[evtx/sysmon/1] Process created with command C:\Windows\system32\wsmprovhost.exe -Embedding (pid: 9724) by user ‘CORP\alice’ via C:\Windows\System32\svchost.exe -k DcomLaunch -p (pid: 728)
Event ID 3 – Network Connection Detected
The network connection event logs TCP/UDP connections on the machine. Each connection is linked to a process through the ProcessId and ProcessGUID fields. The event also contains the source and destination host names, IP addresses, port numbers and IPv6 status.
Sysmon recorded 4 network connections to the victim workstation on port TCP\5985 (HTTP default WinRM port) and, since the beacon type used for this test is smb, one more to TCP port TCP\445 (SMB).
Time
Description
13:38:12.005
[evtx/sysmon/3] An unknown process (pid: 4) created a TCP network connection from ‘192.168.56.119:54176’ to ‘192.168.56.117:5985’
13:38:12.907
[evtx/sysmon/3] An unknown process (pid: 4) created a TCP network connection from ‘192.168.56.119:54177’ to ‘192.168.56.117:5985’
13:38:15.662
[evtx/sysmon/3] An unknown process (pid: 4) created a TCP network connection from ‘192.168.56.119:54179’ to ‘192.168.56.117:5985’
13:38:15.935
[evtx/sysmon/3] An unknown process (pid: 4) created a TCP network connection from ‘192.168.56.119:54180’ to ‘192.168.56.117:5985’
13:38:20.995
[evtx/sysmon/3] An unknown process (pid: 4) created a TCP network connection from ‘192.168.56.119:54181’ to ‘192.168.56.117:445’
Event ID 7 – Image Loaded
The image loaded event logs when a module is loaded in a specific process. It indicates the process in which the module is loaded, hashes and signature information.
This event records the libraries loaded by a process during its execution. Without Sysmon installed on the victim workstation, it is hard to get the same information from other artefacts. However, because in that particular case the MFT artefact was able to get close information, this event is displayed here. The wsmprovhost.exe process (PID 9724) loads 88 DLL and we chose to list only two because of their records in the MFT (see below).
Time
Description
13:38:10.177
[evtx/sysmon/7] Process C:\Windows\System32\wsmprovhost.exe (pid: 9724) executed by ‘CORP\alice’ loaded module C:\Windows\System32\wsmprovhost.exe
13:38:10.333
[evtx/sysmon/7] Process C:\Windows\System32\wsmprovhost.exe (pid: 9724) executed by ‘CORP\alice’ loaded module C:\Windows\System32\WsmSvc.dll
13:38:10.523
[evtx/sysmon/7] Process C:\Windows\System32\wsmprovhost.exe (pid: 9724) executed by ‘CORP\alice’ loaded module C:\Windows\System32\wsmplpxy.dll
13:38:10.600
[evtx/sysmon/7] Process C:\Windows\System32\wsmprovhost.exe (pid: 9724) executed by ‘CORP\alice’ loaded module C:\Windows\assembly\NativeImages_v4.0.30319_64\mscorlib\97c421700557a331a31041b81ac3b698\mscorlib.ni.dll
13:38:10.600
[evtx/sysmon/7] Process C:\Windows\System32\wsmprovhost.exe (pid: 9724) executed by ‘CORP\alice’ loaded module ¨C159C
13:38:10.600
[evtx/sysmon/7] Process ¨C160C (pid: 9724) executed by ‘CORP\alice’ loaded module ¨C161C
13:38:10.600
[evtx/sysmon/7] Process ¨C162C (pid: 9724) executed by ‘CORP\alice’ loaded module ¨C163C
13:38:10.618
[evtx/sysmon/7] Process ¨C164C (pid: 9724) executed by ‘CORP\alice’ loaded module ¨C165C
13:38:10.662
[evtx/sysmon/7] Process ¨C166C (pid: 9724) executed by ‘CORP\alice’ loaded module ¨C167C
13:38:10.662
[evtx/sysmon/7] Process ¨C168C (pid: 9724) executed by ‘CORP\alice’ loaded module ¨C169C
Event ID 11 – File Create
File create operations are logged when a file is created or overwritten. This event is useful for monitoring autostart locations, like the Startup folder, as well as temporary and download directories, which are common places where malware is dropped during an initial infection.
Our malicious wsmprovhost.exe process has the PID 9724. The Cobalt Strike Beacon runs under the context of PowerShell, this is why two PowerShell script files are generated by Microsoft to test against Applocker. If the test file executes, then it assumed that Applocker is disabled.
Time
Description
13:38:11.653
[evtx/sysmon/11] Process C:\Windows\system32\wsmprovhost.exe (pid=9724) created file C:\Users\alice\AppData\Local\Temp\__PSScriptPolicyTest_amxqtozh.ie2.psm1 run by user ‘CORP\alice’
13:38:11.653
[evtx/sysmon/11] Process C:\Windows\system32\wsmprovhost.exe (pid=9724) created file C:\Users\alice\AppData\Local\Temp\__PSScriptPolicyTest_psmlbjet.gus.ps1 run by user ‘CORP\alice’
13:38:29.313
[evtx/sysmon/11] Process C:\Windows\system32\wsmprovhost.exe (pid=9724) created file C:\Users\alice\AppData\Local\Microsoft\Windows\PowerShell\ModuleAnalysisCache run by user ‘CORP\alice’
13:38:29.313
[evtx/sysmon/11] Process C:\Windows\system32\wsmprovhost.exe (pid=9724) created file C:\Users\alice\AppData\Local\Microsoft\Windows\PowerShell run by user ‘CORP\alice’
Event ID 17 / 18 – Pipe Created or Accessed
Pipe creation operations map to these event types when a named pipe is created (event ID 17) and when a named pipe is created or accessed (event ID 18).
The previous spotted processes with PID 4 and 9724 used several names pipes. The created pipe \\msagend_bd is made by the SMB beacon (by default) for the communication with the C2.
Time
Description
13:38:11.959
[evtx/sysmon/17] User ‘CORP\alice’ used the process C:\Windows\system32\wsmprovhost.exe (pid: 9724) to create named pipe \PSHost.132924298901870926.9724.DefaultAppDomain.wsmprovhost
13:38:17.148
[evtx/sysmon/17] User ‘CORP\alice’ used the process C:\Windows\system32\wsmprovhost.exe (pid: 9724) to create named pipe \msagent_bd
13:38:10.558
[evtx/sysmon/18] User ‘CORP\alice’ used the process C:\Windows\system32\wsmprovhost.exe (pid: 9724) to connect named pipe \lsass
13:38:19.169
[evtx/sysmon/18] User ‘NT AUTHORITY\SYSTEM’ used the process System (pid: 4) to connect named pipe \msagent_bd
Findings
Now that we have seen the events and other artefacts generated by the execution of the jump winrm64 command, let us dwell on the evidence present natively on a Windows 10 system out of the box.
Winevtx – Microsoft-Windows-Security-Auditing
Like the remote-exec winrm command, 5 authentications (event ID 4624) are recorded with the logon type ‘3’ from the compromised account CORP\alice, along with the associated privilege assignment events (event ID 4672). The source IP address and hostname are not always recorded, nor is the logon process name.
Time
Description
13:38:11.036
[evtx/sec/4624] User ‘CORP.LOCAL\alice’ (S-1-5-21-1155457554-2149841727-2293290625-1108) successfully logon (type=3) from ‘-‘ (‘-‘) (logon_id=0x00000000005eb099) with ‘-‘
13:38:11.036
[evtx/sec/4672] Special privileges assigned to ‘CORP\alice’ (S-1-5-21-1155457554-2149841727-2293290625-1108) (logon_id=0x00000000005eb099): SeSecurityPrivilege SeBackupPrivilege SeRestorePrivilege SeTakeOwnershipPrivilege SeDebugPrivilege SeSystemEnvironmentPrivilege SeLoadDriverPrivilege SeImpersonatePrivilege SeDelegateSessionUserImpersonatePrivilege
13:38:13.705
[evtx/sec/4624] User ‘CORP.LOCAL\alice’ (S-1-5-21-1155457554-2149841727-2293290625-1108) successfully logon (type=3) from ‘-‘ (‘-‘) (logon_id=0x00000000005edc9b) with ‘-‘
13:38:13.705
[evtx/sec/4672] Special privileges assigned to ‘CORP\alice’ (S-1-5-21-1155457554-2149841727-2293290625-1108) (logon_id=0x00000000005edc9b): SeSecurityPrivilege SeBackupPrivilege SeRestorePrivilege SeTakeOwnershipPrivilege SeDebugPrivilege SeSystemEnvironmentPrivilege SeLoadDriverPrivilege SeImpersonatePrivilege SeDelegateSessionUserImpersonatePrivilege
13:38:13.828
[evtx/sec/4624] User ‘CORP.LOCAL\alice’ (S-1-5-21-1155457554-2149841727-2293290625-1108) successfully logon (type=3) from ‘-‘ (‘-‘) (logon_id=0x00000000005edd18) with ‘-‘
13:38:13.828
[evtx/sec/4672] Special privileges assigned to ‘CORP\alice’ (S-1-5-21-1155457554-2149841727-2293290625-1108) (logon_id=0x00000000005edd18): SeSecurityPrivilege SeBackupPrivilege SeRestorePrivilege SeTakeOwnershipPrivilege SeDebugPrivilege SeSystemEnvironmentPrivilege SeLoadDriverPrivilege SeImpersonatePrivilege SeDelegateSessionUserImpersonatePrivilege
13:38:19.168
[evtx/sec/4624] User ‘CORP.LOCAL\alice’ (S-1-5-21-1155457554-2149841727-2293290625-1108) successfully logon (type=3) from ‘192.168.56.119’ (‘-‘) (logon_id=0x00000000005f30a3) with ‘-‘
13:38:19.168
[evtx/sec/4672] Special privileges assigned to ‘CORP\alice’ (S-1-5-21-1155457554-2149841727-2293290625-1108) (logon_id=0x00000000005f30a3): SeSecurityPrivilege SeBackupPrivilege SeRestorePrivilege SeTakeOwnershipPrivilege SeDebugPrivilege SeSystemEnvironmentPrivilege SeLoadDriverPrivilege SeImpersonatePrivilege SeDelegateSessionUserImpersonatePrivilege
13:39:05.880
[evtx/sec/4624] User ‘CORP.LOCAL\alice’ (S-1-5-21-1155457554-2149841727-2293290625-1108) successfully logon (type=3) from ‘-‘ (‘-‘) (logon_id=0x000000000061217d) with ‘-‘
13:39:05.880
[evtx/sec/4672] Special privileges assigned to ‘CORP\alice’ (S-1-5-21-1155457554-2149841727-2293290625-1108) (logon_id=0x000000000061217d): SeSecurityPrivilege SeBackupPrivilege SeRestorePrivilege SeTakeOwnershipPrivilege SeDebugPrivilege SeSystemEnvironmentPrivilege SeLoadDriverPrivilege SeImpersonatePrivilege SeDelegateSessionUserImpersonatePrivilege
13:39:05.893
[evtx/sec/4624] User ‘CORP.LOCAL\alice’ (S-1-5-21-1155457554-2149841727-2293290625-1108) successfully logon (type=3) from ‘-‘ (‘-‘) (logon_id=0x0000000000612198) with ‘-‘
13:39:05.893
[evtx/sec/4672] Special privileges assigned to ‘CORP\alice’ (S-1-5-21-1155457554-2149841727-2293290625-1108) (logon_id=0x0000000000612198): SeSecurityPrivilege SeBackupPrivilege SeRestorePrivilege SeTakeOwnershipPrivilege SeDebugPrivilege SeSystemEnvironmentPrivilege SeLoadDriverPrivilege SeImpersonatePrivilege SeDelegateSessionUserImpersonatePrivilege
The five network sessions (logon_type = 3) opened by user « CORP\alice » end a few moments later, just after the remote code execution.
Time
Description
13:39:05.879
[evtx/sec/4634] User logged off ‘CORP\alice’ (S-1-5-21-1155457554-2149841727-2293290625-1108) (logon_id=0x00000000005eb099) from logon type=3
13:39:05.892
[evtx/sec/4634] User logged off ‘CORP\alice’ (S-1-5-21-1155457554-2149841727-2293290625-1108) (logon_id=0x00000000005edd18) from logon type=3
13:39:05.924
[evtx/sec/4634] User logged off ‘CORP\alice’ (S-1-5-21-1155457554-2149841727-2293290625-1108) (logon_id=0x00000000005edc9b) from logon type=3
13:39:05.924
[evtx/sec/4634] User logged off ‘CORP\alice’ (S-1-5-21-1155457554-2149841727-2293290625-1108) (logon_id=0x000000000061217d) from logon type=3
13:39:21.622
[evtx/sec/4634] User logged off ‘CORP\alice’ (S-1-5-21-1155457554-2149841727-2293290625-1108) (logon_id=0x00000000005f30a3) from logon type=3
Winevtx – Microsoft-Windows-WinRM
Obviously, some good indicators to detect WinRM lateral movements are stored in the Microsoft-Windows-WinRM log file, like the event ID 91 (Creating WSMan shell on server) on the target host. This event indicates that the WinRM service has begun to listen for incoming connections on the specified ports (HTTP and HTTPS by default). On our targeted host, this event was the only record in the Microsoft-Windows-WinRM log file after the remote code execution.
While the process of creating the PowerShell beacon on the remote host is done via the Windows Remote Management (WinRM) service and not via a PowerShell session, you can detect the wsmprovhost.exe process using the PowerShell log files if PowerShell script block logging is enabled.
Unlike the remote-exec winrm command, the jump winrm64 command generates a PowerShell event ID 4104 because the block content was considered as suspicious. Script block logging events are recorded when a user starts a new session using the PowerShell remoting feature and stores blocks of code as they are executed by the PowerShell engine. This allows capturing the full PowerShell Beacon.
N.B.: Starting from PowerShell 5.0, anything that is determined as suspicious by AMSI (Antimalware Scan Interface) will automatically log a Script block/4104 event with a level of Warning4.
It is important to note that the event 4104 will be generated only when a user starts a new session using the PowerShell remoting feature, and not when a session is started using the jump winrm64 command in Cobalt Strike. All 29 events 4104 have been merged into a single event in the following timeline.
Time
Description
13:38:11.964
[evtx/powershell/53504] Windows PowerShell has started an IPC listening thread on process ‘9724’ in AppDomain ‘DefaultAppDomain’
13:38:13.007
[evtx/powershell/600] The PowerShell provider ‘Environment’ hosted by application C:\Windows\system32\wsmprovhost.exe -Embedding is Started.
13:38:13.007
[evtx/powershell/600] The PowerShell provider ‘Alias’ hosted by application C:\Windows\system32\wsmprovhost.exe -Embedding is Started.
13:38:13.007
[evtx/powershell/600] The PowerShell provider ‘Registry’ hosted by application C:\Windows\system32\wsmprovhost.exe -Embedding is Started.
13:38:13.027
[evtx/powershell/600] The PowerShell provider ‘Variable’ hosted by application C:\Windows\system32\wsmprovhost.exe -Embedding is Started.
13:38:13.027
[evtx/powershell/600] The PowerShell provider ‘Function’ hosted by application C:\Windows\system32\wsmprovhost.exe -Embedding is Started.
13:38:13.027
[evtx/powershell/600] The PowerShell provider ‘FileSystem’ hosted by application C:\Windows\system32\wsmprovhost.exe -Embedding is Started.
13:38:13.099
[evtx/powershell/400] The PowerShell engine state hosted by application C:\Windows\system32\wsmprovhost.exe -Embedding is changed from ‘None’ to ‘Available’.
13:38:14.362
[evtx/powershell/4104] The remote PowerShell scriptblock named ‘3cdb4718-452a-469b-bf94-b8a1ad197fa6‘ is executed (29 blocks)
The recorded payload stored in the event 4104 (and split into 29 pieces of code) contains two functions, func_get_proc_address and func_get_delegate_type. These two PowerShell functions are likely used to dynamically load and execute unmanaged code in a managed environment:
func_get_proc_address appears to use the Microsoft.Win32.UnsafeNativeMethods class to load a function pointer for a specified procedure in a specified module. This function is commonly used in interop scenarios when calling unmanaged functions from managed code.
func_get_delegate_type appears to dynamically create a delegate type that can be used to invoke a function with a specified signature. This function may be used in scenarios where a delegate with a specific signature is required but cannot be generated at compile time.
Together, these functions could be used to dynamically load and execute unmanaged code with a specific signature in a managed environment. They will be used by the following scheme (base64-encoded payloads have been removed for more readability):
The PowerShell script is designed to decode, inject and execute a base64-encoded shellcode in the current process using dynamic memory allocation and function pointers.
First, the code checks if the size of IntPtr is 8, which indicates a 64-bit operating system. If the system is running on a 64-bit architecture, the script continues to execute.
Next, it converts the base64-encoded payload into a byte array using the [System.Convert]::FromBase64String method and applies a bitwise XOR operation with the value 35 to each byte. This is likely used to obfuscate the payload by applying a simple obfuscation technique.
After that, the code retrieves the function pointer for the VirtualAlloc function in the kernel32.dll library using the func_get_proc_address function. It also uses the func_get_delegate_type function to define a delegate type with the appropriate parameters for the VirtualAlloc function. The code uses the Marshal.Copy method to copy the byte array containing the shellcode into the allocated memory.
Finally, the code retrieves the function pointer for the shellcode using the Marshal.GetDelegateForFunctionPointer method and creates a delegate of type Void that can invoke the shellcode. The shellcode is then executed by calling the delegate with the Invoke() method. This causes the payload to be executed in memory.
Prefecth – Program execution
Since the wsmprohost.exe process is used by the Windows Remote Management (WinRM) service to handle the incoming connection and execute the command or payload, the Prefecth artefacts can successfully detect the execution of wsmprohost.exe.
It is important to mention that the presence of wsmprovhost.exe alone is not necessarily an indication of malicious activity. The process is a legitimate component of the Windows operating system and is typically used for system management and administration tasks.
File System – MFT
As mentioned earlier in the Sysmon event ID 7, in that case the MFT can be used to get information on the images loaded by the wsmprovhost.exe process. As a matter of fact, accesses to many DLLs can be observed within the MFT.
In our case, since the Windows Remote Management (WinRM) service has run for the first time, the birth of the prefetch file can be observed in the MFT (here in both $FILE_NAME and $STANDARD_INFORMATION of the WSMPROVHOST.EXE-EF06207C.pf file), otherwise only its modification would be visible. It is possible to notice, as expected, that the execution datetime recorded in the Prefetch file occurs 10 seconds before the file itself is created on the file system.
Just like the MFT, and as observed in the SysMon logs (event ID 11), the USN journal can also detect the temporary files that are generated by the PowerShell script execution policy stored in the user’s directory here: C:\Users\alice\AppData\Local\Temp\__PSScriptPolicyTest_*.
In addition, when PowerShell starts running, the C:\Users\alice\AppData\Local\Microsoft\Windows\PowerShell\ folder is created to store the ModuleAnalysisCache file, created at the same time to store cached information about modules that have been analyzed.
Many artefacts can lead to the conclusion that a beacon has been dropped using WinRM on the victim workstation:
The WinRM service begins to listen for incoming connections (« Microsoft-Windows-WinRM » event ID 91);
The PowerShell engine starts (« PowerShell » event ID 400), as well as its providers, hosted by the C:\Windows\system32\wsmprovhost.exe -Embedding application (« PowerShell » event ID 600);
Thanks to AMSI, PowerShell scriptblock may record the Cobalt Strike Beacon (« Microsoft-Windows-PowerShell » event ID 4104);
Regarding the file system and execution artefacts, some events could confirm the drop of the beacon, but cannot be used as proof by themselves:
The wsmprohost.exe executable that is used by the Windows Remote Management (WinRM) service can be seen among the Prefetch files, this file being present in the MFT and in the USN journal;
Accesses to many DLLs can be observed within the MFT, also recorded by « Sysmon » event ID 7 (Image Loaded);
PowerShell activities also leave traces in the MFT and the USN journal in the user directory of « CORP\alice ».
Finally, once the proof of execution of the beacon has been established, the origin of the connection can sometimes be recorded by the « Security » event ID 4624 (also with event IDs 4672 and 4634).
Detection Rule Example
The timeline is processed using plaso (https://plaso.readthedocs.io/) on data collected with DFIR-Orc (https://dfir-orc.github.io/). The availablefields and their names may vary depending on how you use log2timeline and psort.
Kibana
The various KQL queries correspond to each aspect of the conclusion stated above and can of course be grouped together. Note that all these events occur in a short period of time.
parser : "winevtx" and source_name : "Microsoft-Windows-WinRM" and eid : 91
parser : "winevtx" and source_name : "PowerShell" and eid : ( 400 or 600 ) and message : *HostApplication=*wsmprovhost.exe*
parser : "winevtx" and source_name : "Microsoft-Windows-PowerShell" and eid : 4104
parser : "winevtx" and source_name : "Microsoft-Windows-Security-Auditing" and eid : (4624 or 4672 or 4634)
parser : "usnjrnl" and message : ( WSMPROVHOST.EXE* or *__PSScriptPolicyTest_* )
parser : "mft" and message : ( *WsmSvc.dll or *atl.dll or *clr.dll or *clrjit.dll or *mscoreei.dll or *mscorlib.ni.dll or *System.Core.ni.dll or *System.ni.dll or *wsmplpxy.dll )
parser : ( "prefetch" or "mft" ) and message : *WSMPROVHOST.EXE*
Splunk
This rule can be the same as the remote-exec winrm command seen in part 1, and focuses on PowerShell and WinRM events only:
host="*" index="*" parser=winevtx eid=91 OR (eid=400 AND host_application="*wsmprovhost.exe*")
| bin span=15s _time
| eventstats distinct_count(event ID) as dis_count by _time
| where dis_count==2
| table _time eid message dis_count
The Cobalt Strike jump psexec_psh command creates a Beacon on the remote host using the psexec and PowerShell techniques. The Beacon type used for this test is smb.
Microsoft-Windows-Sysmon
Event ID 1 – Process Create
The process creation event provides extended information about a newly created process. The full command line provides context on the process execution. The ProcessGUID field is a unique value for this process across a domain to make event correlation easier. The hash is a full hash of the file with the algorithms in the HashType field.
The process chain created by the jump psexec_psh command on the victim workstation is cmd.exe -> powershell.exe. The PowerShell payload is base64 encoded several times, gzip compressed and XOR encrypted (with key « 35 »).
Time
Description
13:45:07.770
[evtx/sysmon/1] Process created with command C:\\Windows\\SysWOW64\\cmd.exe /b /c start /b /min powershell -nop -w hidden -encodedcommand <base64enc_payload> (id 3608) by user NT AUTHORITY\SYSTEM via C:\\Windows\\System32\\services.exe (id 596)
13:45:07.813
[evtx/sysmon/1] Process created with command powershell -nop -w hidden -encodedcommand <base64enc_payload> (id 6920) by user NT AUTHORITY\SYSTEM via C:\\Windows\\SysWOW64\\cmd.exe (id 3608)
Event ID 3 – Network Connection Detected
The network connection event logs TCP/UDP connections on the machine. Each connection is linked to a process through the ProcessId and ProcessGUID fields. The event also contains the source and destination host names, IP addresses, port numbers and IPv6 status.
In both of our tests, 3 connections are made. The first one on port 135, the second one to a random port and the last one to port 445.
Time
Description
13:45:09.111
[evtx/sysmon/3] Tcp network connection from host – (192.168.56.119:54310) to host – (192.168.56.117:135) (pid=832)
13:45:09.112
[evtx/sysmon/3] Tcp network connection from host – (192.168.56.119:54311) to host – (192.168.56.117:49692) (pid=596)
13:45:09.880
[evtx/sysmon/3] Tcp network connection from host – (192.168.56.119:54312) to host – (192.168.56.117:445) (pid=4)
Event ID 11 – File Created
File create operations are logged when a file is created or overwritten. This event is useful for monitoring autostart locations, like the Startup folder, as well as temporary and download directories, which are common places where malware is dropped during an initial infection.
A Prefetch file is generated for each process executed (cmd.exe and powershell.exe) and two PowerShell test scripts generated by Microsoft are created (__PSScriptPolicyTest_<random_number>.ps1):
Time
Description
13:45:07.842
[evtx/sysmon/11] Process C:\\Windows\\system32\\svchost.exe (pid=1860) created file C:\\Windows\\Prefetch\\CMD.EXE-AC113AA8.pf with user NT AUTHORITY\SYSTEM
13:45:09.526
[evtx/sysmon/11] Process C:\\Windows\\SysWOW64\\WindowsPowerShell\\v1.0\\powershell.exe (pid=6920) created file C:\Windows\Temp\__PSScriptPolicyTest_0tg0e3gp.i3q.psm1 with user NT AUTHORITY\SYSTEM
13:45:09.526
[evtx/sysmon/11] Process C:\\Windows\\SysWOW64\\WindowsPowerShell\\v1.0\\powershell.exe (pid=6920) created file C:\Windows\Temp\__PSScriptPolicyTest_2nmpla2r.cyj.ps1 with user NT AUTHORITY\SYSTEM
13:45:17.997
[evtx/sysmon/11] Process C:\\Windows\\system32\\svchost.exe (pid=1860) created file C:\\Windows\\Prefetch\\POWERSHELL.EXE-767FB1AE.pf with user NT AUTHORITY\SYSTEM
Event ID 13 – Registry Value Set
Registry key and value create and delete operations map to this event type.
Cobalt Strike creates a service to run the PowerShell command as « SYSTEM ». So a registry key with a random name is created under HKLM\\System\\CurrentControlSet\\Services\\4b3d5bc by the Services.exe process and the ImagePath registry key is set to the Beacon path.
Time
Description
13:45:07.758
[evtx/sysmon/13] Registry event : user NT AUTHORITY\SYSTEM process C:\\Windows\\system32\\services.exe (pid 596) has SetValue HKLM\\System\\CurrentControlSet\\Services\\4b3d5bc\\Start value to DWORD (0x00000003)
13:45:07.758
[evtx/sysmon/13] Registry event : user NT AUTHORITY\SYSTEM process C:\\Windows\\system32\\services.exe (pid 596) has SetValue HKLM\\System\\CurrentControlSet\\Services\\4b3d5bc\\Type value to DWORD (0x00000010)
13:45:07.760
[evtx/sysmon/13] Registry event : user NT AUTHORITY\SYSTEM process C:\\Windows\\system32\\services.exe (pid 596) has SetValue HKLM\\System\\CurrentControlSet\\Services\\4b3d5bc\\ObjectName value to LocalSystem
13:45:07.760
[evtx/sysmon/13] Registry event : user NT AUTHORITY\SYSTEM process C:\\Windows\\system32\\services.exe (pid 596) has SetValue HKLM\\System\\CurrentControlSet\\Services\\4b3d5bc\\WOW64 value to DWORD (0x0000014c)
13:45:07.760
[evtx/sysmon/13] Registry event : user NT AUTHORITY\SYSTEM process C:\\Windows\\system32\\services.exe (pid 596) has SetValue ¨C296C value to ¨C297C
13:45:07.760
[evtx/sysmon/13] Registry event : user NT AUTHORITY\SYSTEM process ¨C298C (pid 596) has SetValue ¨C299C value to DWORD (0x00000000)
13:45:07.841
[evtx/sysmon/13] Registry event : user NT AUTHORITY\SYSTEM process ¨C300C (pid 596) has SetValue ¨C301C value to DWORD (0x00000001)
13:45:07.842
[evtx/sysmon/13] Registry event : user NT AUTHORITY\SYSTEM process ¨C302C (pid 596) has SetValue ¨C303C value to DWORD (0x00000004)
Event ID 17 – Pipe Created
Pipe creation operations map to this event type.
The default named pipe created by the SMB Beacon for the communication is \\msagent_## and the default named pipe created for the PowerShell payload staging is \\.\pipe\status_##.
Time
Description
13:45:08.203
[evtx/sysmon/17] Process C:\\windows\\syswow64\\windowspowershell\\v1.0\\powershell.exe (pid=6988) created pipe \\msagent_bd with user NT AUTHORITY\SYSTEM
13:45:09.832
[evtx/sysmon/17] Process C:\\Windows\\SysWOW64\\WindowsPowerShell\\v1.0\\powershell.exe (pid=6920) created pipe \\PSHost.132924303078028554.6920.DefaultAppDomain.powershell with user NT AUTHORITY\SYSTEM
13:45:11.423
[evtx/sysmon/17] Process C:\\Windows\\SysWOW64\\WindowsPowerShell\\v1.0\\powershell.exe (pid=6920) created pipe \\status_8b with user NT AUTHORITY\SYSTEM
Findings
Winevtx – Microsoft-Windows-Security-Auditing
Without the audit policies enabled, not many events are generated. Only two successful logons (event ID 4624) are recorded, with the logon type ‘3’ (Network), from the compromised account « CORP\alice ». If correlated, this behavior may help during the investigation to support a hypothesis. The source hostnames are not always recorded, nor is the logon process name.
Time
Description
13:45:07.730
[evtx/sec/4672] Special privileges assigned to ‘CORP\alice’ (S-1-5-21-1155457554-2149841727-2293290625-1108) (logon_id=0x00000000008629e3): SeSecurityPrivilege SeBackupPrivilege SeRestorePrivilege SeTakeOwnershipPrivilege SeDebugPrivilege SeSystemEnvironmentPrivilege SeLoadDriverPrivilege SeImpersonatePrivilege SeDelegateSessionUserImpersonatePrivilege
13:45:07.732
[evtx/sec/4624] User ‘CORP.LOCAL\alice’ (S-1-5-21-1155457554-2149841727-2293290625-1108) successfully logon (type=3) from ‘192.168.56.119’ (‘-‘) (logon_id=0x00000000008629e3) with ‘-‘
13:45:07.904
[evtx/sec/4672] Special privileges assigned to ‘CORP\alice’ (S-1-5-21-1155457554-2149841727-2293290625-1108) (logon_id=0x0000000000862fb5): SeSecurityPrivilege SeBackupPrivilege SeRestorePrivilege SeTakeOwnershipPrivilege SeDebugPrivilege SeSystemEnvironmentPrivilege SeLoadDriverPrivilege SeImpersonatePrivilege SeDelegateSessionUserImpersonatePrivilege
13:45:07.904
[evtx/sec/4624] User ‘CORP.LOCAL\alice’ (S-1-5-21-1155457554-2149841727-2293290625-1108) successfully logon (type=3) from ‘192.168.56.119’ (‘-‘) (logon_id=0x0000000000862fb5) with ‘-‘
The two network sessions (logon_type = 3) opened by user « CORP\alice » end a few moments later, just after the remote code execution.
Time
Description
13:46:23.310
[evtx/sec/4634] User logged off ‘CORP\alice’ (S-1-5-21-1155457554-2149841727-2293290625-1108) (logon_id=0x0000000000862fb5) from logon type=3
13:49:28.185
[evtx/sec/4634] User logged off ‘CORP\alice’ (S-1-5-21-1155457554-2149841727-2293290625-1108) (logon_id=0x00000000008629e3) from logon type=3
Winevtx – PowerShell
The jump psexec_pth command generates a PowerShell event ID 4104 because the block content was considered as suspicious. Script block logging events are recorded when a user starts a new session using the PowerShell remoting feature and stores blocks of code as they are executed by the PowerShell engine. This allows capturing the full PowerShell Beacon.
N.B.: Starting from PowerShell 5.0, anything that is determined as suspicious by AMSI (Antimalware Scan Interface) will automatically log a Script block/4104 event with a level of Warning4.
It is important to note that the event 4104 will be generated only when a user starts a new session using the PowerShell remoting feature, and not when a session is started using the jump winrm64 command in Cobalt Strike. All 29 events 4104 have been merged into a single event in the following timeline.
Time
Description
13:45:09.308
[evtx/powershell/40961] A new PowerShell runspace has been created
13:45:09.834
[evtx/powershell/53504] Windows PowerShell has started an IPC listening thread on process ‘6920’ in AppDomain ‘DefaultAppDomain’
13:45:10.240
[evtx/powershell/600] The PowerShell provider ‘Alias’ hosted by application powershell -nop -w hidden -encodedcommand <base64enc_payload> is Started.
13:45:10.240
[evtx/powershell/600] The PowerShell provider ‘Environment’ hosted by application powershell -nop -w hidden -encodedcommand <base64enc_payload> is Started.
13:45:10.240
[evtx/powershell/600] The PowerShell provider ‘Registry’ hosted by application powershell -nop -w hidden -encodedcommand <base64enc_payload> is Started.
13:45:10.286
[evtx/powershell/600] The PowerShell provider ‘FileSystem’ hosted by application powershell -nop -w hidden -encodedcommand <base64enc_payload> is Started.
13:45:10.286
[evtx/powershell/600] The PowerShell provider ‘Function’ hosted by application powershell -nop -w hidden -encodedcommand <base64enc_payload> is Started.
13:45:10.286
[evtx/powershell/600] The PowerShell provider ‘Variable’ hosted by application powershell -nop -w hidden -encodedcommand <base64enc_payload> is Started.
13:45:10.348
[evtx/powershell/400] The PowerShell engine state hosted by application powershell -nop -w hidden -encodedcommand <base64enc_payload> is changed from ‘None’ to ‘Available’.
13:45:10.387
[evtx/powershell/40962] A PowerShell runspace have been closed
13:45:10.681
[evtx/powershell/4104] The remote PowerShell scriptblock named ‘7998c69a-4170-4f37-afb8-ef7ce9a2533c‘ is executed (1 block)
13:45:11.213
[evtx/powershell/4104] The remote PowerShell scriptblock named ‘23fe9a7e-31ee-473b-bcb0-8bd7c9b9ca38‘ is executed (1 block)
13:45:11.246
[evtx/powershell/4104] The remote PowerShell scriptblock named ‘¨C323C’ is executed (1 block)
The last two PowerShell scriptblocks are similar to the one seen for the jump winrm64 command with the two functions, func_get_proc_address and func_get_delegate_type, which are used to dynamically load and execute unmanaged code with a specific signature in a managed environment.
The first PowerShell scriptblock decodes and decompresses a base64-encoded and gzip-compressed payload, reads the resulting data as a string, and then executes it as a PowerShell command using the IEX cmdlet. This code is the one that appears as an argument to the PowerShell command powershell -nop -w hidden -encodedcommand <base64enc_payload> (running in a hidden window with « NoProfile »).
Once decoded and decompressed, the payload gives us the PowerShell script that will be executed. The code checks if the operating system is running on a 64-bit architecture and executes a PowerShell script block using a 32-bit PowerShell process if necessary, otherwise it executes the script block in the current process. The payload stored in $DoIt is similar to the one seen for the other ones with the two functions, func_get_proc_address and func_get_delegate_type, used to dynamically load and execute unmanaged code with a specific signature in a managed environment.
The beacon runs as a service, so the PowerShell activity seen above is also recorded by the Service Control Manager (SCM) with the installation of a randomly-named1 service (event ID 7045). Although the randomness of the service name makes writing a detection rule complicated, the mentions of %COMSPEC% and powershell -nop -w hidden -encodedcommand in the program run by the service makes it easier to spot.
Time
Description
13:45:07.755
[evtx/sys/scm/7045] Service ‘4b3d5bc’ (%COMSPEC% /b /c start /b /min powershell -nop -w hidden -encodedcommand <base64enc_payload>) was installed by user ‘LocalSystem’ (type: user mode service, start: demand start)
Prefecth – Program execution
Since both of the Command Shell and PowerShell consoles are used, two Prefetch files are generated or edited, one for the cmd.exe process and the other for the PowerShell.exe process. In some cases, other Prefetch files may be modified or created depending on the command run by the Cobalt Strike beacon, such as conhost.exe here.
It is important to mention that the presence of the cmd.exe and powershell.exe processes alone is not necessarily an indication of malicious activity.
File System – MFT
No additional information is provided by the MFT, but it confirms the use of the Command Shell and the PowerShell consoles, by modifying not only the Prefetch files, but also the executables.
The USN artefacts provide the same information as the Sysmon Event ID 11 (file created). Prefetch files for cmd.exe and powershell.exe are created and a PowerShell test script is generated.
The default Cobalt Strike jump command with psexec_psh is fairly easy to detect because it creates a service with a random name2 with an embedded PowerShell command, so many PowerShell logs are generated to capture the full PowerShell staging payload. Unlike the jump psexec64 command, which also uses a service, the payload of the jump psexec_pth command is not dropped on the system but encoded in a PowerShell command.
Detection Rule Example
The timeline is processed using plaso (https://plaso.readthedocs.io/) on data collected with DFIR-Orc (https://dfir-orc.github.io/). The available fields and their names may vary depending on how you use log2timeline and psort.
Kibana
The various KQL queries correspond to each aspect of the conclusion stated above and can of course be grouped together. Note that all these events occur in a short period of time.
parser : "winevtx" and source_name : "Service Control Manager" and eid : 7045 and message : *%COMSPEC%*powershell*hidden*-encodedcommand*
parser : "winevtx" and source_name : "PowerShell" and eid : ( 400 or 600 ) and message : *HostApplication=powershell*hidden*-encodedcommand*
parser : "winevtx" and source_name : "Microsoft-Windows-PowerShell" and eid : 4104
parser : "winevtx" and source_name : "Microsoft-Windows-Security-Auditing" and eid : (4624 or 4672 or 4634)
parser : "usnjrnl" and message : ( CMD.EXE* or POWERSHELL.EXE* or *__PSScriptPolicyTest_* )
parser : ( "prefetch" or "mft" ) and message : ( *CMD.EXE* or *POWERSHELL.EXE* )
Splunk
Many rules can be created to detect this command.
Search for the cmd.exe and powershell.exe Prefetch files;
Search for a logon connection followed by a service installation (like the remote-exec psexec rule created in part 1);
sigma-cli >>> sigma convert -t splunk -p sysmon ../sigma/rules/windows/builtin/system/win_cobaltstrike_service_installs.yml
Parsing Sigma rules [####################################] 100%
Provider_Name="Service Control Manager" EventID=7045 (ImagePath="*ADMIN$*" ImagePath="*.exe*" OR ImagePath="*%COMSPEC%*" ImagePath="*start*" ImagePath="*powershell*" OR ImagePath="*powershell -nop -w hidden -encodedcommand*" OR ImagePath="*SUVYIChOZXctT2JqZWN0IE5ldC5XZWJjbGllbnQpLkRvd25sb2FkU3RyaW5nKCdodHRwOi8vMTI3LjAuMC4xO*" OR ImagePath="*lFWCAoTmV3LU9iamVjdCBOZXQuV2ViY2xpZW50KS5Eb3dubG9hZFN0cmluZygnaHR0cDovLzEyNy4wLjAuMT*" OR ImagePath="*JRVggKE5ldy1PYmplY3QgTmV0LldlYmNsaWVudCkuRG93bmxvYWRTdHJpbmcoJ2h0dHA6Ly8xMjcuMC4wLjE6*")
Part 2 – Conclusion
The three built-in jump commands tested are fairly easy to detect in a default Windows 10 workstation without any particular audit policies enabled.
The psexec64 and psexec_psh built-in commands are the easiest to detect because they are both executed as a service (with a random name2). For the psexec64 command, the ImagePath service pointed to a binary on the C:\Windows directory (previously copied), and for the psexec_psh command, it pointed to a PowerShell one-liner payload (base64-encoded and gzip-compressed).
The winrm64 built-in command is a little bit harder to detect because it does not use services, but should be fairly easy to detect because the PowerShell event ID 4104 is generated by AMSI and the full PowerShell payload is captured. In addition, a WinRM event (event id 91) is generated to warn that a connection is received.
To detect lateral movements even more efficiently, we advise installing Sysmon with a custom configuration and/or activating the relevant audit policies.
Although it was not originally designed for this use, Cobalt Strike has become one of the most frequently used tools for lateral movements and it is not uncommon to observe traces of its use during digital forensic.
This article aims to analyze the different Cobalt Strike commands to find evidence that the tools could drop behind him. Several blogs have already explained how to detect Cobalt Strike, but for this analysis we choose to let the Windows log levels by default without activating special « Windows Audit Policies » and we used post-compromising tools to extract artifacts.
In this first part, we will focus on the Cobalt Strike built-in remote-exec command and its different methods of remote code execution:
A second blogpost will focus on the persistent Cobalt Strike session using Beacon and the built-in jump commands with different methods such as « psexec64 », « winrm64 » or « psexec_psh ».
Approach
The aim here is to provide basic information on what kinds of logs and other artefacts could be generated from Cobalt Strike on a default Windows 10 host. To get a better context and understanding, we enabled Sysmon on the victim Workstation, so that we get a based line to compare with.
The tests have been done with Cobalt Strike version 4.4 with the default configuration without any kind of customization. It’is important to note that Cobalt Strike allow users to change various settings (pipes names, service name, default temporary process, etc.) to customize its footprint. Depending on Cobalt Strike settings used by the attackers, the events generated may be slightly different and detection rule may fail.
Each command has been executed twice to avoid false positive. This short analysis can be later on used as a reference to build rules to detect Cobalt Strike movements during a forensics incident response (without Sysmon or Audit Policies).
The Lab is composed of the following elements:
Windows 10 workstations with Sysmon installed;
Windows Server 2016 Domain Controller.
The different steps and tools used to extract and analyze the artifacts post compromise are:
Run DFIR_ORC to extract artifacts on the Windows 10 machine
Run log2timeline/plaso combined with Logstash on the extracted data to build a clear timeline
Analyze data using Splunk
By using DFIR_Orc and Plaso, we were able to process the most important artifacts:
Event log (*.evtx), including PowerShell command history;
Prefetch files;
USNjrnl;
MFT;
User and System hives (userassist, appcompatcache, etc.).
Findings Summary
A summary of the most important findings (excluding Sysmon events) is available on the timeline below:
[evtx/sec/4624] user ‘CORP.LOCAL\alice’ (S-1-5-21-1155457554-2149841727-2293290625-1108) successfully logon (type=3) from ‘-‘ (‘-‘) (logon_id=0x0000000000483901) with ‘-‘
remote-exec winrm
[evtx/powershell/400] the PowerShell engine state hosted by application C:\Windows\system32\wsmprovhost.exe -Embedding with command line ‘-‘ is changed from ‘None’ to ‘Available’.
remote-exec winrm
[evtx/powershell/403] the PowerShell engine state hosted by application C:\Windows\system32\wsmprovhost.exe -Embedding with command line ‘-‘ is changed from ‘Available’ to ‘Stopped’.
remote-exec winrm
[evtx/powershell/600] the PowerShell provider ‘Alias’ hosted by application C:\Windows\system32\wsmprovhost.exe -Embedding with command line ‘-‘ is Started.
remote-exec winrm
[evtx/powershell/600] the PowerShell provider ‘Environment’ hosted by application C:\Windows\system32\wsmprovhost.exe -Embedding with command line ‘-‘ is Started.
remote-exec winrm
[evtx/powershell/600] the PowerShell provider ‘FileSystem’ hosted by application C:\Windows\system32\wsmprovhost.exe -Embedding with command line ‘-‘ is Started.
remote-exec winrm
[evtx/powershell/600] the PowerShell provider ‘Function’ hosted by application ¨C12C with command line ‘-‘ is Started.
remote-exec winrm
[evtx/powershell/600] the PowerShell provider ‘Registry’ hosted by application ¨C13C with command line ‘-‘ is Started.
remote-exec winrm
[evtx/powershell/600] the PowerShell provider ‘Variable’ hosted by application ¨C14C with command line ‘-‘ is Started.
….
remote-exec wmi
[evtx/sec/4624] user ‘CORP.LOCAL\alice’ (S-1-5-21-1155457554-2149841727-2293290625-1108) successfully logon (type=3) from ‘192.168.56.119’ (‘-‘) (logon_id=0x00000000004d811f) with ‘-‘
remote-exec wmi
[evtx/dcom/10016] the application-specific permission settings do not grant Local Activation permission for the COM Server application with CLSID {3480A401-BDE9-4407-BC02-798A866AC051} and APPID {30AD8C8E-AE85-42FA-B9E8-7E99E3DFBFC5} to the user ‘CORP\alice’ (S-1-5-21-1155457554-2149841727-2293290625-1108) from address LocalHost (Using LRPC) running in the application container Unavailable SID Unavailable
[evtx/sec/4624] user ‘CORP.LOCAL\alice’ (S-1-5-21-1155457554-2149841727-2293290625-1108) successfully logon (type=3) from ‘192.168.56.119’ (‘-‘) (logon_id=0x00000000005eda88) with ‘-‘
remote-exec psexec
[evtx/sys/scm/7045] service ‘d8041e9’ (notepad.exe) was installed by user ‘LocalSystem’ (type: user mode service, start: demand start)
Cobalt Strike remote-exec winrm
The Cobalt Strike remote-exec winrm command allows the user to execute a command using WinRM on the remote host without creating a persistent session with a Beacon. For this example, the executed command is ipconfig.
Sysmon Events
As explained earlier, System Monitor (Sysmon) was installed on the Windows 10 workstation to have reference events on which to base our analyses. We therefore first reviewed the events recorded by Sysmon to get a based line to compare with extracted artifacts. The Sysmon events below has been filtered to the most useful.
Event ID 1 – Process Creation
The process creation event provides extended information about a newly created process. The full command line provides context on the process execution. The ProcessGUID field is a unique value for this process across a domain to make event correlation easier.
The process chain created by the remote-exec winrm commands on the victim workstation is svchost.exe -> wsmprovhost.exe -> ipconfig.exe.
Time
Description
14:24:01.884
[evtx/sysmon/1] process created with command C:\Windows\system32\wsmprovhost.exe -Embedding (id 9040) by user ‘CORP\alice’ via C:\Windows\System32\svchost.exe (id 728)
14:24:05.631
[evtx/sysmon/1] process created with command "C:\Windows\system32\ipconfig.exe" (id 9384) by user ‘CORP\alice’ via C:\Windows\System32\wsmprovhost.exe (id 9040)
14:24:05.653
[evtx/sysmon/1] process created with command \??\C:\Windows\system32\conhost.exe 0xffffffff -ForceV1 (id 8268) by user ‘CORP\alice’ via C:\Windows\System32\ipconfig.exe (id 9384)
Event ID 3 – Network Connection Detected
The network connection event logs TCP/UDP connections on the machine. Each connection is linked to a process through the ProcessId and ProcessGUID fields. The event also contains the source and destination host names IP addresses, port numbers and IPv6 status.
The execution of the remote-exec winrm commands leads to the creation of 3 network connections made to the victim workstation on the port 5985. The ports 5985 (HTTP) and 5986 (HTTPS) are the default TCP ports used by WinRM:
Time
Description
14:24:04.015
[evtx/sysmon/3] tcp network connection from host ‘-‘ (192.168.56.119:54074) to host ‘-‘ (192.168.56.117:5985) (pid=4)
14:24:05.430
[evtx/sysmon/3] tcp network connection from host ‘-‘ (192.168.56.119:54075) to host ‘-‘ (192.168.56.117:5985) (pid=4)
14:24:06.461
[evtx/sysmon/3] tcp network connection from host ‘-‘ (192.168.56.119:54076) to host ‘-‘ (192.168.56.117:5985) (pid=4)
Event ID 7 – Image Loaded
The image loaded event logs when a module is loaded in a specific process. It indicates the process in which the module is loaded, hashes and signature information.
Without Sysmon installed on the victim workstation, it is hard to get the same information from other artifacts. Nevertheless, and this will be discussed later in the article, MFT provides similar evidence and this is why we have chosen to include these events.
Time
Description
14:24:01.896
[evtx/sysmon/7] image C:\Windows\System32\wsmprovhost.exe loaded from process C:\Windows\System32\wsmprovhost.exe (pid=9040) with user ‘CORP\alice’
14:24:01.976
[evtx/sysmon/7] image C:\Windows\System32\WsmSvc.dll loaded from process C:\Windows\System32\wsmprovhost.exe (pid=9040) with user ‘CORP\alice’
14:24:02.023
[evtx/sysmon/7] image C:\Windows\System32\wsmplpxy.dll loaded from process C:\Windows\System32\wsmprovhost.exe (pid=9040) with user ‘CORP\alice’
14:24:04.425
[evtx/sysmon/7] image C:\Windows\System32\WindowsPowerShell\v1.0\pwrshsip.dll loaded from process C:\Windows\System32\wsmprovhost.exe (pid=9040) with user ‘CORP\alice’
…
…
Event ID 11 – File created
File create operations are logged when a file is created or overwritten. This event is useful for monitoring autostart locations, like the Startup folder, as well as temporary and download directories, which are common places malware drops during initial infection.
On the disk, two PowerShell scripts, generated by Microsoft, are created (__PSScriptPolicyTest_<random_number>.ps1) to test against AppLocker. If the test file executes, then it assumed that AppLocker is disabled. Two Prefetch files for ipconfig, and wsmprovhost.exe binaries are also created, as well as a log file.
Time
Description
14:24:03.978
[evtx/sysmon/11] process C:\Windows\system32\wsmprovhost.exe (pid=9040) created file C:\Users\alice\AppData\Local\Temp\__PSScriptPolicyTest_3yycbqb2.1vu.psm1 with user ‘CORP\alice’
14:24:03.978
[evtx/sysmon/11] process C:\Windows\system32\wsmprovhost.exe (pid=9040) created file C:\Users\alice\AppData\Local\Temp\__PSScriptPolicyTest_jcfqwafa.032.ps1 with user ‘CORP\alice’
14:24:05.722
[evtx/sysmon/11] process C:\Windows\system32\svchost.exe (pid=1860) created file C:\Windows\Prefetch\IPCONFIG.EXE-912F3D5B.pf with user ‘NT AUTHORITY\SYSTEM’
14:24:05.724
[evtx/sysmon/11] process C:\Windows\system32\svchost.exe (pid=1860) created file C:\Windows\Prefetch\CONHOST.EXE-1F3E9D7E.pf with user ‘NT AUTHORITY\SYSTEM’
14:24:06.872
[evtx/sysmon/11] process C:\Windows\system32\wsmprovhost.exe (pid=9040) created file ¨C50C with user ‘CORP\alice’
14:24:06.947
[evtx/sysmon/11] process ¨C51C (pid=1860) created file ¨C52C with user ‘NT AUTHORITY\SYSTEM’
Findings
Now that we have seen the events and other artifacts generated by the execution of the remote-exec winrm commands, let’s dwell on the evidence present natively on a Windows 10 system out of the box.
Winevtx – Microsoft-Windows-Security-Auditing
Without the audit policies enabled, there are not much events generated. However, in both tests, Windows recorded 5 successful logons (event ID 4624) with the logon type ‘3’ (Network) from the compromised account « CORP.LOCAL\alice ». If correlated, this behavior may help during the investigation to support a hypothesis.
Time
Description
14:24:01.836
[evtx/sec/4672] special privileges assigned to ‘CORP\alice’ (S-1-5-21-1155457554-2149841727-2293290625-1108) (logon_id=0x0000000000483901): SeSecurityPrivilege SeBackupPrivilege SeRestorePrivilege SeTakeOwnershipPrivilege SeDebugPrivilege SeSystemEnvironmentPrivilege SeLoadDriverPrivilege SeImpersonatePrivilege SeDelegateSessionUserImpersonatePrivilege
14:24:01.836
[evtx/sec/4624] user ‘CORP.LOCAL\alice’ (S-1-5-21-1155457554-2149841727-2293290625-1108) successfully logon (type=3) from ‘-‘ (‘-‘) (logon_id=0x0000000000483901) with ‘-‘
14:24:03.395
[evtx/sec/4672] special privileges assigned to ‘CORP\alice’ (S-1-5-21-1155457554-2149841727-2293290625-1108) (logon_id=0x0000000000485580): SeSecurityPrivilege SeBackupPrivilege SeRestorePrivilege SeTakeOwnershipPrivilege SeDebugPrivilege SeSystemEnvironmentPrivilege SeLoadDriverPrivilege SeImpersonatePrivilege SeDelegateSessionUserImpersonatePrivilege
14:24:03.395
[evtx/sec/4624] user ‘CORP.LOCAL\alice’ (S-1-5-21-1155457554-2149841727-2293290625-1108) successfully logon (type=3) from ‘-‘ (‘-‘) (logon_id=0x0000000000485580) with ‘-‘
14:24:05.436
[evtx/sec/4672] special privileges assigned to ‘CORP\alice’ (S-1-5-21-1155457554-2149841727-2293290625-1108) (logon_id=0x0000000000487c94): SeSecurityPrivilege SeBackupPrivilege SeRestorePrivilege SeTakeOwnershipPrivilege SeDebugPrivilege SeSystemEnvironmentPrivilege SeLoadDriverPrivilege SeImpersonatePrivilege SeDelegateSessionUserImpersonatePrivilege
14:24:05.436
[evtx/sec/4624] user ‘CORP.LOCAL\alice’ (S-1-5-21-1155457554-2149841727-2293290625-1108) successfully logon (type=3) from ‘-‘ (‘-‘) (logon_id=0x0000000000487c94) with ‘-‘
14:24:06.843
[evtx/sec/4634] user logged off ‘CORP\alice’ (S-1-5-21-1155457554-2149841727-2293290625-1108) (logon_id=0x0000000000487c94) from logon type=3
14:24:06.844
[evtx/sec/4672] special privileges assigned to ‘CORP\alice’ (S-1-5-21-1155457554-2149841727-2293290625-1108) (logon_id=0x00000000004891b0): SeSecurityPrivilege SeBackupPrivilege SeRestorePrivilege SeTakeOwnershipPrivilege SeDebugPrivilege SeSystemEnvironmentPrivilege SeLoadDriverPrivilege SeImpersonatePrivilege SeDelegateSessionUserImpersonatePrivilege
14:24:06.844
[evtx/sec/4624] user ‘CORP.LOCAL\alice’ (S-1-5-21-1155457554-2149841727-2293290625-1108) successfully logon (type=3) from ‘-‘ (‘-‘) (logon_id=0x00000000004891b0) with ‘-‘
14:24:06.868
[evtx/sec/4634] user logged off ‘CORP\alice’ (S-1-5-21-1155457554-2149841727-2293290625-1108) (logon_id=0x0000000000485580) from logon type=3
14:24:06.869
[evtx/sec/4672] special privileges assigned to ‘CORP\alice’ (S-1-5-21-1155457554-2149841727-2293290625-1108) (logon_id=0x00000000004891fe): SeSecurityPrivilege SeBackupPrivilege SeRestorePrivilege SeTakeOwnershipPrivilege SeDebugPrivilege SeSystemEnvironmentPrivilege SeLoadDriverPrivilege SeImpersonatePrivilege SeDelegateSessionUserImpersonatePrivilege
14:24:06.869
[evtx/sec/4624] user ‘CORP.LOCAL\alice’ (S-1-5-21-1155457554-2149841727-2293290625-1108) successfully logon (type=3) from ‘-‘ (‘-‘) (logon_id=0x00000000004891fe) with ‘-‘
14:24:06.871
[evtx/sec/4634] user logged off ‘CORP\alice’ (S-1-5-21-1155457554-2149841727-2293290625-1108) (logon_id=0x00000000004891b0) from logon type=3
14:24:06.905
[evtx/sec/4634] user logged off ‘CORP\alice’ (S-1-5-21-1155457554-2149841727-2293290625-1108) (logon_id=0x00000000004891fe) from logon type=3
Winevtx – Microsoft Windows WinRM
When executed, a successful remote WinRM connection will log an event ID 91 (Creating WSMan shell on servers) within the WinRM event log on the targeted host. Another good indicator to detect WinRM lateral movements is the event ID 6 on the source host:
Cobalt Strike WinRM cmdlets run over PowerShell script, so the PowerShell events ID 600, 400 and 403 are recorded and display the hosted application (C:\Windows\system32\wsmprovhost.exe -Embedding).
time
Description
14:24:04.560
[evtx/powershell/53504] Windows PowerShell has started an IPC listening thread on process: 9040 in AppDomain: ‘DefaultAppDomain
14:24:05.124
[evtx/powershell/600] the PowerShell provider ‘Environment’ hosted by application C:\Windows\system32\wsmprovhost.exe -Embedding with command line » is Started.
14:24:05.124
[evtx/powershell/600] the PowerShell provider ‘Alias’ hosted by application C:\Windows\system32\wsmprovhost.exe -Embedding with command line » is Started.
14:24:05.124
[evtx/powershell/600] the PowerShell provider ‘Registry’ hosted by application C:\Windows\system32\wsmprovhost.exe -Embedding with command line » is Started.
14:24:05.186
[evtx/powershell/600] the PowerShell provider ‘Variable’ hosted by application C:\Windows\system32\wsmprovhost.exe -Embedding with command line » is Started.
14:24:05.186
[evtx/powershell/600] the PowerShell provider ‘Function’ hosted by application C:\Windows\system32\wsmprovhost.exe -Embedding with command line » is Started.
14:24:05.186
[evtx/powershell/600] the PowerShell provider ‘FileSystem’ hosted by application C:\Windows\system32\wsmprovhost.exe -Embedding with command line » is Started.
14:24:05.249
[evtx/powershell/400] the PowerShell engine state hosted by application C:\Windows\system32\wsmprovhost.exe -Embedding with command line » is changed from ‘None’ to ‘Available’.
14:24:06.827
[evtx/powershell/403] the PowerShell engine state hosted by application C:\Windows\system32\wsmprovhost.exe -Embedding with command line » is changed from ‘Available’ to ‘Stopped’.
Prefetch
Prefetch files allow to recover the process chain created and find out that wsrmprovhost has executed the ipconfig programs.
As with Sysmon which showed the creation of Prefetch files (event ID 11 – File Create), the USN journal gives a good overview of what’s happened, from the wsmprovhost.exe execution to the final commands (ipconfig) and the PowerShell execution.
As we saw earlier with Sysmon (event ID 7 – Image Loaded), in that case the MFT can be used to get information on the image loaded by the wsmprovhost.exe program. Indeed, the collection of evidence having been carried out very shortly after the execution, the DLLs accessed by the wsmprovhost.exe program have not (yet) been accessed by other programs, and the timestamps present in the MFT coincide with the binary access.
Reliable artifacts can lead us to the conclusion that WinRM has been used to execute remote commands using Cobalt Strike on the victim workstation:
A PowerShell execution (Microsoft Windows Powershell, event ID 600, 400, 403) host by the application C:\Windows\system32\wsmprovhost.exe -Embedding;
A WinRM connection received (Microsoft Windows WinRM, event ID 91);
Execution traces of the \Windows\SysWOW64\wsmprovhost.exe binary, visible in the MFT, the USN journal or even the Prefetch files.
These events can be accompanied by network authentication as we have seen with the logon type 3 of the user « CORP\alice », as well as other events related to actions performed using WinRM. In our case, the execution of the ipconfig.exe command generated openings of TCP connections as well as the creation/modifications of the Prefetch files.
Detection Rule Example
Splunk queries
To make the detection rule query, for each span time of 15 seconds, we can:
Search for the events ID 91 and event ID 400 where the PowerShell host application name contains the strings wsmprovhost.exe.
Count distinctly the number of event ID (this avoid to trigger the rule if two events with the same « eid » occur).
host="*" index="*" parser=winevtx eid=91 OR (eid=400 AND host_application="*wsmprovhost.exe*")
| bin span=15s _time
| eventstats distinct_count(eid) as dis_count by _time
| where dis_count==2
| table _time eid report_desc dis_count
Both tests are displayed successfully by this requests:
| _time | report_desc | dis_count |
| 14:24:00 | **[evtx/powershell/400]** the PowerShell engine state hosted by application 'C:\Windows\system32\wsmprovhost.exe -Embedding' with command line ''is changed from 'None' to 'Available'. | 2 |
| 14:24:00 | **[evtx/winrm/91]** Creating WSMan shell on server with ResourceURI: 'http://schemas.microsoft.com/powershell/Microsoft.PowerShell' | 2 |
| 14:26:00 | **[evtx/powershell/400]** the PowerShell engine state hosted by application 'C:\Windows\system32\wsmprovhost.exe -Embedding' with command line ''is changed from 'None' to 'Available'. | 2 |
| 14:26:00 | **[evtx/winrm/91]** Creating WSMan shell on server with ResourceURI: 'http://schemas.microsoft.com/powershell/Microsoft.PowerShell' | 2 |
Another way to do it, is by using the Splunk transaction command. This command allow to find transaction that meet various constraints. In our example, the first event transaction must contains the event ID 91, the last event must contains the event ID 400 and the events in the transaction must span less than 5 seconds.
host="*" index="*" sourcetype="lexhunt_json" eid=91 OR (eid=400 AND host_application="*wsmprovhost.exe*")
| transaction parser startswith=eid=91 endswith=eid=400 maxspan=5s
| table _time report_desc duration
| sort _time
| _time | report_desc | duration |
| ---- | ----- | ------ |
| 14:24:02.586 | **[evtx/winrm/91]** Creating WSMan shell on server with ResourceURI: 'http://schemas.microsoft.com/powershell/Microsoft.PowerShell'. **[evtx/powershell/400]** the PowerShell engine state hosted by application 'C:\\Windows\\system32\\wsmprovhost.exe -Embedding' with command line ''is changed from 'None' to 'Available'. | 2.663 |
| 14:26:02.828 | **[evtx/winrm/91]** Creating WSMan shell on server with ResourceURI: 'http://schemas.microsoft.com/powershell/Microsoft.PowerShell'. **[evtx/powershell/400]** the PowerShell engine state hosted by application 'C:\\Windows\\system32\\wsmprovhost.exe -Embedding' with command line ''is changed from 'None' to 'Available'. | 1.234 |
The Cobalt Strike remote-exec wmi command allows the user to execute a command using WMI on the remote host without creating a persistent session with a Beacon. For this test, the command executed is calc.exe.
Sysmon Events
Just like in the case above, we start by observing what Sysmon logs so that we can later compare with extracted artifacts. The Sysmon events below have been filtered to the most useful.
Event ID 1 – Process Create
The process creation event provides extended information about a newly created process. The full command line provides context on the process execution. The ProcessGUID field is a unique value for this process across a domain to make event correlation easier.
The process chain created by the remote-exec wmi commands is WmiPrvSE.exe -> <cmd>. In both of our tests, the program OpenWith.exe is also triggered a moment after by the parent process svchost.exe.
Time
Description
14:28:02.523
[evtx/sysmon/1] process created with command calc.exe (id 8180) by user ‘CORP\alice’ via C:\Windows\System32\wbem\WmiPrvSE.exe (id 10652)
14:28:03.017
[evtx/sysmon/1] process created with command C:\Windows\system32\OpenWith.exe -Embedding (id 8624) by user ‘CORP\alice’ via C:\Windows\System32\svchost.exe (id 728)
Event ID 3 – Network Connection Detected
The network connection event logs TCP/UDP connections on the machine. Each connection is linked to a process through the ProcessId and ProcessGUID fields. The event also contains the source and destination host names IP addresses, port numbers and IPv6 status.
By default, WMI uses a randomly selected dynamic port range for TCP between 49152 and 65535.
Time
Description
14:28:03.331
[evtx/sysmon/3] tcp network connection from host ‘-‘ (192.168.56.119:54136) to host ‘-‘ (192.168.56.117:135) (pid=832)
14:28:03.332
[evtx/sysmon/3] tcp network connection from host ‘-‘ (192.168.56.119:54138) to host ‘-‘ (192.168.56.117:49799) (pid=1760)
14:28:03.583
[evtx/sysmon/3] tcp network connection from host ‘-‘ (192.168.56.117:49800) to host ‘-‘ (192.168.56.119:135) (pid=604)
Event ID 11 – File Create
File create operations are logged when a file is created or overwritten. This event is useful for monitoring autostart locations, like the Startup folder, as well as temporary and download directories, which are common places malware drops during initial infection.
The only interesting files created on the file system are the Preftech files.
Time
Description
14:28:03.430
[evtx/sysmon/11] process C:\Windows\system32\svchost.exe (pid=1860) created file C:\Windows\Prefetch\CALC.EXE-77FDF17F.pf with user ‘NT AUTHORITY\SYSTEM’
14:28:03.435
[evtx/sysmon/11] process C:\Windows\system32\svchost.exe (pid=1860) created file C:\Windows\Prefetch\OPENWITH.EXE-5C93E816.pf with user ‘NT AUTHORITY\SYSTEM’
Findings
Winevtx – Microsoft-Windows-Security-Auditing
Without the audit policies enabled, there are not much events generated. However, in both tests, Windows recorded 4 short connections (event ID 4624) with the logon type ‘3’ (Network) from the compromised account « CORP.LOCAL\alice ». If correlated, this behavior may help during the investigation to support a hypothesis.
Time
Description
14:28:02.083
[evtx/sec/4672] special privileges assigned to ‘CORP\alice’ (S-1-5-21-1155457554-2149841727-2293290625-1108) (logon_id=0x00000000004d811f): SeSecurityPrivilege SeBackupPrivilege SeRestorePrivilege SeTakeOwnershipPrivilege SeDebugPrivilege SeSystemEnvironmentPrivilege SeLoadDriverPrivilege SeImpersonatePrivilege SeDelegateSessionUserImpersonatePrivilege
14:28:02.084
[evtx/sec/4624] user ‘CORP.LOCAL\alice’ (S-1-5-21-1155457554-2149841727-2293290625-1108) successfully logon (type=3) from ‘192.168.56.119’ (‘-‘) (logon_id=0x00000000004d811f) with ‘-‘
14:28:02.232
[evtx/sec/4672] special privileges assigned to ‘CORP\alice’ (S-1-5-21-1155457554-2149841727-2293290625-1108) (logon_id=0x00000000004d8957): SeSecurityPrivilege SeBackupPrivilege SeRestorePrivilege SeTakeOwnershipPrivilege SeDebugPrivilege SeSystemEnvironmentPrivilege SeLoadDriverPrivilege SeImpersonatePrivilege SeDelegateSessionUserImpersonatePrivilege
14:28:02.233
[evtx/sec/4624] user ‘CORP.LOCAL\alice’ (S-1-5-21-1155457554-2149841727-2293290625-1108) successfully logon (type=3) from ‘192.168.56.119’ (‘-‘) (logon_id=0x00000000004d8957) with ‘-‘
14:28:02.244
[evtx/sec/4672] special privileges assigned to ‘CORP\alice’ (S-1-5-21-1155457554-2149841727-2293290625-1108) (logon_id=0x00000000004d89bb): SeSecurityPrivilege SeBackupPrivilege SeRestorePrivilege SeTakeOwnershipPrivilege SeDebugPrivilege SeSystemEnvironmentPrivilege SeLoadDriverPrivilege SeImpersonatePrivilege SeDelegateSessionUserImpersonatePrivilege
14:28:02.248
[evtx/sec/4624] user ‘CORP.LOCAL\alice’ (S-1-5-21-1155457554-2149841727-2293290625-1108) successfully logon (type=3) from ‘192.168.56.119’ (‘-‘) (logon_id=0x00000000004d89bb) with ‘-‘
14:28:02.481
[evtx/sec/4672] special privileges assigned to ‘CORP\alice’ (S-1-5-21-1155457554-2149841727-2293290625-1108) (logon_id=0x00000000004d8bb6): SeSecurityPrivilege SeBackupPrivilege SeRestorePrivilege SeTakeOwnershipPrivilege SeDebugPrivilege SeSystemEnvironmentPrivilege SeLoadDriverPrivilege SeImpersonatePrivilege SeDelegateSessionUserImpersonatePrivilege
14:28:02.481
[evtx/sec/4624] user ‘CORP\alice’ (S-1-5-21-1155457554-2149841727-2293290625-1108) successfully logon (type=3) from ‘192.168.56.119’ (‘DC01’) (logon_id=0x00000000004d8bb6) with ‘-‘
14:28:17.079
[evtx/sec/4634] user logged off ‘CORP\alice’ (S-1-5-21-1155457554-2149841727-2293290625-1108) (logon_id=0x00000000004d811f) from logon type=3
14:28:41.727
[evtx/sec/4634] user logged off ‘CORP\alice’ (S-1-5-21-1155457554-2149841727-2293290625-1108) (logon_id=0x00000000004d8957) from logon type=3
14:28:41.728
[evtx/sec/4634] user logged off ‘CORP\alice’ (S-1-5-21-1155457554-2149841727-2293290625-1108) (logon_id=0x00000000004d8bb6) from logon type=3
14:28:41.728
[evtx/sec/4634] user logged off ‘CORP\alice’ (S-1-5-21-1155457554-2149841727-2293290625-1108) (logon_id=0x00000000004d89bb) from logon type=3
Winevtx – DCOM
Because WMI uses DCOM to handle remote calls, related events may be generated. In our case we get an error about the permission for the COM server with CLSID {3480A401-BDE9-4407-BC02-798A866AC051} (ShellServiceHostBrokerProvider). This error may be specific to the labs, even if the configuration is almost by default.
time
Description
14:28:02.595
[evtx/dcom/10016] the application-specific permission settings do not grant Local Activation permission for the COM Server application with CLSID {3480A401-BDE9-4407-BC02-798A866AC051} and APPID {30AD8C8E-AE85-42FA-B9E8-7E99E3DFBFC5} to the user ‘CORP\alice’ (S-1-5-21-1155457554-2149841727-2293290625-1108) from address LocalHost (Using LRPC) running in the application container Unavailable SID Unavailable
14:28:03.342
[evtx/dcom/10016] the application-specific permission settings do not grant Local Activation permission for the COM Server application with CLSID {3480A401-BDE9-4407-BC02-798A866AC051} and APPID {30AD8C8E-AE85-42FA-B9E8-7E99E3DFBFC5} to the user ‘CORP\alice’ (S-1-5-21-1155457554-2149841727-2293290625-1108) from address LocalHost (Using LRPC) running in the application container Unavailable SID Unavailable
14:28:03.359
[evtx/dcom/10016] the application-specific permission settings do not grant Local Activation permission for the COM Server application with CLSID {3480A401-BDE9-4407-BC02-798A866AC051} and APPID {30AD8C8E-AE85-42FA-B9E8-7E99E3DFBFC5} to the user ‘CORP\alice’ (S-1-5-21-1155457554-2149841727-2293290625-1108) from address LocalHost (Using LRPC) running in the application container Unavailable SID Unavailable
Prefetch files, USNjrnl and MFT
The Prefetch, USNjrnl and MFT artifacts shows that the calc.exe and openwith.exe programs have been executed.
This is probably the hardest Cobalt Strike command to detect because not many events are generated. The most accurate artifacts to know that the command remote-exec wmi has been executed are:
The openwith.exe observable among Prefetch files;
Many short successful logons (Microsoft Windows Security Auditing, event ID 4624) with logon type ‘3’ (Network);
Some DCOM events, such as warnings (DCOM, event ID 10016).
Detection Rule Example
Splunk queries
To make the detection rule query, for each span time of 10 seconds, we can:
Search 1 event where the Prefetch executable name is openwith.exe
Search 4 logon connection (with logon type 3).
We cannot reuse the previous query because Prefetch events has no field « eid ». The first attempt was this query:
host="*" index="*" (parser=prefetch AND executable="OPENWITH.EXE") OR (parser=winevtx AND eid=4624 AND logon_type=3)
| bin span=10s _time
| eventstats count by _time
| where count>=5
| table _time parser report_desc count
| sort _time
But it generates multiple false positives because 5 events with eid 4624 may occur in 10 seconds without the needed Prefetch events:
| _time | parser | report_desc | count |
| 14:26:00 | winevtx | **[evtx/sec/4624]** user 'CORP.LOCAL\alice' (S-1-5-21-1155457554-2149841727-2293290625-1108) successfully logon (type=3) from '-' ('-') (logon_id=0x00000000004ae65c) with '-' | 5 |
| 14:26:00 | winevtx | **[evtx/sec/4624]** user 'CORP.LOCAL\alice' (S-1-5-21-1155457554-2149841727-2293290625-1108) successfully logon (type=3) from '-' ('-') (logon_id=0x00000000004ae638) with '-' | 5 |
| 14:26:00 | winevtx | **[evtx/sec/4624]** user 'CORP.LOCAL\alice' (S-1-5-21-1155457554-2149841727-2293290625-1108) successfully logon (type=3) from '-' ('-') (logon_id=0x00000000004ad37e) with '-' | 5 |
| 14:26:00 | winevtx | **[evtx/sec/4624]** user 'CORP.LOCAL\alice' (S-1-5-21-1155457554-2149841727-2293290625-1108) successfully logon (type=3) from '-' ('-') (logon_id=0x00000000004acafc) with '-' | 5 |
| 14:26:00 | winevtx | **[evtx/sec/4624]** user 'CORP.LOCAL\alice' (S-1-5-21-1155457554-2149841727-2293290625-1108) successfully logon (type=3) from '-' ('-') (logon_id=0x00000000004abf4b) with '-' | 5 |
| 14:28:00 | prefetch | **[prefetch]** Prefetch [OPENWITH.EXE] was executed - run count 3 path hints: \WINDOWS\SYSTEM32\OPENWITH.EXE hash: 0x5C93E816 volume: 1 [serial number: 0x228095FD device path: \VOLUME{01d80e8a80662822-228095fd}] | 5 |
| 14:28:00 | winevtx | **[evtx/sec/4624]** user 'CORP\alice' (S-1-5-21-1155457554-2149841727-2293290625-1108) successfully logon (type=3) from '192.168.56.119' ('DC01') (logon_id=0x00000000004d8bb6) with '-' | 5 |
| 14:28:00 | winevtx | **[evtx/sec/4624]** user 'CORP.LOCAL\alice' (S-1-5-21-1155457554-2149841727-2293290625-1108) successfully logon (type=3) from '192.168.56.119' ('-') (logon_id=0x00000000004d89bb) with '-' | 5 |
| 14:28:00 | winevtx | **[evtx/sec/4624]** user 'CORP.LOCAL\alice' (S-1-5-21-1155457554-2149841727-2293290625-1108) successfully logon (type=3) from '192.168.56.119' ('-') (logon_id=0x00000000004d8957) with '-' | 5 |
| 14:28:00 | winevtx | **[evtx/sec/4624]** user 'CORP.LOCAL\alice' (S-1-5-21-1155457554-2149841727-2293290625-1108) successfully logon (type=3) from '192.168.56.119' ('-') (logon_id=0x00000000004d811f) with '-' | 5 |
So, we need to count distinctly by parser as well:
host="*" index="*" (parser=prefetch AND executable="OPENWITH.EXE") OR (parser=winevtx AND eid=4624 AND logon_type=3)
| bin span=10s _time
| eventstats count by _time
| eventstats distinct_count(parser) as parser_dis_count by _time
| where parser_dis_count > 1 AND count >= 4
| table _time parser report_desc count parser_dis_count
| sort _time
The results:
| _time | parser | report_desc | count | parser_dis_count |
| 14:28:00 | prefetch | **[prefetch]** Prefetch [OPENWITH.EXE] was executed - run count 3 path hints: \WINDOWS\SYSTEM32\OPENWITH.EXE hash: 0x5C93E816 volume: 1 [serial number: 0x228095FD device path: \VOLUME{01d80e8a80662822-228095fd}] | 5 | 2 |
| 14:28:00 | winevtx | **[evtx/sec/4624]** user 'CORP\alice' (S-1-5-21-1155457554-2149841727-2293290625-1108) successfully logon (type=3) from '192.168.56.119' ('DC01') (logon_id=0x00000000004d8bb6) with '-' | 5 | 2 |
| 14:28:00 | winevtx | **[evtx/sec/4624]** user 'CORP.LOCAL\alice' (S-1-5-21-1155457554-2149841727-2293290625-1108) successfully logon (type=3) from '192.168.56.119' ('-') (logon_id=0x00000000004d89bb) with '-' | 5 | 2 |
| 14:28:00 | winevtx | **[evtx/sec/4624]** user 'CORP.LOCAL\alice' (S-1-5-21-1155457554-2149841727-2293290625-1108) successfully logon (type=3) from '192.168.56.119' ('-') (logon_id=0x00000000004d8957) with '-' | 5 | 2 |
| 14:28:00 | winevtx | **[evtx/sec/4624]** user 'CORP.LOCAL\alice' (S-1-5-21-1155457554-2149841727-2293290625-1108) successfully logon (type=3) from '192.168.56.119' ('-') (logon_id=0x00000000004d811f) with '-' | 5 | 2 |
| 14:30:00 | prefetch | **[prefetch]** Prefetch [OPENWITH.EXE] was executed - run count 3 path hints: \WINDOWS\SYSTEM32\OPENWITH.EXE hash: 0x5C93E816 volume: 1 [serial number: 0x228095FD device path: \VOLUME{01d80e8a80662822-228095fd}] | 5 | 2 |
| 14:30:00 | winevtx | **[evtx/sec/4624]** user 'CORP\alice' (S-1-5-21-1155457554-2149841727-2293290625-1108) successfully logon (type=3) from '192.168.56.119' ('DC01') (logon_id=0x0000000000598fa4) with '-' | 5 | 2 |
| 14:30:00 | winevtx | **[evtx/sec/4624]** user 'CORP.LOCAL\alice' (S-1-5-21-1155457554-2149841727-2293290625-1108) successfully logon (type=3) from '192.168.56.119' ('-') (logon_id=0x0000000000598ee4) with '-' | 5 | 2 |
| 14:30:00 | winevtx | **[evtx/sec/4624]** user 'CORP.LOCAL\alice' (S-1-5-21-1155457554-2149841727-2293290625-1108) successfully logon (type=3) from '192.168.56.119' ('-') (logon_id=0x0000000000598ed0) with '-' | 5 | 2 |
| 14:30:00 | winevtx | **[evtx/sec/4624]** user 'CORP.LOCAL\alice' (S-1-5-21-1155457554-2149841727-2293290625-1108) successfully logon (type=3) from '192.168.56.119' ('-') (logon_id=0x0000000000598e96) with '-' | 5 | 2 |
Other rules can be created by adding the DCOM events.
Cobalt Strike remote-exec psexec
The Cobalt Strike remote-exec psexec command allows the user to execute a command using PsExec on the remote host without creating a persistent session with a Beacon. It creates and start a service remotely with random Service Name1 and then passed on command as Service File Name. For this test, the command executed is notepad.exe.
Sysmon Events
One last time, as in the two previous cases, the Sysmon events are recorded in order to serve as elements of comparison with the other artifacts collected on the workstation. The Sysmon events below has been filtered to the most useful.
Event ID 1 – Process Creation
The process creation event provides extended information about a newly created process. The full command line provides context on the process execution. The ProcessGUID field is a unique value for this process across a domain to make event correlation easier.
Cobalt Strike creates a service to run the arbitrary command with the SYSTEM rights so the process chain is services.exe -> notepad.exe.
Time
Description
14:32:05.936
[evtx/sysmon/1] process created with command notepad.exe (id 8516) by user ‘NT AUTHORITY\SYSTEM’ via C:\Windows\System32\services.exe (id 596)
Event ID 3 – Network Connection Detected
The network connection event logs TCP/UDP connections on the machine. Each connection is linked to a process through the ProcessId and ProcessGUID fields. The event also contains the source and destination host names IP addresses, port numbers and IPv6 status.
Two connections are recorded, one to the TCP port 135 and the second to a random TCP port.
Time
Description
14:32:06.749
[evtx/sysmon/3] tcp network connection from host ‘-‘ (192.168.56.119:54206) to host ‘-‘ (192.168.56.117:135) (pid=832)
14:32:06.750
[evtx/sysmon/3] tcp network connection from host ‘-‘ (192.168.56.119:54207) to host ‘-‘ (192.168.56.117:49692) (pid=596)
Event ID 11 – File Create
File create operations are logged when a file is created or overwritten. This event is useful for monitoring autostart locations, like the Startup folder, as well as temporary and download directories, which are common places malware drops during initial infection.
Because the process services.exe is already running, only one Prefetch file is generated.
Time
Description
14:32:16.064
[evtx/sysmon/11] process C:\Windows\system32\svchost.exe (pid=1860) created file C:\Windows\Prefetch\NOTEPAD.EXE-D8414F97.pf with user ‘NT AUTHORITY\SYSTEM’
Event ID 13 – Registry Value Set
Registry key and value create and delete operations map to this event type.
Cobalt Strike creates a service to run the arbitrary command, so a registry key with a random name is created under HKLM\System\CurrentControlSet\Services\d8041e9 by the Services.exe process and the ImagePath is set to the arbitrary commands to execute.
Time
Description
14:32:05.923
[evtx/sysmon/13] registry event : user ‘NT AUTHORITY\SYSTEM’ process C:\Windows\system32\services.exe (pid 596) has set HKLM\System\CurrentControlSet\Services\d8041e9\ErrorControl value to DWORD (0x00000000)
14:32:05.923
[evtx/sysmon/13] registry event : user ‘NT AUTHORITY\SYSTEM’ process C:\Windows\system32\services.exe (pid 596) has set HKLM\System\CurrentControlSet\Services\d8041e9\Start value to DWORD (0x00000003)
14:32:05.923
[evtx/sysmon/13] registry event : user ‘NT AUTHORITY\SYSTEM’ process C:\Windows\system32\services.exe (pid 596) has set HKLM\System\CurrentControlSet\Services\d8041e9\Type value to DWORD (0x00000010)
14:32:05.925
[evtx/sysmon/13] registry event : user ‘NT AUTHORITY\SYSTEM’ process ¨C147C (pid 596) has set ¨C148C value to ¨C149C
14:32:05.925
[evtx/sysmon/13] registry event : user ‘NT AUTHORITY\SYSTEM’ process ¨C150C (pid 596) has set ¨C151C value to ¨C152C
Findings
Winevtx – Microsoft Windows Security Auditing
Without the audit policies enabled, there are not much events generated. Only one successful logons (event ID 4624) is recorded, with the logon type ‘3’ (Network) from the compromised account « CORP.LOCAL\alice ». If correlate, this behavior may help during the investigation to support an hypothesis.
Time
Description
14:32:05.736
[evtx/sec/4672] special privileges assigned to ‘CORP\alice’ (S-1-5-21-1155457554-2149841727-2293290625-1108) (logon_id=0x00000000005eda88): SeSecurityPrivilege SeBackupPrivilege SeRestorePrivilege SeTakeOwnershipPrivilege SeDebugPrivilege SeSystemEnvironmentPrivilege SeLoadDriverPrivilege SeImpersonatePrivilege SeDelegateSessionUserImpersonatePrivilege
14:32:05.819
[evtx/sec/4624] user ‘CORP.LOCAL\alice’ (S-1-5-21-1155457554-2149841727-2293290625-1108) successfully logon (type=3) from ‘192.168.56.119’ (‘-‘) (logon_id=0x00000000005eda88) with ‘-‘
14:36:11.728
[evtx/sec/4634] user logged off ‘CORP\alice’ (S-1-5-21-1155457554-2149841727-2293290625-1108) (logon_id=0x00000000005eda88) from logon type=3
Winevtx – Service Control Manager
In that particular case, the most useful Windows logs generated is the event ID 7045 (a service randomly named was installed by user ‘LocalSystem’). In this case, we choose to run notpad.exe, but it would be interesting to monitor services.exe child process for malicious behavior like spawning system shells using cmd.exe and powershell.exe or some discovery behavior like whoami.exe, systeminfo.exe, net.exe, etc.
Time
Description
14:32:05.920
[evtx/sys/scm/7045] service ‘d8041e9’ (notepad.exe) was installed by user ‘LocalSystem’ (type: user mode service, start: demand start)
Prefetch and USNjrnl
The Prefetch files shows only the binary called by services.exe, and the only activity recorded by the USN journal is access to the Prefetch file.
The use of remote-exec psexec causes the installation of a randomly named service on the targeted host, which is particularly visible in the logs of the Service Control Manager: the 7045 event records the creation of the service as well as the name of the child process which is executed. Other artifacts may be correlated with the creation of this service, in particular the creation of Prefetch files associated with the child process, or the successful logon (event ID 4624) of the account used to create the malicious service.
Detection Rule Example
Splunk queries
In a forensics context, a simple query enumerating the services installed (Service Control Manager, event ID 7045) should be enough, the randomness of the service name and the child process visually identifying illegitimate services. However, you can also add to the query the successful logons (event ID 4624):
host="*" index="*" (parser=winevtx AND eid=7045) OR (parser=winevtx AND eid=4624 AND logon_type=3)
| bin span=1m _time
| eventstats distinct_count(eid) as dis_count by _time
| where dis_count==2
| table _time eid report_desc dis_count
| sort _time
| _time | eid | report_desc | dis_count |
| 14:32:00 | 7045 | **[evtx/sys/scm/7045]** service 'd8041e9' (notepad.exe) was installed by user 'LocalSystem' (type: user mode service, start: demand start) | 2 |
| 14:32:00 | 4624 | **[evtx/sec/4624]** user 'CORP.LOCAL\alice' (S-1-5-21-1155457554-2149841727-2293290625-1108) successfully logon (type=3) from '192.168.56.119' ('-') (logon_id=0x00000000005eda88) with '-' | 2 |
Or you can select only the events where the service name is only 7 characters long:
The hardest Cobalt Strike command to detect is probably the remote-exec wmi because it does not create a service like remote-exec psexec or use PowerShell like remote-exec winrm. We can notice that each remote-exec commands generated a specific number of successful logons to the victim (event id 4624). As a reminder, remote-exec commands can be triggered detecting the following behavior:
remote-exec winrm
A PowerShell execution (Microsoft Windows Powershell, event ID 600, 400, 403) host by the application C:\Windows\system32\wsmprovhost.exe -Embedding;
A WinRM connection received (Microsoft Windows WinRM, event ID 91);
Execution traces of the \Windows\SysWOW64\wsmprovhost.exe binary, visible in the MFT, the USN journal or even the Prefetch files;
Many successful logons (Microsoft Windows Security Auditing, event ID 4624) with logon type ‘3’ (Network).
remote-exec wmi
The openwith.exe observable among Prefetch files;
Many short successful logons (Microsoft Windows Security Auditing, event ID 4624) with logon type ‘3’ (Network);
Some DCOM events, such as warnings (DCOM, event ID 10016).
remote-exec psexec
The installation of a randomly named service (Service Control Manager, event ID 7045) running suspicious binaries;
One successful logon (Microsoft Windows Security Auditing, event ID 4624) with logon type ‘3’ (Network).
To detect lateral movements more efficiently, we advise installing Sysmon with a custom configuration and/or to activate more audit policies.
By default the command elevate svc-exe, jump psexec, jump psexec64, jump psexec_psh and remote-exec psexec use a service name that consists of random letters and numbers. The Cobalt Strike Aggressor Script PSEXEC_SERVICE hook allows you to change this behavior. ↩
The analyzed sample was found on the public platform MalwareBazaar and its sha256sum is 10ab76cd6d6b50d26fde5fe54e8d80fceeb744de8dbafddff470939fac6a98c4. Based on the ELF header, it was compiled with GCC 4.4.7.
$ readelf -p .comment 10ab76cd6d6b50d26fde5fe54e8d80fceeb744de8dbafddff470939fac6a98c4.elf
String dump of section '.comment':
[ 0] GCC: (GNU) 4.4.7 20120313 (Red Hat 4.4.7-23)
Obviously, the binary is stripped and does not contain any symbols:
$ nm 10ab76cd6d6b50d26fde5fe54e8d80fceeb744de8dbafddff470939fac6a98c4.elf
nm: 10ab76cd6d6b50d26fde5fe54e8d80fceeb744de8dbafddff470939fac6a98c4.elf: no symbols
The ELF header also contains the sections .ctors and .dtors. The .ctors section contains a list of functions ran before the main function to initialize dynamic non-local variables.
$ readelf -S ./10ab76cd6d6b50d26fde5fe54e8d80fceeb744de8dbafddff470939fac6a98c4.elf
Section Headers:
[Nr] Name Type Address Offset
Size EntSize Flags Link Info Align
[ 0] NULL 0000000000000000 00000000
0000000000000000 0000000000000000 0 0 0
[ 1] .interp PROGBITS 0000000000400200 00000200
000000000000001c 0000000000000000 A 0 0 1
....
snip
....
[19] .ctors PROGBITS 0000000000757000 00157000
00000000000000a0 0000000000000000 WA 0 0 8
[20] .dtors PROGBITS 00000000007570a0 001570a0
0000000000000010 0000000000000000 WA 0 0 8
The last constructor function called initializes three strings, the ransom notes, the sample ID, and base64 strings:
The decoded base64 strings are 88-byte long and at first sight I couldn’t figure out what it was.
Finally, three objects are initialized, two of them will hold a public and private key, and one is for the random generator. These objects come from the crypto++ library.
Main function
No technique has been set up to obfuscate and protect the ransomware. The ransomware is basic and accepts two parameters, the number of threads to be used and the directories to encrypt:
If one of the given paths contains the strings « esxi » or « vmfs », a global variable is set to true and the running VMs (virtual machines) are killed using the esxcli command line:
Finally, it will browse the given lists of directories recursively, load the attackers’ public key and build a list of files that the encryption thread routine will consume.
Generating the list of files to encrypt
The function that builds the list of files to encrypt is simple. First, it calls « opendir » with the directory path name to encrypt, and then, using « readdir », it iterates through the files in the directory. If it is a regular file and the name is not « README_FOR_RESTORE » or it does not end with the « .avoslinux » or « .avos2 » extension, it is added to the global list. If the esxi global variable is set to true, only files that end with « .vmdk », « .vmem », « .vswp », « .vmsn » or « .log » are added to the list:
Unlike most Windows pieces of ransomware, that only encrypt data files based on their extension name using a whitelist or a blacklist, this Linux variant may encrypt all the files, including system files.
Load the attackers’ public key
Because the ransomware uses the crypto++ library, we recognize the particular concept of filters and pipes used by the library in the reversed code. Similarly to Unix, Pipes allows data flows from a source to a sink and filters them to transform them. The original function that decodes and loads the base64 attackers’ public key would probably look like this:
AutoSeededRandomPool prng;
string encoded = "MFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAE9U+h7UA0Do9mVDFVJM9Gj5Qi/5zn2b/5dH9qFMApEmVngoc4zlLk49U1iWc2l+in2CtyQb+/+JKvyPvack9gw==";
string decoded;
StringSource ss(encoded, true, new Base64Decoder( new StringSink(decoded)));
ECIES<ECP>::Encryptor e0;
e0.AccessPublicKey().Load(decoded);
e0.GetPublicKey().ThrowIfInvalid(prng, 3); // Validate the public key
Encryption
To encrypt files on the disk, Avoslinux uses the Salsa20 stream ciphers using the 12-round variant. For each file to encrypt, it generates a 32-byte long Salsa key and an 8-byte long nonce.
The generated key and nonce are passed to the function « ECIES_n_b64 » to be encrypted using the ECIES (Elliptic Curve Integrated Encryption Scheme) crypto scheme, and then base64-encoded.
The function would probably look like this:
string key_nonce;
StringSource ss1 (key_nonce, true, new PK_EncryptorFilter(prng, e0, new Base64Encoder( new StringSink(b64_ecies_key_nonce))));
The ECIES-encrypted output is bigger than the original: 125-byte long. Based on the crypto++ ECIES documentation, « The output of the encryption function is the tuple {K,C,T}, where K is the encrypted common secret, C is the ciphertext, and T is the authentication tag. »
The number of Salsa rounds is set:
The file is encrypted using the Salsa20/12 algorithm, and the key with the previously encrypted nonce (ECIES and base64) is appended to the end of the file.
Then, the file is renamed by appending the « .avoslinux » extension to the file.
Finally, the Salsa key and the nonce are erased from the memory:
Conclusion
The Linux variant is very simple and has no special features like network encryption or any anti-reverse techniques to obfuscate codes. The encryption process is not common for a piece of ransomware and it is different from the Windows variant, which uses the RSA and AES combination. Another thing to note is that unlike most Windows pieces of ransomware, that only encrypt data files based on their extension name using a whitelist or a blacklist, this Linux variant may encrypt all the files, including system files.
Since the last blog post from Proofpoint about the version 4 of DanaBot, the new samples available in Threat Intel repository integrate minor changes in their architecture and communications. This short blog post is about the differences spot between those different versions. As a reminder, you can find details on the four major versions here:
Unlike the previous versions, the latest samples found in public repositories included a component that first downloaded and loaded the main module along with configurations and plugins. That’s why two TCP stream appear instead of one in the version 4:
The first TCP connection comes from the Downloader, who downloads the main module (about 14 Mb of encrypted and compressed data) and the second one from the main module itself (similar to version 4).
Downloader Communication Protocol
To download the main module, the Downloader sends two requests:
The requests sent above respect the DanaBot communication protocol described by ESET. The first packet is used to transmit the new RSA public key generated on the host, and the second one is a packet with a very specific structure used to send instructions and data to the C2.
Like version 4, the packet structure is binary format and has a plaintext header (0x1C-bytes long). The packet data structure size is lower than version 4 with 455 bytes and some hashes embedded in the structure are formatted differently. Indeed, before all hashes were formatted using the Delphi TMemoryStream classes and now only the « random hash » has kept this format. You can find below the packet structure used by the Downloader to download the main module:
Offset
Size
Name
Notes
0x00
4-bytes
Packet length
0x04
8-bytes
Random value
0x0C
8-bytes
Checksum
Packet length + random value
0x14
4-bytes
Affiliate ID
Hardcoded field embedded in the Downloader
0x18
4-bytes
Command
Command to send (2048)
0x1c
4-bytes
Sub-Command
Sub-command to send (0)
0x20
60-bytes
Remaining null bytes
[0x5c
1-byte
Embedded hash length
0x5d]
32-bytes
Embedded hash value
Embedded hash in the Downloader
[0x7d
1-byte
Embedded hash length
0x7e]
32-bytes
Embedded hash value
This hash should be the same as above but it can be an embedded hash from an old/new sample. The downloaded module will vary according to this hash.
[0x9e
1-byte
Checksum Hash length
0x9f]
32-bytes
Checksum value
MD5 uppercase hex digest of affiliate ID, and the two previous hash values concatenated together
[0xbf
4-bytes
Random hash length
Raw Delphi TMemoryStream format
0xc3
4-bytes
Random hash CRC32
0xc7]
33-bytes
Random hash value
0xe8
remaining
Remaining null bytes
You can find below an example of request generated and sent by the Downloader to download the main module:
Each data received from the C2 is encrypted using AES and the key located in the last 80 bytes is itself encrypted using RSA. The needed RSA key is the private key generated by the Downloader.
Main Module Decryption
The main module is protected by a second layer of encryption on top of DanaBot communication. Indeed, the module is encrypted using the same technics, but the needed RSA key is the one embedded in the Downloader.
The AES deciphering is using CBC mode with a null IV and it operates by blocks of 0x10010 bytes. It can be resumed with the following scripts:
The uncompressed data is a DLL (the main module) similar to the unpack main module in version 4, although it seems bigger with a size around 18M. Further communications from the main module are similar to version 4 as described in the Proofpoint blog post, except that the data structure is the same as talked previously:
DanaBot commands
DanaBot commands and sub-commands are used to indicate to the recipient how to handle data. On the version analyzed, all the main commands (with id 2048) and sub-commands described by Proofpoint are still present except for the sub-command 10 since the Tor module is already included.
Commands 2048, Sub-command 6
This sub-command is used for online functionalities, that’s why C2 reply may be empty. By analyzing these parts, two « online » functionalities were added. The first one may still be under development. Indeed, except the strings « InstallRDP » found in the function, nothing much is done.
The second one is very similar to the stealer plugin (started in a thread at the beginning of the process) and the following information is gathered on the victim host:
Vault Credentials
OS
Computer name
Local Country
Language
Actual Time
WinKey
Desktop
Uptime
HDDs
Browsers on the host
Processes running
Default browser
Installed programs path
Installed programs names
OS Name
OS Version
System Manufacturer
System Model
System Type
Processor Name
Network Card
Connection Name
Network Status
DHCP Enabled
DHCP Server
IP address
MAC Address
Mute
Volume
Wifi
Bluetooth
Printer
Wallpaper path
Tray
SystemHiddenFiles
BiosTime
IsBattery
PowerLevel
Logical processor count
NUMA Node count
Processor Core count
Commands 2048, Sub-command 3
This sub-command is mainly used to activate/deactivate plugins and set options. First, the main module is asking to the C2 the list of « CommandRecords » available by sending the sub-command 2. A list of hashes is received:
Then, for each of those hashes, the sub-command 3 is sent with the « CommandRecords » hash in parameters. In the data received, there is a command field that indicates to the main module how to handle and what to do with the payload located at the packet end:
In a few weeks, the hardcoded version embedded in each sample has increased 2 or 3 times, meaning that the Trojan DanaBot is still under active development. We expect to see other new features coming in the near future and maybe another blog post with more details.