
Una variante di Gargoyle per x64 per nascondere artefatti di memoria usando solo ROP e PIC
Una variante di Gargoyle per x64 per nascondere artefatti di memoria usando solo ROP e PIC.
Un enorme ringraziamento a @waldoirc per aver documentato gran parte di questa tecnica nel suo blog
Questa implementazione è diversa in quanto non fa uso di APC ed è completamente implementata come PIC.
Ho creato questo per capire meglio come eludere gli artefatti di memoria usando una tecnica simile a Gargoyle su x64. L'idea è di impostare una ROPChain che chiami VirtualProtect() -> Sleep() -> VirtualProtect() per marcare la mia pagina come N/A durante il sonno.
A differenza di Gargoyle e di altre implementazioni simili, mi affido completamente a ROP e non metto in coda alcun APC. DeepSleep stesso è implementato come completamente PIC, il che rende più facile enumerare quali pagine di memoria devono essere nascoste dagli scanner.
Mentre il thread è attivo, appare una MessageBox e la pagina di DeepSleep è marcata come eseguibile. Durante il sonno, la pagina è marcata come N/A.
Questo bypassa efficacemente Moneta al momento della scrittura se DeepSleep è iniettato e l'indirizzo di base del thread in esecuzione non punta a memoria privata committata.
Ho verificato questo usando la tecnica di iniezione Earlybird per iniettare DeepSleep.bin in notepad.exe

Usando Mingw:
Digita make e appare un DeepSleep.bin selvaggio.
In alternativa usa il DeepSleep.bin precompilato :-)
Potrei rilasciare un loader per CS o altri agent C2. Similmente a YouMayPasser, il loader aggancerebbe il sonno usando HW breakpoints per evitare modifiche sospette di kernel32.dll.
Questo è stato testato su 10.0.19044 N/A Build 19044
I ROPgadget su cui mi affido potrebbero non esistere in ntdll.dll in altre versioni di Windows. Probabilmente è una buona idea utilizzare ROPgadget più piccoli e generici e di enumerare i gadget in più dll rispetto a ntdll.dll.
Lo stack di chiamate di un thread nello stato DelayExecution include regioni di memoria sconosciute/manomesse e include inoltre indirizzi a VirtualProtect(). Hunt-Sleeping-Beacons rileva questo.
Potrebbe essere possibile applicare quella metrica ad altri C2 che usano una tecnica diversa per attendere tra i callback.

@waldoirc per aver documentato gran parte della tecnica qui
@forrest Orr per Moneta
Josh Lospinoso per la tecnica originale Gargoyle