Skip to content
KitploitKITPLOIT
工具博客
Log in
提交
工具博客
提交

黑客、渗透测试和网络安全工具,武装您的安全武器库!

Kitploit 是一个黑客、网络安全和渗透测试工具的目录。发现最新的项目更新,查找漏洞、分析系统、自动化测试并加强你的安全。

··订阅源·联系·隐私·© 2026 Kitploit

工具目录

分类

查看所有分类
Loading categories
Inline-Execute-PE — 在CobaltStrike Beacons中执行非托管Windows可执行文件 | Kitploit
工具/GitHubGitHub/octoberfest7/inline-execute-pe
权限提升
GitHuboctoberfest7/inline-execute-pe

Inline-Execute-PE

在CobaltStrike Beacons中执行非托管Windows可执行文件

查看仓库
72310373年前Kitploit 审核通过

最受欢迎

查看全部 →

发现我们社区最常用的工具。

探索所有工具

浏览我们的工具集合

查看所有工具 →
分享

Inline-Execute-PE

免责声明:

本项目较为复杂,若未能理解其工作原理并充分测试,可能导致Beacon崩溃并失去访问权限!

强烈建议您阅读“设计考量与评述”部分之前的所有文档!

简介

Inline-Execute-PE 是一套 Beacon 对象文件(BOF)及对应的 CobaltStrike Aggressor 脚本,使操作员能够将非托管的 Windows 可执行文件加载到 Beacon 内存中并执行,捕获其输出并在 Beacon 控制台中显示。

这使操作员能够使用许多第三方工具(Mimikatz、Dsquery、Sysinternals 工具等),而无需将其写入磁盘、使用 Donut 等工具将其重新格式化为位置无关代码,或创建新进程来运行它们。

这些可执行文件被映射到 Beacon 内存中,因此可以重复运行,无需每次通过网络发送、分配新内存并创建新的 conhost.exe 进程。

加载到 Beacon 中的可执行文件可供所有连接到 CobaltStrike 团队服务器的 CobaltStrike 客户端访问和运行。

Inline-Execute-PE 针对 x64 Beacon 以及使用 Mingw 或 Visual Studio 编译的 x64 Windows C 或 C++ 可执行文件设计。该项目不支持 x86 可执行文件或使用其他语言或编译器编译的 x64 可执行文件。

安装

克隆仓库,可选运行 make 以重新编译 BOF。

将 Inline-Execute-PE.cna 加载到 CobaltStrike 客户端中。确保 CobaltStrike 运行目录可由您的用户写入;Inline-Execute-PE 会在该目录下创建一个文本文件(petable.txt)以确保 Inline-Execute-PE 运行所需数据的可用性。

命令

Inline-Execute-PE 包含 3 个面向目标的命令(运行 BOF)和 3 个操作项目数据结构的内部命令:

面向目标:

  1. peload
  2. perun
  3. peunload

内部数据结构:

  1. petable
  2. peconfig
  3. pebroadcast

peload

peload 是 Inline-Execute-PE 的起始步骤。此命令用于将 PE 加载到 Beacon 内存中。它执行以下主要操作:

  1. 将指定的 PE 通过网络发送到 Beacon,或者发送 PE 的名称以便从目标机器磁盘读取
  2. 在 Beacon 内存中创建一个结构,用于保存在 Inline-Execute-PE 生命周期中所需的各种指针和句柄
  3. 在 Beacon 中分配内存,并以 RW 保护写入 PE
  4. 使用用户指定的密钥对内存中的 PE 进行 XOR 加密
  5. 再分配一块内存,并将 XOR 加密后的 PE 复制到其中。这是为了能够在后续执行时“还原”PE
  6. 在 Beacon 下生成一个 conhost.exe 子进程,以初始化 stdin/stdout/stderr
  7. 将 stdout 和 stderr 重定向到匿名管道,以便捕获 PE 输出

perun

perun 是 Inline-Execute-PE 的第二步。它执行以下主要操作:

  1. 将命令行参数通过网络发送到 Beacon
  2. 对内存中的 PE 进行 XOR 解密
  3. 修复 PE 的导入地址表,挂钩与命令行参数和进程退出相关的某些 API
  4. 将 PE 内存保护更改为 RWX
  5. 在其自己的线程中运行 PE
  6. 捕获 PE 的输出并返回给 CobaltStrike
  7. 将 PE 内存保护恢复为 RW
  8. 用 peload 期间创建的 XOR 副本覆盖内存中的 PE

peunload

当操作员完成 PE 使用或希望加载其他 PE 时,调用 peunload 从 Beacon 内存中移除 PE。它执行以下主要操作:

  1. 关闭 peload 期间创建的句柄和文件指针
  2. 终止 peload 期间创建的 conhost.exe 进程
  3. 将内存中的两个 PE 副本清零并释放
  4. 尝试卸载 PE 加载到 Beacon 进程中的任何 DLL(可选)

petable

petable 用于显示当前加载到所有 Beacon 中的 PE 信息。

每个 CobaltStrike 客户端都有自己的 petable;Inline-Execute-PE 尽力确保所有连接的 CobaltStrike 客户端之间数据同步,以便所有操作员都能使用 PE。更多信息请参见“设计考量与评述”。

image

peconfig

peconfig 用于配置 Inline-Execute-PE 运行的相关选项。当前可修改的两个选项是:

  1. Timeout。决定 perun 在终止 PE 执行前等待的时间。这是一个安全机制,防止因给 PE 传递错误参数导致其永不返回/结束执行。默认设置为 60 秒,可根据需要修改以适配长时间运行的 PE。
  2. UnloadLibraries。控制 peunload 是否尝试从 Beacon 进程中释放由 PE 加载的 DLL。默认设置为 TRUE。某些 PE 在卸载 DLL 时会导致 Beacon 崩溃,这种情况下最好让所有由 PE 加载的 DLL 保留在 Beacon 进程中。在使用 powershell.exe 时曾观察到此现象(可能是由于它加载了 .Net CLR 到 Beacon 进程)。

pebroadcast

pebroadcast 可用于手动将客户端的 petable 内容广播到所有其他连接的 CobaltStrike 客户端。

其他 CobaltStrike 客户端将用广播的数据更新其 petable。通常无需使用此功能,但以防万一而保留。

使用

使用 peload 将 PE 加载到 Beacon 内存中
image

或者,如果目标机器上已有 PE 且不想创建新进程,提供路径和 --local 开关
image

调用 perun,向加载的 PE 传递参数
image

参数中的双引号必须使用反斜杠转义
image

如果发现某个 PE 在卸载时释放 DLL 会导致问题,使用 peconfig 将 unloadlibraries 设置为 false
image

使用完 PE 后,调用 peunload 从 Beacon 中清理
image

现在可以将另一个 PE 加载到 Beacon 中
image

perun 超时

必须小心传递到 PE 的命令行参数;某些 PE 在收到错误参数时会直接崩溃,而另一些则会无限运行,导致 Beacon 即使进程仍在运行也无法回连。

当 Mimikatz.exe 的参数列表末尾未指定 'exit' 时会出现此情况
image

...

image

Inline-Execute-PE 会在指定的超时时间后终止正在运行的 PE 线程。这使 Beacon 能够恢复正常的通信(在 perun BOF 完成执行之前,Beacon 不会回连)。虽然此 Beacon 中仍可使用正常的 CobaltStrike 命令和其他 BOF,但 Inline-Execute-PE 已被禁用;以这种方式终止正在运行的 PE 似乎会破坏 Beacon 进程中的 stdout 和 stderr,并且后续加载的 PE 无法正常工作。

PE 仍然可以(并且应该)从 Beacon 内存中卸载,但查看 petable 会显示此 Beacon 可能无法再加载其他 PE。
image

请务必测试您希望使用 Inline-Execute-PE 运行的 PE,并在向 perun 传递命令行参数时格外小心。某些 PE 比其他 PE 更宽容。

提示、技巧和观察

以下是一些在测试和开发过程中关于某些用户可能希望加载到 Beacon 的 PE 的观察结果(无特定顺序)。

  1. 在 UnloadLibraries 为 TRUE 时,对 Powershell.exe 使用 peunload 通常会崩溃 Beacon;我认为这与 Powershell.exe 加载 CLR 有关。
  2. Cmd.exe 会崩溃 Beacon,除非使用 '/c' 作为第一个参数。例如 'perun /c cd' 没问题,而 'perun cd' 则不行。
  3. 如果 Mimikatz.exe 被加载、使用、卸载,然后在 UnloadLibraries 为 TRUE 的情况下再次加载,会导致 Beacon 崩溃。
  4. 某些 PE 会在退出时打印帮助菜单;这些内容不会显示,因为 ExitProcess 和 exit() 等调用已被挂钩并重定向到 ExitThread,这样 PE 就不会导致 Beacon 进程退出。
  5. 一些 PE 在使用完后不善于释放内存,依赖进程退出时自动释放;由于 PE 运行在 Beacon 进程内部(因此进程不会在 PE 完成后退出),Beacon 可能会随着加载和运行更多 PE 而膨胀。在测试中使用 Process Explorer 等工具观察此现象,并在操作中注意。
  6. Sysinternal 的 Psexec 似乎无法正常工作;虽然它可以运行,但会抱怨远程主机的句柄无效。实践中,如果需要使用类似 psexec 的工具,最好通过 CobaltStrike 的 socks 代理和攻击机版本的 psexec 实现。
  7. 为 Inline-Execute-PE 生成一个新的 Beacon 可能是个好主意,尤其是在您了解不同 PE 在框架内的交互和运行方式时。有一个备份总是好的。
  8. 如果希望使用 LOLBIN 而不产生创建新进程的遥测,可以使用 peload 的 --local 开关从目标系统磁盘读取文件。这也有助于避免版本问题。

IOC 和 AV/EDR

与 Inline-Execute-PE 相关的 IOC 包括但不限于:

  1. 使用 VirtualAlloc 分配内存
  2. 在 RW 和 RWX 之间更改分配内存的保护属性
  3. 创建子 conhost.exe 进程
  4. 加载映射 PE 所需的 DLL
  5. 实际 PE 执行的任何操作;例如 Mimikatz 访问 LSASS

AV/EDR

在开发过程中,我并未对 EDR 进行全面测试,部分由于懒惰,部分由于缺乏测试环境。不过,它已针对最新补丁的 Windows Defender(根据我的经验,这是一款相当好的防病毒产品)进行了测试。

Mimikatz.exe 可能是最适合用 Inline-Execute-PE 运行的已知 PE。我发现 Windows Defender 检测使用 Inline-Execute-PE 运行的 Mimikatz 的能力取决于 Beacon 运行所在的进程。

在独立可执行文件(例如使用 artifact kit 的 beacon.exe,使其能够在 Defender 下正常运行)中运行的 Beacon,在使用 Mimikatz.exe 与 Inline-Execute-PE 时会被检测到。

在 Windows 进程(注入到 Explorer.exe、notepad.exe 等,或通过 DLL 侧加载到合法进程中)中运行的 Beacon,在使用 Mimikatz.exe 与 Inline-Execute-PE 时不会被检测到。

关于执行用户层钩子的 EDR,我尚未测试,但我有以下一般性想法:

由于 PE 运行在 Beacon 进程内部,而您可能已经取消了 NT DLL 的钩子/刷新,因此我认为 PE 调用的 API 被标记的问题应该不大。但 PE 实际执行的操作(访问进程、修改注册表键等)仍然会引发问题。

设计考量与评述

几个月前,我偶然发现了 RunPE-In-Memory,产生了将其转换为 CobaltStrike BOF 的想法。后续的旅程比预期的要复杂得多,耗时也更长。这个项目特别具有挑战性,因为它本身不是一个独立的工具,而是一个用于运行其他工具的工具。这需要极大的灵活性和努力,以实现与各种 PE 及其完成相同任务(获取参数、终止等)的不同方式的兼容性。

起初,Inline-Execute-PE 被设想为一个一体化的 BOF,负责在 Beacon 中加载、执行和释放 PE。项目进行约 3 周时,我完成了约 75% 的概念验证,发现 PEzor 已在约 1.5 年前发布,并且几乎完成了我想做的所有事情;主要区别在于 PEzor 在底层调用 Donut 将 PE 转换为 shellcode,而不是手动将原始 PE 映射到内存。

这一发现在一方面令人欣喜,另一方面也令人失望;有一个成熟的项目可以借鉴灵感,帮助我解决代码中的一些难题,这非常棒,但令人沮丧的是,我实际上是在不知情的情况下重新发明了轮子。在阅读了 PEzor 的相关资料并思考其设计、一些战术相关事宜以及我所在组织的运营需求后,我调整了 Inline-Execute-PE 的方向,成为今天的样子。这一决定由多个因素驱动,下面将讨论这些因素,以及一些可能让读到这里的读者感到好奇的设计选择。

Inline-Execute-PE vs PEzor

根据我的运营经验,我遇到了多个需要重复运行某个工具的场景和工具;使用 PEzor 时,操作员必须反复通过网络发送 PE、创建 conhost.exe、在 Beacon 中分配新内存等,这在考虑 AV/EDR 时可能不太理想。这种思考导致了将 PE“加载”到 Beacon 中的想法,类似于将 .PS1 加载到 Beacon 中重复使用。conhost.exe 在首次加载 PE 时创建,并在 PE 加载到内存期间持续存在;同样,新内存只在首次加载时分配一次,当然也避免了每次使用时都需要通过网络发送 PE。Inline-Execute-PE 采用的模式并非没有缺陷,我尝试以不同程度的成功来解决这些问题。

两个 PE 副本

一个显而易见的设计选择是 Inline-Execute-PE 将 PE 在 Beacon 中映射两次。这当然不是理想的选择,也不是我自愿做出的,而是出于必要。如前所述,Inline-Execute-PE 必须挂接与命令行参数相关的几个函数。由于映射的 PE 在 Beacon 进程内部运行,PE 会尝试使用 PEB 中 PROCESS_PARAMETERS 部分指定的命令行参数;为了解决这个问题,当 PE 调用各种获取命令行参数的函数时,我们必须将 PE 引导到我们自己定义的自定义函数中,以便提供通过 perun 从 CobaltStrike 传递的预期参数。

下载工具