Demystifying Windows Malware Hunting — Part 1 — Detecting Persistence with osquery

Gabriel Pirjolescu
13 min readMar 26, 2020

--

The idea for this series came up when I realised that I don’t have a lot of experience with how Windows malware operates and how to look for indicators on a system already compromised. Therefore, I have decided to dive into the different techniques used to hunt for malware. The purpose of the series is to explain how malware works on Windows to users with no previous security experience, but with a basic understanding of operating system concepts. Besides, I will explain where to look for malware artifacts and some tools to discover them.

In this post, I will try to describe the methods used by malware to achieve persistence on a system. Persistence incorporates how a program makes sure that it will be started again after a system shut down, or maintains access to the system after alterations that would normally cut off the access, like changing credentials.

Setup

The actions shown in this post can be performed locally on the infected machine, or remotely from another host. I am more comfortable to work from my own machine, thus I will explain how I have set up my environment. However, you can skip this entirely if you want to do it locally on the infected machine.

The first step was to enable Remote Desktop (RDP) on the remote host, so I can have easy access to it. This article shows step-by-step how to do it. If your local host is also Windows, the RDP client comes pre-installed. However, if you have a Linux host, you will need to install additional software. Remmina is the perfect tool for this since it works flawlessly.

In addition to RDP, I also like to have a command-line connection. Windows 10 comes with an OpenSSH package that can be installed and configured. This Microsoft post explains how to do it. However, I never managed to set the right permissions on the installation folder so I wasn’t able to start the service. The alternative was to use this implementation. Here you can find the installation instruction. Keep in mind to run FixHostFilePermissions.ps1 and FixUserFilePermissions.ps1 before starting the service.

I have to mention that you need to be on the same network for both types of connections to work. It is possible to connect from different networks, but this is beyond the scope of this article.

Persistence

The tools used for this post are osquery and RegRipper. osquery is a tool developed by Facebook that works on Windows, OS X, Linux and FreeBSD and exposes an operating system as a high-performance relational database. You can use it to explore what is happening in the OS in real-time or configure it to take snapshots at different intervals and log it in a database. On the other hand, RegRipper is a tool for extracting and parsing information from the registry hive. As a methodology, I have chosen to parse all the Mitre Att&Ck persistence techniques, explain and look for them one-by-one. Some of the osquery queries were inspired by this very useful project.

https://osquery.io/

Before starting, I would also like to explain an important term. Dynamic Link Libraries (DLLs) are similar to dynamically link shared object libraries (.so) files in Linux. They are used to expose functions for executables to use. Therefore, to avoid adding boilerplate code in an executable and increasing the size too much, reusable (system and not only) functions are stored in DLLs that have their names hard-coded in the executables. When it executes, the binary loads the functionalities from the DLLs.

Accessibility Features

Windows give the possibility for an accessibility feature to be enabled by pressing a key combination before user login. The two programs usually launched by this feature are C:\Windows\System32\sethc.exe (when the shift key is pressed five times) and C:\Windows\System32\utilman.exe (when the key combination Windows+U is pressed).

An attacker can potentially replace the binaries with malicious ones, or modify a registry key to configure another program as a debugger for the accessibility ones. On newer versions of Windows, the binary replacing these two must be signed, placed in %systemdir%\ and protected by Windows File or Resource Protection.

To detect replacement, check the binaries manually. For the debugger attack, the registry key HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options can be looked into by using the query below. Next, check each of the subkeys if they have a Debugger entry attached. The debugger method can be used as a stand-alone persistence used with any usual system program.

osquery> select name, type, data from registry where key='HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options';

AppCert DDLs

Dynamic Link Libraries mentioned in the AppCert DLLs registry key HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Session Manager are loaded into every process that calls the techniques following functions from the Windows API CreateProcess, CreateProcessAsUser, CreateProcessWithLoginW, CreateProcessWithTokenWand WinExec.

To extract the AppCert DLLs we can use RegRipper. Keep in mind that we can’t access any of the registry hives directly. Therefore, we’ll have to save them to another location. After extracting the list of DLLs, we can submit it to Virus Total for a scan if we don’t spot anything suspicious just by looking at them (this is valid for any of the other hunting methods where we get a list of DLLs).

# Save a copy of the registry hive to use it
reg save HKLM\SYSTEM C:\system
# Extract the information using the appcertdlls plugin
rip.exe -r C:\system -p appcertdlls > appcertdlls.txt

AppInit DLLs

Similar to the AppCert DLLs, AppInit DLLs are loaded into every process that loads user32.dll. This means almost every program since user32.dll is used nearly everywhere. The registry keys used are HKEY_LOCAL_MACHINE\Software\Microsoft\Windows NT\CurrentVersion\Windows and HKEY_LOCAL_MACHINE\Software\Wow6432Node\Microsoft\Windows NT\CurrentVersion\Windows. AppInit DLLs are disabled in Windows 8 and higher when secure boot is enabled.

RegRipper also has a plugin for extracting these.

# Save a copy of the registry hive to use it
reg save HKLM\SYSTEM C:\system
# Extract the information using the appinitdlls plugin
rip.exe -r C:\system -p appinitdlls > appinitdlls.txt

Application Shimming

Windows needed a way to allow for backward compatibility of software when the OS changes functionalities. To achieve this they introduced Microsoft Windows Application Compatibility Framework. It allows developers to apply fixes to an application without rewriting code. When a binary is executed, the shim cache tells it if it needs to use the shim database. If so, hooking is used to redirect the code. To detect it we can perform several queries.

# Find shim databases
osquery> select name, type, data from registry where key='HKEY_LOCAL_MACHINE\software\microsoft\windows nt\currentversion\appcompatflags\installedsdb';
osquery> select name, type, data from registry where key='HKEY_LOCAL_MACHINE\software\microsoft\windows nt\currentversion\appcompatflags\custom\setuphost.exe';

Authentication Package

Authentication Package DLLs are loaded by the Local Security Authority (LSA) at system start. The attacker can use the registry location HKLM\SYSTEM\CurrentControlSet\Control\Lsa\with the key "Authentication Packages". The executable in the value will be executed when the authentication package is loaded.

osquery> select name, type, data from registry where key='HKEY_LOCAL_MACHINE\system\CurrentControlSet\Control\Lsa\Authentication Package';

BITS Jobs

Background Intelligent Transfer Service (BITS) is a file transfer mechanism used in Windows machines. It operates in the background, asynchronously, without interrupting other applications. Tasks can be queued for BITS and it is accessible through PowerShell and BITSAdmin tools. BITS allows persistence by creating long-standing jobs or invoking an arbitrary program when a job completes or errors. The only way to hunt for this is to check if it was previously run.

osquery> select * from file WHERE directory = 'C:\Windows\Prefetch\' and filename like '%bitsadmin%';

Browser Extensions

Malicious browser extensions can be used by attackers to browse to websites in the background, steal all information that a user enters into a browser, include credentials and install other malicious pieces of software on the machine.

osquery> select u.username, ce.name, ce.identifier, ce.version, ce.description, ce.locale, ce.update_url, ce.author, ce.persistent, ce.path from chrome_extensions ce 
LEFT JOIN users u ON ce.uid = u.uid;

File Association

File associations are used to check the default program (associated with a file extension) when a file is open. File associations are stored in the registry and can be modified to change the association for a file. They are stored under HKEY_CLASSES_ROOT. A user can override its preferences by adding subkeys to HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\FileExts.

# Get the list of extensions
osquery> select name, type, data from registry where key='HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\FileExts';
# Example for the .txt extension
osquery> select name, type, data from registry where key='HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\FileExts\.txt\OpenWithList';
+---------+--------+-------------+
| name | type | data |
+---------+--------+-------------+
| a | REG_SZ | chrome.exe |
| b | REG_SZ | ba |
| c | REG_SZ | cab |
| MRUList | REG_SZ | adbc |
| d | REG_SZ | notepad.exe |
+---------+--------+-------------+

Component Object Model Hijacking

The Component Object Model (COM) is used by Windows to enable interaction between different parts of the system. Attackers can hijack the references and relationships used by inserting malicious code. To do this a registry change is required so that it breaks the execution. This leads to the attacker’s object being executed instead.

First, entries in HKEY_CURRENT_USER\Software\Classes\CLSID\ should be investigated since objects that reside there are loaded before machine objects in HKEY_LOCAL_MACHINE\SOFTWARE\Classes\CLSID\.

# Find all the subkeys
osquery> select name, type, data from registry where key='HKEY_CURRENT_USER\Software\Classes\CLSID\';
+----------------------------------------+--------+------+
| name | type | data |
+----------------------------------------+--------+------+
| {018D5C66-4533-4307-9B53-224DE2ED1FE6} | subkey | |
| {021E4F06-9DCC-49AD-88CF-ECC2DA314C8A} | subkey | |
| {031E4825-7B94-4dc3-B131-E946B44C8DD5} | subkey | |
| {1BF42E4C-4AF4-4CFD-A1A0-CF2960B8F63E} | subkey | |
| {389510b7-9e58-40d7-98bf-60b911cb0ea9} | subkey | |
| {4410DC33-BC7C-496B-AA84-4AEA3EEE75F7} | subkey | |
| {5AB7172C-9C11-405C-8DD5-AF20F3606282} | subkey | |
| {71DCE5D6-4B57-496B-AC21-CD5B54EB93FD} | subkey | |
| {7AFDFDDB-F914-11E4-8377-6C3BE50D980C} | subkey | |
| {82CA8DE3-01AD-4CEA-9D75-BE4C51810A9E} | subkey | |
| {94269C4E-071A-4116-90E6-52E557067E4E} | subkey | |
| {9489FEB2-1925-4D01-B788-6D912C70F7F2} | subkey | |
| {9AA2F32D-362A-42D9-9328-24A483E2CCC3} | subkey | |
| {A0396A93-DC06-4AEF-BEE9-95FFCCAEF20E} | subkey | |
| {A78ED123-AB77-406B-9962-2A5D9D2F7F30} | subkey | |
| {A926714B-7BFC-4D08-A035-80021395FFA8} | subkey | |
| {BBACC218-34EA-4666-9D7A-C78F2274A524} | subkey | |
| {C5FF006E-2AE9-408C-B85B-2DFDD5449D9C} | subkey | |
| {CB3D0F55-BC2C-4C1A-85ED-23ED75B5106B} | subkey | |
| {F241C880-6982-4CE5-8CF7-7085BA96DA5A} | subkey | |
+----------------------------------------+--------+------+
# Investigate individual subkey
osquery> select name, type, data from registry where key='HKEY_CURRENT_USER\Software\Classes\CLSID\{018D5C66-4533-4307-9B53-224DE2ED1FE6}';
+--------------------------------+-----------+----------+
| name | type | data |
+--------------------------------+-----------+----------+
| DefaultIcon | subkey | |
| InProcServer32 | subkey | |
| Instance | subkey | |
| ShellFolder | subkey | |
| (Default) | REG_SZ | OneDrive |
| System.IsPinnedToNameSpaceTree | REG_DWORD | 1 |
| SortOrderIndex | REG_DWORD | 66 |
+--------------------------------+-----------+----------+
# Similar query on the machine objects
osquery> select name, type, data from registry where key='HKEY_LOCAL_MACHINE\SOFTWARE\Classes\CLSID\';

Create Account

Attackers can create new accounts on the system to maintain persistence.

osquery> SELECT * FROM users;

File System Permission Weakness

Different processes can execute binaries as part of their functionality. If the directory in which the executable is placed has write permissions for the account the attacker is using, the binary can be replaced to achieve persistence. A variation of this technique is performed when self-extracting installers use sub-directories of %TEMP% to drop executables or DLLs. Therefore, the attacker can replace in a similar fashion with their own malicious binaries.

# Check directories under C:\Windows
osquery> select f.path,f.directory,u.username,f.hard_links,f.symlink,datetime(f.btime, 'unixepoch', 'UTC') as btime, datetime(f.atime, 'unixepoch', 'UTC') as
atime, datetime(f.ctime, 'unixepoch', 'UTC') as ctime, datetime(f.mtime, 'unixepoch', 'UTC') as mtime from file f LEFT JOIN users u on f.uid=u.uid where f.pat
h like 'C:\\Windows\\%' AND f.type='directory';
# Check directories under C:\users\%\AppData\Roaming\
osquery> select f.path,f.directory,u.username,f.hard_links,f.symlink,datetime(f.btime, 'unixepoch', 'UTC') as btime, datetime(f.atime, 'unixepoch', 'UTC') as atime, datetime(f.ctime, 'unixepoch', 'UTC') as ctime, datetime(f.mtime, 'unixepoch', 'UTC') as mtime from file f LEFT JOIN users u on f.uid=u.uid where f.path
like 'C:\users\%\AppData\Roaming\%' AND f.type='directory';
# Check directories under C:\Users\%\AppData\Local
osquery> select f.path,f.directory,u.username,f.hard_links,f.symlink,datetime(f.btime, 'unixepoch', 'UTC') as btime, datetime(f.atime, 'unixepoch', 'UTC') as atime, datetime(f.ctime, 'unixepoch', 'UTC') as ctime, datetime(f.mtime, 'unixepoch', 'UTC') as mtime from file f LEFT JOIN users u on f.uid=u.uid where f.path
like 'C:\users\%\AppData\Local\%' AND f.type='directory';

Logon Scripts

Scripts can be executed at logon time by add entries in the registry. They can be altered or added by an attacker to facilitate the execution of malicious code.

# Search for the location of logon scripts
osquery> select * from registry where key='HKEY_CURRENT_USER\\Environment';

Modify Existing Services and Adding New Services

The information about a service is stored in the registry. An attacker can either add a new malicious service or alter the path to the executable of an existing one.

# Search for existing services
osquery> select * from registry where key='HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services';
# Look up the information for a specific service (e.g. XboxNetApiSvc)
osquery> select * from registry where key='HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\XboxNetApiSvc';

Netsh Helper DLL

Netshell is a command-line utility used to interact with the network configuration of a system. Its job is to add helper DLLs with extending the functionality of the service. The paths registered for netsh.exe are entered under the location HKLM\SOFTWARE\Microsoft\Netsh. Persistence can be achieved by adding a DLL and Netsh must be called by another benign software that is present on the system.

# Query the DLLs used by Netsh
osquery> select * from registry where key='HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\NetSh';
# Check when Netsh was ran the last time
osquery> select * from file WHERE directory = 'C:\Windows\Prefetch\' and filename like '%netsh%';

PowerShell Profile

A PowerShell profile is a script that runs when PowerShell starts and can be used as a logon script to customise user environments. Adversaries can modify profiles to achieve persistence. If a PowerShell profile is not normally used on a machine, the presence of one might be an indicator of compromise.

# Search for a PowerShell profile
osquery> select * from file WHERE directory = 'C:\Windows\' and filename like '%profile%';

Registry Run Keys / Startup Folder and Shortcut Modification

Adding an entry to the run keys in the registry or startup folder will cause the program referenced to be executed when a user logs in. These programs will be executed under the context of the user and will have the account’s associated permissions level.

Shortcurts (symbolic links in Linux) are ways to reference files in other locations. Attackers can change their reference in order to achieve persistence.

# Check items under Roaming\Microsoft\Windows\Start Menu\Programs\Startup
osquery> select f.path, f.directory, u.username, f.hard_links, f.symlink, datetime(f.btime, 'unixepoch', 'UTC') as btime, datetime(f.atime, 'unixepoch', 'UTC') as atime, datetime(f.ctime, 'unixepoch', 'UTC') as ctime, datetime(f.mtime, 'unixepoch', 'UTC') as mtime from file f LEFT JOIN users u on f.uid=u.uid where f.path
like 'C:\users\%\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup\%';
# Check items creation under Roaming\Microsoft\Windows\Start Menu\Programs
osquery> select f.path, f.directory, u.username, f.hard_links, f.symlink, datetime(f.btime, 'unixepoch', 'UTC') as btime, datetime(f.atime, 'unixepoch', 'UTC') as atime, datetime(f.ctime, 'unixepoch', 'UTC') as ctime, datetime(f.mtime, 'unixepoch', 'UTC') as mtime from file f LEFT JOIN users u on f.uid=u.uid where f.path
like 'C:\users\%\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\%';
# Check items creation under ProgramData\Microsoft\Windows\Start Menu
osquery> select f.path, f.directory, u.username, f.hard_links, f.symlink, datetime(f.btime, 'unixepoch', 'UTC') as btime, datetime(f.atime, 'unixepoch', 'UTC') as atime, datetime(f.ctime, 'unixepoch', 'UTC') as ctime, datetime(f.mtime, 'unixepoch', 'UTC') as mtime from file f LEFT JOIN users u on f.uid=u.uid where f.path
like 'C:\ProgramData\Microsoft\Windows\Start Menu\%';
# Check items creation under ProgramData\Microsoft\Windows\Start Menu\Programs
osquery> select f.path,f.directory,u.username,f.hard_links,f.symlink,datetime(f.btime, 'unixepoch', 'UTC') as btime, datetime(f.atime, 'unixepoch', 'UTC') as atime, datetime(f.ctime, 'unixepoch', 'UTC') as ctime, datetime(f.mtime, 'unixepoch', 'UTC') as mtime from file f LEFT JOIN users u on f.uid=u.uid where f.path
like 'C:\ProgramData\Microsoft\Windows\Start Menu\Programs\%';
# Check the content of the key HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion
osquery> select name, type, data from registry where key='HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Run';
# Check the content of the key HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Policies\Explorer\Run
osquery> select name, type, data from registry where key='HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Policies\Explorer\Run';
# Check osquery predefined startup_items table
osquery> select * from startup_items;

Scheduled Task

Windows can schedule programs or scripts to be executed at a certain date and time by using utilities such as at and schtasks and the Windows Task Scheduler.

# Query the osquery table scheduled_tasks
osquery> select name, action, path, enabled, datetime(next_run_time,'unixepoch','UTC') from scheduled_tasks;

Screensaver

Screensavers are actually executables with a .scr file extension that execute after a certain amount of time. An attacker can place malware and disguise it as an executable to maintain persistence.

# Check the registry location HKEY_CURRENT_USER\\Control Panel\\Desktop
osquery> select name,type,data from registry where key='HKEY_CURRENT_USER\Control Panel\Desktop';

Time providers

The Windows Time service (W32Time) enables time synchronization. W32Time time providers are responsible for retrieving time stamps from network resources and outputting these values to other network clients. The providers are DLLs registered in two subkeys. The providers are loaded at startup by the time provider manager.

osquery> select name, data from registry where key='HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\W32Time\TimeProviders\NtpClient';    
+----------------------------------+-----------------------------------+
| name | data |
+----------------------------------+-----------------------------------+
| AllowNonstandardModeCombinations | 1 |
| CompatibilityFlags | -2147483648 |
| CrossSiteSyncFlags | 2 |
| DllName | %systemroot%\system32\w32time.dll |
| Enabled | 1 |
| EventLogFlags | 1 |
| InputProvider | 1 |
| LargeSampleSkew | 3 |
| ResolvePeerBackoffMaxTimes | 7 |
| ResolvePeerBackoffMinutes | 15 |
| SignatureAuthAllowed | 1 |
| SpecialPollInterval | 604800 |
| SpecialPollTimeRemaining | time.windows.com,7e2b0d0 |
+----------------------------------+-----------------------------------+
osquery> select name, data from registry where key='HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\W32Time\TimeProviders\VMICTimeProvider';
+---------------+--------------------------------------------+
| name | data |
+---------------+--------------------------------------------+
| Parameters | |
| DllName | %SystemRoot%\System32\vmictimeprovider.dll |
| Enabled | 1 |
| InputProvider | 1 |
+---------------+--------------------------------------------+

Winlogon Helper DLL

At logon, logoff and when Ctrl+Alt+Delete is pressed, an executable called winlogon.exeis executed. Two registry locations hold additional helpers for Winlogon.

osquery> select name, data from registry where key='HKEY_LOCAL_MACHINE\Software\Wow6432Node\Microsoft\Windows NT\CurrentVersion\Winlogon';        
+-------------------------+----------------------------------------+
| name | data |
+-------------------------+----------------------------------------+
| AlternateShells | |
| GPExtensions | |
| DefaultDomainName | |
| DefaultUserName | |
| PreCreateKnownFolders | {A520A1A4-1780-4FF6-BD18-167343C5AF16} |
| Shell | explorer.exe |
| ShellCritical | 0 |
| SiHostCritical | 0 |
| SiHostReadyTimeOut | 0 |
| SiHostRestartCountLimit | 0 |
| SiHostRestartTimeGap | 0 |
+-------------------------+----------------------------------------+
osquery> select name, data from registry where key='HKEY_LOCAL_MACHINE\Software\Microsoft\Windows NT\CurrentVersion\Winlogon';
+------------------------------+------------------------------------------------+
| name | data |
+------------------------------+------------------------------------------------+
| AlternateShells | |
| GPExtensions | |
| UserDefaults | |
| AutoLogonChecked | |
| VolatileUserMgrKey | |
| AutoRestartShell | 1 |
| Background | 0 0 0 |
| CachedLogonsCount | 10 |
| DebugServerCommand | no |
| DisableBackButton | 1 |
| EnableSIHostIntegration | 1 |
| ForceUnlockLogon | 0 |
| LegalNoticeCaption | |
| LegalNoticeText | |
| PasswordExpiryWarning | 5 |
| PowerdownAfterShutdown | 0 |
| PreCreateKnownFolders | {A520A1A4-1780-4FF6-BD18-167343C5AF16} |
| ReportBootOk | 1 |
| Shell | explorer.exe |
| ShellCritical | 0 |
| ShellInfrastructure | sihost.exe |
| SiHostCritical | 0 |
| SiHostReadyTimeOut | 0 |
| SiHostRestartCountLimit | 0 |
| SiHostRestartTimeGap | 0 |
| VMApplet | SystemPropertiesPerformance.exe /pagefile |
| WinStationsDisabled | 0 |
| scremoveoption | 0 |
| LastLogOffEndTimePerfCounter | 803712302848 |
| ShutdownFlags | 8359 |
| Userinit | C:\Windows\system32\userinit.exe, |
| IsConnectedAutoLogon | 0 |
| DisableCad | 1 |
| DisableLockWorkstation | 0 |
| EnableFirstLogonAnimation | 1 |
| AutoLogonSID | S-1-5-21-1106092278-1377359101-4055884606-1001 |
| LastUsedUsername | ******** |
+------------------------------+------------------------------------------------+

Contact

If you would like to get in touch you can contact me on one of the following platforms:

Sources

  1. https://attack.mitre.org/tactics/TA0003/
  2. https://docs.microsoft.com/en-us/windows-server/remote/remote-desktop-services/clients/remote-desktop-allow-access
  3. https://remmina.org/
  4. https://docs.microsoft.com/en-us/windows-server/administration/openssh/openssh_install_firstuse
  5. https://github.com/PowerShell/openssh-portable
  6. https://github.com/PowerShell/Win32-OpenSSH/wiki/Install-Win32-OpenSSH
  7. https://osquery.io/
  8. https://github.com/keydet89/RegRipper2.8
  9. https://attack.mitre.org/matrices/enterprise/windows/
  10. https://github.com/teoseller/osquery-attck
  11. https://blog.malwarebytes.com/101/2015/12/an-introduction-to-image-file-execution-options/
  12. https://digital-forensics.sans.org/summit-archives/DFIR_Summit/Finding-Malware-Like-Iron-Man-Corey-Harrell.pdf

--

--

Gabriel Pirjolescu

MSc Cyber Security student at the University of Southampton