rtexit-method 0.1.13 → 0.1.15

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.
@@ -0,0 +1,262 @@
1
+ ---
2
+ name: rt-mobile-static-deep
3
+ description: "Deep static analysis of mobile apps — MobSF automated scanning, manual jadx source review, secret scanning (API keys, tokens, hardcoded creds), native library analysis (.so files with Ghidra/radare2), third-party SDK vulnerability hunting, obfuscation bypass, APK/IPA binary analysis. Foundation of every mobile pentest before dynamic testing."
4
+ ---
5
+
6
+ > 🐳 **Docker Environment (Recommended):** `docker exec -it rtexit-kali bash`
7
+
8
+ # rt-mobile-static-deep — Mobile App Static Analysis
9
+
10
+ ## Overview
11
+
12
+ Static analysis reveals hardcoded secrets, insecure code patterns, weak cryptography, and attack surfaces before running a single line of code. Should be the FIRST step in any mobile pentest.
13
+
14
+ **What you find:**
15
+ - Hardcoded API keys, tokens, passwords
16
+ - Backend endpoints and internal hostnames
17
+ - Cryptographic weaknesses
18
+ - Exported components and deep links
19
+ - Third-party SDK vulnerabilities
20
+ - Native library vulnerabilities
21
+
22
+ ---
23
+
24
+ ## Phase 1: MobSF — Automated Full Scan
25
+
26
+ ```bash
27
+ docker exec rtexit-kali bash -c "
28
+ # Run MobSF Docker (fastest setup)
29
+ docker run -it --rm -p 8000:8000 opensecurity/mobile-security-framework-mobsf:latest
30
+
31
+ # Upload APK/IPA via browser: http://localhost:8000
32
+ # Or via API:
33
+ curl -s 'http://localhost:8000/api/v1/upload' \
34
+ -H 'Authorization: YOUR_API_KEY' \
35
+ -F 'file=@target.apk' > /tmp/upload.json
36
+
37
+ SCAN_HASH=\$(cat /tmp/upload.json | python3 -c \"import json,sys; print(json.load(sys.stdin)['hash'])\")
38
+
39
+ # Run scan
40
+ curl -s 'http://localhost:8000/api/v1/scan' \
41
+ -H 'Authorization: YOUR_API_KEY' \
42
+ -d \"scan_type=apk&file_name=target.apk&hash=\${SCAN_HASH}\"
43
+
44
+ # Get JSON report
45
+ curl -s \"http://localhost:8000/api/v1/report_json\" \
46
+ -H 'Authorization: YOUR_API_KEY' \
47
+ -d \"hash=\${SCAN_HASH}\" > /tmp/mobsf_report.json
48
+
49
+ # Extract key findings
50
+ python3 -c \"
51
+ import json
52
+ r = json.load(open('/tmp/mobsf_report.json'))
53
+ print('=== Hardcoded Secrets ===')
54
+ for s in r.get('secrets', []): print(' -', s)
55
+ print('=== URLs ===')
56
+ for u in r.get('urls', []): print(' -', u['url'])
57
+ print('=== HIGH findings ===')
58
+ for k, v in r.get('code_analysis', {}).get('findings', {}).items():
59
+ if v.get('level') == 'high': print(' -', k, ':', v.get('cvss'))
60
+ \"
61
+ "
62
+ ```
63
+
64
+ ---
65
+
66
+ ## Phase 2: Secret Scanning
67
+
68
+ ```bash
69
+ docker exec rtexit-kali bash -c "
70
+ # Decompile APK
71
+ apktool d target.apk -o /tmp/target_dc
72
+ jadx -d /tmp/target_java target.apk 2>/dev/null
73
+
74
+ # Comprehensive secret scan
75
+ # Tool: trufflehog
76
+ pip3 install trufflehog3 2>/dev/null
77
+ trufflehog filesystem /tmp/target_java/ --json > /tmp/secrets.json
78
+ cat /tmp/secrets.json | python3 -m json.tool | grep -A3 'reason\|stringsFound'
79
+
80
+ # Manual grep patterns
81
+ echo '=== API Keys ==='
82
+ grep -rE '(api[_-]?key|apikey)\s*[=:]\s*[\"'\'']\w{20,}' /tmp/target_java/ -i
83
+ echo '=== AWS Keys ==='
84
+ grep -rE 'AKIA[0-9A-Z]{16}' /tmp/target_java/
85
+ echo '=== JWT Tokens ==='
86
+ grep -rE 'eyJ[A-Za-z0-9+/=]{10,}\.[A-Za-z0-9+/=]{10,}' /tmp/target_java/
87
+ echo '=== Hardcoded passwords ==='
88
+ grep -rE '(password|passwd|pwd)\s*[=:]\s*[\"'\'']\w{4,}' /tmp/target_java/ -i
89
+ echo '=== Private keys ==='
90
+ grep -r 'BEGIN.*PRIVATE KEY\|BEGIN RSA\|BEGIN EC' /tmp/target_java/ -l
91
+ echo '=== Firebase URLs ==='
92
+ grep -rE 'firebaseio\.com|firebase\.google\.com' /tmp/target_java/
93
+ echo '=== Google Maps API Key ==='
94
+ grep -rE 'AIza[0-9A-Za-z-_]{35}' /tmp/target_java/
95
+ "
96
+ ```
97
+
98
+ ---
99
+
100
+ ## Phase 3: Endpoint Discovery
101
+
102
+ ```bash
103
+ docker exec rtexit-kali bash -c "
104
+ # Extract all URLs and endpoints from source
105
+ echo '=== HTTPS Endpoints ==='
106
+ grep -rEoh 'https?://[^\"'\'')\s]{10,}' /tmp/target_java/ | sort -u | grep -v 'schema\|xmlns\|android\|google.com/design'
107
+
108
+ echo '=== API Base URLs ==='
109
+ grep -rEi 'base_?url|api_?url|endpoint|host_?url' /tmp/target_java/ | grep -oE '\"[^\"]*\"' | sort -u
110
+
111
+ echo '=== IP Addresses ==='
112
+ grep -rEoh '\b([0-9]{1,3}\.){3}[0-9]{1,3}(:[0-9]+)?\b' /tmp/target_java/ | grep -v '0\.0\.0\|127\.0\.0\|255\.255' | sort -u
113
+
114
+ echo '=== WebSocket URLs ==='
115
+ grep -rEoh 'wss?://[^\"'\'')\s]+' /tmp/target_java/ | sort -u
116
+ "
117
+ ```
118
+
119
+ ---
120
+
121
+ ## Phase 4: AndroidManifest Deep Analysis
122
+
123
+ ```bash
124
+ docker exec rtexit-kali bash -c "
125
+ MANIFEST=/tmp/target_dc/AndroidManifest.xml
126
+
127
+ echo '=== Package + Permissions ==='
128
+ grep 'package\|uses-permission' \$MANIFEST | sort
129
+
130
+ echo '=== DANGEROUS permissions ==='
131
+ grep 'uses-permission' \$MANIFEST | grep -iE 'READ_SMS|READ_CONTACTS|READ_CALL_LOG|CAMERA|RECORD_AUDIO|ACCESS_FINE_LOCATION|PROCESS_OUTGOING_CALLS|BIND_ACCESSIBILITY'
132
+
133
+ echo '=== Exported components (attack surface) ==='
134
+ grep -E 'activity|service|receiver|provider' \$MANIFEST | grep 'exported=\"true\"'
135
+
136
+ echo '=== Deep links / intent filters ==='
137
+ grep -A5 'intent-filter' \$MANIFEST | grep -E 'scheme|host|path'
138
+
139
+ echo '=== Debuggable flag ==='
140
+ grep 'debuggable' \$MANIFEST
141
+
142
+ echo '=== Backup flag ==='
143
+ grep 'allowBackup' \$MANIFEST
144
+
145
+ echo '=== Network security config ==='
146
+ grep 'networkSecurityConfig' \$MANIFEST
147
+ "
148
+ ```
149
+
150
+ ---
151
+
152
+ ## Phase 5: Native Library Analysis
153
+
154
+ ```bash
155
+ docker exec rtexit-kali bash -c "
156
+ # Extract and analyze .so files
157
+ unzip target.apk 'lib/arm64-v8a/*.so' -d /tmp/libs/
158
+ ls /tmp/libs/lib/arm64-v8a/
159
+
160
+ # Quick strings analysis on each .so
161
+ for lib in /tmp/libs/lib/arm64-v8a/*.so; do
162
+ echo \"=== \$lib ===\"
163
+ strings \"\$lib\" | grep -iE 'password|secret|api[_-]?key|token|http|base64|des|aes|rsa' | head -20
164
+ done
165
+
166
+ # Check for known vulnerable native libraries
167
+ strings /tmp/libs/lib/arm64-v8a/*.so | grep -E 'OpenSSL|libcurl' | head -5
168
+ # Look up CVEs for the versions found
169
+
170
+ # Deeper analysis with radare2
171
+ r2 /tmp/libs/lib/arm64-v8a/libapp.so
172
+ # In r2:
173
+ # aaa → analyze all
174
+ # afl → list all functions
175
+ # pdf @sym.verify_pin → disassemble specific function
176
+ "
177
+ ```
178
+
179
+ ---
180
+
181
+ ## Phase 6: Cryptographic Analysis
182
+
183
+ ```bash
184
+ docker exec rtexit-kali bash -c "
185
+ # Find cryptographic usage patterns in source
186
+ echo '=== Weak algorithms ==='
187
+ grep -rE 'DES[^3]|MD5|SHA1[^_]|RC4|ECB' /tmp/target_java/ -i | grep -v '//\|test\|Test'
188
+
189
+ echo '=== Hardcoded IV / Keys ==='
190
+ grep -rE 'IvParameterSpec|SecretKeySpec' /tmp/target_java/ -A2 | grep -E 'new byte\[\]|getBytes'
191
+
192
+ echo '=== Insecure random ==='
193
+ grep -rE 'new Random\(\)|Math\.random' /tmp/target_java/ | grep -v 'SecureRandom'
194
+
195
+ echo '=== Keystore usage (secure vs insecure) ==='
196
+ grep -rE 'KeyStore|AndroidKeyStore|KeyGenerator' /tmp/target_java/ -l
197
+ # If NOT using AndroidKeyStore → keys stored insecurely
198
+ "
199
+ ```
200
+
201
+ ---
202
+
203
+ ## Phase 7: Third-Party SDK Vulnerability Check
204
+
205
+ ```bash
206
+ docker exec rtexit-kali bash -c "
207
+ # Extract all third-party SDKs/libraries
208
+ grep -r 'implementation\|compile' /tmp/target_java/ 2>/dev/null | grep -oE \"'[^']+:[^']+:[^']+'\"|sort -u
209
+
210
+ # Check for known vulnerable SDKs from strings in APK
211
+ strings /tmp/target_apk/classes*.dex | grep -E 'com\.(facebook|google|firebase|amazonaws|stripe|braintree|okhttp|retrofit)' | sort -u | head -30
212
+
213
+ # Check OkHttp version (critical — many CVEs)
214
+ grep -r 'okhttp' /tmp/target_java/ | grep -oE 'okhttp:[0-9]+\.[0-9]+\.[0-9]+' | sort -u
215
+ "
216
+ ```
217
+
218
+ ---
219
+
220
+ ## iOS Static Analysis
221
+
222
+ ```bash
223
+ docker exec rtexit-kali bash -c "
224
+ # Extract IPA
225
+ unzip target.ipa -d /tmp/ipa_extracted/
226
+ APP_DIR=\$(find /tmp/ipa_extracted/Payload -name '*.app' -type d)
227
+
228
+ # Binary analysis
229
+ file \$APP_DIR/TargetApp
230
+ # Check: encryption, architecture
231
+
232
+ # Strings
233
+ strings \$APP_DIR/TargetApp | grep -iE 'api[_-]?key|secret|password|http|token' | head -50
234
+
235
+ # class-dump (get all Obj-C class declarations)
236
+ class-dump \$APP_DIR/TargetApp > /tmp/classes.h
237
+ grep -i 'password\|token\|pin\|secret\|auth' /tmp/classes.h | head -30
238
+
239
+ # Check Info.plist (often has API keys, URLs)
240
+ plutil -p \$APP_DIR/Info.plist 2>/dev/null || python3 -c \"
241
+ import plistlib
242
+ with open('\$APP_DIR/Info.plist', 'rb') as f:
243
+ plist = plistlib.load(f)
244
+ for k, v in plist.items():
245
+ if any(x in k.lower() for x in ['key', 'secret', 'token', 'url', 'api']):
246
+ print(k, '=', v)
247
+ \"
248
+ "
249
+ ```
250
+
251
+ ---
252
+
253
+ ## Related Skills
254
+ - `rt-exploit-android` — dynamic testing following static findings
255
+ - `rt-exploit-ios` — iOS dynamic testing
256
+ - `rt-frida-advanced` — confirm static findings at runtime
257
+ - `rt-android-intent-exploitation` — exploit exported components found in manifest
258
+
259
+ ## References
260
+ - https://github.com/MobSF/Mobile-Security-Framework-MobSF
261
+ - https://owasp.org/www-project-mobile-application-security-design-guide/
262
+ - https://attack.mitre.org/techniques/T1418/ — Software Discovery
@@ -3,6 +3,7 @@ const { resolveRepoRoot, resolveTargetRoot } = require('../lib/paths');
3
3
  const { copyPackagedAssets } = require('../lib/copy-assets');
4
4
  const { writeUserConfig } = require('../lib/write-config');
5
5
  const { askInstallQuestions } = require('../lib/prompts');
6
+ const { resolveSkillSet } = require('../lib/profiles');
6
7
 
7
8
  async function installCommand(options = {}) {
8
9
  const repoRoot = options.repoRoot || resolveRepoRoot();
@@ -21,7 +22,8 @@ async function installCommand(options = {}) {
21
22
  const targetRoot = resolveTargetRoot(answers.targetDirectory);
22
23
 
23
24
  const ides = answers.ides && answers.ides.length ? answers.ides : ['agents'];
24
- await copyPackagedAssets({ repoRoot, targetRoot, ides });
25
+ const allowedSkills = resolveSkillSet(answers.profiles || ['all']);
26
+ await copyPackagedAssets({ repoRoot, targetRoot, ides, allowedSkills });
25
27
  await writeUserConfig({
26
28
  targetRoot,
27
29
  answers: {
@@ -36,7 +38,7 @@ async function installCommand(options = {}) {
36
38
  });
37
39
 
38
40
  io.log('RTExit installed successfully.');
39
- io.log(`Skills installed into: ${ideFolders.join(', ')}`);
41
+ io.log(`Skills installed: ${allowedSkills.size} skills into ${ideFolders.join(', ')}`);
40
42
  io.log('Next steps:');
41
43
  io.log('1. Open _rtexit/config.user.toml and complete client/project details');
42
44
  io.log('2. Open your AI IDE in this project');
@@ -5,12 +5,17 @@ const IDE_SKILL_FOLDERS = {
5
5
  codex: '.codex/skills',
6
6
  };
7
7
 
8
- function getInstallEntries(ides = ['agents']) {
8
+ /**
9
+ * @param {string[]} ides
10
+ * @param {Set<string>|null} allowedSkills — if null, install everything
11
+ */
12
+ function getInstallEntries(ides = ['agents'], allowedSkills = null) {
9
13
  const skillEntries = ides.map((ide) => ({
10
14
  type: 'glob-dir-prefix',
11
15
  base: 'packaged-assets/.agents/skills',
12
16
  targetBase: IDE_SKILL_FOLDERS[ide] || `.${ide}/skills`,
13
17
  prefix: 'rt-',
18
+ allowedSkills,
14
19
  }));
15
20
 
16
21
  return [
@@ -17,8 +17,8 @@ function copyRecursive(source, target) {
17
17
  fs.copyFileSync(source, target);
18
18
  }
19
19
 
20
- async function copyPackagedAssets({ repoRoot, targetRoot, ides }) {
21
- for (const entry of getInstallEntries(ides)) {
20
+ async function copyPackagedAssets({ repoRoot, targetRoot, ides, allowedSkills = null }) {
21
+ for (const entry of getInstallEntries(ides, allowedSkills)) {
22
22
  if (entry.type === 'path') {
23
23
  const sourcePath = path.join(repoRoot, entry.value);
24
24
  const targetPath = path.join(targetRoot, entry.target || entry.value);
@@ -29,12 +29,12 @@ async function copyPackagedAssets({ repoRoot, targetRoot, ides }) {
29
29
  const skillsRoot = path.join(repoRoot, entry.base);
30
30
  const targetBase = entry.targetBase || entry.base;
31
31
  for (const name of fs.readdirSync(skillsRoot)) {
32
- if (name.startsWith(entry.prefix)) {
33
- copyRecursive(
34
- path.join(skillsRoot, name),
35
- path.join(targetRoot, targetBase, name)
36
- );
37
- }
32
+ if (!name.startsWith(entry.prefix)) continue;
33
+ if (entry.allowedSkills && !entry.allowedSkills.has(name)) continue;
34
+ copyRecursive(
35
+ path.join(skillsRoot, name),
36
+ path.join(targetRoot, targetBase, name)
37
+ );
38
38
  }
39
39
  }
40
40
  }
@@ -0,0 +1,250 @@
1
+ /**
2
+ * Install profiles — each profile maps to a set of skill folder names.
3
+ * Skills in CORE are always installed regardless of profile selection.
4
+ * Users pick one or more profiles; they get CORE + selected profiles.
5
+ */
6
+
7
+ const CORE = [
8
+ // Agents
9
+ 'rt-agent-breaker',
10
+ 'rt-agent-commander',
11
+ 'rt-agent-ghost',
12
+ 'rt-agent-navigator',
13
+ 'rt-agent-phantom',
14
+ 'rt-agent-scout',
15
+ 'rt-agent-scribe',
16
+ // Base methodology
17
+ 'rt-help',
18
+ 'rt-status',
19
+ 'rt-party-mode',
20
+ 'rt-scope-definition',
21
+ 'rt-rules-of-engagement',
22
+ 'rt-methodology-selector',
23
+ // Recon & mapping
24
+ 'rt-active-recon',
25
+ 'rt-osint',
26
+ 'rt-shodan-recon',
27
+ 'rt-attack-surface-map',
28
+ 'rt-subdomain-enum',
29
+ 'rt-subdomain-takeover',
30
+ 'rt-wordlist-generation',
31
+ 'rt-password-spray',
32
+ // Infrastructure
33
+ 'rt-c2-operations',
34
+ 'rt-redteam-infra',
35
+ // Core execution
36
+ 'rt-defense-evasion',
37
+ 'rt-lateral-movement',
38
+ 'rt-persistence',
39
+ 'rt-post-exploitation',
40
+ 'rt-privilege-escalation',
41
+ 'rt-credential-access',
42
+ 'rt-credential-hunt',
43
+ 'rt-lsass-dumping',
44
+ 'rt-data-exfiltration',
45
+ ];
46
+
47
+ const PROFILES = {
48
+ web: {
49
+ label: 'Web & API',
50
+ description: 'Web apps, APIs, injection, auth, OWASP Top 10',
51
+ skills: [
52
+ 'rt-exploit-web',
53
+ 'rt-exploit-injection',
54
+ 'rt-exploit-xss',
55
+ 'rt-exploit-ssrf',
56
+ 'rt-exploit-auth',
57
+ 'rt-exploit-idor',
58
+ 'rt-exploit-api',
59
+ 'rt-exploit-jwt',
60
+ 'rt-exploit-file-upload',
61
+ 'rt-cors-csrf',
62
+ 'rt-clickjacking',
63
+ 'rt-dom-attacks',
64
+ 'rt-cache-attacks',
65
+ 'rt-business-logic',
66
+ 'rt-race-conditions',
67
+ 'rt-request-smuggling',
68
+ 'rt-path-traversal',
69
+ 'rt-deserialization',
70
+ 'rt-prototype-pollution',
71
+ 'rt-http-parameter-pollution',
72
+ 'rt-ldap-xpath-injection',
73
+ 'rt-xxe',
74
+ 'rt-oauth-oidc',
75
+ 'rt-websockets-grpc',
76
+ 'rt-js-analysis',
77
+ 'rt-browser-exploitation',
78
+ 'rt-exploit-wordpress',
79
+ 'rt-exploit-nodejs',
80
+ 'rt-exploit-php',
81
+ 'rt-exploit-python',
82
+ 'rt-exploit-java',
83
+ 'rt-exploit-dotnet',
84
+ 'rt-exploit-ruby',
85
+ 'rt-exploit-frameworks',
86
+ 'rt-exploit-electron',
87
+ 'rt-exploit-firebase',
88
+ 'rt-supabase',
89
+ 'rt-exploit-osticket',
90
+ 'rt-exploit-bec',
91
+ 'rt-serverless',
92
+ 'rt-exploit-elasticsearch',
93
+ 'rt-exploit-databases',
94
+ 'rt-exploit-mongodb',
95
+ 'rt-exploit-mssql',
96
+ 'rt-exploit-mysql',
97
+ 'rt-exploit-postgresql',
98
+ 'rt-exploit-redis',
99
+ 'rt-ai-llm-security',
100
+ 'rt-crypto-attacks',
101
+ 'rt-exploit-fuzzing',
102
+ ],
103
+ },
104
+
105
+ mobile: {
106
+ label: 'Mobile',
107
+ description: 'Android, iOS, BLE, Frida, SSL bypass, cross-platform, C2',
108
+ skills: [
109
+ // Core mobile
110
+ 'rt-exploit-android',
111
+ 'rt-exploit-ios',
112
+ 'rt-bluetooth-ble',
113
+ // Advanced mobile (new)
114
+ 'rt-frida-advanced',
115
+ 'rt-mobile-ssl-pinning',
116
+ 'rt-apk-repackaging',
117
+ 'rt-android-intent-exploitation',
118
+ 'rt-cross-platform-mobile',
119
+ 'rt-mobile-malware-c2',
120
+ 'rt-mobile-static-deep',
121
+ ],
122
+ },
123
+
124
+ cloud: {
125
+ label: 'Cloud',
126
+ description: 'AWS, Azure, GCP, Kubernetes, containers',
127
+ skills: [
128
+ 'rt-exploit-cloud-aws',
129
+ 'rt-exploit-cloud-azure',
130
+ 'rt-exploit-cloud-gcp',
131
+ 'rt-kubernetes',
132
+ 'rt-exploit-containers',
133
+ 'rt-serverless',
134
+ 'rt-supply-chain',
135
+ 'rt-exploit-firebase',
136
+ 'rt-supabase',
137
+ 'rt-exploit-elasticsearch',
138
+ ],
139
+ },
140
+
141
+ ad: {
142
+ label: 'Active Directory & Windows',
143
+ description: 'AD, ADCS, Kerberos, lateral movement, EDR bypass, APT techniques',
144
+ skills: [
145
+ 'rt-exploit-active-directory',
146
+ 'rt-exploit-adcs',
147
+ 'rt-adcs-esc9-13',
148
+ 'rt-adfs',
149
+ 'rt-azure-ad',
150
+ 'rt-exchange-sharepoint',
151
+ 'rt-exploit-desktop-win',
152
+ 'rt-exploit-desktop-mac',
153
+ 'rt-printer-attacks',
154
+ 'rt-network-segmentation',
155
+ 'rt-exploit-network',
156
+ 'rt-ssl-mitm',
157
+ 'rt-citrix-vdi',
158
+ // Nation-state / APT
159
+ 'rt-kerberos-relay',
160
+ 'rt-diamond-sapphire-tickets',
161
+ 'rt-zerologon',
162
+ 'rt-printnightmare-rce',
163
+ 'rt-golden-saml',
164
+ 'rt-skeleton-key',
165
+ 'rt-syscall-bypass',
166
+ 'rt-etw-bypass',
167
+ 'rt-process-injection-advanced',
168
+ 'rt-ppid-spoofing',
169
+ 'rt-beacon-sleep-masking',
170
+ 'rt-clm-jea-escape',
171
+ ],
172
+ },
173
+
174
+ reporting: {
175
+ label: 'Reporting & Documentation',
176
+ description: 'Reports, findings, CVSS, MITRE, scenarios, compliance',
177
+ skills: [
178
+ 'rt-technical-report',
179
+ 'rt-executive-report',
180
+ 'rt-finding-document',
181
+ 'rt-finding-tracker',
182
+ 'rt-autodoc',
183
+ 'rt-create-sead',
184
+ 'rt-evidence-chain',
185
+ 'rt-compliance-mapper',
186
+ 'rt-cvss-calculator',
187
+ 'rt-poc-writer',
188
+ 'rt-risk-matrix',
189
+ 'rt-mitre-map',
190
+ 'rt-kill-chain-map',
191
+ 'rt-remediation-roadmap',
192
+ 'rt-attack-chain-builder',
193
+ 'rt-timeline',
194
+ 'rt-threat-model',
195
+ 'rt-scenario-library',
196
+ 'rt-scenario-c001', 'rt-scenario-c002', 'rt-scenario-c003', 'rt-scenario-c004', 'rt-scenario-c005',
197
+ 'rt-scenario-d001', 'rt-scenario-d002', 'rt-scenario-d003', 'rt-scenario-d004', 'rt-scenario-d005',
198
+ 'rt-scenario-m001', 'rt-scenario-m002', 'rt-scenario-m003', 'rt-scenario-m004', 'rt-scenario-m005',
199
+ 'rt-scenario-n001', 'rt-scenario-n002', 'rt-scenario-n003', 'rt-scenario-n004', 'rt-scenario-n005',
200
+ 'rt-scenario-w001', 'rt-scenario-w002', 'rt-scenario-w003', 'rt-scenario-w004', 'rt-scenario-w005',
201
+ 'rt-scenario-w006', 'rt-scenario-w007', 'rt-scenario-w008', 'rt-scenario-w009', 'rt-scenario-w010',
202
+ ],
203
+ },
204
+
205
+ specialist: {
206
+ label: 'Specialist',
207
+ description: 'SCADA/ICS, IoT, hardware, physical, social engineering, wireless',
208
+ skills: [
209
+ 'rt-exploit-scada',
210
+ 'rt-exploit-iot',
211
+ 'rt-hardware-hacking',
212
+ 'rt-exploit-wireless',
213
+ 'rt-wireless-rogue-ap',
214
+ 'rt-exploit-physical',
215
+ 'rt-exploit-phishing',
216
+ 'rt-exploit-vishing',
217
+ 'rt-social-engineering',
218
+ 'rt-voip-sip',
219
+ 'rt-traffic-analysis',
220
+ 'rt-binary-reverse-engineering',
221
+ 'rt-sap-exploitation',
222
+ 'rt-steganography',
223
+ ],
224
+ },
225
+ };
226
+
227
+ /**
228
+ * Resolve the full set of skill folder names to install.
229
+ * @param {string[]|'all'} selectedProfiles — array of profile keys or 'all'
230
+ * @returns {Set<string>} — set of skill folder names
231
+ */
232
+ function resolveSkillSet(selectedProfiles) {
233
+ if (selectedProfiles === 'all' || (Array.isArray(selectedProfiles) && selectedProfiles.includes('all'))) {
234
+ const all = new Set(CORE);
235
+ for (const profile of Object.values(PROFILES)) {
236
+ for (const s of profile.skills) all.add(s);
237
+ }
238
+ return all;
239
+ }
240
+
241
+ const result = new Set(CORE);
242
+ for (const key of selectedProfiles) {
243
+ if (PROFILES[key]) {
244
+ for (const s of PROFILES[key].skills) result.add(s);
245
+ }
246
+ }
247
+ return result;
248
+ }
249
+
250
+ module.exports = { PROFILES, CORE, resolveSkillSet };
@@ -1,4 +1,5 @@
1
1
  const prompts = require('@clack/prompts');
2
+ const { PROFILES } = require('./profiles');
2
3
 
3
4
  async function askInstallQuestions({ cwd }) {
4
5
  const targetDirectory = await prompts.text({
@@ -34,12 +35,28 @@ async function askInstallQuestions({ cwd }) {
34
35
  required: true,
35
36
  });
36
37
 
38
+ const profileOptions = [
39
+ { value: 'all', label: 'All Skills (Full install — everything)', hint: 'recommended for full red team ops' },
40
+ ...Object.entries(PROFILES).map(([key, p]) => ({
41
+ value: key,
42
+ label: `${p.label}`,
43
+ hint: p.description,
44
+ })),
45
+ ];
46
+
47
+ const profiles = await prompts.multiselect({
48
+ message: 'Which skill profiles do you need? (space to select, enter to confirm)',
49
+ options: profileOptions,
50
+ initialValues: ['all'],
51
+ required: true,
52
+ });
53
+
37
54
  const confirmed = await prompts.confirm({
38
55
  message: `Install RTExit into ${targetDirectory}?`,
39
56
  initialValue: true,
40
57
  });
41
58
 
42
- return { targetDirectory, language, document_output_language, ides, confirmed };
59
+ return { targetDirectory, language, document_output_language, ides, profiles, confirmed };
43
60
  }
44
61
 
45
62
  module.exports = { askInstallQuestions };