Repository navigation
Expand file tree
/
Copy pathsetup.sh
More file actions
executable file
·169 lines (161 loc) · 8.59 KB
/
Copy pathsetup.sh
File metadata and controls
executable file
·169 lines (161 loc) · 8.59 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
#!/usr/bin/env bash
# setup.sh — Configura el entorno de nutcracker
set -euo pipefail
echo "==> Creando entorno virtual..."
python3 -m venv .venv
source .venv/bin/activate
echo "==> Instalando dependencias Python..."
pip install --upgrade pip --quiet
pip install -r requirements.txt --quiet
echo ""
echo "==> Verificando apkeep (necesario para descargar desde Google Play)..."
if command -v apkeep &>/dev/null; then
echo " apkeep ya está instalado: $(apkeep --version 2>&1 | head -1)"
else
echo " apkeep NO encontrado. Instalando..."
if [[ "$(uname)" == "Darwin" ]]; then
if command -v brew &>/dev/null; then
brew install apkeep
else
echo " Homebrew no encontrado. Descarga apkeep manualmente desde:"
echo " https://github.com/EFForg/apkeep/releases"
fi
else
# Resuelto en vivo, no fijo a mano -- una versión pineada rompió sola
# cuando apkeep cortó un major (0.10.0 -> 1.0.0) y borró el asset
# viejo del release (404). Fallback a un tag conocido si la API de
# GitHub no responde (rate limit, sin red).
#
# OJO: curl se captura primero en una variable (command substitution
# lee hasta EOF) y RECIÉN DESPUÉS se le hace grep -m1 -- si el pipe
# fuera directo (curl | grep -m1 | sed), grep corta la lectura apenas
# encuentra el primer match y cierra su extremo del pipe, y curl
# termina en SIGPIPE a mitad de escritura -- imprime un
# "curl: (23) Failure writing output to destination" que parece un
# error real (confundió a un usuario en vivo) pero es cosmético: el
# valor ya estaba capturado igual. Evitado de raíz, no silenciado.
APKEEP_RELEASE_JSON="$(curl -fsSL https://api.github.com/repos/EFForg/apkeep/releases/latest)"
APKEEP_VERSION="$(echo "$APKEEP_RELEASE_JSON" | grep -m1 '"tag_name"' | sed -E 's/.*"tag_name": *"([^"]+)".*/\1/')"
if [[ -z "$APKEEP_VERSION" ]]; then
APKEEP_VERSION="1.0.0"
echo " (no se pudo resolver la última versión vía GitHub API, usando ${APKEEP_VERSION} fijo)"
fi
APKEEP_URL="https://github.com/EFForg/apkeep/releases/download/${APKEEP_VERSION}/apkeep-x86_64-unknown-linux-gnu"
echo " Descargando apkeep ${APKEEP_VERSION}..."
# /usr/local/bin normalmente requiere root -- setup.sh corre como el
# usuario normal (a propósito, ver deploy/README.md: el dashboard no
# debe correr como root). Si /usr/local/bin es escribible (root, o un
# setup con permisos relajados) se usa igual; si no, cae a
# ~/.local/bin (estándar XDG, normalmente ya en el PATH de Ubuntu).
if [[ -w /usr/local/bin ]]; then
APKEEP_DEST="/usr/local/bin/apkeep"
else
mkdir -p "$HOME/.local/bin"
APKEEP_DEST="$HOME/.local/bin/apkeep"
fi
if curl -fsSL "$APKEEP_URL" -o "$APKEEP_DEST"; then
chmod +x "$APKEEP_DEST"
echo " apkeep instalado en $APKEEP_DEST"
if [[ "$APKEEP_DEST" == "$HOME/.local/bin/apkeep" ]] && [[ ":$PATH:" != *":$HOME/.local/bin:"* ]]; then
echo " AVISO: ~/.local/bin no está en tu PATH todavía. Agregá a tu ~/.bashrc:"
echo " export PATH=\"\$HOME/.local/bin:\$PATH\""
echo " y abrí una terminal nueva (o corré ese export ahora mismo)."
fi
else
echo " AVISO: no se pudo descargar apkeep ${APKEEP_VERSION} (¿cambió el nombre del"
echo " asset de nuevo?). Instalalo a mano desde:"
echo " https://github.com/EFForg/apkeep/releases"
fi
fi
fi
echo ""
echo ""
echo "==> Verificando desensamblador para libs nativas (.so ARM64)..."
if command -v objdump &>/dev/null || command -v aarch64-linux-gnu-objdump &>/dev/null || command -v r2 &>/dev/null; then
echo " OK: desensamblador disponible"
else
if [[ "$(uname)" == "Linux" ]]; then
echo " AVISO: no se encontró objdump ARM64. Instalando binutils-aarch64-linux-gnu..."
sudo apt-get install -y binutils-aarch64-linux-gnu 2>/dev/null || \
echo " No se pudo instalar automáticamente. Ejecuta: sudo apt install binutils-aarch64-linux-gnu"
else
echo " INFO (macOS): objdump del sistema soporta ELF ARM64. OK"
fi
fi
DASHBOARD_DIR="nutcracker_core/plugins/dashboard"
WEBUSB_DIR="$DASHBOARD_DIR/webusb"
# El plugin dashboard (y aipwn) vive bajo nutcracker_core/plugins/, que el
# .gitignore raíz excluye por completo (regla "plugins/") -- en un checkout
# fresco del repo puede simplemente no estar presente. Todo lo de abajo es
# opcional y se salta en silencio si la carpeta no existe.
if [[ -d "$DASHBOARD_DIR" ]]; then
echo ""
echo ""
echo "==> Instalando dependencias del dashboard web (fastapi/uvicorn)..."
if [[ -f "$DASHBOARD_DIR/requirements.txt" ]]; then
if pip install -r "$DASHBOARD_DIR/requirements.txt" --quiet; then
echo " OK: 'nutcracker dashboard' listo para usar."
else
echo " AVISO: no se pudieron instalar automáticamente. Se reintenta solo (lazy-install)"
echo " la primera vez que corras 'nutcracker dashboard' -- ver plugins/__init__.py."
fi
fi
echo ""
echo "==> Video USB fluido del dashboard (WebUSB + WebCodecs, único modo -- sin fallback)..."
# pnpm (no npm): bloquea por defecto los scripts postinstall de las
# dependencias -- justo el vector de varios ataques de supply-chain
# recientes en el ecosistema npm. Este proyecto solo aprueba el de
# esbuild (necesario, baja el binario nativo de la plataforma -- ver
# webusb/pnpm-workspace.yaml). Se activa vía corepack (viene con Node
# 16.9+), que además fija la versión exacta via el campo
# "packageManager" de package.json -- instalación reproducible sin
# depender de qué pnpm tengas instalado global.
if [[ ! -d "$WEBUSB_DIR" ]]; then
echo " Subproyecto webusb/ no presente en este checkout -- omitiendo (opcional)."
elif ! command -v node &>/dev/null; then
echo " Node.js NO encontrado -- opcional, solo habilita el video en vivo de la pestaña"
echo " 'Dispositivo' (requiere Chrome/Edge + USB directo). Instala Node.js 20+ (trae"
echo " corepack) y corre:"
echo " cd $WEBUSB_DIR && corepack enable && pnpm install && pnpm run build"
echo " Detalles/troubleshooting (incluye un problema conocido en WSL): $WEBUSB_DIR/README.md"
elif [[ "$(command -v node)" == /mnt/c/* ]]; then
echo " AVISO: 'node' resuelve al Node de Windows (interop de WSL) -- el build falla"
echo " con errores de rutas UNC. Instala Node nativo de Linux (nvm) y reintenta a mano:"
echo " curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.6/install.sh | bash"
echo " nvm install --lts # y volvé a correr:"
echo " cd $WEBUSB_DIR && corepack enable && pnpm install && pnpm run build"
echo " Detalles: $WEBUSB_DIR/README.md"
elif ! command -v corepack &>/dev/null; then
echo " corepack NO encontrado (viene con Node 16.9+, pero algunos paquetes de distro lo"
echo " separan) -- instalalo y reintentá a mano:"
echo " npm install -g corepack # o el paquete 'corepack' de tu distro"
echo " cd $WEBUSB_DIR && corepack enable && pnpm install && pnpm run build"
else
echo " Node + corepack detectados, compilando el bundle (puede tardar un minuto)..."
corepack enable &>/dev/null || true
if (cd "$WEBUSB_DIR" && pnpm install --silent && pnpm run build); then
echo " OK: bundle generado -- el botón '🔌 USB directo (fluido)' aparecerá en el dashboard."
else
echo " AVISO: el build falló -- opcional, el resto del dashboard sigue funcionando sin"
echo " el video en vivo. Detalles: $WEBUSB_DIR/README.md"
fi
fi
fi
echo ""
echo "==> ¡Configuración completada!"
echo ""
echo "Activa el entorno virtual con:"
echo " source .venv/bin/activate"
echo ""
echo "Uso:"
echo " # Descargar y analizar desde Google Play:"
echo " python nutcracker.py scan 'https://play.google.com/store/apps/details?id=com.example.app'"
echo ""
echo " # Analizar una APK local:"
echo " python nutcracker.py analyze ruta/al/archivo.apk"
echo ""
echo " # Guardar informe JSON:"
echo " python nutcracker.py analyze app.apk --report informe.json"
echo ""
echo " # Levantar el dashboard web (cola + apps + video del dispositivo):"
echo " python nutcracker.py dashboard"