Evil-WinRM
WinRM is een fantastische attack vector welke door een hacker of penetration tester enorm misbruikt kan worden met alle gevolgen van dien. Een fantastisch framework welke gebouwd is door “HackPlayers” om WinRM te misbruiken is “Evil-WinRM”. Evil-WinRM creëert een speciale shell vanuit waar WinRM misbruikt kan worden om typische “hacker” goals te verwezenlijken zoals het laden van Powershell scripts in memory, pass the hash en nog vele andere toepassingen. Laten we eens gaan kijken naar Evil-WinRM!
Om te begrijpen hoe Evil-WinRM zo succesvol is in wat het doet is het eerst zaak om te begrijpen wat WinRM is en hoe het werkt.
WinRM staat voor “Windows Remote Management en is Microsoft’s implementatie van het WS-Management Protocol welke feitelijk een vervanging is voor het RPC protocol. WinRM is een command-line tool welke gebruikt wordt om remote commando’s uit te voeren en devices te beheren. Dat klinkt al best wel leuk toch? Nog leuker is het dat WinRM (1.1) standaard aanwezig is sinds Windows Vista maar ook additioneel geinstalleerd kan worden op Windows XP en 2003. WinRM 2.0 is aanwezig op Windows 7 en Windows 2008R2 en WinRM3.0 is pre-installed in Windows 8 en 2012 server. WinRM 3.0 is ook beschikbaar voor Windows 10 maar hier is deze niet standaard ingeschakeld.
Je kunt WinRM zien als het “server gedeelte”. WinRM luistert standaard op poort 5985 of 5986 (SSL). Oudere varianten van WinRM functioneerde gewoon over poort 80 en 443 waardoor het blokkeren van een poort wat lastig was. Mocht je toch willen dat WinRM op poort 80 en/of 443 luistert dan is dit nog prima te configureren middels group policy of via WinRM zelf:
winrm set winrm/config/service @{EnableCompatibilityHttpListener=”true”} winrm set winrm/config/service @{EnableCompatibilityHttpsListener=”true”} |
Het clientgedeelte van WinRM is WinRS ofwel Windows Remote Shell. WinRS maakt het mogelijk om te communiceren met WinRM. Commando’s en functionaliteiten om WinRM aan te spreken gebeuren via WinRS.
Het voordeel van WinRS en WinRM is dat ze SOAP requests in XML format gebruiken. Dit is relatief makkelijk te gebruiken en wordt ondersteund door een breed scala aan leveranciers. WinRM en WinRS zitten dus beide standaard in Windows wat de installatie wat gemakkelijker maakt. WinRM functioneert op Windows systemen over WMI en op niet-Windows systemen over WS-Management. WinRM kan dus (extern) beheer bieden voor een reeks apparaten en applicaties en is dus niet gelimiteerd tot Windows tasks. Er wordt een breed scala aan hardware van verschillende leveranciers ondersteund, verschillende besturingssystemen (niet alleen Windows) en verschillende applicaties. WinRM is dus in essentie ontzettend krachtig en ideaal voor diverse beheer- en monitoring taken.
Het nadeel (vanuit hackers oogpunt) is dat WinRM pas te gebruiken is wanneer de juiste credentials in-place zijn. Wanneer ik een admin ben op systeem A welke ook admin rechten heeft op systeem B dan kan ik zonder problemen een WinRM sessie opzetten met systeem B. Echter is er een juiste authenticatie nodig en dit maakt WinRM ideaal in de post-exploitation fase (is het actief) en in de latere fases wanneer de hacker of pentester de beschikking heeft over afdoende credentials.
Om WinRM te starten gebruik je (in een elevated Powershell prompt):
Enable-PSRemoting -force |
Zoals je aan de naam al ziet enabelen we hiermee PowerShell Remote Support en kunnen we dus remote Powershellen tegenover de WinRM service.
Wanneer WinRM op een server is gestart en geconfigureerd is kun je zijn configuratie als volgt opvragen:
winrm get winrm/config -format:pretty |

Op dezelfde manier kun je de configuratie aanpassen (zie ook het voorgaande commando):
winrm set winrm/config @{MaxEnvelopeSizekb="100"} |
Wanneer je v.a. een remote computer wilt praten met een WinRM server en je bent geen lid van hetzelfde domein dan kan er geen verbinding tot stand worden gebracht. Om verbinding tot stand te brengen moet je toegevoegd worden aan de “trusted machines” op de server of moet HTTPS worden gebruikt. Het toevoegen aan de trusted computers list doe je als volgt:
winrm set winrm/config/client @{TrustedHosts="serverA,serverB,serverC"} |
Of via Powershell:
Set-Item WSMan:\localhost\Client\TrustedHosts -Value "serverA,serverB,serverC" -Force |
Om de trustedhosts te bekijken kun je het volgende (PowerShell) commando gebruiken:
Get-Item WSMan:\localhost\Client\TrustedHosts |
Om een connectie te maken met een remote machine (deze moet aanwezig zijn binnen hetzelfde domein of in de trustedhosts):
Enter-PSSession -ComputerName 192.168.178.21 -Credential $Credentials |

Zoals je ziet is er nu een sessie met de server. Dit kunnen we verifiëren met:
Get-PSSession |

Om te zien welke sessies er verbonden zijn met de lokale machine gebruik je:
Get-WSManInstance -ResourceURI Shell -Enumerate |
Maar…. Weer terug naar WinRM.
Om met WinRM een service (zoals in dit geval de print spooler) te starten op een remote computer kun je het volgende gebruiken:
winrm invoke StartService wmicimv2/Win32_Service?Name=spooler |
Nu we een remote sessie hebben kunnen we feitelijk de computer besturen en dus b.v. een applicatie starten:
Start-process notepad.exe |

Zonder WinRM kunnen we hetzelfde met Powershell op de volgende manier:
$remotepc = %servernaam% Invoke-command -computername $remotepc -scriptblock { Start-process notepad.exe} |
Of zoals we het “vroeger” dezen via PSExec:
psexec \\%servernaam% -u "DOMAIN\%username%" -p "%password%" cmd /c "notepad.exe" |
WinRM is een stuk makkelijker en krachtiger dan PSExec. Zo maakt PSExec gebruik van SMB om binaries over te kopiëren en wordt voor elke sessie een service gemaakt en afgebroken. Met andere woorden, PSExec is ontzettend noisy. WinRM is simpelweg een virtuele connectie / sessie.
Omdat we weten dat WinRM op specifieke poorten luistent kunnen we deze scannen. Wanneer een URL string op deze poorten actief is die eindigt op “wsman” dan weet je zeker dat WinRM actief is. Een voorbeeld scan kan dus zijn:
nmap -p 5985 %server-ip% |

Zoals je ziet staat de poort open. Maar om zeker te weren of dit WinRM is moet er een GET uitgevoerd worden waarmee de webservice URL verkregen kan worden welke moet eindigen op “wsman”.
Hier is een zeer handig nmap script voor gemaakt. Deze is hierhier te vinden. Plaats dit script in je huidige directory of sla deze op in de nmap scripts directory om te gebruiken. Je kunt de scripts directory vinden middels:
locate *.nse |
Wanneer het script geplaatst is kunnen we deze uitvoeren:
nmap -p 5985 192.168.178.21 -Pn -sV -v --script=winrm.nse |
En zoals je ziet, WinRM is gestart en actief:

Bingo!
Nu we weten dat WinRM draait kunnen we deze gaan gebruiken / misbruiken (mits we beschikken over de juiste credentials. En dat is waar Evil-WinRM ons komt helpen.
Evil-WinRM
Evil-WinRM maakt het exploiten van remote PC’s over het WinRM protocol gemakkelijk. Wanneer WinRM enables is help Evil-WinRM je met het volgende:
- Powershell scripts en files (DLL / C# assemblies) in-memory plaatsen (en hiermee sommige AV’s omzeilen)
- x64 payloads laden welke gegenereerd zijn met “donutdonut”. Zie ook mijn eerdere post over Donut: https://jarnobaselier.nl/donut-shellcode-generator/
- De AMSI (Antimalware Scan Interface) omzeilen
- Pass-the-Hash
- Kerberos ondersteuning
- Ondersteuning voor SSL en certificaten
- Het up- en downloaden van files (incl. progressiebar)
- Alle services bekijken (ook zonder privileges)
- Command-line access met command history
- WinRM command completion
- Local files completion
- CLI en output messages zijn overzichtelijk (door de gebruikte kleuren)
- Docker support
- Etc.
Er zijn verschillende manieren om Evil-WinRM te installeren. Gebruik een Docker image, installeer handmatig of installeer het automatisch.
Wij kiezen voor de automatische installatie. Om dit te doen voer je onderstaande commando uit. Evil-WinRM incl. dependencies worden nu geïnstalleerd:
gem install evil-winrm |

Na installatie kunnen we Evil-WinRM gebruiken. Het basis commando ziet er als volgt uit:
evil-winrm -i 192.168.178.21 -u Administrator -p 'LekkerVeiligWachtw00rd' -s '/home/scripts/' -e '/home/executables/' |
In bovenstaande commando worden de volgende flags gebruikt:
- -i = IP | Het IP adres waarmee Evil-WinRM moet verbinden
- -u = Username | De gebruikersnaam om te verbinden
- -p = Password | Het wachtwoord om te verbinden
- -s = Scripts | De Powershell scripts folder waar de scripts in staan die je wilt gebruiken
- -e = Executables | De folder met C# executables welke je tijdens de Evil-WinRM sessie wilt gebruiken
Via de Evil-WinRM help (-h) vindt je additionele flags zoals voor het gebruik van alternatieve poorten (-P) of SSL (-S).
Let op, WinRM heeft een dubble-hop probleem. Dit betekend dat je vanuit een WinRM sessie niet nogmaals een WinRM sessie kunt starten (al dan niet met privilege execution). Zorg er dus voor dat je verbinding maakt met een gebruiker die voldoende rechten heeft.
Laten we eens connectie maken:

Het voorvoegsel “*Evil-WinRM* PS” geeft aan dat we een Evil-WinRM sessie hebben gevolgd door het pad op de remote PC waar we ons momenteel in bevinden. V.a. nu kunnen we alle Powershell commando’s uitvoeren die we willen (mits de ingelogde gebruiker afdoende rechten heeft). Bijvoorbeeld:
Get-Process Get-Service whoami whoami /groups Clear-History etc… |

Om alle Evil-WinRM functies te bekijken welke Evil-WinRM heeft gebruik je het “menu” commando:

Wanneer je een Donut payload ter beschikking hebt gebruik je de Donut-Loader. Voor een DLL de DLL-Loader maar verreweg de coolste optie is de “Bypass-4MSI” functie. Met deze functie bypass je de beveiliging van de Antimalware Scan Interface (AMSI). AMSI is een Microsoft feature welke het mogelijk maakt om je applicaties en services te integreren met het antimalware product op de machine. AMSI zorgt voor een geavanceerde malware beveiliging en is compatible met vele fabrikanten. Vele Windows onderdelen zijn geïntegreerd met AMSI zoals UAC, Powershell, Windows Script Host, Javascript etc. Dit betekend dat het uitvoeren van malicious scripts en applicaties erg lastig wordt met AMSI in-place. Als je een administrator bent is AMSI zeer gemakkelijk uit te schakelen. Kijk maar:

Het enige wat je in Evil-WinRM hoeft te doen is:
Bypass-4MSI |
ByPass-4MSI vult een AMSI buffer zodat de uitkomst altijd “false” is en er dus zonder tussenkomst van AMSI scripts en software gedraaid kan worden.
Dan hebben we uiteraard nog de script folder die meegegeven kan worden. Tijdens het aanloggen gebruikte we de “s” flag als volgt:
-s “/home/scripts” |
Alle PowerShell scripts in deze folder kunnen nu gebruikt worden op de overgenomen WinRM machine. Let op, PowerShell scripts moeten aanwezig zijn in de opgegeven folder en niet in een subfolder. Daarnaast moeten de scripts tijdens de initialisatie aanwezig zijn. Als je tijdens een actieve sessie scripts toevoegt kun je deze pas gebruiken nadat je een nieuwe connectie hebt gemaakt. Wanneer de scripts aanwezig zijn kun je deze gewoon aanroepen binnen Evil-WinRM (zelfs incl. auto completion).

Het uitvoeren van de scripts kan wat langer duren omdat deze eerst overgebracht moeten worden. Vervolgens worden ze op de doelcomputer in-memory uitgevoerd.
Wanneer we de PowerSploit PowerUp Privilege Escalation Tool gebruiken zul je zien dat het menu wordt aangevuld met nieuwe cmdlets.

En deze cmdlets kunnen we uiteraard ook gewoon op de doelcomputer gebruiken:

Tot zover deze post over Evil-WinRM. Uiteraard kunnen we nog meer met Evil-WinRM. Denk aan Kerberos, Certificatren, Binaries etc. Al deze onderdelen komen terug in een toekomstige Evil-WinRM post. In deze post wilde ik graag WinRM laten zien en de handigheid die Evil-WinRM biedt om de WinRM service te exploiten op een gemakkelijke manier met de tools die wij fijn vinden om te gebruiken.
★ Vond je deze post interessant, leuk om te lezen (je bent immers al hier gekomen) dan zou ik het ontzettend waarderen wanneer je hier een heel klein beetje “love” voor teruggeeft in de vorm van een like of reshare op je social media of eigen website. T-H-A-N-K-S-! ★