Tuesday 27 October 2015

Parse Mimikatz Output One-Liner

Love mimikatz but hate the output? Yeah me too. In this post I'll show you how to parse the output with one simple line.

The Output

Running either the mimikatz binary or powershell equivalent Invoke-Mimikatz will give you output similar to the following:
Authentication Id : 0 ; 92831308 (00000000:05889d8c)
Session           : RemoteInteractive from 3
User Name         : john.smith
Domain            : ACME
SID               : S-1-5-21-2052118978-2816230894-3584936141-8335
 msv : 
  [00000003] Primary
  * Username : john.smith
  * Domain   : ACME
  * NTLM     : 1acd1a77416c50969d66867cd1e27e91
  * SHA1     : fc1a13cdf5e6d8da249812b320764fbaac0cb1bb
  [00010000] CredentialKeys
  * NTLM     : 1acd1a77416c50969d66867cd1e27e91
  * SHA1     : fc1a13cdf5e6d8da249812b320764fbaac0cb1bb
 tspkg : 
 wdigest : 
  * Username : john.smith
  * Domain   : ACME
  * Password : Myl0ngs3cretP@ssword
 kerberos : 
  * Username : john.smith
  * Domain   : ACME.mycompany
  * Password : (null)
 ssp : 
 credman : 
In most situations you'll often just want to know the users and passwords however this is hidden among a whole load of other output. Now we could go and patch the mimikatz code or we could use a cheeky one-liner...


I Love A One-Liner

My goal was to obtain a list of all usernames with domains and passwords from a set of mimikatz output files. This is simple to do with the following one-liner:
cat *|tr -d '\011\015' |awk '/Username/ { user=$0; getline; domain=$0; getline; print user " " domain " " $0}'|grep -v "* LM\|* NTLM\|Microsoft_OC1\|* Password : (null)"|awk '{if (length($12)>2) print $8 "\\" $4 ":" $12}'|sort -u

Parsing the example above you get the following:
ACME\john.smith:Myl0ngP@ssword
jira.acme.com\john.smith@acme.com:Myj1raP@ssword

Hows it work?
  • I start by outputting all files in the current directory and removing carriage return characters as these seemed to break awk. I also remove tab characters to clean up the output.
  • Next up I used awk to effectively put the username, domain and password all on the same line. This makes greppping, cutting or more awking easier.
  • I used grep to remove lines I didn't care about. For example NTLM hashes and null passwords.
  • I then did a final awk to remove hex string passwords. I'm not sure how/why mimikatz generates this output, if anyone knows please leave a comment! :)
  • And finally I sorted and uniqued the list.

I modified the one-liner to also output just the usernames and passwords without the domain:
cat *|tr -d '\011\015' |awk '/Username/ { user=$0; getline; getline; print user " " $0}'|grep -v "* LM\|* NTLM\|Microsoft_OC1\|* Password : (null)"|awk '{if (length($8)>2) print $4 ":" $8}'|sort -u
john.smith:Myl0ngP@ssword
john.smith@acme.com:Myj1raP@ssword
And also output usernames and NTLM hashes ready for use with pth-winexe:
cat *|tr -d '\011\015' |awk '/Username/ { user=$0; getline; domain=$0; getline; print user " " domain " " $0}'|grep -v "* LM\|* Password\|Microsoft_OC1"|awk '{if (length($12)>2) print $8 "/" $4 "%aad3b435b51404eeaad3b435b51404ee:" $12}'|sort -u
ACME/john.smith%aad3b435b51404eeaad3b435b51404ee:1acd1a77416c50969d66867cd1e27e91
If you want a different output format just modify the final print statement.


Final Thoughts

Mimikatz is such an awesome tool unfortunately the default output is not that user/grep friendly. Luckily with a simple one-liner we can easily work the output into something more useful. As mentioned in my smb-share enumeration post, don't be afraid to jump in and learn some grep/awk/sed, these tools can speed up data analysis massively!

Hopefully this post has been useful, if you have any suggestions for improvements or better ways to get usable output then leave a comment below.

Pwndizzle out.