文章总结: 本文介绍用Rust重写CobaltStrike4.4Beacon并保持协议兼容的项目,实现上线、命令执行、BOF加载、进程注入等功能,并通过PEB动态API获取、间接syscall、配置加密、AMSI/ETW补丁等手段降低静态与行为特征,提升规避能力。文章提供详细模块设计、实现方案与构建测试方法,对红队工具开发具有较高参考价值。 综合评分: 85 文章分类: 红队,免杀,渗透测试,安全开发
Rust Cobalt Strike 4.4 Beacon 重写与强规避改造
原创
cc cc
freedom安全
2026年9月2日 12:00 北京
在小说阅读器读本章
去阅读
在公众号小说中沉浸阅读
1. 项目定位
这个项目是把原 C 语言 Cobalt Strike Beacon 客户端重写为 Rust,并且保持与 Cobalt Strike 4.4 的 HTTP Beacon 协议兼容。
目标不是完全复刻 Cobalt Strike,而是:
- 能正常上线 CS 4.4 teamserver
- 能执行常用 Beacon 命令
- 能在隔离环境中验证 BOF、进程注入、任务管理、截图、键盘记录、hashdump
- 逐步把静态特征和行为特征改弱,降低杀软和 EDR 的直接命中率
2. 项目结构
beacon-rs/├── Cargo.toml├── build.rs├── config.plain.json├── asm/│ └── syscall.asm├── docs/│ └── rust-beacon-evasion.md└── src/ ├── main.rs ├── api.rs ├── syscall.rs ├── inject.rs ├── jobs.rs ├── bof.rs ├── packet.rs ├── http.rs ├── metadata.rs ├── crypto.rs ├── config.rs ├── encoding.rs ├── fsops.rs ├── system.rs ├── features.rs ├── patch.rs └── util.rs
核心模块职责:
| 模块 | 作用 |
| — | — |
| api.rs | PEB 动态获取 API |
| syscall.rs | SSN 解析、syscall stub 调用 |
| inject.rs | 进程创建、内存分配、注入、线程恢复 |
| jobs.rs | 管道、job、execute-assembly |
| bof.rs | BOF COFF 加载和 relocation |
| packet.rs | CS 4.4 报文封装和命令解析 |
| http.rs | HTTP 通信 |
| metadata.rs | Beacon metadata 构造 |
| crypto.rs | AES、HMAC、RSA、hash |
| config.rs | 加密配置运行时解密 |
3. 已实现功能
3.1 基础 Beacon 功能
- sleep
- pwd
- getuid
- shell
- cd
- filebrowse
- upload
- download
- mkdir
- drives
- rm
- cp
- mv
- setenv
- getprivs
- ps
3.2 进阶功能
- jobs / jobkill
- execute-assembly
- inject
- spawn
- dllinject
- inline-execute,即 BOF
- screenshot
- keylogger
- hashdump
- AMSI patch
- ETW patch
4. Cobalt Strike 4.4 协议兼容
为了继续兼容 CS 4.4,协议没有大改。
核心链路:
生成 metadata -> RSA PKCS1 v1.5 加密 -> Base64 -> Cookie 头 -> HTTP GET 收到任务 -> 去掉 data= / %% -> NetBIOS 解码 -> mask XOR 解码 -> AES-CBC 解密 -> 解析 commandType + commandLen + commandBuf 执行任务 -> 生成 callback packet -> AES-CBC + HMAC -> mask + Base64 -> HTTP POST
报文相关算法:
- AES-128-CBC
- HMAC-SHA256,前 16 字节
- SHA256 生成会话 AES/HMAC 密钥
- RSA PKCS1 v1.5 加密 metadata
- NetBIOS 编码
- mask XOR
- Base64
5. PEB 动态 API 获取
为了减少静态导入,项目实现了一套 PEB 动态 API 解析。
5.1 获取 PEB
通过 x64 TEB 获取 PEB:
TEB -> gs:[0x60] -> PEB
Rust 使用 asm! 读取:
core::arch::asm!( ”mov {0}, gs:[0x60]”, out(reg) peb, options(nostack, preserves_flags));
5.2 遍历模块
PEB + 0x18 -> PEB_LDR_DATAPEB_LDR_DATA + 0x20 -> InMemoryOrderModuleList
遍历链表时:
InMemoryOrderLinks 位于 entry + 0x10DllBase 位于 entry + 0x30BaseDllName 位于 entry + 0x58
5.3 解析导出表
找到模块后,解析 PE 导出表:
IMAGE_EXPORT_DIRECTORYAddressOfFunctionsAddressOfNamesAddressOfNameOrdinals
模块名和函数名使用 FNV hash,避免在代码中直接保存敏感 API 名。
6. Syscall 实现
6.1 已 syscall 化的函数
当前已实现:
NtOpenProcessNtAllocateVirtualMemoryNtWriteVirtualMemoryNtProtectVirtualMemoryNtCreateThreadExNtGetContextThreadNtSetContextThreadNtResumeThreadNtFreeVirtualMemoryNtReadFileNtWriteFileNtClose
6.2 SSN 解析
动态解析 ntdll 函数后,扫描函数 stub:
mov r10, rcxmov eax,
从而获得 SSN。
6.3 indirect syscall
多数 stub 采用 indirect syscall:
动态找到 ntdll 内 syscall 指令stub 跳转到 ntdll 的 syscall; ret
这样调用栈更接近正常 ntdll 调用。
部分稳定性敏感函数使用 direct syscall:
NtResumeThread
原因是 indirect 跳转在恢复线程场景下出现过异常。
6.4 汇编 stub
asm/syscall.asm 中定义:
beacon_NtOpenProcess PROC mov r10, rcx mov eax, DWORD PTR [g_ssn] mov r11, QWORD PTR [g_addr] jmp r11beacon_NtOpenProcess ENDP
7. 敏感 API 动态化
除了 syscall,很多非 syscall API 也改成 PEB 动态调用。
例如:
CreateProcessAGetThreadContextSetThreadContextResumeThreadIsWow64ProcessFlushInstructionCacheCreateToolhelp32SnapshotProcess32FirstWProcess32NextWProcessIdToSessionIdCreateFileWMiniDumpWriteDumpGetAsyncKeyStateGetLogicalDrivesFileTimeToLocalFileTimeFileTimeToSystemTimeGetUserNameAGetComputerNameAGetACPGetOEMCPGetCurrentProcessIdGetVersionExWGetModuleFileNameAMultiByteToWideCharWideCharToMultiByteCreatePipePeekNamedPipeWaitForSingleObject
这些 API 通过 api::resolve_fn 运行时获取。
8. 进程注入
8.1 spawn
CreateProcessA 动态调用CREATE_SUSPENDEDNtAllocateVirtualMemoryNtWriteVirtualMemoryNtProtectVirtualMemoryNtGetContextThreadNtSetContextThreadNtResumeThread
8.2 inject
NtOpenProcessNtAllocateVirtualMemoryNtWriteVirtualMemoryNtProtectVirtualMemoryNtCreateThreadEx
8.3 execute-assembly
CreatePipeCreateProcessA注入 invokeassembly DLL管道读取输出注册 job
9. Job 与管道
job 模块支持:
- 匿名管道
- 命名管道
- SMB message 模式
- 普通 byte 模式
jobsjobkill
读取管道时:
PeekNamedPipe 检查数据ReadFile / NtReadFile 读取
10. BOF 加载器
inline-execute 支持基础 COFF BOF 加载:
解析 entryPoint读取 code / rdata / data / relocations / argsVirtualAlloc / NtAllocateVirtualMemory处理 COFF relocation加载动态模块调用 entry释放内存
Beacon API 表已经提供基础实现,包括:
BeaconDataParseBeaconDataPtrBeaconDataIntBeaconDataShortBeaconDataLengthBeaconDataExtractBeaconFormatAllocBeaconFormatResetBeaconFormatAppendBeaconFormatIntBeaconFormatFreeBeaconOutputBeaconPrintf
11. Screenshot / Keylogger / Hashdump
11.1 screenshot
- CS 原生 screenshot 使用 Job + DLL 注入
- 项目内 shell screenshot 使用 PowerShell System.Drawing
11.2 keylogger
- CS 原生 keylogger 使用 Job + DLL 注入
- 项目内 shell keylogger 使用
GetAsyncKeyState轮询
11.3 hashdump
- CS 原生 hashdump 使用 Job + DLL 注入
- 项目内 hashdump 使用
MiniDumpWriteDump生成 LSASS minidump
12. 字符串与配置加密
因为beacon本身自带配置文件的字符串 所以对配置文件做了加密处理 防止被静态分析或者通过strings定位到关键位置
12.1 设计
配置文件:
beacon-rs/config.plain.json
构建时由 build.rs:
读取 config.plain.json生成随机 XOR key对配置字段加密生成 generated_config.rs
运行时由 config.rs:
读取 encrypted bytesblack_box 防止优化XOR 解密OnceLock 只解密一次
12.2 已加密内容
C2 IP端口GET URIPOST URIHost 头User-AgentServer 头Content-TypeCookie 前缀SESSIONIDdata=%%User:user=IVRSA 公钥
12.3 验证
构建后可以搜索二进制:
Select-String -Path target-new\release\beacon-rs.exe ` -Pattern ”172.20.10.3” -SimpleMatch
正常情况下不会找到明文。
13. AMSI / ETW Patch
AMSIScanBuffer patchEtwEventWrite patch
实现方式:
PEB 动态获取 LoadLibraryAPEB 动态获取 GetProcAddressVirtualProtect 动态调用内存补丁恢复保护属性
14. 构建与测试
14.1 环境
Windows 10 / 11Rust MSVC toolchainVisual Studio Build Tools
14.2 构建
cd beacon-rscargo testcargo build --release --target-dir target-new
14.3 测试
cargo test
当前测试覆盖:
mask / netbiosAES-CBCHMACSHA256metadata 构造PEB 导出解析NtAllocateVirtualMemoryNtOpenProcess
15. 配置方法
15.1 修改 C2
编辑:
beacon-rs/config.plain.json
例如:
{ ”server”: ”10.10.10.10”, ”port”: 443, ”get_path”: ”/checkin”, ”post_path”: ”/result”}
然后:
cargo build --release
15.2 修改 RSA 公钥
替换:
”pub_key_pem”: ”-----BEGIN PUBLIC KEY-----\n...\n-----END PUBLIC KEY-----\n”
注意换行使用 \n。
16. 使用方式
16.1 启动 teamserver
使用原 Cobalt Strike 4.4 和对应 profile 启动服务端。
16.2 启动 Beacon
运行:
beacon-rs\target-new\release\beacon-rs.exe
16.3 常用命令
shell whoamipwdgetuidpsfilebrowse C:\upload local.txt C:\Windows\Temp\local.txtdownload C:\Windows\Temp\local.txt spawn x64inject x64execute-assembly C:\Tools\test.exeinline-execute C:\Tools\whoami.o jobsjobkill 0 screenshotkeyloggerhashdump shell amsishell etw
17. 当前规避能力
| 分类 | 当前状态 | | — | — | | PEB 动态 API | 已实现 | | indirect syscall | 主要路径已实现 | | NtCreateThreadEx | 已实现 | | NtReadFile | 已实现 | | NtWriteFile | 已实现 | | NtClose | 已实现 | | 配置加密 | 已实现 | | RSA 公钥加密 | 已实现 | | sleep mask | 未实现 | | ntdll unhook | 未实现 | | threadless injection | 未实现 | | PPID spoofing | 未实现 | | C2 流量伪装 | 未实现 | | 完全 no_std | 未实现 |
18. 实战环境
原生马 编译直接可以绕过卡巴 无需loader或者sleepmask
天擎 不过对于这种EDR还需要流量二开 这里只是演示动静
火绒新版增加了内存查杀 这里我主动扫描依然扫不到 图里扫的不是我的beacon 是其他软件 注意我的进程名
onesec
免责声明:
本文所载程序、技术方法仅面向合法合规的安全研究与教学场景,旨在提升网络安全防护能力,具有明确的技术研究属性。
任何单位或个人未经授权,将本文内容用于攻击、破坏等非法用途的,由此引发的全部法律责任、民事赔偿及连带责任,均由行为人独立承担,本站不承担任何连带责任。
本站内容均为技术交流与知识分享目的发布,若存在版权侵权或其他异议,请通过邮件联系处理,具体联系方式可点击页面上方的联系我。
本文转载自:freedom安全 cc cc《Rust Cobalt Strike 4.4 Beacon 重写与强规避改造》
版权声明
本站仅做备份收录,仅供研究与教学参考之用。
读者将信息用于其他用途的,全部法律及连带责任由读者自行承担,本站不承担任何责任。












评论