Server Internals
The C2 server (server.js) is the relay between the attacker's browser and the rootkit kernel module. It manages three concurrent services in a single process.
TCP Server (Rootkit Side)
The TCP server listens on port 4242 and accepts a single connection from the rootkit at a time.
Connection Handling
When the rootkit connects:
- The server stores the socket reference and the remote IP.
- A
rootkit_statusmessage is broadcast to all connected browser clients. - Incoming data is line-buffered: bytes are accumulated until a newline (
\n) is found, then processed as a complete message.
Message Decoding
All incoming data from the rootkit is ROT64-encoded. The server decodes each chunk immediately upon reception:
Rootkit → [ROT64 encoded bytes] → TCP Server → [decode] → plain text → process
Protocol Messages
The server recognizes two special messages from the rootkit by inspecting the decoded text:
| Message content (contains) | Action |
|---|---|
[+] Authentification réussie | Broadcasts auth_result with success: true |
[-] Mot de passe incorrect | Broadcasts auth_result with success: false |
All other messages are forwarded as output to the browser clients.
Disconnection
When the rootkit disconnects, the server:
- Clears the socket reference.
- Broadcasts a
rootkit_statuswithconnected: false. - The rootkit will automatically reconnect after 5 seconds (handled by the kernel module).
HTTP Server (Static Files)
A minimal static file server on port 8080 serves the Web UI from the public/ directory. It supports the following MIME types:
| Extension | Content-Type |
|---|---|
.html | text/html; charset=utf-8 |
.css | text/css |
.js | application/javascript |
.ico | image/x-icon |
.png | image/png |
Requests to / are mapped to index.html.
WebSocket Server (Browser Bridge)
The WebSocket server runs on the same HTTP server (port 8080) and handles real-time communication with the attacker's browser.
On Connection
When a browser client connects, the server immediately sends the current rootkit status so the UI can update without waiting for a state change.
Messages from Browser to Server
The browser sends JSON messages with a type field:
auth
Authenticates the attacker to the rootkit.
{ "type": "auth", "password": "my_secret_password" }
The server:
- Validates the rootkit is connected.
- Validates the password is not empty.
- Hashes the password with SHA-256.
- Sends the hash (ROT64-encoded) to the rootkit with a trailing newline.
command
Sends a shell command to the rootkit for execution.
{ "type": "command", "cmd": "ls -la /root" }
The server:
- Validates the rootkit is connected.
- Broadcasts an
echomessage to all browser clients (so the command appears in the terminal). - Sends the command (ROT64-encoded) to the rootkit with a trailing newline.
Messages from Server to Browser
| Type | Fields | Description |
|---|---|---|
rootkit_status | connected, ip | Rootkit connection state changed |
auth_result | success | Authentication succeeded or failed |
echo | data | Echo of a command sent by any browser |
output | data | Output line from the rootkit |
error | message | Error message (rootkit unreachable, etc.) |
ROT64 Cipher Implementation
The server implements the same ROT64 cipher as the kernel module to encode/decode traffic:
// Encode: shift each byte forward by 64 (mod 256)
buf[i] = (buf[i] + 64) & 0xff;
// Decode: shift each byte back by 64 (mod 256)
out[i] = (out[i] - 64 + 256) & 0xff;
This must match the kernel module's rot64_encrypt / rot64_decrypt functions exactly, otherwise communication will be garbled.
Graceful Shutdown
The server handles SIGINT (Ctrl+C) by:
- Destroying the rootkit socket if connected.
- Closing both TCP and HTTP servers.
- Exiting the process.