icoa-cli 2.19.245 → 2.19.247
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/commands/ai4ctf.js +1 -1
- package/dist/commands/ctf4ai-demo.js +1 -1
- package/dist/commands/ctf4vla.js +1 -1
- package/dist/commands/env.js +1 -1
- package/dist/commands/exam.js +1 -1
- package/dist/index.js +1 -1
- package/dist/lib/hint-client.js +1 -1
- package/dist/lib/menu-nav.d.ts +7 -0
- package/dist/lib/menu-nav.js +1 -1
- package/dist/repl.js +1 -1
- package/docker/Dockerfile +3 -3
- package/docker/constraints.txt +12 -8
- package/package.json +1 -1
package/dist/commands/env.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import chalk from"chalk";import{execSync as e}from"node:child_process";import{existsSync as o,readFileSync as n}from"node:fs";import{platform as t}from"node:os";import{dirname as r,join as c}from"node:path";import{fileURLToPath as a}from"node:url";const s="3.12.13",i="22.22.2",l=[{name:"pwntools",check:'python3 -c "import pwn"',install:"pwntools==4.12.0",category:"CTF Core"},{name:"pycryptodome",check:'python3 -c "import Crypto"',install:"pycryptodome==3.20.0",category:"CTF Core"},{name:"z3-solver",check:'python3 -c "import z3"',install:"z3-solver==4.12.6",category:"CTF Core"},{name:"angr",check:'python3 -c "import angr"',install:"angr",category:"CTF Core"},{name:"requests",check:'python3 -c "import requests"',install:"requests==2.31.0",category:"Web & Network"},{name:"beautifulsoup4",check:'python3 -c "import bs4"',install:"beautifulsoup4==4.12.3",category:"Web & Network"},{name:"flask",check:'python3 -c "import flask"',install:"flask==3.0.0",category:"Web & Network"},{name:"scapy",check:'python3 -c "import scapy"',install:"scapy==2.5.0",category:"Web & Network"},{name:"paramiko",check:'python3 -c "import paramiko"',install:"paramiko==3.4.0",category:"Web & Network"},{name:"sympy",check:'python3 -c "import sympy"',install:"sympy==1.12",category:"Crypto & Math"},{name:"gmpy2",check:"darwin"===process.platform?'/opt/homebrew/opt/python@3.12/bin/python3.12 -c "import gmpy2"':'python3 -c "import gmpy2"',install:"gmpy2>=2.2.0",category:"Crypto & Math"},{name:"cryptography",check:'python3 -c "import cryptography"',install:"cryptography==42.0.0",category:"Crypto & Math"},{name:"capstone",check:'python3 -c "import capstone"',install:"capstone==5.0.1",category:"Binary & RE"},{name:"ropper",check:'python3 -c "import ropper"',install:"ropper==1.13.8",category:"Binary & RE"},{name:"ROPgadget",check:"which ROPgadget",install:"ROPgadget==7.4",category:"Binary & RE"},{name:"pefile",check:'python3 -c "import pefile"',install:"pefile==2023.2.7",category:"Binary & RE"},{name:"pillow",check:'python3 -c "import PIL"',install:"pillow==10.2.0",category:"Data & Forensics"},{name:"numpy",check:'python3 -c "import numpy"',install:"numpy==1.26.4",category:"Data & Forensics"},{name:"python-magic",check:'python3 -c "import magic"',install:"python-magic==0.4.27",category:"Data & Forensics"},{name:"yara-python",check:'python3 -c "import yara"',install:"yara-python==4.5.0",category:"Data & Forensics"},{name:"sqlmap",check:"which sqlmap",install:"sqlmap",category:"Security Tools"},{name:"ipython",check:"which ipython3 || which ipython",install:"ipython",category:"Security Tools"},{name:"uncompyle6",check:'python3 -c "import uncompyle6"',install:"uncompyle6==3.9.1",category:"Security Tools"},{name:"volatility3",check:'python3 -c "import volatility3"',install:"volatility3",category:"Security Tools"},{name:"pyserial",check:'python3 -c "import serial"',install:"pyserial==3.5",category:"Security Tools"}],g="win32"===process.platform,p=(e,o)=>g?o||`where ${e}`:`which ${e}`,y=[{name:"vim",check:p("vim"),brew:"vim",apt:"vim",choco:"vim",category:"Editors & Terminal"},{name:"nano",check:p("nano"),brew:"nano",apt:"nano",choco:"nano",category:"Editors & Terminal"},{name:"tmux",check:p("tmux"),brew:"tmux",apt:"tmux",category:"Editors & Terminal"},{name:"screen",check:p("screen"),brew:"screen",apt:"screen",category:"Editors & Terminal"},{name:"less",check:p("less"),category:"Editors & Terminal"},{name:"gcc",check:p("gcc"),brew:"gcc",apt:"gcc",choco:"mingw",category:"Compilers & Build"},{name:"g++",check:p("g++"),brew:"gcc",apt:"g++",choco:"mingw",category:"Compilers & Build"},{name:"make",check:p("make"),brew:"make",apt:"make",choco:"make",category:"Compilers & Build"},{name:"nasm",check:p("nasm"),brew:"nasm",apt:"nasm",choco:"nasm",category:"Compilers & Build"},{name:"cmake",check:p("cmake"),brew:"cmake",apt:"cmake",choco:"cmake",category:"Compilers & Build"},{name:"as",check:p("as"),category:"Compilers & Build"},{name:"ld",check:p("ld"),category:"Compilers & Build"},{name:"pkg-config",check:p("pkg-config"),brew:"pkg-config",apt:"pkg-config",category:"Compilers & Build"},{name:"python3",check:"darwin"===process.platform?"/opt/homebrew/opt/python@3.12/bin/python3.12 --version":g?"python --version":"python3 --version",brew:"python@3.12",apt:"python3",choco:"python312",category:"Python Runtime"},{name:"pip3",check:"darwin"===process.platform?"/opt/homebrew/opt/python@3.12/bin/pip3.12 --version":g?"pip --version":"pip3 --version",category:"Python Runtime"},{name:"python3-venv",check:g?'python -c "import venv"':'python3 -c "import venv"',apt:"python3-venv",category:"Python Runtime"},{name:"curl",check:p("curl"),brew:"curl",apt:"curl",choco:"curl",category:"Networking"},{name:"wget",check:p("wget"),brew:"wget",apt:"wget",choco:"wget",category:"Networking"},{name:"nc",check:p("nc","where ncat"),brew:"netcat",apt:"netcat-openbsd",choco:"nmap",category:"Networking"},{name:"socat",check:p("socat"),brew:"socat",apt:"socat",category:"Networking"},{name:"nmap",check:p("nmap"),brew:"nmap",apt:"nmap",choco:"nmap",category:"Networking"},{name:"ssh",check:p("ssh"),apt:"openssh-client",category:"Networking"},{name:"dig",check:p("dig"),brew:"bind",apt:"dnsutils",category:"Networking"},{name:"whois",check:p("whois"),brew:"whois",apt:"whois",choco:"whois",category:"Networking"},{name:"ping",check:p("ping"),apt:"iputils-ping",category:"Networking"},{name:"traceroute",check:p("traceroute","where tracert"),brew:"traceroute",apt:"traceroute",category:"Networking"},{name:"tcpdump",check:p("tcpdump"),brew:"tcpdump",apt:"tcpdump",category:"Networking"},{name:"tshark",check:p("tshark"),brew:"wireshark",apt:"tshark",choco:"wireshark",category:"Networking"},{name:"gdb",check:p("gdb"),brew:"gdb",apt:"gdb",choco:"mingw",category:"Debuggers"},..."darwin"!==process.platform?[{name:"ltrace",check:p("ltrace"),apt:"ltrace",category:"Debuggers"},{name:"strace",check:p("strace"),apt:"strace",category:"Debuggers"}]:[],{name:"objdump",check:p("objdump"),category:"Debuggers"},..."darwin"!==process.platform?[{name:"readelf",check:p("readelf"),category:"Debuggers"}]:[],{name:"radare2",check:p("r2"),brew:"radare2",apt:"radare2",choco:"radare2",category:"Reverse Engineering"},{name:"rabin2",check:p("rabin2"),category:"Reverse Engineering"},{name:"upx",check:p("upx"),brew:"upx",apt:"upx",choco:"upx",category:"Reverse Engineering"},{name:"strings",check:p("strings"),category:"Reverse Engineering"},{name:"binwalk",check:p("binwalk"),brew:"binwalk",apt:"binwalk",category:"Forensics"},..."darwin"!==process.platform?[{name:"foremost",check:p("foremost"),apt:"foremost",category:"Forensics"}]:[],{name:"exiftool",check:p("exiftool"),brew:"exiftool",apt:"exiftool",choco:"exiftool",category:"Forensics"},..."darwin"!==process.platform?[{name:"steghide",check:p("steghide"),apt:"steghide",category:"Forensics"}]:[],{name:"file",check:p("file"),category:"Forensics"},{name:"xxd",check:p("xxd"),brew:"vim",apt:"xxd",category:"Forensics"},{name:"pdftotext",check:p("pdftotext"),brew:"poppler",apt:"poppler-utils",category:"Forensics"},{name:"pngcheck",check:p("pngcheck"),brew:"pngcheck",apt:"pngcheck",category:"Forensics"},{name:"sleuthkit",check:p("mmls"),brew:"sleuthkit",apt:"sleuthkit",choco:"sleuthkit",category:"Forensics"},{name:"john",check:p("john"),brew:"john",apt:"john",choco:"john",category:"Crypto & Password"},{name:"hashcat",check:p("hashcat"),brew:"hashcat",apt:"hashcat",choco:"hashcat",category:"Crypto & Password"},{name:"openssl",check:p("openssl"),category:"Crypto & Password"},{name:"gpg",check:p("gpg"),brew:"gnupg",apt:"gpg",choco:"gnupg",category:"Crypto & Password"},{name:"jq",check:p("jq"),brew:"jq",apt:"jq",choco:"jq",category:"Data Processing"},{name:"sqlite3",check:p("sqlite3"),brew:"sqlite",apt:"sqlite3",choco:"sqlite",category:"Data Processing"},{name:"base64",check:p("base64"),category:"Data Processing"},{name:"hexdump",check:p("hexdump"),category:"Data Processing"},{name:"od",check:p("od"),category:"Data Processing"},{name:"sort",check:p("sort"),category:"Data Processing"},{name:"uniq",check:p("uniq"),category:"Data Processing"},{name:"wc",check:p("wc"),category:"Data Processing"},{name:"unzip",check:p("unzip"),brew:"unzip",apt:"unzip",category:"Archive"},{name:"zip",check:p("zip"),brew:"zip",apt:"zip",category:"Archive"},{name:"tar",check:p("tar"),category:"Archive"},{name:"gzip",check:p("gzip"),category:"Archive"},{name:"bzip2",check:p("bzip2"),category:"Archive"},{name:"xz",check:p("xz"),brew:"xz",apt:"xz-utils",category:"Archive"},{name:"cat",check:p("cat"),category:"Core Unix"},{name:"grep",check:p("grep"),category:"Core Unix"},{name:"sed",check:p("sed"),category:"Core Unix"},{name:"awk",check:p("awk"),category:"Core Unix"},{name:"find",check:p("find"),category:"Core Unix"},{name:"head",check:p("head"),category:"Core Unix"},{name:"tail",check:p("tail"),category:"Core Unix"},{name:"diff",check:p("diff"),category:"Core Unix"},{name:"patch",check:p("patch"),category:"Core Unix"},{name:"chmod",check:p("chmod"),category:"Core Unix"},{name:"chown",check:p("chown"),category:"Core Unix"},{name:"ln",check:p("ln"),category:"Core Unix"},{name:"cp",check:p("cp"),category:"Core Unix"},{name:"mv",check:p("mv"),category:"Core Unix"},{name:"mkdir",check:p("mkdir"),category:"Core Unix"},{name:"rm",check:p("rm"),category:"Core Unix"},{name:"git",check:p("git"),brew:"git",apt:"git",choco:"git",category:"Git & Docker"},{name:"docker",check:p("docker"),brew:"--cask docker",choco:"docker-desktop",category:"Git & Docker"}],h=y.length+l.length;function m(o){const n=o.startsWith("python3 ")?w()+o.slice(7):o;try{return e(n,{stdio:"ignore"}),!0}catch{return!1}}function d(o){const n={python3:`${w()} --version`,pip3:"darwin"===process.platform?"/opt/homebrew/opt/python@3.12/bin/pip3.12 --version":"linux"===process.platform?`${w()} -m pip --version`:"pip --version",gcc:"gcc --version","g++":"g++ --version",make:"make --version",nasm:"nasm --version",cmake:"cmake --version",vim:"vim --version",nano:"nano --version",tmux:"tmux -V",screen:"screen --version",curl:"curl --version",wget:"wget --version",nmap:"nmap --version",ssh:"ssh -V",socat:"socat -V",gdb:"gdb --version",radare2:"r2 -v",upx:"upx --version",binwalk:"binwalk --help",exiftool:"exiftool -ver",john:"john --help",hashcat:"hashcat --version",openssl:"openssl version",gpg:"gpg --version",jq:"jq --version",sqlite3:"sqlite3 --version",git:"git --version",docker:"docker --version",tshark:"tshark --version",tcpdump:"tcpdump --version",pdftotext:"pdftotext -v",pngcheck:"pngcheck 2>&1"}[o];if(!n)return"";try{const o=e(`${n} 2>&1`,{encoding:"utf-8",timeout:3e3}).trim().match(/(\d+\.\d+[.\d]*)/);return o?.[1]||""}catch{}return""}let u=null;export function resetPyBin(){u=null}function w(){if(u)return u;if("darwin"===process.platform)return u="/opt/homebrew/opt/python@3.12/bin/python3.12",u;if("win32"===process.platform)return u="python",u;try{e("python3.12 --version",{stdio:"ignore"}),u="python3.12"}catch{u="python3"}return u}function b(){try{return e(`${w()} -c "import sys; print(f'{sys.version_info.major}.{sys.version_info.minor}')"`,{encoding:"utf-8"}).trim()}catch{return""}}function k(){try{return e(`${w()} --version`,{encoding:"utf-8"}).trim().replace("Python ","")}catch{return""}}export function registerEnvCommand(n){const s=n.command("env").description("Manage competition environment");s.command("status").alias("check").description(`Check all ${h} tools`).action(()=>f()),s.command("setup").description("Install all Python libraries + system tools").action(async()=>{await async function(){console.log();const n=t(),s="darwin"===n||"linux"===n?"--break-system-packages":"";console.log(chalk.bold.white(" ICOA Environment Setup")),console.log(chalk.gray(" ─────────────────────────────────────────────")),console.log(chalk.gray(" This will install:")),console.log(chalk.white(" Python 3.12")+chalk.gray(" Runtime for CTF tools")),console.log(chalk.white(` ${l.length} Python libraries`)+chalk.gray(" pwntools, z3, crypto...")),console.log(chalk.white(` ${y.length} system tools`)+chalk.gray(" gcc, gdb, nmap, wireshark...")),console.log(),console.log(chalk.gray(" Estimated: ~500 MB disk, 5-15 min (depends on network)")),console.log(chalk.gray(" Already installed tools will be skipped.")),console.log(chalk.gray(" ─────────────────────────────────────────────")),console.log(),x("Installing system packages needs administrator access"),console.log();const g=process.versions.node;if(g===i)console.log(chalk.green(` ✓ Node.js ${i}`));else{console.log(chalk.yellow(` Node.js ${g} — installing ${i}...`));try{"darwin"===n?e("brew install node@22",{stdio:"inherit"}):"linux"===n?(await $(),e("curl -fsSL https://deb.nodesource.com/setup_22.x | sudo -E bash - && sudo apt-get install -y nodejs",{stdio:"inherit"})):e(`winget install OpenJS.NodeJS.LTS --version ${i}`,{stdio:"inherit"}),console.log(chalk.green(` ✓ Node.js ${i} installed`)),console.log(chalk.gray(" Restart icoa to use the new version."))}catch{console.log(chalk.yellow(` ~ Node.js upgrade skipped. Install manually: nvm install ${i}`))}}console.log();const p=b(),h=k();if("3.12"===p)console.log(chalk.green(` ✓ Python ${h}`)),console.log();else{console.log(chalk.yellow(` Python ${h||"not found"} — installing Python 3.12 (side-by-side)...`));try{if("darwin"===n)e("brew install python@3.12",{stdio:"inherit"}),resetPyBin(),console.log(chalk.green(" ✓ Python 3.12 installed")),console.log(chalk.gray(" icoa uses it at: /opt/homebrew/opt/python@3.12/bin/python3.12"));else if("linux"===n){console.log(chalk.gray(" Installing python3.12 via apt (your system python3 stays untouched)..."));let o=!1;await $();try{e("sudo apt-get install -y python3.12 python3.12-venv python3.12-dev",{stdio:"inherit"}),o=!0}catch{}if(!o)try{console.log(chalk.gray(" Not in default repos — adding deadsnakes PPA...")),await $(),e("sudo apt-get install -y software-properties-common && sudo add-apt-repository -y ppa:deadsnakes/ppa && sudo apt-get update",{stdio:"inherit"}),await $(),e("sudo apt-get install -y python3.12 python3.12-venv python3.12-dev",{stdio:"inherit"}),o=!0}catch{}if(!o)throw new Error("python3.12 apt install failed");try{e("sudo python3.12 -m ensurepip --upgrade",{stdio:"inherit"})}catch{try{e("curl -sS https://bootstrap.pypa.io/get-pip.py | sudo python3.12",{stdio:"inherit"})}catch{}}resetPyBin(),console.log(chalk.green(" ✓ Python 3.12 installed (as python3.12; system python3 unchanged)")),console.log(chalk.gray(" Run Python challenges with `python3.12`, or use the sandbox where `python3` is 3.12."))}else{try{e("winget install Python.Python.3.12 --accept-package-agreements --accept-source-agreements",{stdio:"inherit"})}catch{e("choco install -y python312",{stdio:"inherit"})}console.log(chalk.green(" ✓ Python 3.12 installed"))}}catch{console.log(chalk.red(" ✗ Failed to install Python 3.12"));const e="darwin"===n?"brew install python@3.12":"linux"===n?"sudo apt install python3.12":"winget install Python.Python.3.12";console.log(chalk.gray(` Manual install: ${e}`))}console.log()}"win32"===n&&(console.log(chalk.yellow(" Windows: Most CTF tools require Linux. Recommended:")),console.log(chalk.white(" wsl --install")),console.log(chalk.gray(" Then run icoa inside WSL Ubuntu for full tool support.")),console.log());const d=[];for(const e of y)m(e.check)||("darwin"===n?e.brew:"linux"===n?e.apt:e.choco)&&d.push(e);if(d.length>0&&"win32"!==n){const o="darwin"===n?"brew":"apt";if(console.log(chalk.bold.white(` System Tools via ${o} (${d.length} missing)`)),console.log(chalk.gray(" ─────────────────────────────────────────────")),await $(),x("Installing system tools needs administrator access"),"linux"===n)try{e("sudo apt-get update",{stdio:["ignore","ignore","pipe"]})}catch{}for(const t of d){const r="darwin"===n?t.brew:"linux"===n?t.apt:t.choco;P(t.name);try{let o;o="darwin"===n?`brew install ${r}`:"linux"===n?`sudo apt-get install -y ${r}`:`choco install -y ${r}`,e(o,{stdio:["ignore","ignore","pipe"]}),C(),console.log(chalk.green(` ✓ ${t.name}`))}catch(e){C();const n=E(e);console.log(chalk.red(` ✗ ${t.name}`)+chalk.gray(` (${o} install ${r})`)+(n?chalk.gray(`\n ${n}`):""))}}console.log()}let u="pip3";if("darwin"===n){const o="/opt/homebrew/opt/python@3.12/bin/pip3.12";try{e(`${o} --version`,{stdio:"ignore"}),u=o,console.log(chalk.gray(` Using: ${o}`))}catch{try{e("pip3.12 --version",{stdio:"ignore"}),u="pip3.12"}catch{}}}else if("linux"===n)try{e("python3.12 -m pip --version",{stdio:"ignore"}),u="python3.12 -m pip"}catch{try{e("pip3.12 --version",{stdio:"ignore"}),u="pip3.12"}catch{}}else"win32"===n&&(u="pip");if("darwin"===n){console.log(chalk.gray(" Installing build dependencies..."));try{e("brew install gmp mpfr libmpc libmagic",{stdio:"ignore"}),console.log(chalk.green(" ✓ Build dependencies ready (gmp, mpfr, libmpc, libmagic)"))}catch{}}else if("linux"===n){console.log(chalk.gray(" Installing build dependencies..."));try{await $(),x("Build dependencies need administrator access"),e("sudo apt-get install -y libgmp-dev libmpfr-dev libmpc-dev libmagic1",{stdio:["ignore","ignore","pipe"]}),console.log(chalk.green(" ✓ Build dependencies ready (libgmp, libmpfr, libmpc, libmagic)"))}catch(e){const o=E(e);console.log(chalk.yellow(" ~ Build dependencies may be incomplete")+(o?chalk.gray(`: ${o}`):"")),console.log(chalk.gray(" gmpy2 needs: sudo apt-get install -y libgmp-dev libmpfr-dev libmpc-dev"))}}console.log();const w={...process.env};"darwin"===n&&(w.CFLAGS=`-I/opt/homebrew/include ${w.CFLAGS||""}`.trim(),w.LDFLAGS=`-L/opt/homebrew/lib ${w.LDFLAGS||""}`.trim(),w.C_INCLUDE_PATH=`/opt/homebrew/include:${w.C_INCLUDE_PATH||""}`,w.LIBRARY_PATH=`/opt/homebrew/lib:${w.LIBRARY_PATH||""}`);const f=c(r(a(import.meta.url)),"..","..","docker","constraints.txt"),v=o(f)?`-c '${f}'`:"";let T=0,S=0;console.log(chalk.bold.white(` Python Libraries (${l.length} packages)`)),console.log(chalk.gray(" ─────────────────────────────────────────────"));for(const o of l)if(o.install)if(m(o.check))console.log(chalk.green(` ✓ ${o.name}`)+chalk.gray(" (installed)")),T++;else{P(o.name);try{e(`${u} install ${s} ${v} '${o.install}'`,{stdio:["ignore","ignore","pipe"],env:w}),C(),console.log(chalk.green(` ✓ ${o.name}`)+chalk.gray(` (${o.install})`)),T++}catch(e){C();const n=E(e);console.log(chalk.red(` ✗ ${o.name}`)+chalk.gray(" (failed)")+(n?chalk.gray(`\n ${n}`):"")),S++}}if(console.log(),console.log(chalk.gray(" ─────────────────────────────────────────────")),console.log(` ${chalk.green(`✓ ${T} installed`)} ${S>0?chalk.red(`✗ ${S} failed`):chalk.green("All ready!")}`),console.log(),"win32"!==n){console.log(chalk.bold.white(" GDB Extension (bata24/gef default · pwndbg optional)")),console.log(chalk.gray(" ─────────────────────────────────────────────")),P("bata24/gef");try{e('wget -qO "$HOME/.gef-bata24.py" https://raw.githubusercontent.com/bata24/gef/master/gef.py && touch "$HOME/.gdbinit" && (grep -q gef-bata24 "$HOME/.gdbinit" || printf \'\\nsource %s/.gef-bata24.py\\n\' "$HOME" >> "$HOME/.gdbinit")',{stdio:["ignore","ignore","pipe"]}),C(),console.log(chalk.green(" ✓ bata24/gef")+chalk.gray(" (default gdb)"))}catch(e){C();const o=E(e);console.log(chalk.red(" ✗ bata24/gef")+(o?chalk.gray(`\n ${o}`):""))}if(m('test -d "$HOME/pwndbg"'))console.log(chalk.green(" ✓ pwndbg")+chalk.gray(" (run: gdb-pwndbg)"));else{const o="darwin"===n?"command -v uv >/dev/null 2>&1 || brew install uv":"command -v uv >/dev/null 2>&1 || pip3 install --user uv";P("pwndbg (optional)");try{e(`export PATH="$HOME/.local/bin:$PATH" && ${o} && rm -rf "$HOME/pwndbg" && git clone --depth 1 https://github.com/pwndbg/pwndbg "$HOME/pwndbg" && cd "$HOME/pwndbg" && ./setup.sh && mkdir -p "$HOME/.local/bin" && printf '#!/bin/sh\\nexec gdb -q -nx -ex "source $HOME/pwndbg/gdbinit.py" "$@"\\n' > "$HOME/.local/bin/gdb-pwndbg" && chmod +x "$HOME/.local/bin/gdb-pwndbg" && sed -i.bak '/pwndbg/d' "$HOME/.gdbinit" 2>/dev/null || true`,{stdio:["ignore","ignore","pipe"],env:w}),C(),console.log(chalk.green(" ✓ pwndbg")+chalk.gray(" (run: gdb-pwndbg)"))}catch{C(),console.log(chalk.yellow(" ~ pwndbg skipped")+chalk.gray(" (optional — bata24/gef is your default debugger)"))}}console.log(chalk.gray(" Default `gdb` loads bata24/gef; where installed, `gdb-pwndbg` loads pwndbg.")),console.log(chalk.gray(" (ensure ~/.local/bin is on PATH for gdb-pwndbg)")),console.log()}}()}),s.command("python").description("Show Python 3.12 install guide for your platform").action(()=>function(){const o=t();console.log(),console.log(chalk.bold.white(" Python 3.12 — Installation Guide")),console.log(chalk.gray(" ─────────────────────────────────────────────")),console.log();let n="",r="missing";const c=["python3.12 --version","/opt/homebrew/opt/python@3.12/bin/python3.12 --version","/usr/local/opt/python@3.12/bin/python3.12 --version","python3 --version"];for(const o of c)try{const t=e(o,{encoding:"utf-8",timeout:3e3}).trim().replace("Python ",""),c=t.split(".").map(Number);if(3===c[0]&&12===c[1]){n=t,r="ok";break}n=t,r=3===c[0]&&c[1]>=10&&c[1]<12?"old":3===c[0]&&c[1]>12?"new":"missing"}catch{}if("ok"===r)return console.log(chalk.green(` ✓ Python ${n} — you're good!`)),console.log(chalk.gray(" Exam toolkit ready. Next: ")+chalk.bold.cyan("exam setup")),void console.log();if("old"===r?console.log(chalk.yellow(` ⚠ Python ${n} — works, but 3.12 recommended`)):"new"===r?(console.log(chalk.yellow(` ⚠ Python ${n} — some packages (pwntools, scapy) lack wheels`)),console.log(chalk.gray(" Downgrading to 3.12 is strongly recommended"))):console.log(chalk.red(" ✗ Python 3 not found")),console.log(),"darwin"===o)console.log(chalk.bold.white(" macOS (Homebrew)")),console.log(),console.log(chalk.green(" brew install python@3.12"));else if("linux"===o){let o="ubuntu";try{const n=e("cat /etc/os-release 2>/dev/null",{encoding:"utf-8",timeout:2e3});o=/fedora|rhel|centos/i.test(n)?"fedora":/arch|manjaro/i.test(n)?"arch":"ubuntu"}catch{}"ubuntu"===o?(console.log(chalk.bold.white(" Ubuntu / Debian / Kali (deadsnakes PPA)")),console.log(),console.log(chalk.gray(" Copy-paste this one-liner:")),console.log(),console.log(chalk.green(" sudo add-apt-repository ppa:deadsnakes/ppa -y && \\")),console.log(chalk.green(" sudo apt update && \\")),console.log(chalk.green(" sudo apt install -y python3.12 python3.12-venv python3.12-dev")),console.log(),console.log(chalk.gray(" This installs ")+chalk.cyan("python3.12")+chalk.gray(" alongside your system python3 — run it as ")+chalk.cyan("python3.12")),console.log(chalk.gray(" (don’t repoint /usr/bin/python3 — it breaks apt & command-not-found on Ubuntu)."))):"fedora"===o?(console.log(chalk.bold.white(" Fedora / RHEL / CentOS")),console.log(),console.log(chalk.green(" sudo dnf install -y python3.12 python3.12-pip"))):"arch"===o&&(console.log(chalk.bold.white(" Arch / Manjaro (via pyenv)")),console.log(),console.log(chalk.green(" sudo pacman -S pyenv && pyenv install 3.12 && pyenv global 3.12")))}else"win32"===o?(console.log(chalk.bold.white(" Windows (WSL recommended)")),console.log(),console.log(chalk.gray(" WSL + Ubuntu (best):")),console.log(chalk.green(" wsl --install")),console.log(chalk.gray(" Then inside Ubuntu, run the Ubuntu commands.")),console.log(),console.log(chalk.gray(" Or native:")),console.log(chalk.green(" winget install Python.Python.3.12"))):console.log(chalk.gray(" https://www.python.org/downloads/"));console.log(),console.log(chalk.white(" After installing, verify:")),console.log(chalk.bold.cyan(" env python")+chalk.gray(" # re-check Python")),console.log(chalk.bold.cyan(" exam setup")+chalk.gray(" # install the 13 exam packages")),console.log()}()),s.action(()=>f())}function f(){console.log();const r=t(),c="darwin"===r?"brew":"linux"===r?"apt":"winget";console.log(chalk.bold.white(" ICOA Competition Environment")),console.log(chalk.gray(" ─────────────────────────────────────────────")),console.log(),console.log(chalk.gray(" These tools power your CTF competition environment.")),console.log(chalk.gray(" Not all are required — here's what matters:")),console.log(),console.log(chalk.green(" Essential")+chalk.gray(" pwntools, z3, requests, numpy")),console.log(chalk.gray(" You need these for most challenges")),console.log(chalk.yellow(" Recommended")+chalk.gray(" pycryptodome, beautifulsoup4, scapy, sympy")),console.log(chalk.gray(" Covers Web, Crypto, and Forensics")),console.log(chalk.gray(` Full (${h}) All tools for every category`)),console.log(),console.log(chalk.gray(" Missing tools? Run ")+chalk.bold.cyan("env setup")+chalk.gray(" to install everything.")),console.log(chalk.gray(" ─────────────────────────────────────────────")),console.log(),console.log(chalk.gray(" OS: ")+chalk.white(function(){const r=t();try{if("darwin"===r)return`macOS ${e("sw_vers -productVersion",{encoding:"utf-8"}).trim()} (${e("uname -m",{encoding:"utf-8"}).trim()})`;if("linux"===r)try{let t="Linux";try{const o=e("cat /etc/os-release | grep PRETTY_NAME",{encoding:"utf-8"}).match(/PRETTY_NAME="(.+)"/);o&&(t=o[1])}catch{}const r=e("uname -m",{encoding:"utf-8"}).trim(),c=function(){try{if(process.env.WSL_DISTRO_NAME)return"WSL";if(n("/proc/version","utf-8").toLowerCase().includes("microsoft"))return"WSL"}catch{}try{if(o("/opt/google/cros-containers"))return"Crostini"}catch{}return""}();return c?`${t} (${r}, ${c})`:`${t} (${r})`}catch{return"Linux"}else if("win32"===r)return e("ver",{encoding:"utf-8"}).trim()||"Windows"}catch{}return r}())),console.log(chalk.gray(" Node: ")+chalk.white(`Node.js ${process.version}`)),console.log(chalk.gray(" Package: ")+chalk.white(c)),console.log(chalk.gray(" Target: ")+chalk.white(`Node ${i} | Python ${s}`)),"win32"===r&&(console.log(),console.log(chalk.yellow(" Windows: recommend WSL (Ubuntu) for full CTF tool support")),console.log(chalk.gray(" Install WSL: ")+chalk.white("wsl --install")),console.log(chalk.gray(" Then run icoa inside WSL for 100% tool compatibility"))),console.log(chalk.gray(" ─────────────────────────────────────────────"));const a=process.versions.node,g=a.split(".").map(Number);g[0]>22||22===g[0]&&g[1]>22||22===g[0]&&22===g[1]&&g[2]>=2?console.log(chalk.green(` ✓ Node.js ${a}`)+chalk.gray(` (>= ${i})`)):(console.log(chalk.red(` ✗ Node.js ${a}`)+chalk.gray(` (>= ${i} required)`)),console.log(chalk.gray(" Install: nvm install 22 or visit https://nodejs.org/")));const p=b(),u=k();"3.12"===p?console.log(chalk.green(` ✓ Python ${u}`)+chalk.gray(u===s?" (official)":"")):p?console.log(chalk.yellow(` ~ Python ${u}`)+chalk.gray(" (3.12 required, run env setup)")):console.log(chalk.red(" ✗ Python 3 not found")),console.log();let w=0,f=0,v="";for(const e of y){e.category!==v&&(v=e.category,console.log(chalk.bold.gray(` ${v}`)));const o=m(e.check),n=o?d(e.name):"",t=n?chalk.gray(` (${n})`):"";o?(console.log(chalk.green(` ✓ ${e.name}`)+t),w++):(console.log(chalk.red(` ✗ ${e.name}`)),f++)}"win32"!==r&&(console.log(chalk.bold.gray(" GDB Extension")),m('grep -qi pwndbg "$HOME/.gdbinit" 2>/dev/null || test -f "$HOME/.gef-bata24.py"')?(console.log(chalk.green(" ✓ bata24-gef (+pwndbg)")),w++):(console.log(chalk.red(" ✗ bata24-gef (+pwndbg)")+chalk.gray(" (run env setup)")),f++)),v="";const $="darwin"===r?"/opt/homebrew/opt/python@3.12/bin/pip3.12":"win32"===r?"pip":"pip3";for(const o of l)if(o.category!==v&&(v=o.category,console.log(chalk.bold.gray(` ${v}`))),m(o.check)){let n="";for(const t of[$,"pip3","pip"])try{const r=o.name.replace("python-magic","python_magic"),c=e(`${t} show ${r}`,{encoding:"utf-8",timeout:3e3,stdio:["pipe","pipe","ignore"]}).match(/Version:\s*(\S+)/);if(c){n=c[1];break}}catch{}console.log(chalk.green(` ✓ ${o.name}`)+chalk.gray(n?` (${n})`:"")),w++}else console.log(chalk.red(` ✗ ${o.name}`)+chalk.gray(` → ${o.install||"latest"}`)),f++;const x=w+f;console.log(),console.log(chalk.gray(" ─────────────────────────────────────────────")),console.log(` ${chalk.green(`✓ ${w}/${x}`)} ${f>0?chalk.red(`✗ ${f} missing`):chalk.green(`All ${x} ready!`)}`),f>0&&console.log(chalk.gray(" Install everything: ")+chalk.white("env setup")+chalk.gray(" (~5 min, one-time)")),console.log(chalk.gray(" You are back at the ")+chalk.cyan("icoa>")+chalk.gray(" prompt. ")+chalk.cyan("help")+chalk.gray(" for all commands.")),console.log()}function v(){for(const o of["/var/lib/dpkg/lock-frontend","/var/lib/dpkg/lock","/var/lib/apt/lists/lock"])try{return e(`sudo fuser ${o} 2>/dev/null`,{stdio:"ignore",timeout:5e3}),!0}catch{}return!1}async function $(e=3e5){if("linux"!==t())return;if(!v())return;console.log(chalk.yellow(" ⏳ System package manager is busy")+chalk.gray(" (ChromeOS may be updating in the background).")),console.log(chalk.gray(` Waiting up to ${Math.round(e/6e4)} min for it to finish… `)+chalk.gray("(Ctrl+C to cancel, or re-run ")+chalk.cyan("env setup")+chalk.gray(" later)")),process.stdout.write(chalk.gray(" "));const o=Date.now();let n=0;for(;v();){if(Date.now()-o>e)return console.log(),console.log(chalk.yellow(" ~ Still busy after waiting. Skipping the wait.")),void console.log(chalk.gray(" If installs fail, re-run ")+chalk.cyan("env setup")+chalk.gray(" in a few minutes."));process.stdout.write(chalk.gray(".")),++n%50==0&&process.stdout.write(chalk.gray("\n ")),await new Promise(e=>setTimeout(e,3e3))}console.log(),console.log(chalk.green(" ✓ Package manager free — continuing."))}function x(o){if("linux"===t()){try{return void e("sudo -n true",{stdio:"ignore"})}catch{}console.log(chalk.yellow(` 🔑 ${o}`)+chalk.gray(" — enter your password if prompted:"));try{e("sudo -v",{stdio:"inherit"})}catch{console.log(chalk.gray(" (sudo unavailable — some installs may fail)"))}}}function P(e){process.stdout.isTTY&&process.stdout.write(chalk.gray(` ⏳ ${e}...`))}function C(){process.stdout.isTTY&&process.stdout.write("\r[2K")}function E(e){const o=e,n=(o?.stderr?o.stderr.toString():"").split("\n").map(e=>e.trim()).filter(Boolean);return n.length?n[n.length-1].slice(0,100):""}
|
|
1
|
+
import chalk from"chalk";import{execSync as e}from"node:child_process";import{existsSync as o,readFileSync as n}from"node:fs";import{platform as t}from"node:os";import{dirname as r,join as c}from"node:path";import{fileURLToPath as a}from"node:url";const s="3.12.13",i="22.22.2",l=[{name:"pwntools",check:'python3 -c "import pwn"',install:"pwntools==4.12.0",category:"CTF Core"},{name:"pycryptodome",check:'python3 -c "import Crypto"',install:"pycryptodome==3.20.0",category:"CTF Core"},{name:"z3-solver",check:'python3 -c "import z3"',install:"z3-solver==4.13.0.0",category:"CTF Core"},{name:"angr",check:'python3 -c "import angr"',install:"angr",category:"CTF Core"},{name:"requests",check:'python3 -c "import requests"',install:"requests==2.31.0",category:"Web & Network"},{name:"beautifulsoup4",check:'python3 -c "import bs4"',install:"beautifulsoup4==4.12.3",category:"Web & Network"},{name:"flask",check:'python3 -c "import flask"',install:"flask==3.0.0",category:"Web & Network"},{name:"scapy",check:'python3 -c "import scapy"',install:"scapy==2.5.0",category:"Web & Network"},{name:"paramiko",check:'python3 -c "import paramiko"',install:"paramiko==3.4.0",category:"Web & Network"},{name:"sympy",check:'python3 -c "import sympy"',install:"sympy==1.12",category:"Crypto & Math"},{name:"gmpy2",check:"darwin"===process.platform?'/opt/homebrew/opt/python@3.12/bin/python3.12 -c "import gmpy2"':'python3 -c "import gmpy2"',install:"gmpy2>=2.2.0",category:"Crypto & Math"},{name:"cryptography",check:'python3 -c "import cryptography"',install:"cryptography==42.0.0",category:"Crypto & Math"},{name:"capstone",check:'python3 -c "import capstone"',install:"capstone==5.0.6",category:"Binary & RE"},{name:"ropper",check:'python3 -c "import ropper"',install:"ropper==1.13.8",category:"Binary & RE"},{name:"ROPgadget",check:"which ROPgadget",install:"ROPgadget==7.4",category:"Binary & RE"},{name:"pefile",check:'python3 -c "import pefile"',install:"pefile==2024.8.26",category:"Binary & RE"},{name:"pillow",check:'python3 -c "import PIL"',install:"pillow==10.2.0",category:"Data & Forensics"},{name:"numpy",check:'python3 -c "import numpy"',install:"numpy==1.26.4",category:"Data & Forensics"},{name:"python-magic",check:'python3 -c "import magic"',install:"python-magic==0.4.27",category:"Data & Forensics"},{name:"yara-python",check:'python3 -c "import yara"',install:"yara-python==4.5.0",category:"Data & Forensics"},{name:"sqlmap",check:"which sqlmap",install:"sqlmap",category:"Security Tools"},{name:"ipython",check:"which ipython3 || which ipython",install:"ipython",category:"Security Tools"},{name:"uncompyle6",check:'python3 -c "import uncompyle6"',install:"uncompyle6==3.9.1",category:"Security Tools"},{name:"volatility3",check:'python3 -c "import volatility3"',install:"volatility3",category:"Security Tools"},{name:"pyserial",check:'python3 -c "import serial"',install:"pyserial==3.5",category:"Security Tools"}],g="win32"===process.platform,p=(e,o)=>g?o||`where ${e}`:`which ${e}`,y=[{name:"vim",check:p("vim"),brew:"vim",apt:"vim",choco:"vim",category:"Editors & Terminal"},{name:"nano",check:p("nano"),brew:"nano",apt:"nano",choco:"nano",category:"Editors & Terminal"},{name:"tmux",check:p("tmux"),brew:"tmux",apt:"tmux",category:"Editors & Terminal"},{name:"screen",check:p("screen"),brew:"screen",apt:"screen",category:"Editors & Terminal"},{name:"less",check:p("less"),category:"Editors & Terminal"},{name:"gcc",check:p("gcc"),brew:"gcc",apt:"gcc",choco:"mingw",category:"Compilers & Build"},{name:"g++",check:p("g++"),brew:"gcc",apt:"g++",choco:"mingw",category:"Compilers & Build"},{name:"make",check:p("make"),brew:"make",apt:"make",choco:"make",category:"Compilers & Build"},{name:"nasm",check:p("nasm"),brew:"nasm",apt:"nasm",choco:"nasm",category:"Compilers & Build"},{name:"cmake",check:p("cmake"),brew:"cmake",apt:"cmake",choco:"cmake",category:"Compilers & Build"},{name:"as",check:p("as"),category:"Compilers & Build"},{name:"ld",check:p("ld"),category:"Compilers & Build"},{name:"pkg-config",check:p("pkg-config"),brew:"pkg-config",apt:"pkg-config",category:"Compilers & Build"},{name:"python3",check:"darwin"===process.platform?"/opt/homebrew/opt/python@3.12/bin/python3.12 --version":g?"python --version":"python3 --version",brew:"python@3.12",apt:"python3",choco:"python312",category:"Python Runtime"},{name:"pip3",check:"darwin"===process.platform?"/opt/homebrew/opt/python@3.12/bin/pip3.12 --version":g?"pip --version":"pip3 --version",category:"Python Runtime"},{name:"python3-venv",check:g?'python -c "import venv"':'python3 -c "import venv"',apt:"python3-venv",category:"Python Runtime"},{name:"curl",check:p("curl"),brew:"curl",apt:"curl",choco:"curl",category:"Networking"},{name:"wget",check:p("wget"),brew:"wget",apt:"wget",choco:"wget",category:"Networking"},{name:"nc",check:p("nc","where ncat"),brew:"netcat",apt:"netcat-openbsd",choco:"nmap",category:"Networking"},{name:"socat",check:p("socat"),brew:"socat",apt:"socat",category:"Networking"},{name:"nmap",check:p("nmap"),brew:"nmap",apt:"nmap",choco:"nmap",category:"Networking"},{name:"ssh",check:p("ssh"),apt:"openssh-client",category:"Networking"},{name:"dig",check:p("dig"),brew:"bind",apt:"dnsutils",category:"Networking"},{name:"whois",check:p("whois"),brew:"whois",apt:"whois",choco:"whois",category:"Networking"},{name:"ping",check:p("ping"),apt:"iputils-ping",category:"Networking"},{name:"traceroute",check:p("traceroute","where tracert"),brew:"traceroute",apt:"traceroute",category:"Networking"},{name:"tcpdump",check:p("tcpdump"),brew:"tcpdump",apt:"tcpdump",category:"Networking"},{name:"tshark",check:p("tshark"),brew:"wireshark",apt:"tshark",choco:"wireshark",category:"Networking"},{name:"gdb",check:p("gdb"),brew:"gdb",apt:"gdb",choco:"mingw",category:"Debuggers"},..."darwin"!==process.platform?[{name:"ltrace",check:p("ltrace"),apt:"ltrace",category:"Debuggers"},{name:"strace",check:p("strace"),apt:"strace",category:"Debuggers"}]:[],{name:"objdump",check:p("objdump"),category:"Debuggers"},..."darwin"!==process.platform?[{name:"readelf",check:p("readelf"),category:"Debuggers"}]:[],{name:"radare2",check:p("r2"),brew:"radare2",apt:"radare2",choco:"radare2",category:"Reverse Engineering"},{name:"rabin2",check:p("rabin2"),category:"Reverse Engineering"},{name:"upx",check:p("upx"),brew:"upx",apt:"upx",choco:"upx",category:"Reverse Engineering"},{name:"strings",check:p("strings"),category:"Reverse Engineering"},{name:"binwalk",check:p("binwalk"),brew:"binwalk",apt:"binwalk",category:"Forensics"},..."darwin"!==process.platform?[{name:"foremost",check:p("foremost"),apt:"foremost",category:"Forensics"}]:[],{name:"exiftool",check:p("exiftool"),brew:"exiftool",apt:"exiftool",choco:"exiftool",category:"Forensics"},..."darwin"!==process.platform?[{name:"steghide",check:p("steghide"),apt:"steghide",category:"Forensics"}]:[],{name:"file",check:p("file"),category:"Forensics"},{name:"xxd",check:p("xxd"),brew:"vim",apt:"xxd",category:"Forensics"},{name:"pdftotext",check:p("pdftotext"),brew:"poppler",apt:"poppler-utils",category:"Forensics"},{name:"pngcheck",check:p("pngcheck"),brew:"pngcheck",apt:"pngcheck",category:"Forensics"},{name:"sleuthkit",check:p("mmls"),brew:"sleuthkit",apt:"sleuthkit",choco:"sleuthkit",category:"Forensics"},{name:"john",check:p("john"),brew:"john",apt:"john",choco:"john",category:"Crypto & Password"},{name:"hashcat",check:p("hashcat"),brew:"hashcat",apt:"hashcat",choco:"hashcat",category:"Crypto & Password"},{name:"openssl",check:p("openssl"),category:"Crypto & Password"},{name:"gpg",check:p("gpg"),brew:"gnupg",apt:"gpg",choco:"gnupg",category:"Crypto & Password"},{name:"jq",check:p("jq"),brew:"jq",apt:"jq",choco:"jq",category:"Data Processing"},{name:"sqlite3",check:p("sqlite3"),brew:"sqlite",apt:"sqlite3",choco:"sqlite",category:"Data Processing"},{name:"base64",check:p("base64"),category:"Data Processing"},{name:"hexdump",check:p("hexdump"),category:"Data Processing"},{name:"od",check:p("od"),category:"Data Processing"},{name:"sort",check:p("sort"),category:"Data Processing"},{name:"uniq",check:p("uniq"),category:"Data Processing"},{name:"wc",check:p("wc"),category:"Data Processing"},{name:"unzip",check:p("unzip"),brew:"unzip",apt:"unzip",category:"Archive"},{name:"zip",check:p("zip"),brew:"zip",apt:"zip",category:"Archive"},{name:"tar",check:p("tar"),category:"Archive"},{name:"gzip",check:p("gzip"),category:"Archive"},{name:"bzip2",check:p("bzip2"),category:"Archive"},{name:"xz",check:p("xz"),brew:"xz",apt:"xz-utils",category:"Archive"},{name:"cat",check:p("cat"),category:"Core Unix"},{name:"grep",check:p("grep"),category:"Core Unix"},{name:"sed",check:p("sed"),category:"Core Unix"},{name:"awk",check:p("awk"),category:"Core Unix"},{name:"find",check:p("find"),category:"Core Unix"},{name:"head",check:p("head"),category:"Core Unix"},{name:"tail",check:p("tail"),category:"Core Unix"},{name:"diff",check:p("diff"),category:"Core Unix"},{name:"patch",check:p("patch"),category:"Core Unix"},{name:"chmod",check:p("chmod"),category:"Core Unix"},{name:"chown",check:p("chown"),category:"Core Unix"},{name:"ln",check:p("ln"),category:"Core Unix"},{name:"cp",check:p("cp"),category:"Core Unix"},{name:"mv",check:p("mv"),category:"Core Unix"},{name:"mkdir",check:p("mkdir"),category:"Core Unix"},{name:"rm",check:p("rm"),category:"Core Unix"},{name:"git",check:p("git"),brew:"git",apt:"git",choco:"git",category:"Git & Docker"},{name:"docker",check:p("docker"),brew:"--cask docker",choco:"docker-desktop",category:"Git & Docker"}],h=y.length+l.length;function m(o){const n=o.startsWith("python3 ")?w()+o.slice(7):o;try{return e(n,{stdio:"ignore"}),!0}catch{return!1}}function d(o){const n={python3:`${w()} --version`,pip3:"darwin"===process.platform?"/opt/homebrew/opt/python@3.12/bin/pip3.12 --version":"linux"===process.platform?`${w()} -m pip --version`:"pip --version",gcc:"gcc --version","g++":"g++ --version",make:"make --version",nasm:"nasm --version",cmake:"cmake --version",vim:"vim --version",nano:"nano --version",tmux:"tmux -V",screen:"screen --version",curl:"curl --version",wget:"wget --version",nmap:"nmap --version",ssh:"ssh -V",socat:"socat -V",gdb:"gdb --version",radare2:"r2 -v",upx:"upx --version",binwalk:"binwalk --help",exiftool:"exiftool -ver",john:"john --help",hashcat:"hashcat --version",openssl:"openssl version",gpg:"gpg --version",jq:"jq --version",sqlite3:"sqlite3 --version",git:"git --version",docker:"docker --version",tshark:"tshark --version",tcpdump:"tcpdump --version",pdftotext:"pdftotext -v",pngcheck:"pngcheck 2>&1"}[o];if(!n)return"";try{const o=e(`${n} 2>&1`,{encoding:"utf-8",timeout:3e3}).trim().match(/(\d+\.\d+[.\d]*)/);return o?.[1]||""}catch{}return""}let u=null;export function resetPyBin(){u=null}function w(){if(u)return u;if("darwin"===process.platform)return u="/opt/homebrew/opt/python@3.12/bin/python3.12",u;if("win32"===process.platform)return u="python",u;try{e("python3.12 --version",{stdio:"ignore"}),u="python3.12"}catch{u="python3"}return u}function b(){try{return e(`${w()} -c "import sys; print(f'{sys.version_info.major}.{sys.version_info.minor}')"`,{encoding:"utf-8"}).trim()}catch{return""}}function k(){try{return e(`${w()} --version`,{encoding:"utf-8"}).trim().replace("Python ","")}catch{return""}}export function registerEnvCommand(n){const s=n.command("env").description("Manage competition environment");s.command("status").alias("check").description(`Check all ${h} tools`).action(()=>f()),s.command("setup").description("Install all Python libraries + system tools").action(async()=>{await async function(){console.log();const n=t(),s="darwin"===n||"linux"===n?"--break-system-packages":"";console.log(chalk.bold.white(" ICOA Environment Setup")),console.log(chalk.gray(" ─────────────────────────────────────────────")),console.log(chalk.gray(" This will install:")),console.log(chalk.white(" Python 3.12")+chalk.gray(" Runtime for CTF tools")),console.log(chalk.white(` ${l.length} Python libraries`)+chalk.gray(" pwntools, z3, crypto...")),console.log(chalk.white(` ${y.length} system tools`)+chalk.gray(" gcc, gdb, nmap, wireshark...")),console.log(),console.log(chalk.gray(" Estimated: ~500 MB disk, 5-15 min (depends on network)")),console.log(chalk.gray(" Already installed tools will be skipped.")),console.log(chalk.gray(" ─────────────────────────────────────────────")),console.log(),x("Installing system packages needs administrator access"),console.log();const g=process.versions.node;if(g===i)console.log(chalk.green(` ✓ Node.js ${i}`));else{console.log(chalk.yellow(` Node.js ${g} — installing ${i}...`));try{"darwin"===n?e("brew install node@22",{stdio:"inherit"}):"linux"===n?(await $(),e("curl -fsSL https://deb.nodesource.com/setup_22.x | sudo -E bash - && sudo apt-get install -y nodejs",{stdio:"inherit"})):e(`winget install OpenJS.NodeJS.LTS --version ${i}`,{stdio:"inherit"}),console.log(chalk.green(` ✓ Node.js ${i} installed`)),console.log(chalk.gray(" Restart icoa to use the new version."))}catch{console.log(chalk.yellow(` ~ Node.js upgrade skipped. Install manually: nvm install ${i}`))}}console.log();const p=b(),h=k();if("3.12"===p)console.log(chalk.green(` ✓ Python ${h}`)),console.log();else{console.log(chalk.yellow(` Python ${h||"not found"} — installing Python 3.12 (side-by-side)...`));try{if("darwin"===n)e("brew install python@3.12",{stdio:"inherit"}),resetPyBin(),console.log(chalk.green(" ✓ Python 3.12 installed")),console.log(chalk.gray(" icoa uses it at: /opt/homebrew/opt/python@3.12/bin/python3.12"));else if("linux"===n){console.log(chalk.gray(" Installing python3.12 via apt (your system python3 stays untouched)..."));let o=!1;await $();try{e("sudo apt-get install -y python3.12 python3.12-venv python3.12-dev",{stdio:"inherit"}),o=!0}catch{}if(!o)try{console.log(chalk.gray(" Not in default repos — adding deadsnakes PPA...")),await $(),e("sudo apt-get install -y software-properties-common && sudo add-apt-repository -y ppa:deadsnakes/ppa && sudo apt-get update",{stdio:"inherit"}),await $(),e("sudo apt-get install -y python3.12 python3.12-venv python3.12-dev",{stdio:"inherit"}),o=!0}catch{}if(!o)throw new Error("python3.12 apt install failed");try{e("sudo python3.12 -m ensurepip --upgrade",{stdio:"inherit"})}catch{try{e("curl -sS https://bootstrap.pypa.io/get-pip.py | sudo python3.12",{stdio:"inherit"})}catch{}}resetPyBin(),console.log(chalk.green(" ✓ Python 3.12 installed (as python3.12; system python3 unchanged)")),console.log(chalk.gray(" Run Python challenges with `python3.12`, or use the sandbox where `python3` is 3.12."))}else{try{e("winget install Python.Python.3.12 --accept-package-agreements --accept-source-agreements",{stdio:"inherit"})}catch{e("choco install -y python312",{stdio:"inherit"})}console.log(chalk.green(" ✓ Python 3.12 installed"))}}catch{console.log(chalk.red(" ✗ Failed to install Python 3.12"));const e="darwin"===n?"brew install python@3.12":"linux"===n?"sudo apt install python3.12":"winget install Python.Python.3.12";console.log(chalk.gray(` Manual install: ${e}`))}console.log()}"win32"===n&&(console.log(chalk.yellow(" Windows: Most CTF tools require Linux. Recommended:")),console.log(chalk.white(" wsl --install")),console.log(chalk.gray(" Then run icoa inside WSL Ubuntu for full tool support.")),console.log());const d=[];for(const e of y)m(e.check)||("darwin"===n?e.brew:"linux"===n?e.apt:e.choco)&&d.push(e);if(d.length>0&&"win32"!==n){const o="darwin"===n?"brew":"apt";if(console.log(chalk.bold.white(` System Tools via ${o} (${d.length} missing)`)),console.log(chalk.gray(" ─────────────────────────────────────────────")),await $(),x("Installing system tools needs administrator access"),"linux"===n)try{e("sudo apt-get update",{stdio:["ignore","ignore","pipe"]})}catch{}for(const t of d){const r="darwin"===n?t.brew:"linux"===n?t.apt:t.choco;P(t.name);try{let o;o="darwin"===n?`brew install ${r}`:"linux"===n?`sudo apt-get install -y ${r}`:`choco install -y ${r}`,e(o,{stdio:["ignore","ignore","pipe"]}),C(),console.log(chalk.green(` ✓ ${t.name}`))}catch(e){C();const n=E(e);console.log(chalk.red(` ✗ ${t.name}`)+chalk.gray(` (${o} install ${r})`)+(n?chalk.gray(`\n ${n}`):""))}}console.log()}let u="pip3";if("darwin"===n){const o="/opt/homebrew/opt/python@3.12/bin/pip3.12";try{e(`${o} --version`,{stdio:"ignore"}),u=o,console.log(chalk.gray(` Using: ${o}`))}catch{try{e("pip3.12 --version",{stdio:"ignore"}),u="pip3.12"}catch{}}}else if("linux"===n)try{e("python3.12 -m pip --version",{stdio:"ignore"}),u="python3.12 -m pip"}catch{try{e("pip3.12 --version",{stdio:"ignore"}),u="pip3.12"}catch{}}else"win32"===n&&(u="pip");if("darwin"===n){console.log(chalk.gray(" Installing build dependencies..."));try{e("brew install gmp mpfr libmpc libmagic",{stdio:"ignore"}),console.log(chalk.green(" ✓ Build dependencies ready (gmp, mpfr, libmpc, libmagic)"))}catch{}}else if("linux"===n){console.log(chalk.gray(" Installing build dependencies..."));try{await $(),x("Build dependencies need administrator access"),e("sudo apt-get install -y libgmp-dev libmpfr-dev libmpc-dev libmagic1",{stdio:["ignore","ignore","pipe"]}),console.log(chalk.green(" ✓ Build dependencies ready (libgmp, libmpfr, libmpc, libmagic)"))}catch(e){const o=E(e);console.log(chalk.yellow(" ~ Build dependencies may be incomplete")+(o?chalk.gray(`: ${o}`):"")),console.log(chalk.gray(" gmpy2 needs: sudo apt-get install -y libgmp-dev libmpfr-dev libmpc-dev"))}}console.log();const w={...process.env};"darwin"===n&&(w.CFLAGS=`-I/opt/homebrew/include ${w.CFLAGS||""}`.trim(),w.LDFLAGS=`-L/opt/homebrew/lib ${w.LDFLAGS||""}`.trim(),w.C_INCLUDE_PATH=`/opt/homebrew/include:${w.C_INCLUDE_PATH||""}`,w.LIBRARY_PATH=`/opt/homebrew/lib:${w.LIBRARY_PATH||""}`);const f=c(r(a(import.meta.url)),"..","..","docker","constraints.txt"),v=o(f)?`-c '${f}'`:"";let T=0,S=0;console.log(chalk.bold.white(` Python Libraries (${l.length} packages)`)),console.log(chalk.gray(" ─────────────────────────────────────────────"));for(const o of l)if(o.install)if(m(o.check))console.log(chalk.green(` ✓ ${o.name}`)+chalk.gray(" (installed)")),T++;else{P(o.name);try{e(`${u} install ${s} ${v} '${o.install}'`,{stdio:["ignore","ignore","pipe"],env:w}),C(),console.log(chalk.green(` ✓ ${o.name}`)+chalk.gray(` (${o.install})`)),T++}catch(e){C();const n=E(e);console.log(chalk.red(` ✗ ${o.name}`)+chalk.gray(" (failed)")+(n?chalk.gray(`\n ${n}`):"")),S++}}if(console.log(),console.log(chalk.gray(" ─────────────────────────────────────────────")),console.log(` ${chalk.green(`✓ ${T} installed`)} ${S>0?chalk.red(`✗ ${S} failed`):chalk.green("All ready!")}`),console.log(),"win32"!==n){console.log(chalk.bold.white(" GDB Extension (bata24/gef default · pwndbg optional)")),console.log(chalk.gray(" ─────────────────────────────────────────────")),P("bata24/gef");try{e('wget -qO "$HOME/.gef-bata24.py" https://raw.githubusercontent.com/bata24/gef/master/gef.py && touch "$HOME/.gdbinit" && (grep -q gef-bata24 "$HOME/.gdbinit" || printf \'\\nsource %s/.gef-bata24.py\\n\' "$HOME" >> "$HOME/.gdbinit")',{stdio:["ignore","ignore","pipe"]}),C(),console.log(chalk.green(" ✓ bata24/gef")+chalk.gray(" (default gdb)"))}catch(e){C();const o=E(e);console.log(chalk.red(" ✗ bata24/gef")+(o?chalk.gray(`\n ${o}`):""))}if(m('test -d "$HOME/pwndbg"'))console.log(chalk.green(" ✓ pwndbg")+chalk.gray(" (run: gdb-pwndbg)"));else{const o="darwin"===n?"command -v uv >/dev/null 2>&1 || brew install uv":"command -v uv >/dev/null 2>&1 || pip3 install --user uv";P("pwndbg (optional)");try{e(`export PATH="$HOME/.local/bin:$PATH" && ${o} && rm -rf "$HOME/pwndbg" && git clone --depth 1 https://github.com/pwndbg/pwndbg "$HOME/pwndbg" && cd "$HOME/pwndbg" && ./setup.sh && mkdir -p "$HOME/.local/bin" && printf '#!/bin/sh\\nexec gdb -q -nx -ex "source $HOME/pwndbg/gdbinit.py" "$@"\\n' > "$HOME/.local/bin/gdb-pwndbg" && chmod +x "$HOME/.local/bin/gdb-pwndbg" && sed -i.bak '/pwndbg/d' "$HOME/.gdbinit" 2>/dev/null || true`,{stdio:["ignore","ignore","pipe"],env:w}),C(),console.log(chalk.green(" ✓ pwndbg")+chalk.gray(" (run: gdb-pwndbg)"))}catch{C(),console.log(chalk.yellow(" ~ pwndbg skipped")+chalk.gray(" (optional — bata24/gef is your default debugger)"))}}console.log(chalk.gray(" Default `gdb` loads bata24/gef; where installed, `gdb-pwndbg` loads pwndbg.")),console.log(chalk.gray(" (ensure ~/.local/bin is on PATH for gdb-pwndbg)")),console.log()}}()}),s.command("python").description("Show Python 3.12 install guide for your platform").action(()=>function(){const o=t();console.log(),console.log(chalk.bold.white(" Python 3.12 — Installation Guide")),console.log(chalk.gray(" ─────────────────────────────────────────────")),console.log();let n="",r="missing";const c=["python3.12 --version","/opt/homebrew/opt/python@3.12/bin/python3.12 --version","/usr/local/opt/python@3.12/bin/python3.12 --version","python3 --version"];for(const o of c)try{const t=e(o,{encoding:"utf-8",timeout:3e3}).trim().replace("Python ",""),c=t.split(".").map(Number);if(3===c[0]&&12===c[1]){n=t,r="ok";break}n=t,r=3===c[0]&&c[1]>=10&&c[1]<12?"old":3===c[0]&&c[1]>12?"new":"missing"}catch{}if("ok"===r)return console.log(chalk.green(` ✓ Python ${n} — you're good!`)),console.log(chalk.gray(" Exam toolkit ready. Next: ")+chalk.bold.cyan("exam setup")),void console.log();if("old"===r?console.log(chalk.yellow(` ⚠ Python ${n} — works, but 3.12 recommended`)):"new"===r?(console.log(chalk.yellow(` ⚠ Python ${n} — some packages (pwntools, scapy) lack wheels`)),console.log(chalk.gray(" Downgrading to 3.12 is strongly recommended"))):console.log(chalk.red(" ✗ Python 3 not found")),console.log(),"darwin"===o)console.log(chalk.bold.white(" macOS (Homebrew)")),console.log(),console.log(chalk.green(" brew install python@3.12"));else if("linux"===o){let o="ubuntu";try{const n=e("cat /etc/os-release 2>/dev/null",{encoding:"utf-8",timeout:2e3});o=/fedora|rhel|centos/i.test(n)?"fedora":/arch|manjaro/i.test(n)?"arch":"ubuntu"}catch{}"ubuntu"===o?(console.log(chalk.bold.white(" Ubuntu / Debian / Kali (deadsnakes PPA)")),console.log(),console.log(chalk.gray(" Copy-paste this one-liner:")),console.log(),console.log(chalk.green(" sudo add-apt-repository ppa:deadsnakes/ppa -y && \\")),console.log(chalk.green(" sudo apt update && \\")),console.log(chalk.green(" sudo apt install -y python3.12 python3.12-venv python3.12-dev")),console.log(),console.log(chalk.gray(" This installs ")+chalk.cyan("python3.12")+chalk.gray(" alongside your system python3 — run it as ")+chalk.cyan("python3.12")),console.log(chalk.gray(" (don’t repoint /usr/bin/python3 — it breaks apt & command-not-found on Ubuntu)."))):"fedora"===o?(console.log(chalk.bold.white(" Fedora / RHEL / CentOS")),console.log(),console.log(chalk.green(" sudo dnf install -y python3.12 python3.12-pip"))):"arch"===o&&(console.log(chalk.bold.white(" Arch / Manjaro (via pyenv)")),console.log(),console.log(chalk.green(" sudo pacman -S pyenv && pyenv install 3.12 && pyenv global 3.12")))}else"win32"===o?(console.log(chalk.bold.white(" Windows (WSL recommended)")),console.log(),console.log(chalk.gray(" WSL + Ubuntu (best):")),console.log(chalk.green(" wsl --install")),console.log(chalk.gray(" Then inside Ubuntu, run the Ubuntu commands.")),console.log(),console.log(chalk.gray(" Or native:")),console.log(chalk.green(" winget install Python.Python.3.12"))):console.log(chalk.gray(" https://www.python.org/downloads/"));console.log(),console.log(chalk.white(" After installing, verify:")),console.log(chalk.bold.cyan(" env python")+chalk.gray(" # re-check Python")),console.log(chalk.bold.cyan(" exam setup")+chalk.gray(" # install the 13 exam packages")),console.log()}()),s.action(()=>f())}function f(){console.log();const r=t(),c="darwin"===r?"brew":"linux"===r?"apt":"winget";console.log(chalk.bold.white(" ICOA Competition Environment")),console.log(chalk.gray(" ─────────────────────────────────────────────")),console.log(),console.log(chalk.gray(" These tools power your CTF competition environment.")),console.log(chalk.gray(" Not all are required — here's what matters:")),console.log(),console.log(chalk.green(" Essential")+chalk.gray(" pwntools, z3, requests, numpy")),console.log(chalk.gray(" You need these for most challenges")),console.log(chalk.yellow(" Recommended")+chalk.gray(" pycryptodome, beautifulsoup4, scapy, sympy")),console.log(chalk.gray(" Covers Web, Crypto, and Forensics")),console.log(chalk.gray(` Full (${h}) All tools for every category`)),console.log(),console.log(chalk.gray(" Missing tools? Run ")+chalk.bold.cyan("env setup")+chalk.gray(" to install everything.")),console.log(chalk.gray(" ─────────────────────────────────────────────")),console.log(),console.log(chalk.gray(" OS: ")+chalk.white(function(){const r=t();try{if("darwin"===r)return`macOS ${e("sw_vers -productVersion",{encoding:"utf-8"}).trim()} (${e("uname -m",{encoding:"utf-8"}).trim()})`;if("linux"===r)try{let t="Linux";try{const o=e("cat /etc/os-release | grep PRETTY_NAME",{encoding:"utf-8"}).match(/PRETTY_NAME="(.+)"/);o&&(t=o[1])}catch{}const r=e("uname -m",{encoding:"utf-8"}).trim(),c=function(){try{if(process.env.WSL_DISTRO_NAME)return"WSL";if(n("/proc/version","utf-8").toLowerCase().includes("microsoft"))return"WSL"}catch{}try{if(o("/opt/google/cros-containers"))return"Crostini"}catch{}return""}();return c?`${t} (${r}, ${c})`:`${t} (${r})`}catch{return"Linux"}else if("win32"===r)return e("ver",{encoding:"utf-8"}).trim()||"Windows"}catch{}return r}())),console.log(chalk.gray(" Node: ")+chalk.white(`Node.js ${process.version}`)),console.log(chalk.gray(" Package: ")+chalk.white(c)),console.log(chalk.gray(" Target: ")+chalk.white(`Node ${i} | Python ${s}`)),"win32"===r&&(console.log(),console.log(chalk.yellow(" Windows: recommend WSL (Ubuntu) for full CTF tool support")),console.log(chalk.gray(" Install WSL: ")+chalk.white("wsl --install")),console.log(chalk.gray(" Then run icoa inside WSL for 100% tool compatibility"))),console.log(chalk.gray(" ─────────────────────────────────────────────"));const a=process.versions.node,g=a.split(".").map(Number);g[0]>22||22===g[0]&&g[1]>22||22===g[0]&&22===g[1]&&g[2]>=2?console.log(chalk.green(` ✓ Node.js ${a}`)+chalk.gray(` (>= ${i})`)):(console.log(chalk.red(` ✗ Node.js ${a}`)+chalk.gray(` (>= ${i} required)`)),console.log(chalk.gray(" Install: nvm install 22 or visit https://nodejs.org/")));const p=b(),u=k();"3.12"===p?console.log(chalk.green(` ✓ Python ${u}`)+chalk.gray(u===s?" (official)":"")):p?console.log(chalk.yellow(` ~ Python ${u}`)+chalk.gray(" (3.12 required, run env setup)")):console.log(chalk.red(" ✗ Python 3 not found")),console.log();let w=0,f=0,v="";for(const e of y){e.category!==v&&(v=e.category,console.log(chalk.bold.gray(` ${v}`)));const o=m(e.check),n=o?d(e.name):"",t=n?chalk.gray(` (${n})`):"";o?(console.log(chalk.green(` ✓ ${e.name}`)+t),w++):(console.log(chalk.red(` ✗ ${e.name}`)),f++)}"win32"!==r&&(console.log(chalk.bold.gray(" GDB Extension")),m('grep -qi pwndbg "$HOME/.gdbinit" 2>/dev/null || test -f "$HOME/.gef-bata24.py"')?(console.log(chalk.green(" ✓ bata24-gef (+pwndbg)")),w++):(console.log(chalk.red(" ✗ bata24-gef (+pwndbg)")+chalk.gray(" (run env setup)")),f++)),v="";const $="darwin"===r?"/opt/homebrew/opt/python@3.12/bin/pip3.12":"win32"===r?"pip":"pip3";for(const o of l)if(o.category!==v&&(v=o.category,console.log(chalk.bold.gray(` ${v}`))),m(o.check)){let n="";for(const t of[$,"pip3","pip"])try{const r=o.name.replace("python-magic","python_magic"),c=e(`${t} show ${r}`,{encoding:"utf-8",timeout:3e3,stdio:["pipe","pipe","ignore"]}).match(/Version:\s*(\S+)/);if(c){n=c[1];break}}catch{}console.log(chalk.green(` ✓ ${o.name}`)+chalk.gray(n?` (${n})`:"")),w++}else console.log(chalk.red(` ✗ ${o.name}`)+chalk.gray(` → ${o.install||"latest"}`)),f++;const x=w+f;console.log(),console.log(chalk.gray(" ─────────────────────────────────────────────")),console.log(` ${chalk.green(`✓ ${w}/${x}`)} ${f>0?chalk.red(`✗ ${f} missing`):chalk.green(`All ${x} ready!`)}`),f>0&&console.log(chalk.gray(" Install everything: ")+chalk.white("env setup")+chalk.gray(" (~5 min, one-time)")),console.log(chalk.gray(" You are back at the ")+chalk.cyan("icoa>")+chalk.gray(" prompt. ")+chalk.cyan("help")+chalk.gray(" for all commands.")),console.log()}function v(){for(const o of["/var/lib/dpkg/lock-frontend","/var/lib/dpkg/lock","/var/lib/apt/lists/lock"])try{return e(`sudo fuser ${o} 2>/dev/null`,{stdio:"ignore",timeout:5e3}),!0}catch{}return!1}async function $(e=3e5){if("linux"!==t())return;if(!v())return;console.log(chalk.yellow(" ⏳ System package manager is busy")+chalk.gray(" (ChromeOS may be updating in the background).")),console.log(chalk.gray(` Waiting up to ${Math.round(e/6e4)} min for it to finish… `)+chalk.gray("(Ctrl+C to cancel, or re-run ")+chalk.cyan("env setup")+chalk.gray(" later)")),process.stdout.write(chalk.gray(" "));const o=Date.now();let n=0;for(;v();){if(Date.now()-o>e)return console.log(),console.log(chalk.yellow(" ~ Still busy after waiting. Skipping the wait.")),void console.log(chalk.gray(" If installs fail, re-run ")+chalk.cyan("env setup")+chalk.gray(" in a few minutes."));process.stdout.write(chalk.gray(".")),++n%50==0&&process.stdout.write(chalk.gray("\n ")),await new Promise(e=>setTimeout(e,3e3))}console.log(),console.log(chalk.green(" ✓ Package manager free — continuing."))}function x(o){if("linux"===t()){try{return void e("sudo -n true",{stdio:"ignore"})}catch{}console.log(chalk.yellow(` 🔑 ${o}`)+chalk.gray(" — enter your password if prompted:"));try{e("sudo -v",{stdio:"inherit"})}catch{console.log(chalk.gray(" (sudo unavailable — some installs may fail)"))}}}function P(e){process.stdout.isTTY&&process.stdout.write(chalk.gray(` ⏳ ${e}...`))}function C(){process.stdout.isTTY&&process.stdout.write("\r[2K")}function E(e){const o=e,n=(o?.stderr?o.stderr.toString():"").split("\n").map(e=>e.trim()).filter(Boolean);return n.length?n[n.length-1].slice(0,100):""}
|