Notes while working through the (excellent) Sektor7 windows persistence course. Important point: don’t just rely on the notes here. They’re mainly reminders for me :) It’s the templates and tools as well as extra context that makes the training really valuable. (Tools include things like scripts to AES encrypt and dynamically decrypt the payloads associated with the persistence techniques).
%APPDATA%probably an easier way to go about it. Like
copy myimplant.exe "%APPDATA%\Microsoft\Windows\Start Menu\Programs\Startup"
- Note, there is the machine equivalent, but this is the low priv section of the notes. If you had admin rights you could also set
- userinit launches the local logon scripts.
REG_SZfor a implant.bat that launches an executable.
- Modifying the
.lnkfiles that the user interacts with regularly.
- They are not straight up text files and you can’t just modify them directly to point somewhere else.
- The course script provides an example of a shortcut creator that will replace a
lnkon the desktop with one that is the same except for the target. The new target is a script that launches the payload and then the intended shortcut target.
HKCU\ControlPanel\Desktopcontains the screensaver keys (if configured).
- We add
SCRNSAVE.EXEas a string value pointing at
- We also add the timeout before the “screensaver” should execute -
- Keep in mind GPO might override this.
- Does rely on something PowerShell running on the machine.
profile.ps1launched when powershell is launched for that user.
- We’re hoping to replace something in the search path with our code.
- dll loader is checking for dll already in memory first, then
HKLM\SYSTEM\CurrentControlSet\Session Manager\KnownDLLs, then the applications folder, then c:\windows\system32 and SysWow64 (depending), then c:\windows\system, c:\windows, current directory and finally things in %PATH%.
- You want to be careful here to create a module that can pass off to the real .dll if breaking the application is a concern.
- Procmon is a good way to find out if the application is a good candidate that is calling .dll’s. Result contains ‘NOT FOUND’ and the process name is a good starting filter.
dumpbin(SDK tools) can allow us to inspect the imported functions. We need to be careful though, sometimes there are additional functions required (via getProcAddress). If you wanted to be mega safe you could do all the exported functions from a dll (found using dumpbin).
- Sektor7 demo and template for creating the proxy .dll is the way to go here. The lazy way is to let the app crash, but if we find a reference to a dll with only a few functions we can proxy to the real dll without too much effort.
- Remember to be careful with 32 bit v 64 bit with the .dll.
- .dll is created in one language but designed to be usable by developers in others
- via Application Binary Interface (ABI)
- Identified by Unique Id (and referenced by Id)
- COM objects can live on a different machine, transparent to the application; appears like a regular local function call.
- For Process Loading: (Program.exe -> OLE32.DLL) – Service Control Manager (SCM) – Registry (HKCR which is first HKCM\Software\Classes and then HKLM\Sofware\Classes) – the .dll referenced in the registry path. Then, the app loads it like a ‘normal’ dll. We see these as
- We may be able to hijack at the HKCU lookup
- For Local COM Loading: Similar, but the COM local proxy inside the process will use RPC to communicate with a separate local process on the machine (still specified in HKCR and referenced via the SCM). We see these as
LocalServerin the registry.
- For Network COM Loading: similar, but the SCM on the hosting machine will call out to the remote SCM on the machine hosting the COM Server. The application will call out via RPC.
HKCR\CLSIDis the place to check out the registrations (the .dll’s linked to id’s). But remember that it is made up of HKLM and HKCU components. The
HKCU\Sotftware\Classes\CLSIDsection is writable low priv, but it is a much smaller set of COM Id’s than we’d see in the local machine section.
- We can find some interesting COM persistence in our scheduled tasks. When we export all the tasks we can inspect for LogonTrigger types.
- We also know that although most of the com objects are in HKLM, we can hijack by adding to HKCU because that location is checked first. Sektor7 provide a template for creating a hijack .dll. (Implementing the
DllGetClassObjectfunction). But to take it even further, they show the proxy technique to make the system function ‘as normal’.
schtasks /create /tn 'Mytasks\go' /sc daily /st 10:00 /tr 'c:\mything\mything.exe'
- Standard (created as admin):
schtasks /create /sc onlogon /tn "BonzaiBuddyUpdate" /tr 'c:\mything\mything.exe'
- To create admin level task we export the definition via
schtasks /query /tn BonzaiBuddyUpdate /xmlthen edit the principal section we edit the
to HighestAvailable. Then we delete the existing with `schtasks /delete /f /tn BonzaiBuddyUpdate` and create again with `schtasks /create /tn BonzaiBuddyUpdate /xml task.xml` with the edited task. (If we don't do this we end up with a task that _could_ run as admin, but wont by default).
- It’s also possible to configure the task with multiple actions which would allow the original action to happen.
New or Modified Services
- Either create a new one, or modify an existing service.
sc create UpdaterService binpath= "c:\ourImplant.exe" start= auto
- Default for this will be local system.
sc query UpdaterServiceto confirm.
- We need to make sure our implant is compiled as a service though, else SCM is going to give up on the process reasonably quickly. Sektor7 provide a template. There are SCM related functions that we should have and they’ve provided them. (We just need to implement the RunMe section of the template and optionally include AES Encryption function for payload - also provided)
- We could modify an existing service instead via
sc config UpdaterService binpath= "c:\somethingelse.exe"
Image File Execution Options
- IFEO is around to make debugging easier (attach the debugger or tools to process in various scenarios).
- Debugger, Exit, or Verifier options.
- Debugger allows us to start a process under a debugger (but instead we use our binary)
- Exit allows the same on exit
- Verifier options are the old school compat options we used to touch via verifier.exe that allow us to hook specific functions.
HKLM\Software\Microsoft\Windows NT\CurrentVersion\Image File Execution Options
- We create a subkey for the process we want to start under a ‘debugger’ (our persistence implant).
- The challenge here is that we are effectively starting a ‘debugger’ now, passing the real process as a parameter to the debugger, but since our implant is not really a debugger the actual process wont get a chance to start. We’d either have to implement this, or choose a process that wouldn’t be noticed.
- To do the same on exit, we set up a
ReportingModekey in the same place.
- To do the same for verifier we use
VerifierDllsbut we need to remember that the .dll needs to live in system32 or syswow AND we need to use a specific dll type that Sektor7 provide a template for (it has a
DLL_PROCESS_VERIFIERevent case configured; we use that to create a thread for the persistence module). We also need to set
GlobalFlagto make this work. You can play with this stuff with verifier to see legitimate uses.
- Windows AppCompat
- Hook address table in the process, patch app code, inject dll’s to make it work across OS.
- More relevant to 32 bit process (limited 64 bit support)
Inject dllis the app compat option from the App Compat toolkit we leverage.
- Once we create the shim we need to install it via
sdbinst-u OurShim.sdbto remove)
WMI Event Subscription
- “Windows Management Instrumentation (WMI) is the Microsoft implementation of Web-Based Enterprise Management (WBEM), which is an industry initiative to develop a standard technology for accessing management information in an enterprise environment. WMI uses the Common Information Model (CIM) industry standard to represent systems, applications, networks, devices, and other managed components. CIM is developed and maintained by the Distributed Management Task Force (DMTF).”
- Made up of filters, consumers and bindings.
- WMI event subscriptions persist over reboot.
wmic /NAMESPACE:"\\root\subscription" PATH __EventFilter GET /format:listto see the current event filters.
wmic /NAMESPACE:"\\root\subscription" PATH __EventCOnsumer GET /format:listto see current event consumers.
wmic /NAMESPACE:"\\root\subscription" PATH __FilterToConsumerBinding GET /format:listto see bindings
- To set up WMI based persistence:
wmic /NAMESPACE:"\\root\subscription" PATH __EventFilter CREATE Name="INFilter", EventNameSpace="root\cimv2",QueryLanguage="WQL", Query="Select * From __InstanceCreationEvent Within 15 Where (TargetInstance Isa 'Win32_Process' And TargetInstance.Name = 'wordpad.exe')" wmic /NAMESPACE:"\\root\subscription" PATH CommandLineEventConsumer CREATE Name="INConsumer", WorkingDirectory="C:\rto\PERS\implant", CommandLineTemplate="c:\rto\PERS\implant\implant.exe" wmic /NAMESPACE:"\\root\subscription" PATH __FilterToConsumerBinding CREATE Filter="__EventFilter.Name=\"INFilter\"", Consumer="CommandLineEventConsumer.Name=\"INConsumer\""
- WMI runs as SYSTEM in session 0 by default, so testing implants might not be visible (but you’ll see with procexp)
wmic /NAMESPACE:"\\root\subscription" PATH __FilterToConsumerBinding WHERE Filter="__EventFilter.Name='INFilter'" DELETE wmic /NAMESPACE:"\\root\subscription" PATH __EventFilter WHERE Name="INFilter" DELETE wmic /NAMESPACE:"\\root\subscription" PATH CommandLineEventConsumer WHERE Name="INConsumer" DELETE
- Loaded during the first call of any win32 functions that load process like
HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\AppCertDllswe add a dll to
- It’s a special DLL type though (template provided) that has a CreateProcessNotify function.
- Once configured, you can see them in the “AppInit” section of autoruns:
- (we need a reboot for this one to take effect)
- Doesn’t work reliably against GUI applications. Stick to console apps.
- Very similar to AppCert DLL
HKEY_LOCAL_MACHINE\Software\Microsoft\Windows NT\CurrentVersion\Windowsand add a dll to
AppInit_DLLs. We also need to modify
- Any valid DLL will work with this one though (unlike AppCert DLL approach). BUT! You need to be careful how it is used. Because every process will load the config we define. This includes the process we are creating, and the process it creates and so on… (infinite). Shellcode might be a safer approach here - creating a process would be bad.
Netsh Helper DLLs
- Microsoft added extensibility to NetSh (helper dll)
- Downside: relies on running netsh. You’re looking for enterprise with scripts.
- We need to use a specific DLL type that exports a function called InitHelperDll (but its otherwise similar to standard dll)
netsh.exe add helper c:\temp\nethelp.dllto add the .dll (which adds a registry entry).
removeto get rid of it.
HKEY_LOCAL_MACHINE\Software\Microsoft\Windows NT\CurrentVersion\Winlogonwe look at
shellwhich is the system shell being used;
userinitinitializes the user session.
- Interestingly, they can store more than one application in the value like
explorer.exe,backdoor.exe(where backdoor is also in system32).
- Unlike Shell,
userinitwill take a full path.
- Inward (get time) and Outwards (provide time) both controlled by the SCM.
HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\W32Time\TimeProviders\TimeProv. You’ll see NTPClient, NTPServer usually, but might also see others for VM software etc on a standard machine. To set up a new one we create a new key and define
- The course provides a template .dll that will provide the three required functions
- We restart w32tm to get the provider loaded.
- Since this is service based it will run in session 0 (wont be visible in testing except via procexp etc)
- Very similar to time providers, but on the printing side of the house.
- dll that can pass commands to the printer.
- Use the template provided by Sektor7 which implements the functions required. It has to export an
InitializePrintMonitor2function at the least, but there’s also other implementation requirements that make the template particularly handy in this case.
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Print\Monitors\PortMonitorjust takes a driver dll value as a string. It needs to live in System32 (cant be a path).
AddMonitorAPI is an alternate method for configuration. [https://docs.microsoft.com/en-us/windows/win32/printdocs/addmonitor]](https://docs.microsoft.com/en-us/windows/win32/printdocs/addmonitor)
Local Security Authority (LSA)
- Dangerous one :) We’ll load inside lsass and in addition to being system, we’ll have access to whatever is in the process.
- If LSASS is running protected it should kill this though, because it requires signed (by Microsoft) code. See https://attack.mitre.org/techniques/T1177/
- One approach is to use “SSPs & AuthPkgs”, we’ll be looking in here
Authenticationackages. More information is available on MSDN: https://docs.microsoft.com/en-us/windows/win32/secauthn/using-security-packages
- The SSP approach will require us to implement specific functions but the template provided by Sektor7 is a perfect start.
- When configuring the registry for multi string type to support this, don’t forget the
\0zero byte delim between packages.
- Password Filters are another approach in this space. They show up in the same spot
Notification Packageswhich is a multi-string value (remember the
- Sektor7 provide the template which implements the basic format of a password filter.
- LSASS will load the password filters on reboot and execute the persistence code.