Progreso John the Ripper en Windows

Que sí, que lo normal sería utilizarlo en Linux o WSL… pero para una «pequeña prueba» acabas generando un script en PowerShell donde…

  • Busca el ejecutable john.exe en directorios habituales
  • Ordena las sesiones por fecha y pre-selecciona la más reciente
  • Refresca cada minutos el estado de la sesión y si sigue activa

Los «ya que»… mientras la gráfica está al 100%:

<#
Este script está disponible bajo la licencia MIT.
Copyright (c) 2025 Kaizen Development Solutions.

Se permite el uso, copia, modificación y distribución del software
siempre que se mantenga este aviso de copyright y la referencia a la
licencia MIT. El software se proporciona "tal cual", sin garantías de
ningún tipo. Para más detalles consulte el archivo LICENSE del
repositorio.

.SYNOPSIS
Muestra el estado de sesiones activas de John the Ripper en Windows,
permitiendo refresco automático y autodetección del ejecutable john.exe.

.DESCRIPTION
Este script lista las sesiones .rec en el directorio del usuario,
permite seleccionar una, detecta automáticamente si John está ejecutando
esa sesión y muestra el progreso con formato compacto y marca temporal.

.EXAMPLE
.\jtr-status.ps1

Muestra la lista de sesiones y realiza una consulta del estado.

.EXAMPLE
.\jtr-status.ps1 -RefreshSeconds 30

Refresca continuamente el estado de la sesión seleccionada cada
30 segundos hasta que deje de estar activa.
#>

param(
    # Ruta al ejecutable john.exe (se intentará autodetectar si no existe)
    [string]$JohnExe = "C:\DATOS\JtR\run\john.exe",

    # Intervalo de refresco en segundos.
    # 0 o negativo -> solo consulta una vez y termina.
    [int]$RefreshSeconds = 60
)

$sessionDir = Join-Path $env:USERPROFILE ".john\sessions"

# --- Autodetección de john.exe ---
if (-not (Test-Path $JohnExe)) {
    $candidates = @()

    # Carpetas base donde buscar
    $roots = @()
    if ($PSScriptRoot) { $roots += $PSScriptRoot }
    $roots += (Get-Location).Path

    foreach ($root in $roots) {
        $candidates += (Join-Path $root "john.exe")
        $candidates += (Join-Path $root "run\john.exe")
        $candidates += (Join-Path $root "JtR\john.exe")
        $candidates += (Join-Path $root "JtR\run\john.exe")
    }

    $found = $null
    foreach ($c in $candidates) {
        if (Test-Path $c) {
            $found = $c
            break
        }
    }

    if ($found) {
        Write-Host ("john.exe no encontrado en la ruta configurada. Usando autodetectado: {0}" -f $found) -ForegroundColor Yellow
        $JohnExe = $found
    }
    else {
        Write-Host "ERROR: No se encontró john.exe. Revisa la variable `\$JohnExe` en el script o coloca john.exe en una de estas rutas:" -ForegroundColor Red
        Write-Host "  - (carpeta del script)\john.exe"
        Write-Host "  - (carpeta del script)\run\john.exe"
        Write-Host "  - (carpeta actual)\john.exe"
        Write-Host "  - (carpeta actual)\run\john.exe"
        Write-Host "  - (carpeta actual)\JtR\john.exe"
        Write-Host "  - (carpeta actual)\JtR\run\john.exe"
        exit 1
    }
}

if (-not (Test-Path $sessionDir)) {
    Write-Host "ERROR: No existe la carpeta de sesiones: $sessionDir" -ForegroundColor Red
    exit 1
}

# Obtener las sesiones .rec ordenadas por última modificación (más reciente primero)
$sessions = Get-ChildItem -Path $sessionDir -Filter "*.rec" |
            Sort-Object LastWriteTime -Descending

if ($sessions.Count -eq 0) {
    Write-Host "No se encontraron sesiones (.rec) en $sessionDir" -ForegroundColor Yellow
    exit 0
}

Write-Host ""
Write-Host ("Sesiones encontradas en {0}:" -f $sessionDir)
Write-Host ""

# La más reciente es la preseleccionada
$defaultIndex = 1

# Mostrar lista numerada
for ($i = 0; $i -lt $sessions.Count; $i++) {
    $idx  = $i + 1
    $name = [System.IO.Path]::GetFileNameWithoutExtension($sessions[$i].Name)
    $time = $sessions[$i].LastWriteTime.ToString("yyyy-MM-dd HH:mm:ss")

    if ($idx -eq $defaultIndex) {
        Write-Host ("[{0}] {1}  (última actividad: {2})  <-- RECIENTE" -f $idx, $name, $time) -ForegroundColor Cyan
    }
    else {
        Write-Host ("[{0}] {1}  (última actividad: {2})" -f $idx, $name, $time)
    }
}

# Preguntar selección
$selection = Read-Host ("Selecciona sesión (1-{0}) [ENTER = {1}]" -f $sessions.Count, $defaultIndex)

if ([string]::IsNullOrWhiteSpace($selection)) {
    $selection = $defaultIndex
}

if (-not ($selection -as [int]) -or $selection -lt 1 -or $selection -gt $sessions.Count) {
    Write-Host "Selección inválida." -ForegroundColor Red
    exit 1
}

# Sesión seleccionada:
$chosen            = $sessions[$selection - 1]
$sessionId         = [System.IO.Path]::GetFileNameWithoutExtension($chosen.Name)     # solo nombre, sin ruta
$sessionPathNoExt  = [System.IO.Path]::Combine($chosen.DirectoryName, $sessionId)    # ruta completa sin .rec

Write-Host ""
Write-Host ("Mostrando estado de la sesión: {0}" -f $sessionPathNoExt) -ForegroundColor Green
Write-Host ""

do {
    # Mostrar estado de la sesión (una sola llamada a john)
    $output = & $JohnExe "--status=$sessionPathNoExt" 2>&1

    # Buscar la línea de estado (empieza normalmente por "0g " o "1g ")
    $statusLine = $output | Where-Object { $_ -match '^\d+g ' } | Select-Object -Last 1

    if (-not $statusLine) {
        # Si por lo que sea no cuadra el patrón, usamos la última línea no vacía
        $statusLine = ($output | Where-Object { $_.Trim().Length -gt 0 } | Select-Object -Last 1)
    }

    $timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
    Write-Host ("{0} - {1}" -f $timestamp, $statusLine)

    # Si el refresco es 0 o negativo, solo mostramos una vez
    if ($RefreshSeconds -le 0) {
        break
    }

    # Detectar si la sesión sigue activa (buscamos procesos john.exe cuyo CommandLine contenga el nombre de la sesión)
    $procs    = Get-CimInstance Win32_Process -Filter "Name = 'john.exe'" -ErrorAction SilentlyContinue
    $isActive = $false

    foreach ($p in $procs) {
        if ($p.CommandLine -and $p.CommandLine -like "*$sessionId*") {
            $isActive = $true
            break
        }
    }

    if (-not $isActive) {
        Write-Host ("{0} - La sesión ya no está activa (no hay procesos john.exe con ese nombre de sesión)." -f (Get-Date -Format "yyyy-MM-dd HH:mm:ss")) -ForegroundColor Yellow
        break
    }

    Start-Sleep -Seconds $RefreshSeconds

} while ($true)

ACTUALIZADO 2025-11-25: añadido al repositorio de PowerShell

Un comentario en «Progreso John the Ripper en Windows»

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *


El periodo de verificación de reCAPTCHA ha caducado. Por favor, recarga la página.