恒美微站 Logo 恒美微站
  • 首页
  • 关于我们
  • 建站服务
  • 主题模板
  • 案例展示
  • 资讯中心
  • 联系我们

Viper 红队实战:execute-assembly 内存执行 C 汇编 —— MSF 与 Cobalt Strike 对比、源码级问题剖析与修复

  • 首页
  • 资讯中心
  • /
  • Viper 红队实战:execute-assembly 内存执行 C 汇编 —— MSF 与 Cobalt Strike 对比、源码级问题剖析与修复

相关资讯

8G显存跑MiniMax-H3视频生成:720p二采优化实战 2026/10/14 14:53:59
AI时代软件工程师的核心竞争力与转型策略 2026/10/14 14:53:59
自动驾驶边缘场景攻坚:端到端落地的核心瓶颈与实战方法论 2026/10/14 14:53:59

最新资讯

MySQL面试连环问:锁机制、日志备份与分表策略深度拆解
0x10E蓝屏排查指南:显存管理内部错误的完整解决路径
泛微OA e-cology 8 WebService接口实战:从部署到调用避坑指南
K8s集群Containerd备份过期清理策略
蓝屏代码0x10E排查全攻略:显存管理错误从驱动到硬件的修复
dplyr 逆向依赖失败报告(revdep/failures.md)深度解读:28 个安装失败包背后的 API 兼容性变更

今日推荐

IBM Verify Identity Access 修复 22 个漏洞:两个 9.8 严重 RCE 无需认证
小区物业管理系统
小型超市仓库管理系统

本周热门

UE动画修改实战:从资产编辑到重定向与蒙太奇驱动
统计随机数生成器攻击下的KLJN安全密钥交换协议Matlab仿真
政务API安全治理:资产测绘、低代码编排与行标对标实践

本月精选

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证
2026 大模型集体涨价:用 Python 做企业 Token 成本测算与选型避坑(附配置)

Viper 红队实战:execute-assembly 内存执行 C 汇编 —— MSF 与 Cobalt Strike 对比、源码级问题剖析与修复

发布时间:2026/10/14 14:58:59
Viper 红队实战:execute-assembly 内存执行 C 汇编 —— MSF 与 Cobalt Strike 对比、源码级问题剖析与修复 文档教程网络安全【免费下载链接】ViperAdversary simulation and Red teaming platform with AI项目地址https://gitcode.com/gh_mirrors/vip/Viper点击查看免费下载本文为 Viper 红队训练文档的实战解析围绕 Cobalt Strike 与 metasploit-framework 两大红队平台的execute-assemblyC# 可执行文件内存执行功能展开先通过一个完整的 C# 测试程序演示两套平台的实际用法与执行链路再从 HostingCLR 注入器源码层面剖析 MSF 官方模块的三个已知限制仅支持 x64、仅 .NET 2.0 环境不可用、无参调用触发Invoke_30x8002000e 错误并逐条给出修复方案与验证截图。读完后你可以独立地在两类平台上部署、运行内存执行 C# 汇编的完整链路并针对特殊目标环境完成定制修复。背景无文件执行与 execute-assembly 的定位metasploit-framework 与 Cobalt Strike下文简称 CS是当前主流的两个红队评估工具。在红队评估过程中为了与杀软对抗无文件渗透是实现免杀的简单有效手段——目标机器上不落盘任何可执行文件全部逻辑在内存中完成。execute-assembly是其中一类常用手法把已编译好的 C# 可执行文件.NET 程序集读入受控进程的内存借助进程内已加载或反射注入的 CLR 直接执行并取回其标准输出。目前 metasploit-framework 和 Cobalt Strike 都已实现了这一功能。本文以源码分析的方式演示两者的使用方式并讲解如何修复 MSF 侧使用过程中遇到的问题。Cobalt Strike 的 execute-assemblyexecute-assembly是 Cobalt Strike 的重要功能。获取 beacon 后的操作步骤非常直接将编译完成的 C# 可执行文件拷贝到 cobalt strike 的本地目录在 beacon 控制台执行execute-assembly [/path/to/file.exe] [arguments]程序在 beacon 内存中执行beacon 回传可执行文件的输出。测试程序 TestAssembly.exe以下 C# 代码用于生成测试用的 C# 可执行文件TestAssembly.exe它输出目标系统位数通过 WMI 查询Win32_Processor.AddressWidth、当前 CLR 运行时版本Environment.Version并回显第一个命令行参数using System; using System.Management; namespace TestAssembly { class Program { static void Main(string[] args) { Console.WriteLine([] Process: {0},Distinguish64or32System()); Console.WriteLine([] Net Vsersion: {0}, Environment.Version.ToString()); Console.WriteLine(args[0]); } private static string Distinguish64or32System() { try { string addressWidth String.Empty; ConnectionOptions mConnOption new ConnectionOptions(); ManagementScope mMs new ManagementScope(//localhost, mConnOption); ObjectQuery mQuery new ObjectQuery(select AddressWidth from Win32_Processor); ManagementObjectSearcher mSearcher new ManagementObjectSearcher(mMs, mQuery); ManagementObjectCollection mObjectCollection mSearcher.Get(); foreach (ManagementObject mObject in mObjectCollection) { addressWidth mObject[AddressWidth].ToString(); } return addressWidth; } catch (Exception ex) { return String.Empty; } } } }执行效果beacon 控制台中先执行了拼写错误的命令报Unknown command随后用正确的execute-assembly TestAssembly-Net2-0.exe imargs触发典型交互如下beacon execute-assembly TestAssembly-Net2-0.exe imargs [] Tasked beacon to run .NET program: TestAssembly-Net2-0.exe imargs host called home, sent: 111159 bytes [] received output: imargs [] Process: 64 [] Net Vsersion: 4.0.30319.42000即任务下发后 beacon 执行该 .NET 程序host 回传 111159 字节控制台收到程序输出的三行结果参数回显imargs、64 位系统、.NET 版本4.0.30319.42000。从执行截图还能看到宿主进程是notepad.exex64说明 CS 是在 beacon 所在的宿主进程内存中完成程序集加载与执行的全程无需在目标上写入 exe。execute-assembly之所以在国内安全人员中很受欢迎原因也很实际使用方便、免杀效果好——只需把已有的 C# 安全工具拷贝到 Cobalt Strike 目录再添加一个简单的 CNA 界面就能封装成一个 Cobalt Strike 插件发布。Metasploit 官方 execute-assemblyMSF 目前官方已经通过模块的方式集成了 execute-assembly模块路径为post/windows/manage/execute_dotnet_assembly。来源与核心原理该功能最初由安全研究员 b4rtik 发布于其个人仓库 metasploit-execute-assembly项目 readme 中对开发流程与实现原理有详细说明。其核心原理是通过Reflective dll反射注入在目标进程内存中创建 CLR 环境把 C# 可执行文件读入内存后再执行。后续该功能被移植进 metasploit-framework 官方成为本文讨论的模块。模块参数在 msfconsole 中对post/windows/manage/execute_dotnet_assembly执行show options参数一览如下表中 Current Setting 为原文实测环境中的取值示例参数当前取值示例必填说明AMSIBYPASStrueyes启用 AMSI 绕过Enable Amsi bypassARGUMENTS空no传给程序集的命令行参数DOTNET_EXE/home/wolf/.msf4/loot/TestAssembly-Net2-0.exeyes程序集C# 可执行文件路径ETWBYPASStrueyes启用 ETW 绕过Enable Etw bypassPID0no要注入的进程 PIDPPID0no创建新进程时用于 PPID 伪造的进程标识0 表示不伪造PROCESSnotepad.exeno用于承载 CLR 的进程SESSION10yes模块运行的 sessionUSETHREADTOKENtrueno以线程模拟方式创建进程WAIT3no等待秒数执行流程从运行截图可以完整还原官方模块的调用链对目标DESKTOP-J08FM51的 session 10 执行run[*] Running module against DESKTOP-J08FM51 [] Launching notepad.exe to host CLR... [] Process 9504 launched. [*] Reflectively injecting the Host DLL into 9504... [*] Injecting Host into 9504... [] Host injected. Copy assembly into 9504... [*] Assembly copied. [*] Executing... [] Start reading output [] imargs [] [] Process: 64 [] [] Net Vsersion: 2.0.50727.9151 [] Succeeded流程分为几步先启动notepad.exe作为承载 CLR 的宿主进程把 Host DLL即 HostingCLR 注入器反射注入到该进程Reflectively injecting the Host DLL再把程序集文件复制到进程内存Assembly copied执行Executing最后回读标准输出。输出中Environment.Version为2.0.50727.9151可见测试程序集是面向 .NET 2.0 编译的目标在运行时由 CLR v2 加载执行。官方模块的三个问题源码级剖析虽然 MSF 官方 execute-assembly 基本可用但在部分特殊场景下会出现问题。以下分析基于模块随带的 HostingCLR 注入器源码external/source/HostingCLR_inject/HostingCLR/目录下的HostingCLR.cpp、Syscalls.asm与数据文件。问题 1模块只支持 x64 环境查看模块依赖的数据目录data/post/execute-dotnet-assembly可以发现b4rtik 只提供了HostingCLRx64.dll这一个适配 x64 环境的 dll并没有提供 x86 环境所需的文件。进一步分析HostingCLRx64.dll的源码Syscalls.asm可知b4rtik 为了实现ETW 绕过功能在项目中加入了汇编代码而该汇编代码只适配了 x64 环境因此最终的模块只支持 x64。问题 2仅安装 .NET 2.0 的环境中无法使用实测发现如果目标 Windows 系统只安装了 .NET 2.0而没有安装 .NET 3.5 或 .NET 4.0例如一台干净的 Windows Server 2008 R2 x64MSF 官方模块无法使用。分析HostingCLR.cpp第 161 行附近有如下代码hr CLRCreateInstance(CLSID_CLRMetaHost, IID_ICLRMetaHost, (VOID**)pMetaHost); if(FAILED(hr)) { printf(CLRCreateInstance failed w/hr 0x%08lx\n, hr); return -1; }根据 .NET 非托管宿主 API 的官方文档CLRCreateInstance函数自.NET Framework 4起才可用。也就是说在根本没有安装 .NET 4.0 的机器上这一步会直接失败并返回 -1模块不可用。问题 3程序集可接受参数但未传参时无法获取默认输出现象如截图所示ARGUMENTS为空时执行报错。按 C# 代码的正常逻辑输出本应是[] [] Process: 64 [] [] Net Vsersion: 2.0.50727.9151但模块实际报错pMethodInfo-Invoke_3 w/hr 0x8002000e该 HRESULT 为 COM 层面的类型不匹配类错误。定位到HostingCLR.cpp第 269 行附近的参数处理代码if(arg_s[0]! \x00) { //if we have at least 1 parameter set cEleemnt to 1 psaStaticMethodArgs SafeArrayCreateVector(VT_VARIANT, 0, 1); LPWSTR *szArglist; int nArgs; wchar_t *wtext (wchar_t *)malloc((sizeof(wchar_t) * raw_args_length 1)); mbstowcs(wtext, (char *)arg_s, raw_args_length 1); szArglist CommandLineToArgvW(wtext, nArgs); free(wtext); vtPsa.parray SafeArrayCreateVector(VT_BSTR, 0, nArgs); for(long i 0;i nArgs;i) { size_t converted; size_t strlength wcslen(szArglist[i]) 1; OLECHAR *sOleText1 new OLECHAR[strlength]; char * buffer (char *)malloc(strlength * sizeof(char)); wcstombs(buffer, szArglist[i], strlength); mbstowcs_s(converted, sOleText1, strlength, buffer, strlength); BSTR strParam1 SysAllocString(sOleText1); SafeArrayPutElement(vtPsa.parray, i, strParam1); free(buffer); } long iEventCdIdx(0); hr SafeArrayPutElement(psaStaticMethodArgs, iEventCdIdx, vtPsa); } else { //if no parameters set cEleemnt to 0 psaStaticMethodArgs SafeArrayCreateVector(VT_VARIANT, 0, 0); } //Assembly execution hr pMethodInfo-Invoke_3(obj, psaStaticMethodArgs, retVal); if(FAILED(hr)) { printf(Failed pMethodInfo-Invoke_3 w/hr 0x%08lx\n, hr); return -1; }问题所在很清晰如果 C# 程序以static void Main(string[] args)作为入口函数但执行时未输入任何参数代码会走else分支用SafeArrayCreateVector(VT_VARIANT, 0, 0)生成一个长度为 0 的空参数向量而Main(string[] args)的签名要求第 0 个参数是一个字符串数组哪怕为空数组空向量与预期参数结构不匹配导致后续pMethodInfo-Invoke_3调用失败。修复方案上述三个问题都可以修复或绕过。问题 1 修复x86 适配通常情况下来讲ETW 绕过功能并不影响免杀与执行。因此直接删除 ETW 功能再将 HostingCLR dll 生成 x86 版本即可模块即可同时覆盖 32 位宿主环境。问题 2 修复兼容仅 .NET 2.0 的环境问题根源是CLRCreateInstance这一函数在 .NET 4 以下不存在。在 .NET 2.0 中可以使用CorBindToRuntimeEx函数替代CLRCreateInstance实现相同的效果绑定并启动 CLR 运行时从而让注入器在没有 .NET 4.0 的机器上也能工作。问题 3 修复统一按“有参数模式”处理绝大多数 C# 程序都使用static void Main(string[] args)作为入口函数。修复思路修改HostingCLR.cpp中的参数解析部分无论是否输入参数都按“有参数模式”构造参数向量——无参数时构造一个包含空数组0 个 BSTR 元素的向量保证Invoke_3收到的参数结构始终与Main(string[] args)签名匹配。修复后代码if(arg_s[0]! \x00) { //if we have at least 1 parameter set cEleemnt to 1 psaStaticMethodArgs SafeArrayCreateVector(VT_VARIANT, 0, 1); LPWSTR *szArglist; int nArgs; wchar_t *wtext (wchar_t *)malloc((sizeof(wchar_t) * raw_args_length 1)); mbstowcs(wtext, (char *)arg_s, raw_args_length 1); szArglist CommandLineToArgvW(wtext, nArgs); free(wtext); vtPsa.parray SafeArrayCreateVector(VT_BSTR, 0, nArgs); for(long i 0;i nArgs;i) { size_t converted; size_t strlength wcslen(szArglist[i]) 1; OLECHAR *sOleText1 new OLECHAR[strlength]; char * buffer (char *)malloc(strlength * sizeof(char)); wcstombs(buffer, szArglist[i], strlength); mbstowcs_s(converted, sOleText1, strlength, buffer, strlength); BSTR strParam1 SysAllocString(sOleText1); SafeArrayPutElement(vtPsa.parray, i, strParam1); free(buffer); } long iEventCdIdx(0); hr SafeArrayPutElement(psaStaticMethodArgs, iEventCdIdx, vtPsa); } else { //if no parameters set cEleemnt to 0 psaStaticMethodArgs SafeArrayCreateVector(VT_VARIANT, 0, 1); long iEventCdIdx(0); vtPsa.parray SafeArrayCreateVector(VT_BSTR, 0, 0); hr SafeArrayPutElement(psaStaticMethodArgs, iEventCdIdx, vtPsa); }与原始代码的关键差异在else分支不再创建长度为 0 的psaStaticMethodArgs而是先创建长度为 1 的外层向量再放入一个长度为 0 的VT_BSTR内层向量即“空参数数组”随后同样执行SafeArrayPutElement填充使两种路径传给Invoke_3的参数结构保持一致。修复后验证从修复版截图可见模块名变为post/windows/manage/execute_assembly原DOTNET_EXE选项更名为ASSEMBLY执行前会先探测目标机器的运行时Dot Net Versions installed on target: [2.0.50727.4927, 3.0.30729.4926, 3.5.30729.5003, 4.0.30319, 4.0.0.0]并输出Assembly CLR version required v2.0.50727——即自动识别程序集所需的 CLR 版本这对应问题 2 的修复按程序集目标版本绑定运行时同样采用“启动 notepad.exe 承载 CLR → 反射注入 Host DLL → 复制程序集 → 执行”的链路在ARGUMENTS为空的情况下不再报错正常回读到[] Process: 64 [] [] Net Vsersion: 2.0.50727.9151 ExecuteSharp end问题 3 修复验证通过。相关资料修复版的完整 MSF execute-assembly 代码由原作者发布于其公开的 execute-assembly 代码仓库b4rtik 的 metasploit-execute-assembly 原始仓库、MSF 官方模块execute_dotnet_assembly与HostingCLR_inject源码的完整链接均可在 Viper 训练文档原文 msfexecute_assembly_and_cobaltstrikeexecute_assembly.md 中按图索骥CLRCreateInstance的可用性说明可查阅 .NET Framework 非托管宿主Unmanaged HostingAPI 文档。Viper 项目内的佐证Viper 自身的模块库中同样提供了基于 CLR 的 C# 内存执行能力可作为本文结论的交叉印证。参考 CsharpAssemblyLoader 模块文档ATTCK 分类为 DefenseEvasion/ProcessInjection另有增强版 CsharpAssemblyLoaderPlus其文档明确给出两条约束被控主机需要安装 .NET 2.0Windows 2008 默认安装或 .NET 4.0Windows 2012 默认安装可执行文件必须与被控主机的 .NET 版本匹配。此外该文档提示与 CS 的 execute-assembly 类似当 C# 程序需要输入参数时务必填写参数。这三点恰好与本文剖析的“版本匹配问题 2”“参数传递问题 3”是同一类坑——在内存执行 .NET 程序集的场景中程序集目标 CLR 版本与目标机器已安装运行时的匹配、入口参数结构的正确构造是决定执行成败的两个关键前提。小结Cobalt Strike的execute-assembly开箱即用拷贝 C# 程序集到 CS 目录、beacon 控制台一行命令即可内存执行并回传输出且易于封装成插件MSF 官方post/windows/manage/execute_dotnet_assembly模块通过“启动宿主进程 反射注入 HostingCLR 内存复制程序集”实现同等能力但存在仅支持 x64、依赖 .NET 4.0 的CLRCreateInstance、无参调用空向量导致Invoke_3失败三个已知问题三个问题分别可通过“移除 ETW 功能并构建 x86 dll”“以CorBindToRuntimeEx替代CLRCreateInstance”“统一按有参数模式构造参数向量”修复修复后在仅 .NET 2.0 环境、无参调用等边界场景下均可正常回读输出。赞分享文档教程网络安全【免费下载链接】ViperAdversary simulation and Red teaming platform with AI项目地址https://gitcode.com/gh_mirrors/vip/Viper点击查看免费下载相关推荐Viper项目中MSF与Cobalt Strike的execute-assembly技术对比与优化Viper项目中MSF与Cobalt Strike的execute assembly技术对比与优化 前言无文件渗透的技术演进 在红队评估过程中对抗杀毒软件文档教程网络安全Viper 内存执行 C 可执行文件CsharpAssemblyLoader 模块实战解析Viper 内存执行 C 可执行文件CsharpAssemblyLoader 模块实战解析 导读 CsharpAssemblyLoader 是 Viper 红文档教程网络安全如何用AI智能体团队打造你的个人投资顾问TradingAgents-CN深度解析如何用AI智能体团队打造你的个人投资顾问TradingAgents CN深度解析 在人工智能技术飞速发展的今天金融投资领域正迎来一场革命性的变革。Tradi人工智能大模型AI Agent多智能体金融科技后端前端创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

关于恒美微站

恒美微站专注于为个体商户、工作室提供极简自助建站服务,让每个人都能轻松拥有专业网站。

快速链接

  • 关于我们
  • 建站服务
  • 主题模板
  • 案例展示
  • 资讯中心

服务项目

  • 可视化建站
  • 拖拽编辑
  • 主题定制
  • SEO 优化
  • 网站托管

联系方式

  • 📍 地址:北京市朝阳区建国路 88 号
  • 📞 电话:400-888-8888
  • ✉️ 邮箱:info@hmyw.cn
  • 🕐 时间:周一至周日 9:00-18:00

© 2024 恒美微站 hmyw.cn 版权所有 | 京 ICP 备 12345678 号