Donut 载荷兼容性速查:.NET 程序集与 PE 文件内存执行自检清单

📅 2026/8/23 13:56:54
Donut 载荷兼容性速查:.NET 程序集与 PE 文件内存执行自检清单
Donut 载荷兼容性速查.NET 程序集与 PE 文件内存执行自检清单【免费下载链接】donutGenerates x86, x64, or AMD64x86 position-independent shellcode that loads .NET Assemblies, PE files, and other Windows payloads from memory and runs them with parameters项目地址: https://gitcode.com/gh_mirrors/don/donutDonut 可以把 .NET 程序集、PE 文件等 Windows 载荷打包成 x86/x64 的位置无关 shellcode在目标进程内存中加载并带参数执行。如果你的载荷生成后无法运行问题往往出在入口点签名、程序集纯度或重定位信息这几处。这份清单按载荷类型给出判断标准帮你快速定位“能不能被 Donut 加载、哪里不满足、怎么改”。一、先给结论三类载荷的兼容边界Donut 对三类载荷各有硬性条件不满足就直接失败。先看总表再进对应小节核对细节。载荷类型必须满足的条件常见失败原因处理建议.NET 程序集入口点public static参数为无参或字符串包含类必须public纯托管代码、无 Unmanaged Exports方法私有/非静态、参数是 int 或自定义类型、混入原生代码改方法签名与可见性剥离 [DllImport] 导出单独拆出原生部分原生 EXE/DLL必须保留重定位表编译器不得是 Cygwin链接时剥离了重定位Cygwin 初始化逻辑假设从磁盘运行内存执行直接崩宿主换 MSVC 或 MinGW 重编译确认未启用移除重定位的优化选项非托管 DLL自定义入口点用户指定入口点只能无参或接受一个字符串参数入口点带多个参数或非字符串参数参考官方示例目录 DonutTest/ 下 dlltest.c 的写法改签名生成 shellcode 时指定架构x86 或 amd64也要与载荷一致架构不匹配是另一类高频失败原因。二、.NET 程序集怎么改才能被 Donut 加载Donut 加载 .NET 程序集的路径是shellcode 先加载 CLR再创建一个新的应用程序域把程序集放进去执行。默认面向 .NET Framework 4.0 及以上版本的 CLR如果指定版本加载失败它会回退到系统上可用的 CLR。理解这条链路后入口点的检查标准其实就一句话CLR 宿主必须能用反射稳定地找到并调用这个方法。Donut .NET 入口点怎么设置逐项核对任何一项不满足都可能导致加载或调用失败方法必须publicstatic。实例方法、private/protected 方法都不可用。参数只能是字符串或无参。不要传 int、bool、自定义对象也不要传多个不同类型参数——参数用逗号或分号分隔传递但每个都必须是字符串语义。包含入口点的类必须public。常见漏改方法是 public static但类忘了加 public。程序集必须是纯托管。混合程序集同时含托管与原生代码不支持由此推导程序集中不能包含任何 Unmanaged Exports非托管导出方法。程序集加载失败的排查顺序按顺序过一遍基本能覆盖全部原因入口点可见性方法、类两级是否都是 public。参数类型是否混入非字符串参数。是否混合代码检查程序集里有没有 [DllImport] 导出或嵌入原生资源导致的混合标记。CLR 版本目标机器是否装有对应版本框架没有的话确认 Donut 的回退逻辑是否命中可用 CLR。三、原生 PE 文件为什么必须包含重定位Donut 对原生 EXE/DLL 走的是自定义 PE 加载器把镜像头部和各个节复制到可读写可执行内存然后应用重定位、处理导入表。加载器支持延迟导入Delayed Imports、TLS线程局部存储和命令行修补三个兼容点但前提是镜像里有完整的重定位信息。PE 文件为什么必须包含重定位内存中的加载地址几乎必然不等于 PE 的期望基地址。没有重定位表加载器无法修正镜像内部的绝对地址引用运行到第一次远跳转就会崩。所以检查镜像是否含重定位表。剥离重定位的构建某些发布优化或 strip 操作不能直接用作载荷。确认编译环境。Cygwin 编译的二进制文件明确不支持其初始化例程假设宿主进程从磁盘运行改成从内存执行时宿主进程大概率崩溃。需要原生载荷时改用 MSVC 或 MinGW。32/64 位与目标进程匹配。x86 载荷注入 x64 进程会触发 WOW64 场景行为与预期不同优先选择架构一致的载荷。非托管 DLL 入口点如何兼容如果 DLL 使用用户指定的入口点函数而非默认 DllMain 行为入口点只能无参或接受一个字符串参数其他签名不受支持。官方在 DonutTest/ 目录里提供了 dlltest.c就是一个兼容入口点的参考实现照它的签名改即可。四、生成前自检与失败排查生成前自检执行 Donut 生成 shellcode 之前把下面几张表过一遍检查项判断标准不满足时入口点方法public static补修饰符或改为静态入口入口点参数无参或字符串去掉非字符串参数用字符串承载包含类public给类加 public程序集纯度无混合代码、无 Unmanaged Exports拆出原生代码单独发布重定位表PE 文件保留重新编译不要 strip编译器非 Cygwin换 MSVC/MinGW架构x86 对 x86、amd64 对 amd64重新生成对应架构载荷失败时按现象定位shellcode 跑起来但无输出多半是 CLR 加载或程序集定位问题优先核对入口点三要素可见性、static、参数。宿主进程直接崩溃原生载荷的高危信号先查编译器是否 Cygwin和重定位表。加载成功但入口没被调用检查传入的类名/方法名是否与程序集内实际定义一致DLL 场景再核对入口点签名。五、验证与收尾清单验证手段项目里都有现成配套DonutTest/ 是一个 C# 注入器测试工具把 base64 编码后的 shellcode 作为字符串注入目标进程不带 PID 则注入自身适合做端到端验证ModuleMonitor/ 则用于从防御视角观察 CLR 注入行为确认程序域与 CLR 加载状态。5 步兼容性自检清单定类型确认载荷属于 .NET 程序集、原生 EXE/DLL 还是非托管 DLL进入对应检查表。核入口点.NET 看方法/类的 public static 与字符串参数非托管 DLL 看单字符串或无参签名不确定就照 DonutTest/ 中 dlltest.c 改。查程序集纯度确认非混合程序集、无 Unmanaged Exports。查 PE 结构确认含重定位表、编译器不是 Cygwin、架构与目标进程一致。端到端验证用 DonutTest 生成并注入测试再用 ModuleMonitor 观察 CLR 加载是否符合预期。五项全过你的载荷就满足 Donut 内存执行的兼容条件任何一项不满足回到对应小节按处理建议修改后重新生成即可。更多细节可查阅项目内文档docs/ 下的开发笔记与架构说明以及 loader/ 目录中 inmem_pe.c、inmem_dotnet.c 对应的加载实现。【免费下载链接】donutGenerates x86, x64, or AMD64x86 position-independent shellcode that loads .NET Assemblies, PE files, and other Windows payloads from memory and runs them with parameters项目地址: https://gitcode.com/gh_mirrors/don/donut创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考