#Requires -Version 5.1 <# .SYNOPSIS Inventario de la flota: que maquinas ejecutaron el ejercicio, cuando y con que resultado. .DESCRIPTION Lee los check-in que cada activo envia al C2 y construye el detalle que va al informe: - una fila por maquina con su ULTIMA accion: ejercicio, accion, modo, resultado, Victim ID, run_id y hora - el estado por maquina en formato tabla (o CSV con -ExportCsv) - un resumen: cuantas maquinas han reportado, cuantas terminaron bien y cuantas no - y el desglose por accion y por resultado Es de SOLO LECTURA y no toca el token ni hace peticiones HTTP: lee el JSONL de informes directamente. A proposito, para que no lo bloquee el antivirus por "leer un secreto de un fichero de configuracion", que es lo que le pasa a las utilidades que si lo leen. .PARAMETER Path Fichero JSONL de informes. Por defecto C:\RT\c2-storage\reports.jsonl .PARAMETER Host_ Filtra por maquina (opcional). .PARAMETER ExportCsv Ruta de un CSV de salida, para adjuntar al informe. .EXAMPLE .\Get-C2Fleet.ps1 .EXAMPLE .\Get-C2Fleet.ps1 -ExportCsv C:\RT\informe\flota.csv #> [CmdletBinding()] param( [string]$Path = 'C:\RT\c2-storage\reports.jsonl', [string]$Host_ = '', [string]$ExportCsv ) $ErrorActionPreference = 'Stop' function Rt-Titulo([string]$t) { Write-Host ''; Write-Host "== $t ==" -ForegroundColor Cyan } Write-Host '' Write-Host '=== INVENTARIO DE LA FLOTA ===' -ForegroundColor White Write-Host "Informes: $Path" if (-not (Test-Path -LiteralPath $Path)) { Write-Host '' Write-Host ' Todavia no hay informes: ningun activo ha hecho check-in.' -ForegroundColor Yellow Write-Host ' Comprueba que el stager del C2 apunta a este C2 y que report.php esta desplegado.' -ForegroundColor Yellow Write-Host '' return } $rows = @() foreach ($linea in (Get-Content -LiteralPath $Path)) { if ([string]::IsNullOrWhiteSpace($linea)) { continue } try { $rows += ($linea | ConvertFrom-Json) } catch { } } if ($rows.Count -eq 0) { Write-Host ' El fichero existe pero no tiene lineas validas.' -ForegroundColor Yellow return } if ($Host_) { $rows = @($rows | Where-Object { [string]$_.host -eq $Host_ }) } # Ultimo informe por maquina (el que interesa para saber como quedo cada una) $porHost = @{} foreach ($r in ($rows | Sort-Object ts_unix)) { $porHost[[string]$r.host] = $r } $tabla = foreach ($h in ($porHost.Keys | Sort-Object)) { $r = $porHost[$h] [pscustomobject]@{ Maquina = $h Ejercicio = [string]$r.exercise Accion = [string]$r.action Modo = [string]$r.mode Resultado = [string]$r.result VictimId = [string]$r.victim_id RunId = [string]$r.run_id Ultimo = [string]$r.ts_server } } Rt-Titulo 'Por maquina (ultima accion reportada)' $tabla | Format-Table -AutoSize Rt-Titulo 'Resumen' $ok = @($tabla | Where-Object { $_.Resultado -eq 'completado' }).Count $mal = @($tabla | Where-Object { $_.Resultado -ne 'completado' }).Count Write-Host " Maquinas que han reportado : $($tabla.Count)" Write-Host " Ultima accion completada : $ok" -ForegroundColor Green if ($mal -gt 0) { Write-Host " Ultima accion con problemas: $mal" -ForegroundColor Red } Write-Host " Informes totales : $($rows.Count)" Write-Host '' Write-Host ' Por accion:' -ForegroundColor Gray $rows | Group-Object action | Sort-Object Name | ForEach-Object { Write-Host (" {0,-18} {1,4} informe(s) ({2} maquina/s)" -f $_.Name, $_.Count, (@($_.Group | ForEach-Object { $_.host } | Select-Object -Unique)).Count) } Write-Host ' Por resultado:' -ForegroundColor Gray $rows | Group-Object result | Sort-Object Name | ForEach-Object { Write-Host (" {0,-18} {1,4}" -f $_.Name, $_.Count) } Write-Host ' Por modo:' -ForegroundColor Gray $rows | Group-Object mode | Sort-Object Name | ForEach-Object { Write-Host (" {0,-18} {1,4}" -f $_.Name, $_.Count) } if ($ExportCsv) { $dir = Split-Path -Parent $ExportCsv if ($dir -and -not (Test-Path -LiteralPath $dir)) { New-Item -ItemType Directory -Path $dir -Force | Out-Null } $rows | Select-Object ts_server, host, exercise, action, mode, result, exit_code, victim_id, run_id, user | Export-Csv -LiteralPath $ExportCsv -NoTypeInformation -Encoding UTF8 Write-Host '' Write-Host "CSV exportado: $ExportCsv" -ForegroundColor Green } Write-Host ''