English | 简体中文
⚠️ Disclaimer: This repository is the client implementation of the Rshell C2 framework, intended solely for security research, authorized penetration testing, red/blue teaming and education. Obey your local laws; do not use it for any unauthorized purpose. Users assume all consequences.
Rshell-client-rust is a Rust rewrite of the Rshell C2 client: a Cargo workspace with one shared core library (rshell-core) plus 7 transport binaries, fully compatible with the Go C2 server (double-encrypted protocol: AES-256-CFB + X25519). Compared to the Golang client, binaries are smaller, and compile-time LLVM obfuscation is supported.
| Project | Description |
|---|---|
| Rshell---A-Cross-Platform-C2 | C2 server (Go) |
| Rshell-client | Golang client |
| Rshell-client-rust | Rust client (this repo) |
- Multi-protocol transports: TCP / WebSocket / HTTP polling / KCP (FEC 10+3) / Alibaba Cloud OSS / SOCKS5 forwarding (TCP, WS)
- Encrypted traffic: X25519 key agreement + AES-256-CFB double encryption, with configurable or random keys to harden reverse engineering
- Compile-time templates: server address, public key and anti-sandbox password are placeholder constants, replaced by the server when generating a client
- Anti-sandbox: optional execution password — the binary silently exits unless launched with the correct argument
- In-memory execution: Execute Assembly, Inline Bin/Exe, process injection, BOF (built-in COFF loader)
- Interactive terminal: PTY-backed interactive shell on Windows via embedded winpty
- Privilege & credentials: getsystem (named pipe), mimikatz-style credential dump, token manipulation
- Day-to-day operations: file management (upload/download/browse), screenshots, process management, sensitive-information search, SOCKS5 tunneling
- Obfuscation: optional amice LLVM obfuscation (control-flow flattening, bogus control flow, MBA, etc., levels L1–L3)
| Crate | Transport | Default Port | Notes |
|---|---|---|---|
reacon-tcp |
Raw TCP | 10002 | Persistent connection, dedicated writer thread |
reacon-ws |
WebSocket | 10003 | Persistent connection, single-threaded read/write |
reacon-http |
HTTP polling | 10005 | GET pull + POST push, HTTPS supported |
reacon-kcp |
KCP + UDP + FEC(10+3) | 10004 | Compatible with Go kcp-go, custom XOR FEC |
reacon-oss |
Alibaba Cloud OSS | — | Bucket polling (experimental; configure AK/SK/bucket yourself) |
reacon-tcp-fwd |
TCP via SOCKS5 | 10002 | Egress through a proxy |
reacon-ws-fwd |
WS via SOCKS5 | 10003 | Egress through a proxy |
All transports share the same core library and command dispatch; only the transport layer differs.
The following workflow has been fully verified on Arch Linux (LLVM 21): both plain and amice L3 obfuscated builds compile from a clean checkout.
# Arch Linux
sudo pacman -S llvm21 clang21 mingw-w64-gcc patchelf mold
# Debian/Ubuntu (LLVM 21 via https://apt.llvm.org)
sudo apt install llvm-21 llvm-21-dev clang-21 gcc-mingw-w64 patchelf
# Pinned nightly toolchain + targets for both platforms
rustup toolchain install nightly-2025-10-01 --profile minimal
rustup target add x86_64-pc-windows-gnu --toolchain nightly-2025-10-01Obfuscation depends on the rustc-internal LLVM ABI, so the toolchain must be paired with LLVM 21. The build script pins the compiler via the
RUSTCenvironment variable to avoidE0463 can't find crate for stdcaused by another rustc on PATH.
# Linux + Windows, all 5 protocols
bash build_obfuscated.sh
# Linux only
bash build_obfuscated.sh --targets=linux
# Or plain cargo (host platform)
cargo +nightly-2025-10-01 build --release -p reacon-tcpArtifacts land in target/<triple>/release/ (e.g. target/x86_64-pc-windows-gnu/release/reacon-tcp.exe).
amice is an LLVM pass plugin; first build libamice.so from source:
git clone https://github.com/fuqiuluo/amice.git ~/amice
cd ~/amice
LLVM_SYS_211_PREFIX=/usr/lib/llvm21 cargo build --release
# artifact: target/release/libamice.soThen run the one-command obfuscated build (the script handles the LLVM-ABI patchelf fix and the two-phase build automatically):
bash build_obfuscated.sh --targets=linux,windows --amice --level=L3| Level | Duration | Effect |
|---|---|---|
| L1 | minutes | control-flow transforms disabled, base processing only |
| L2 | ~10 min | + control-flow flattening, basic-block splitting |
| L3 (default) | ~10 min | + bogus control flow, indirect calls, MBA, indirect branches |
Measured on Linux at L3: reacon-tcp grows 3.6 MB → 5.4 MB (+50%), reacon-ws +62%. A significant size increase indicates the control-flow passes took effect.
Note:
AMICE_STRING_ENCRYPTIONis off by default — current amice master reportsunexpected StructValueon some Rust constant structs (a known upstream limitation); control-flow obfuscation is unaffected.
Each transport has three placeholder constants at the top of src/main.rs:
| Placeholder | Meaning |
|---|---|
HOSTAAA... |
Server address (with port; full URL for HTTP) |
ServerPublicKeyAAA... |
Server X25519 public key (Base64) |
PASSAAA... |
Anti-sandbox execution password (placeholder/empty = disabled) |
Using binaries as Rshell server templates (recommended flow): the server embeds client template binaries from pkg/api/server/<protocol>/ via go:embed and performs equal-length plaintext replacement of the placeholders when generating a client (HTTPS reuses the HTTP template). Since string encryption is disabled by default here, both plain and obfuscated build outputs work directly as templates:
# 1. Build (plain or obfuscated — placeholders stay plaintext)
bash build_obfuscated.sh --targets=windows
# 2. Copy into the server's protocol dir using its naming convention
cp target/x86_64-pc-windows-gnu/release/reacon-tcp \
/path/to/Rshell/pkg/api/server/tcp/r_windows_amd64.exe
# 3. Rebuild the Rshell server; the new template is embedded| Crate in this repo | Server template dir |
|---|---|
reacon-tcp |
pkg/api/server/tcp/ |
reacon-ws |
pkg/api/server/websocket/ |
reacon-http |
pkg/api/server/http/ |
reacon-kcp |
pkg/api/server/kcp/ |
reacon-oss |
pkg/api/server/oss/ |
reacon-tcp-fwd |
pkg/api/server/forward-tcp/ |
reacon-ws-fwd |
pkg/api/server/forward-websocket/ |
String obfuscation vs placeholders: --amice keeps AMICE_STRING_ENCRYPTION off, so placeholders remain plaintext in the binary and server-side replacement works. If you enable string encryption yourself, the placeholder constants get encrypted and the server can no longer locate them — in that case, patch the placeholders in the source first, then build and distribute the binary standalone:
sed -i "s/HOSTAAA.*AAA\"/192.168.1.10:10002\"/" reacon-tcp/src/main.rs├── shared/ # rshell-core: crypto, protocol, command dispatch, terminal, SOCKS5
│ └── bin/ # embedded winpty binaries (Windows interactive terminal)
├── reacon-tcp/ # TCP transport
├── reacon-ws/ # WebSocket transport
├── reacon-http/ # HTTP polling transport
├── reacon-kcp/ # KCP+FEC transport
├── reacon-oss/ # OSS transport (experimental)
├── reacon-tcp-fwd/ # SOCKS5-proxied TCP transport
├── reacon-ws-fwd/ # SOCKS5-proxied WS transport
├── coffee-ldr/ # vendored GPL-3.0 COFF loader (patched for new nightly)
├── scripts/ # amice obfuscation build helpers
└── build_obfuscated.sh
- winpty (MIT License):
winpty.dll/winpty-agent.exeundershared/bin/are embedded at compile time, dropped and loaded at runtime to back the Windows interactive terminal. - coffee-ldr (modified,
coffee-ldr/directory): upstream is hakaioffsec/coffee (crates.iocoffee-ldr0.2.2, GPL-3.0-or-later). The original fails to compile on recent nightlies (VaListremoval,core_intrinsicschanges — verifiedE0308), so this repo vendors a portability patch and enforces it via[patch.crates-io]. That directory and its changes remain under GPL-3.0-or-later, independent from the MIT-licensed remainder of the repo (consumed as a standalone crate, not merged into the main code). - amice (obfuscated builds, optional): not vendored; fetched from upstream at build time. Point
AMICE_DIRat its source checkout — no modifications required.
The main body of this repository is licensed under the MIT © Rubby2001; the coffee-ldr/ directory is licensed under GPL-3.0-or-later (copyright belongs to the upstream authors) — see the LICENSE inside that directory.