
Implementazione di un PoC di uno spoofer dello stack di chiamate completamente dinamico.
Implementazione PoC di uno spoofing dello stack di chiamate completamente dinamico
SilentMoonwalk è un'implementazione PoC di uno spoofing dello stack di chiamate completamente dinamico, che implementa una tecnica per rimuovere il chiamante originale dallo stack di chiamate, utilizzando ROP per desincronizzare lo srotolamento dello stack dal flusso di controllo.
Questo PoC è il risultato di una ricerca congiunta sullo spoofing dello stack. Gli autori della ricerca sono:
Voglio sottolineare che questo lavoro sarebbe stato impossibile senza il contributo di Waldo-IRC e Trickster0, che hanno entrambi contribuito alle fasi iniziali del PoC e alla ricerca alla base del PoC.
Questo repository dimostra un'implementazione PoC per spoofare lo stack di chiamate quando si chiamano API Windows arbitrarie.
Questo tentativo è stato ispirato da questo thread su Twitter e questo thread su Twitter, dove il sensei namazso ha mostrato e suggerito di estendere l'approccio di srotolamento dello stack con una catena ROP per desincronizzare lo srotolamento dal flusso di controllo reale e ripristinare lo stack originale successivamente.
Questo PoC tenta di fare qualcosa di simile a quanto sopra e utilizza uno stack desincronizzato per nascondere completamente lo stack di chiamate originale, rimuovendo anche la base dell'immagine EXE da esso. Al ritorno, viene invocato un gadget ROP per ripristinare lo stack originale. Nel codice, questo processo viene ripetuto 10 volte in un ciclo, utilizzando frame diversi ad ogni iterazione, per dimostrare la stabilità.
Lo strumento supporta attualmente 2 modalità, dove una è in realtà una patch errata a un frame pop RBP non funzionante identificato, che opera spostando l'attuale RSP e aggiungendo due frame fittizi allo stack di chiamate. Poiché opera utilizzando frame sintetici, mi riferisco a questa modalità come "SYNTHETIC".
Quando si seleziona il frame che si srotola tramite pop del registro RBP dallo stack, lo strumento potrebbe selezionare un frame non adatto, risultando in uno stack di chiamate tagliato bruscamente, come osservabile di seguito.

Una soluzione sciocca al problema sarebbe creare due frame fittizi e collegarli allo stack di chiamate tagliato. Questo creerebbe una sorta di stack di chiamate apparentemente legittimo, anche senza un frame adatto che si srotoli chiamando POP RBP, ma:
Il risultato dello spoof sintetico può essere osservato nell'immagine qui sotto:

Figura 1: Windows 10 - Stack di chiamate apparentemente legittimo, non srotolabile, in cui il modulo EXE è stato completamente rimosso (chiamata alla funzione getchar senza parametri)
Nota: Questa modalità operativa è disabilitata per impostazione predefinita. Per abilitarla, imposta CALLSTACK_TYPE su 1
Questa modalità è la soluzione corretta al problema sopra, in cui il frame non adatto viene semplicemente sostituito con un altro, adatto.

Figura 2: Windows 10 - Stack di chiamate legittimo, srotolabile, in cui il modulo EXE è stato completamente rimosso (chiamata alla funzione MessageBoxA con 4 parametri)
Nel repository, puoi trovare anche una piccola utility per ispezionare le funzioni runtime, che potrebbe essere utile per analizzare le voci delle funzioni runtime.
UnwindInspector.exe -h
Unwind Inspector v0.100000
Mandatory args:
-m <module>: Target DLL
-f <function>: Target Function
-a <function-address>: Target Function Address
Sample Output:
UnwindInspector.exe -m kernelbase -a 0x7FFAAE12182C
[*] Using function address 0x7ffaae12182c
Runtime Function (0x000000000000182C, 0x00000000000019ED)
Unwind Info Address: 0x000000000026AA88
Version: 0
Ver + Flags: 00000000
SizeOfProlog: 0x1f
CountOfCodes: 0xc
FrameRegister: 0x0
FrameOffset: 0x0
UnwindCodes:
[00h] Frame: 0x741f - 0x04 - UWOP_SAVE_NONVOL (RDI, 0x001f)
[01h] Frame: 0x0015 - 0x00 - UWOP_PUSH_NONVOL (RAX, 0x0015)
[02h] Frame: 0x641f - 0x04 - UWOP_SAVE_NONVOL (RSI, 0x001f)
[03h] Frame: 0x0014 - 0x00 - UWOP_PUSH_NONVOL (RAX, 0x0014)
[04h] Frame: 0x341f - 0x04 - UWOP_SAVE_NONVOL (RBX, 0x001f)
[05h] Frame: 0x0012 - 0x00 - UWOP_PUSH_NONVOL (RAX, 0x0012)
[06h] Frame: 0xb21f - 0x02 - UWOP_ALLOC_SMALL (R11, 0x001f)
[07h] Frame: 0xf018 - 0x00 - UWOP_PUSH_NONVOL (R15, 0x0018)
[08h] Frame: 0xe016 - 0x00 - UWOP_PUSH_NONVOL (R14, 0x0016)
[09h] Frame: 0xd014 - 0x00 - UWOP_PUSH_NONVOL (R13, 0x0014)
[0ah] Frame: 0xc012 - 0x00 - UWOP_PUSH_NONVOL (R12, 0x0012)
[0bh] Frame: 0x5010 - 0x00 - UWOP_PUSH_NONVOL (RBP, 0x0010)
Per compilare il POC e osservare un comportamento simile a quello nell'immagine, assicurati di:
/GS-)/Od)/GL)/Os, /Ot)/Oi)Vale la pena menzionare i lavori precedenti su questo argomento, che hanno gettato le basi di questo lavoro.