blitzstrike 2.4.72 → 2.4.74
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/CHANGELOG.md +30 -0
- package/dist/index.js +254 -99
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,36 @@ All notable changes to Blitz Strike are documented here.
|
|
|
5
5
|
The format follows [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/).
|
|
7
7
|
|
|
8
|
+
## [2.4.74] — 2026-09-17
|
|
9
|
+
|
|
10
|
+
### Fixed — live_recon tech fingerprint false-positive (benchmark-driven)
|
|
11
|
+
|
|
12
|
+
- Tech detection now uses header + cookie signals FIRST (authoritative), then
|
|
13
|
+
body regex as fallback, via a new `detectTech(headers, body)`:
|
|
14
|
+
- `x-powered-by: Express` / `connect.sid` cookie → nodejs (was missed).
|
|
15
|
+
- `laravel_session` / `XSRF-TOKEN` cookie → laravel.
|
|
16
|
+
- `PHPSESSID` → php, `csrftoken`+`sessionid` → django, `rack.session` → rails.
|
|
17
|
+
- Removed the over-broad `_token` / `csrf-token` → laravel body signature (those
|
|
18
|
+
are generic CSRF tokens, present in Node/Express apps too) — this caused the
|
|
19
|
+
Hackbot Arena labs03 (Node/Express) to be mis-flagged as "laravel".
|
|
20
|
+
- `gunicorn` no longer implies "flask" (it's a generic WSGI server shared by
|
|
21
|
+
Flask/Django/FastAPI); only `werkzeug` maps to flask.
|
|
22
|
+
|
|
23
|
+
## [2.4.73] — 2026-09-17
|
|
24
|
+
|
|
25
|
+
### Changed — crack_hash wordlist support (benchmark-driven fix)
|
|
26
|
+
|
|
27
|
+
- `crack_hash` gained a `wordlist` arg (comma-separated paths) + `maxCandidates`
|
|
28
|
+
arg, and `crackHash()` now STREAMS any supplied wordlist and AUTOLOADS the
|
|
29
|
+
standard seclists/rockyou locations (`/usr/share/wordlists/rockyou.txt`,
|
|
30
|
+
`/opt/seclists/.../rockyou-*.txt`, Common-Credentials) when present. Cracking
|
|
31
|
+
is line-streamed (no full-file load), so a 14M-line rockyou won't OOM.
|
|
32
|
+
- Added a pure-JS MD4 (NTLM) implementation so NTLM hashes also crack offline.
|
|
33
|
+
- Result now reports `source` (common/wordlist) + `candidates_checked`.
|
|
34
|
+
- Root cause: the Hackbot Arena labs04 run found the built-in common list was too
|
|
35
|
+
small (missed `md5("xNnWo6272k7x")`, only present in the full rockyou) — the
|
|
36
|
+
tool now reaches whatever wordlist is available on the box.
|
|
37
|
+
|
|
8
38
|
## [2.4.72] — 2026-09-14
|
|
9
39
|
|
|
10
40
|
### Added — Hackbot Arena benchmark integration
|
package/dist/index.js
CHANGED
|
@@ -15584,11 +15584,11 @@ var require_src = __commonJS(function(exports, module) {
|
|
|
15584
15584
|
});
|
|
15585
15585
|
|
|
15586
15586
|
// src/mcp-status.ts
|
|
15587
|
-
import { existsSync as
|
|
15587
|
+
import { existsSync as existsSync10 } from "node:fs";
|
|
15588
15588
|
import { spawnSync as spawnSync3 } from "node:child_process";
|
|
15589
15589
|
async function checkMcpServers() {
|
|
15590
15590
|
const out = [];
|
|
15591
|
-
const bin = ["/usr/bin/chrome-devtools-mcp", "/usr/local/bin/chrome-devtools-mcp"].find((p) =>
|
|
15591
|
+
const bin = ["/usr/bin/chrome-devtools-mcp", "/usr/local/bin/chrome-devtools-mcp"].find((p) => existsSync10(p));
|
|
15592
15592
|
const npxOk = spawnSync3("npx", ["--version"], { timeout: 8000 }).error === undefined;
|
|
15593
15593
|
const devtoolsOk = Boolean(bin) || npxOk;
|
|
15594
15594
|
out.push({
|
|
@@ -17220,7 +17220,7 @@ var init_update = __esm(() => {
|
|
|
17220
17220
|
});
|
|
17221
17221
|
|
|
17222
17222
|
// src/release.ts
|
|
17223
|
-
import { readFileSync as readFileSync28, existsSync as
|
|
17223
|
+
import { readFileSync as readFileSync28, existsSync as existsSync14 } from "node:fs";
|
|
17224
17224
|
import { join as join25 } from "node:path";
|
|
17225
17225
|
import { fileURLToPath as fileURLToPath14 } from "node:url";
|
|
17226
17226
|
import { execSync as execSync2 } from "node:child_process";
|
|
@@ -17260,7 +17260,7 @@ function validateRelease() {
|
|
|
17260
17260
|
return { version: VERSION, checks, consistent: checks.filter((c) => !c.soft).every((c) => c.ok) };
|
|
17261
17261
|
}
|
|
17262
17262
|
function lockfilePresent() {
|
|
17263
|
-
return
|
|
17263
|
+
return existsSync14(join25(ROOT8, "package-lock.json")) || existsSync14(join25(ROOT8, "bun.lock")) || existsSync14(join25(ROOT8, "bun.lockb"));
|
|
17264
17264
|
}
|
|
17265
17265
|
var ROOT8;
|
|
17266
17266
|
var init_release = __esm(() => {
|
|
@@ -17302,7 +17302,7 @@ var init_dependency = __esm(() => {
|
|
|
17302
17302
|
});
|
|
17303
17303
|
|
|
17304
17304
|
// src/cli.ts
|
|
17305
|
-
import { readFileSync as readFileSync30, existsSync as
|
|
17305
|
+
import { readFileSync as readFileSync30, existsSync as existsSync15, writeFileSync as writeFileSync9, mkdirSync as mkdirSync10 } from "node:fs";
|
|
17306
17306
|
import { join as join27, dirname as dirname6 } from "node:path";
|
|
17307
17307
|
import { homedir as homedir11 } from "node:os";
|
|
17308
17308
|
import { fileURLToPath as fileURLToPath16 } from "node:url";
|
|
@@ -17348,7 +17348,7 @@ async function runDoctor() {
|
|
|
17348
17348
|
detail: h1 ? `X-HackerOne-Research: ${h1}` : "H1_USERNAME not set",
|
|
17349
17349
|
fix: h1 ? undefined : "export H1_USERNAME=<your-hackerone-username> (adds X-HackerOne-Research to outbound requests)"
|
|
17350
17350
|
});
|
|
17351
|
-
const dataOk =
|
|
17351
|
+
const dataOk = existsSync15(join27(ROOT10, "chains.json")) && existsSync15(join27(ROOT10, "tools-catalog.json"));
|
|
17352
17352
|
issues.push({
|
|
17353
17353
|
name: "Data layers (chains + tools-catalog)",
|
|
17354
17354
|
status: dataOk ? "ok" : "fail",
|
|
@@ -17400,14 +17400,14 @@ function resolveCommand() {
|
|
|
17400
17400
|
if (which("blitzstrike"))
|
|
17401
17401
|
return { command: "blitzstrike", args: ["serve", "--mcp"] };
|
|
17402
17402
|
const src = join27(ROOT10, "src", "index.ts");
|
|
17403
|
-
if (which("bun") &&
|
|
17403
|
+
if (which("bun") && existsSync15(src))
|
|
17404
17404
|
return { command: "bun", args: ["run", src, "serve", "--mcp"] };
|
|
17405
17405
|
if (which("npx"))
|
|
17406
17406
|
return { command: "npx", args: ["-y", "blitzstrike", "serve", "--mcp"] };
|
|
17407
17407
|
if (which("bunx"))
|
|
17408
17408
|
return { command: "bunx", args: ["blitzstrike", "serve", "--mcp"] };
|
|
17409
17409
|
const dist = join27(ROOT10, "dist", "index.js");
|
|
17410
|
-
if (
|
|
17410
|
+
if (existsSync15(dist))
|
|
17411
17411
|
return { command: "bun", args: [dist, "serve", "--mcp"] };
|
|
17412
17412
|
return { command: "npx", args: ["-y", "blitzstrike", "serve", "--mcp"] };
|
|
17413
17413
|
}
|
|
@@ -17421,7 +17421,7 @@ function readJson(p) {
|
|
|
17421
17421
|
function jsonMcpServersWrite(p) {
|
|
17422
17422
|
return (command, args) => {
|
|
17423
17423
|
const dir = dirname6(p);
|
|
17424
|
-
if (!
|
|
17424
|
+
if (!existsSync15(dir))
|
|
17425
17425
|
mkdirSync10(dir, { recursive: true });
|
|
17426
17426
|
const existing = readJson(p) ?? {};
|
|
17427
17427
|
existing.mcpServers = {
|
|
@@ -17434,7 +17434,7 @@ function jsonMcpServersWrite(p) {
|
|
|
17434
17434
|
function opencodeWrite(p) {
|
|
17435
17435
|
return (command, args) => {
|
|
17436
17436
|
const dir = dirname6(p);
|
|
17437
|
-
if (!
|
|
17437
|
+
if (!existsSync15(dir))
|
|
17438
17438
|
mkdirSync10(dir, { recursive: true });
|
|
17439
17439
|
const existing = readJson(p) ?? {};
|
|
17440
17440
|
existing.mcp = {
|
|
@@ -17448,14 +17448,14 @@ function opencodeWrite(p) {
|
|
|
17448
17448
|
function copyOpenCodeAgents() {
|
|
17449
17449
|
const srcDir = join27(ROOT10, "opencode-agents");
|
|
17450
17450
|
const dstDir = join27(homedir11(), ".config", "opencode", "agents");
|
|
17451
|
-
if (!
|
|
17451
|
+
if (!existsSync15(srcDir))
|
|
17452
17452
|
return;
|
|
17453
|
-
if (!
|
|
17453
|
+
if (!existsSync15(dstDir))
|
|
17454
17454
|
mkdirSync10(dstDir, { recursive: true });
|
|
17455
17455
|
for (const f of ["Blitz Strike.md", "Blitz.md", "Eagle Eye.md", "Strike.md"]) {
|
|
17456
17456
|
const src = join27(srcDir, f);
|
|
17457
17457
|
const dst = join27(dstDir, f);
|
|
17458
|
-
if (
|
|
17458
|
+
if (existsSync15(src)) {
|
|
17459
17459
|
writeFileSync9(dst, readFileSync30(src, "utf8"));
|
|
17460
17460
|
}
|
|
17461
17461
|
}
|
|
@@ -17463,9 +17463,9 @@ function copyOpenCodeAgents() {
|
|
|
17463
17463
|
function codexWrite(p) {
|
|
17464
17464
|
return (command, args) => {
|
|
17465
17465
|
const dir = dirname6(p);
|
|
17466
|
-
if (!
|
|
17466
|
+
if (!existsSync15(dir))
|
|
17467
17467
|
mkdirSync10(dir, { recursive: true });
|
|
17468
|
-
let existing =
|
|
17468
|
+
let existing = existsSync15(p) ? readFileSync30(p, "utf8") : "";
|
|
17469
17469
|
if (!existing.trimEnd().endsWith(`
|
|
17470
17470
|
`))
|
|
17471
17471
|
existing += `
|
|
@@ -17482,9 +17482,9 @@ args = ${JSON.stringify(args)}
|
|
|
17482
17482
|
function hermesWrite(p) {
|
|
17483
17483
|
return (command, args) => {
|
|
17484
17484
|
const dir = dirname6(p);
|
|
17485
|
-
if (!
|
|
17485
|
+
if (!existsSync15(dir))
|
|
17486
17486
|
mkdirSync10(dir, { recursive: true });
|
|
17487
|
-
let existing =
|
|
17487
|
+
let existing = existsSync15(p) ? readFileSync30(p, "utf8") : "";
|
|
17488
17488
|
existing = existing.replace(/^ blitzstrike:\n(?: .*\n?)*/m, "");
|
|
17489
17489
|
if (!existing.trimEnd().endsWith(`
|
|
17490
17490
|
`))
|
|
@@ -17515,70 +17515,70 @@ function detectAgents() {
|
|
|
17515
17515
|
agents.push({
|
|
17516
17516
|
name: "Claude Code",
|
|
17517
17517
|
detectPath: claudeJson,
|
|
17518
|
-
installed: () =>
|
|
17518
|
+
installed: () => existsSync15(claudeJson) || which("claude"),
|
|
17519
17519
|
write: jsonMcpServersWrite(claudeJson)
|
|
17520
17520
|
});
|
|
17521
17521
|
const claudeDesktop = join27(home, ".config", "Claude", "claude_desktop_config.json");
|
|
17522
17522
|
agents.push({
|
|
17523
17523
|
name: "Claude Desktop",
|
|
17524
17524
|
detectPath: claudeDesktop,
|
|
17525
|
-
installed: () =>
|
|
17525
|
+
installed: () => existsSync15(claudeDesktop),
|
|
17526
17526
|
write: jsonMcpServersWrite(claudeDesktop)
|
|
17527
17527
|
});
|
|
17528
17528
|
const cursor = join27(home, ".cursor", "mcp.json");
|
|
17529
17529
|
agents.push({
|
|
17530
17530
|
name: "Cursor",
|
|
17531
17531
|
detectPath: cursor,
|
|
17532
|
-
installed: () =>
|
|
17532
|
+
installed: () => existsSync15(join27(home, ".cursor")) || which("cursor"),
|
|
17533
17533
|
write: jsonMcpServersWrite(cursor)
|
|
17534
17534
|
});
|
|
17535
17535
|
const opencode = join27(home, ".config", "opencode", "opencode.jsonc");
|
|
17536
17536
|
agents.push({
|
|
17537
17537
|
name: "OpenCode",
|
|
17538
17538
|
detectPath: opencode,
|
|
17539
|
-
installed: () =>
|
|
17539
|
+
installed: () => existsSync15(join27(home, ".config", "opencode")) || which("opencode"),
|
|
17540
17540
|
write: opencodeWrite(opencode)
|
|
17541
17541
|
});
|
|
17542
17542
|
const codex = join27(home, ".codex", "config.toml");
|
|
17543
17543
|
agents.push({
|
|
17544
17544
|
name: "Codex",
|
|
17545
17545
|
detectPath: codex,
|
|
17546
|
-
installed: () =>
|
|
17546
|
+
installed: () => existsSync15(join27(home, ".codex")) || which("codex"),
|
|
17547
17547
|
write: codexWrite(codex)
|
|
17548
17548
|
});
|
|
17549
17549
|
const hermes = join27(home, ".hermes", "config.yaml");
|
|
17550
17550
|
agents.push({
|
|
17551
17551
|
name: "Hermes",
|
|
17552
17552
|
detectPath: hermes,
|
|
17553
|
-
installed: () =>
|
|
17553
|
+
installed: () => existsSync15(join27(home, ".hermes")) || which("hermes"),
|
|
17554
17554
|
write: hermesWrite(hermes)
|
|
17555
17555
|
});
|
|
17556
17556
|
const gemini = join27(home, ".gemini", "settings.json");
|
|
17557
17557
|
agents.push({
|
|
17558
17558
|
name: "Gemini CLI",
|
|
17559
17559
|
detectPath: gemini,
|
|
17560
|
-
installed: () =>
|
|
17560
|
+
installed: () => existsSync15(join27(home, ".gemini")) || which("gemini"),
|
|
17561
17561
|
write: jsonMcpServersWrite(gemini)
|
|
17562
17562
|
});
|
|
17563
17563
|
const windsurf = join27(home, ".codeium", "windsurf", "mcp_config.json");
|
|
17564
17564
|
agents.push({
|
|
17565
17565
|
name: "Windsurf",
|
|
17566
17566
|
detectPath: windsurf,
|
|
17567
|
-
installed: () =>
|
|
17567
|
+
installed: () => existsSync15(join27(home, ".codeium")) || which("windsurf"),
|
|
17568
17568
|
write: jsonMcpServersWrite(windsurf)
|
|
17569
17569
|
});
|
|
17570
17570
|
const copilot = join27(home, ".copilot", "mcp.json");
|
|
17571
17571
|
agents.push({
|
|
17572
17572
|
name: "Copilot",
|
|
17573
17573
|
detectPath: copilot,
|
|
17574
|
-
installed: () =>
|
|
17574
|
+
installed: () => existsSync15(join27(home, ".copilot")),
|
|
17575
17575
|
write: jsonMcpServersWrite(copilot)
|
|
17576
17576
|
});
|
|
17577
17577
|
const cline = join27(home, ".cline", "mcp_settings.json");
|
|
17578
17578
|
agents.push({
|
|
17579
17579
|
name: "Cline",
|
|
17580
17580
|
detectPath: cline,
|
|
17581
|
-
installed: () =>
|
|
17581
|
+
installed: () => existsSync15(join27(home, ".cline")),
|
|
17582
17582
|
write: jsonMcpServersWrite(cline)
|
|
17583
17583
|
});
|
|
17584
17584
|
return agents;
|
|
@@ -32417,7 +32417,7 @@ async function nvdLookup(cveId) {
|
|
|
32417
32417
|
|
|
32418
32418
|
// src/orchestrator.ts
|
|
32419
32419
|
init_scanner();
|
|
32420
|
-
import { readFileSync as readFileSync9, existsSync as
|
|
32420
|
+
import { readFileSync as readFileSync9, existsSync as existsSync8, statSync as statSync2 } from "node:fs";
|
|
32421
32421
|
import { join as join11 } from "node:path";
|
|
32422
32422
|
import { fileURLToPath as fileURLToPath5 } from "node:url";
|
|
32423
32423
|
|
|
@@ -33181,6 +33181,8 @@ function resolveFinding(finding, verdict) {
|
|
|
33181
33181
|
|
|
33182
33182
|
// src/hash.ts
|
|
33183
33183
|
import { createHash as createHash3 } from "node:crypto";
|
|
33184
|
+
import { createReadStream, existsSync as existsSync4 } from "node:fs";
|
|
33185
|
+
import { createInterface } from "node:readline";
|
|
33184
33186
|
var COMMON_PASSWORDS = [
|
|
33185
33187
|
"password",
|
|
33186
33188
|
"123456",
|
|
@@ -33211,6 +33213,14 @@ var COMMON_PASSWORDS = [
|
|
|
33211
33213
|
"P@ssw0rd",
|
|
33212
33214
|
"qwertyuiop"
|
|
33213
33215
|
];
|
|
33216
|
+
var AUTOLOAD_WORDLISTS = [
|
|
33217
|
+
"/usr/share/wordlists/rockyou.txt",
|
|
33218
|
+
"/opt/seclists/Passwords/Leaked-Databases/rockyou-70.txt",
|
|
33219
|
+
"/opt/seclists/Passwords/Leaked-Databases/rockyou-35.txt",
|
|
33220
|
+
"/opt/seclists/Passwords/Leaked-Databases/rockyou-40.txt",
|
|
33221
|
+
"/opt/seclists/Passwords/Common-Credentials/100k-most-used-passwords-NCSC.txt",
|
|
33222
|
+
"/opt/seclists/Passwords/Common-Credentials/10k-most-common.txt"
|
|
33223
|
+
];
|
|
33214
33224
|
function identifyHash(hash) {
|
|
33215
33225
|
if (/^\$2[aby]\$\d+\$/.test(hash))
|
|
33216
33226
|
return "bcrypt";
|
|
@@ -33243,31 +33253,141 @@ var HASHCAT_MODE = {
|
|
|
33243
33253
|
sha512crypt: "1800",
|
|
33244
33254
|
ntlm: "1000"
|
|
33245
33255
|
};
|
|
33246
|
-
|
|
33256
|
+
function hashMatches(type, pw, hash) {
|
|
33257
|
+
const target = hash.toLowerCase();
|
|
33258
|
+
if (type === "md5")
|
|
33259
|
+
return createHash3("md5").update(pw).digest("hex") === target;
|
|
33260
|
+
if (type === "sha1")
|
|
33261
|
+
return createHash3("sha1").update(pw).digest("hex") === target;
|
|
33262
|
+
if (type === "sha256")
|
|
33263
|
+
return createHash3("sha256").update(pw).digest("hex") === target;
|
|
33264
|
+
if (type === "sha512")
|
|
33265
|
+
return createHash3("sha512").update(pw).digest("hex") === target;
|
|
33266
|
+
if (type === "ntlm") {
|
|
33267
|
+
const md4 = (buf) => {
|
|
33268
|
+
const pad = (s) => {
|
|
33269
|
+
const len = s.length;
|
|
33270
|
+
const bitLen = len * 8;
|
|
33271
|
+
const out = Buffer.concat([s, Buffer.from([128])]);
|
|
33272
|
+
const mod = out.length % 64;
|
|
33273
|
+
const padLen = mod < 56 ? 56 - mod : 120 - mod;
|
|
33274
|
+
const padded = Buffer.concat([out, Buffer.alloc(padLen)]);
|
|
33275
|
+
const lenBuf = Buffer.alloc(8);
|
|
33276
|
+
lenBuf.writeUInt32LE(bitLen >>> 0, 0);
|
|
33277
|
+
lenBuf.writeUInt32LE(Math.floor(bitLen / 4294967296), 4);
|
|
33278
|
+
return Buffer.concat([padded, lenBuf]);
|
|
33279
|
+
};
|
|
33280
|
+
const rotl = (x, n) => (x << n | x >>> 32 - n) >>> 0;
|
|
33281
|
+
const F = (x, y, z) => x & y | ~x & z;
|
|
33282
|
+
const G = (x, y, z) => x & y | x & z | y & z;
|
|
33283
|
+
const H = (x, y, z) => x ^ y ^ z;
|
|
33284
|
+
const msg = pad(buf);
|
|
33285
|
+
let a0 = 1732584193, b0 = 4023233417, c0 = 2562383102, d0 = 271733878;
|
|
33286
|
+
for (let i = 0;i < msg.length; i += 64) {
|
|
33287
|
+
const X = [];
|
|
33288
|
+
for (let j = 0;j < 16; j++)
|
|
33289
|
+
X[j] = msg.readUInt32LE(i + j * 4);
|
|
33290
|
+
let A = a0, B = b0, C = c0, D = d0;
|
|
33291
|
+
for (let r = 0;r < 16; r++) {
|
|
33292
|
+
const k = r;
|
|
33293
|
+
const s = [3, 7, 11, 19][r % 4];
|
|
33294
|
+
const order = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15];
|
|
33295
|
+
A = rotl(A + F(B, C, D) + X[order[k]] + 0 >>> 0, s);
|
|
33296
|
+
[A, B, C, D] = [D, A, B, C];
|
|
33297
|
+
}
|
|
33298
|
+
for (let r = 0;r < 16; r++) {
|
|
33299
|
+
const order = [0, 4, 8, 12, 1, 5, 9, 13, 2, 6, 10, 14, 3, 7, 11, 15];
|
|
33300
|
+
const s = [3, 5, 9, 13][r % 4];
|
|
33301
|
+
A = rotl(A + G(B, C, D) + X[order[r]] + 1518500249 >>> 0, s);
|
|
33302
|
+
[A, B, C, D] = [D, A, B, C];
|
|
33303
|
+
}
|
|
33304
|
+
for (let r = 0;r < 16; r++) {
|
|
33305
|
+
const order = [0, 8, 4, 12, 2, 10, 6, 14, 1, 9, 5, 13, 3, 11, 7, 15];
|
|
33306
|
+
const s = [3, 9, 11, 15][r % 4];
|
|
33307
|
+
A = rotl(A + H(B, C, D) + X[order[r]] + 1859775393 >>> 0, s);
|
|
33308
|
+
[A, B, C, D] = [D, A, B, C];
|
|
33309
|
+
}
|
|
33310
|
+
a0 = a0 + A >>> 0;
|
|
33311
|
+
b0 = b0 + B >>> 0;
|
|
33312
|
+
c0 = c0 + C >>> 0;
|
|
33313
|
+
d0 = d0 + D >>> 0;
|
|
33314
|
+
}
|
|
33315
|
+
const le = (x) => Buffer.from([x & 255, x >>> 8 & 255, x >>> 16 & 255, x >>> 24 & 255]);
|
|
33316
|
+
return Buffer.concat([le(a0), le(b0), le(c0), le(d0)]).toString("hex");
|
|
33317
|
+
};
|
|
33318
|
+
const utf16le = Buffer.from(pw, "utf16le");
|
|
33319
|
+
return md4(utf16le) === target;
|
|
33320
|
+
}
|
|
33321
|
+
return false;
|
|
33322
|
+
}
|
|
33323
|
+
async function crackWordlists(hash, type, paths, maxCandidates) {
|
|
33324
|
+
let checked = 0;
|
|
33325
|
+
for (const p of paths) {
|
|
33326
|
+
if (!existsSync4(p))
|
|
33327
|
+
continue;
|
|
33328
|
+
const stream = createReadStream(p, { encoding: "utf8" });
|
|
33329
|
+
const rl = createInterface({ input: stream, crlfDelay: Infinity });
|
|
33330
|
+
let found = null;
|
|
33331
|
+
for await (const line of rl) {
|
|
33332
|
+
if (found)
|
|
33333
|
+
break;
|
|
33334
|
+
const pw = line.endsWith("\r") ? line.slice(0, -1) : line;
|
|
33335
|
+
if (!pw)
|
|
33336
|
+
continue;
|
|
33337
|
+
checked += 1;
|
|
33338
|
+
if (checked > maxCandidates)
|
|
33339
|
+
break;
|
|
33340
|
+
if (hashMatches(type, pw, hash))
|
|
33341
|
+
found = pw;
|
|
33342
|
+
}
|
|
33343
|
+
stream.destroy();
|
|
33344
|
+
if (found)
|
|
33345
|
+
return { password: found, checked };
|
|
33346
|
+
if (checked > maxCandidates)
|
|
33347
|
+
break;
|
|
33348
|
+
}
|
|
33349
|
+
return { password: null, checked };
|
|
33350
|
+
}
|
|
33351
|
+
async function crackHash(hash, extra = [], opts = {}) {
|
|
33247
33352
|
const type = identifyHash(hash);
|
|
33248
|
-
const
|
|
33249
|
-
const
|
|
33250
|
-
|
|
33251
|
-
|
|
33252
|
-
|
|
33253
|
-
|
|
33254
|
-
|
|
33255
|
-
|
|
33256
|
-
|
|
33257
|
-
|
|
33258
|
-
|
|
33259
|
-
|
|
33260
|
-
|
|
33261
|
-
|
|
33262
|
-
|
|
33263
|
-
|
|
33353
|
+
const maxCandidates = opts.maxCandidates ?? 5000000;
|
|
33354
|
+
const fast = [...new Set([...extra, ...COMMON_PASSWORDS])];
|
|
33355
|
+
let matched = "";
|
|
33356
|
+
for (const pw of fast) {
|
|
33357
|
+
if (hashMatches(type, pw, hash)) {
|
|
33358
|
+
matched = pw;
|
|
33359
|
+
break;
|
|
33360
|
+
}
|
|
33361
|
+
}
|
|
33362
|
+
if (matched) {
|
|
33363
|
+
return {
|
|
33364
|
+
type,
|
|
33365
|
+
cracked: true,
|
|
33366
|
+
matches: [matched],
|
|
33367
|
+
source: "common",
|
|
33368
|
+
recommendation: `CRACKED — authenticate with '${matched}' and continue the chain (login → dashboard → privileged actions).`
|
|
33369
|
+
};
|
|
33370
|
+
}
|
|
33371
|
+
const explicit = opts.wordlist ? Array.isArray(opts.wordlist) ? opts.wordlist : [opts.wordlist] : [];
|
|
33372
|
+
const paths = [...new Set([...explicit, ...AUTOLOAD_WORDLISTS])];
|
|
33373
|
+
const { password, checked } = await crackWordlists(hash, type, paths, maxCandidates);
|
|
33374
|
+
if (password) {
|
|
33375
|
+
return {
|
|
33376
|
+
type,
|
|
33377
|
+
cracked: true,
|
|
33378
|
+
matches: [password],
|
|
33379
|
+
source: "wordlist",
|
|
33380
|
+
candidates_checked: checked,
|
|
33381
|
+
recommendation: `CRACKED from wordlist — authenticate with '${password}' and continue the chain (login → dashboard → privileged actions).`
|
|
33382
|
+
};
|
|
33264
33383
|
}
|
|
33265
33384
|
const mode = HASHCAT_MODE[type];
|
|
33266
33385
|
return {
|
|
33267
33386
|
type,
|
|
33268
|
-
cracked:
|
|
33269
|
-
matches,
|
|
33270
|
-
|
|
33387
|
+
cracked: false,
|
|
33388
|
+
matches: [],
|
|
33389
|
+
candidates_checked: checked,
|
|
33390
|
+
recommendation: mode ? `Not in the built-in common list or ${checked} wordlist candidates. Full crack: hashcat -m ${mode} -a 0 <hashes.txt> <wordlist> (bcrypt cost 12 needs GPU + time). Pass a target-specific wordlist via the wordlist arg (e.g. company names, usernames, pattern guesses). Reuse the credential if it matches another account's hash (password reuse).` : "Unknown hash format — save it and identify manually before cracking."
|
|
33271
33391
|
};
|
|
33272
33392
|
}
|
|
33273
33393
|
|
|
@@ -33447,7 +33567,7 @@ async function browserValidate(check, target, payload) {
|
|
|
33447
33567
|
|
|
33448
33568
|
// src/devtools.ts
|
|
33449
33569
|
import { spawn as spawn2, spawnSync as spawnSync2 } from "node:child_process";
|
|
33450
|
-
import { existsSync as
|
|
33570
|
+
import { existsSync as existsSync5, readdirSync as readdirSync3 } from "node:fs";
|
|
33451
33571
|
import { join as join7 } from "node:path";
|
|
33452
33572
|
import { homedir as homedir4 } from "node:os";
|
|
33453
33573
|
function mcpClient(command, args) {
|
|
@@ -33521,17 +33641,17 @@ function findChromium() {
|
|
|
33521
33641
|
for (const c of candidates) {
|
|
33522
33642
|
for (const dir of ["/usr/bin", "/usr/local/bin", "/opt/google/chrome"]) {
|
|
33523
33643
|
const p = join7(dir, c);
|
|
33524
|
-
if (
|
|
33644
|
+
if (existsSync5(p))
|
|
33525
33645
|
return p;
|
|
33526
33646
|
}
|
|
33527
33647
|
}
|
|
33528
33648
|
const pw = join7(homedir4(), ".cache", "ms-playwright");
|
|
33529
|
-
if (
|
|
33649
|
+
if (existsSync5(pw)) {
|
|
33530
33650
|
for (const d of readdirSync3(pw)) {
|
|
33531
33651
|
if (!d.startsWith("chromium"))
|
|
33532
33652
|
continue;
|
|
33533
33653
|
const full = join7(pw, d, "chrome-linux64", "chrome");
|
|
33534
|
-
if (
|
|
33654
|
+
if (existsSync5(full))
|
|
33535
33655
|
return full;
|
|
33536
33656
|
}
|
|
33537
33657
|
}
|
|
@@ -33539,7 +33659,7 @@ function findChromium() {
|
|
|
33539
33659
|
}
|
|
33540
33660
|
function chromeDevtoolsCommand() {
|
|
33541
33661
|
for (const c of ["/usr/bin/chrome-devtools-mcp", "/usr/local/bin/chrome-devtools-mcp"]) {
|
|
33542
|
-
if (
|
|
33662
|
+
if (existsSync5(c))
|
|
33543
33663
|
return { command: c, args: [] };
|
|
33544
33664
|
}
|
|
33545
33665
|
const npx = spawnSync2("npx", ["--version"], { timeout: 8000 });
|
|
@@ -33851,12 +33971,12 @@ function uniqueFindings(findings) {
|
|
|
33851
33971
|
}
|
|
33852
33972
|
|
|
33853
33973
|
// src/intel.ts
|
|
33854
|
-
import { readFileSync as readFileSync8, existsSync as
|
|
33974
|
+
import { readFileSync as readFileSync8, existsSync as existsSync7 } from "node:fs";
|
|
33855
33975
|
import { join as join9 } from "node:path";
|
|
33856
33976
|
import { fileURLToPath as fileURLToPath4 } from "node:url";
|
|
33857
33977
|
|
|
33858
33978
|
// src/intelligence.ts
|
|
33859
|
-
import { readFileSync as readFileSync7, appendFileSync as appendFileSync3, mkdirSync as mkdirSync4, existsSync as
|
|
33979
|
+
import { readFileSync as readFileSync7, appendFileSync as appendFileSync3, mkdirSync as mkdirSync4, existsSync as existsSync6 } from "node:fs";
|
|
33860
33980
|
import { join as join8 } from "node:path";
|
|
33861
33981
|
import { createHash as createHash4 } from "node:crypto";
|
|
33862
33982
|
import { homedir as homedir5 } from "node:os";
|
|
@@ -33882,14 +34002,14 @@ function sinkToVector(sinkType) {
|
|
|
33882
34002
|
return SINK_TO_VECTOR[sinkType.toLowerCase()] ?? sinkType.toLowerCase();
|
|
33883
34003
|
}
|
|
33884
34004
|
function ensureDir2() {
|
|
33885
|
-
if (!
|
|
34005
|
+
if (!existsSync6(HOME_DIR3))
|
|
33886
34006
|
mkdirSync4(HOME_DIR3, { recursive: true });
|
|
33887
34007
|
}
|
|
33888
34008
|
function dedupHash2(vector, tech, target, outcome) {
|
|
33889
34009
|
return createHash4("sha256").update(`${vector}\x00${tech}\x00${target}\x00${outcome}`).digest("hex").slice(0, 16);
|
|
33890
34010
|
}
|
|
33891
34011
|
function loadIntel() {
|
|
33892
|
-
if (!
|
|
34012
|
+
if (!existsSync6(INTEL_PATH))
|
|
33893
34013
|
return [];
|
|
33894
34014
|
try {
|
|
33895
34015
|
const out = [];
|
|
@@ -34041,7 +34161,7 @@ var ROOT3 = join9(fileURLToPath4(new URL(".", import.meta.url)), "..");
|
|
|
34041
34161
|
var INTEL = join9(ROOT3, "intelligence");
|
|
34042
34162
|
function loadJson(name) {
|
|
34043
34163
|
const p = join9(INTEL, `${name}.json`);
|
|
34044
|
-
if (!
|
|
34164
|
+
if (!existsSync7(p))
|
|
34045
34165
|
return null;
|
|
34046
34166
|
try {
|
|
34047
34167
|
return JSON.parse(readFileSync8(p, "utf8"));
|
|
@@ -34328,12 +34448,12 @@ var PACKAGE_PAYLOADS = join9(ROOT3, "payloads");
|
|
|
34328
34448
|
var PACKAGE_TEMPLATES = join9(ROOT3, "templates");
|
|
34329
34449
|
var DATA_ROOT = process.env.BLITZSTRIKE_DATA ?? join9(homedir6(), ".blitzstrike", "data");
|
|
34330
34450
|
function payloadsDir() {
|
|
34331
|
-
if (
|
|
34451
|
+
if (existsSync7(PACKAGE_PAYLOADS))
|
|
34332
34452
|
return PACKAGE_PAYLOADS;
|
|
34333
34453
|
return join9(DATA_ROOT, "payloads");
|
|
34334
34454
|
}
|
|
34335
34455
|
function templatesDir() {
|
|
34336
|
-
if (
|
|
34456
|
+
if (existsSync7(PACKAGE_TEMPLATES))
|
|
34337
34457
|
return PACKAGE_TEMPLATES;
|
|
34338
34458
|
return join9(DATA_ROOT, "templates");
|
|
34339
34459
|
}
|
|
@@ -35764,6 +35884,59 @@ function extractVersion(headers, body) {
|
|
|
35764
35884
|
}
|
|
35765
35885
|
return out;
|
|
35766
35886
|
}
|
|
35887
|
+
function detectTech(headers, body) {
|
|
35888
|
+
const techs = new Set;
|
|
35889
|
+
const low = (s) => (s ?? "").toLowerCase();
|
|
35890
|
+
const powered = low(headers["x-powered-by"]);
|
|
35891
|
+
const server = low(headers["server"]);
|
|
35892
|
+
const cookies = low(headers["set-cookie"]);
|
|
35893
|
+
const generator = low(headers["x-generator"]);
|
|
35894
|
+
if (/express|node\b|nodejs/i.test(powered))
|
|
35895
|
+
techs.add("nodejs");
|
|
35896
|
+
if (/^php\b|^php\//i.test(powered))
|
|
35897
|
+
techs.add("php");
|
|
35898
|
+
if (/asp\.net/i.test(powered) || (headers["x-aspnet-version"] ?? ""))
|
|
35899
|
+
techs.add("aspnet");
|
|
35900
|
+
if (/werkzeug/i.test(server))
|
|
35901
|
+
techs.add("flask");
|
|
35902
|
+
if (/drupal/i.test(generator))
|
|
35903
|
+
techs.add("drupal");
|
|
35904
|
+
if (/laravel_session|xsrf-token/i.test(cookies))
|
|
35905
|
+
techs.add("laravel");
|
|
35906
|
+
if (/phpsessid/i.test(cookies))
|
|
35907
|
+
techs.add("php");
|
|
35908
|
+
if (/connect\.sid/i.test(cookies))
|
|
35909
|
+
techs.add("nodejs");
|
|
35910
|
+
if (/csrftoken/i.test(cookies) && /sessionid/i.test(cookies))
|
|
35911
|
+
techs.add("django");
|
|
35912
|
+
if (/rack\.session/i.test(cookies))
|
|
35913
|
+
techs.add("rails");
|
|
35914
|
+
const bodySig = [
|
|
35915
|
+
[/wp-content|wp-includes|wp-json/i, "wordpress"],
|
|
35916
|
+
[/wp-login\.php|wp-admin/i, "wordpress"],
|
|
35917
|
+
[/powered by joomla|com_content/i, "joomla"],
|
|
35918
|
+
[/laravel_session|xsrf-token|\blaravel\b/i, "laravel"],
|
|
35919
|
+
[/react|__NEXT_DATA__|next\/static/i, "nextjs"],
|
|
35920
|
+
[/angular|ng-version/i, "angular"],
|
|
35921
|
+
[/vue|__vue__|v-data/i, "vue"],
|
|
35922
|
+
[/django|csrftoken|__debug__/i, "django"],
|
|
35923
|
+
[/ruby on rails|rails/i, "rails"],
|
|
35924
|
+
[/asp\.net|__VIEWSTATE|__EVENTVALIDATION/i, "aspnet"],
|
|
35925
|
+
[/phpBB|phpbb/i, "phpbb"],
|
|
35926
|
+
[/mybb|mybb/i, "mybb"],
|
|
35927
|
+
[/drupal|Drupal\.settings/i, "drupal"],
|
|
35928
|
+
[/magento|Mage\./i, "magento"],
|
|
35929
|
+
[/shopify|cdn\.shopify/i, "shopify"],
|
|
35930
|
+
[/grafana|kibana|elastic/i, "grafana-kibana"],
|
|
35931
|
+
[/node\.js|express/i, "nodejs"],
|
|
35932
|
+
[/flask|werkzeug/i, "flask"],
|
|
35933
|
+
[/spring|actuator/i, "spring"]
|
|
35934
|
+
];
|
|
35935
|
+
for (const [re, t] of bodySig)
|
|
35936
|
+
if (re.test(body))
|
|
35937
|
+
techs.add(t);
|
|
35938
|
+
return [...techs];
|
|
35939
|
+
}
|
|
35767
35940
|
function correlateIntel(techs, versionList, portList) {
|
|
35768
35941
|
const tech = techs.map((t) => ({ tech: t, ...techCorrelation(t) }));
|
|
35769
35942
|
const versions = versionList.map((v) => ({
|
|
@@ -35799,28 +35972,7 @@ async function liveRecon(target, includeActive = false) {
|
|
|
35799
35972
|
body_size: root.body.length
|
|
35800
35973
|
};
|
|
35801
35974
|
const waf = detectWaf(root.headers, root.body);
|
|
35802
|
-
const
|
|
35803
|
-
[/wp-content|wp-includes|wp-json/i, "wordpress"],
|
|
35804
|
-
[/wp-login\.php|wp-admin/i, "wordpress"],
|
|
35805
|
-
[/powered by joomla|com_content/i, "joomla"],
|
|
35806
|
-
[/laravel|_token|csrf-token/i, "laravel"],
|
|
35807
|
-
[/react|__NEXT_DATA__|next\/static/i, "nextjs"],
|
|
35808
|
-
[/angular|ng-version/i, "angular"],
|
|
35809
|
-
[/vue|__vue__|v-data/i, "vue"],
|
|
35810
|
-
[/django|csrftoken|__debug__/i, "django"],
|
|
35811
|
-
[/ruby on rails|rails/i, "rails"],
|
|
35812
|
-
[/asp\.net|__VIEWSTATE|__EVENTVALIDATION/i, "aspnet"],
|
|
35813
|
-
[/phpBB|phpbb/i, "phpbb"],
|
|
35814
|
-
[/mybb|mybb/i, "mybb"],
|
|
35815
|
-
[/drupal|Drupal\.settings/i, "drupal"],
|
|
35816
|
-
[/magento|Mage\./i, "magento"],
|
|
35817
|
-
[/shopify|cdn\.shopify/i, "shopify"],
|
|
35818
|
-
[/grafana|kibana|elastic/i, "grafana-kibana"],
|
|
35819
|
-
[/node\.js|express/i, "nodejs"],
|
|
35820
|
-
[/flask|werkzeug/i, "flask"],
|
|
35821
|
-
[/spring|actuator/i, "spring"]
|
|
35822
|
-
];
|
|
35823
|
-
const techs = [...new Set(techSig.filter(([re]) => re.test(root.body)).map(([, t]) => t))];
|
|
35975
|
+
const techs = detectTech(root.headers, root.body);
|
|
35824
35976
|
const versions = extractVersion(root.headers, root.body);
|
|
35825
35977
|
const { links, scripts } = crawlLinks(base, root.body);
|
|
35826
35978
|
const { robots, sitemap } = await fetchRobotsAndSitemap(base);
|
|
@@ -35941,7 +36093,7 @@ function classifyTarget(target) {
|
|
|
35941
36093
|
if (/^https?:\/\//i.test(target))
|
|
35942
36094
|
return { kind: "live", target };
|
|
35943
36095
|
try {
|
|
35944
|
-
if (
|
|
36096
|
+
if (existsSync8(target) && (statSync2(target).isDirectory() || statSync2(target).isFile())) {
|
|
35945
36097
|
return { kind: "source", target };
|
|
35946
36098
|
}
|
|
35947
36099
|
} catch {}
|
|
@@ -36082,7 +36234,7 @@ function runEngagement(target, scope = "", mode = "bug-bounty", maxFiles = 2000,
|
|
|
36082
36234
|
};
|
|
36083
36235
|
const isPath = (() => {
|
|
36084
36236
|
try {
|
|
36085
|
-
return
|
|
36237
|
+
return existsSync8(target) && (statSync2(target).isDirectory() || statSync2(target).isFile());
|
|
36086
36238
|
} catch {
|
|
36087
36239
|
return false;
|
|
36088
36240
|
}
|
|
@@ -57558,7 +57710,7 @@ function analyzePatchFiles(oldPath, newPath, language) {
|
|
|
57558
57710
|
}
|
|
57559
57711
|
|
|
57560
57712
|
// src/frameworks.ts
|
|
57561
|
-
import { readFileSync as readFileSync16, existsSync as
|
|
57713
|
+
import { readFileSync as readFileSync16, existsSync as existsSync9 } from "node:fs";
|
|
57562
57714
|
import { join as join15 } from "node:path";
|
|
57563
57715
|
import { fileURLToPath as fileURLToPath7 } from "node:url";
|
|
57564
57716
|
var ROOT4 = join15(fileURLToPath7(new URL(".", import.meta.url)), "..");
|
|
@@ -57568,7 +57720,7 @@ function load2() {
|
|
|
57568
57720
|
if (cache)
|
|
57569
57721
|
return cache;
|
|
57570
57722
|
const p = join15(INTEL2, "frameworks.json");
|
|
57571
|
-
if (!
|
|
57723
|
+
if (!existsSync9(p))
|
|
57572
57724
|
return null;
|
|
57573
57725
|
try {
|
|
57574
57726
|
cache = JSON.parse(readFileSync16(p, "utf8"));
|
|
@@ -58253,7 +58405,7 @@ function submissionGate(input) {
|
|
|
58253
58405
|
// src/git-history.ts
|
|
58254
58406
|
init_complex_bugs();
|
|
58255
58407
|
import { execFileSync as execFileSync4 } from "node:child_process";
|
|
58256
|
-
import { existsSync as
|
|
58408
|
+
import { existsSync as existsSync11 } from "node:fs";
|
|
58257
58409
|
import { join as join17 } from "node:path";
|
|
58258
58410
|
function parseDeletions(output) {
|
|
58259
58411
|
const out = [];
|
|
@@ -58283,7 +58435,7 @@ function blobBeforeDeletion(root, commit, path) {
|
|
|
58283
58435
|
function scanGitHistory(root, opts) {
|
|
58284
58436
|
const limit = opts?.limit ?? 30;
|
|
58285
58437
|
const findings = [];
|
|
58286
|
-
if (!
|
|
58438
|
+
if (!existsSync11(join17(root, ".git"))) {
|
|
58287
58439
|
return { root, is_git_repo: false, total: 0, findings: [], error: "not a git repository (no .git dir)" };
|
|
58288
58440
|
}
|
|
58289
58441
|
if (opts?.secretPattern) {
|
|
@@ -58816,21 +58968,21 @@ function runBenchmark() {
|
|
|
58816
58968
|
}
|
|
58817
58969
|
|
|
58818
58970
|
// src/obligations.ts
|
|
58819
|
-
import { readFileSync as readFileSync22, appendFileSync as appendFileSync4, mkdirSync as mkdirSync8, existsSync as
|
|
58971
|
+
import { readFileSync as readFileSync22, appendFileSync as appendFileSync4, mkdirSync as mkdirSync8, existsSync as existsSync12, writeFileSync as writeFileSync7 } from "node:fs";
|
|
58820
58972
|
import { join as join22 } from "node:path";
|
|
58821
58973
|
import { createHash as createHash6 } from "node:crypto";
|
|
58822
58974
|
import { homedir as homedir9 } from "node:os";
|
|
58823
58975
|
var HOME_DIR4 = process.env.BLITZSTRIKE_HOME ?? join22(homedir9(), ".blitzstrike");
|
|
58824
58976
|
var OBLIGATION_PATH = join22(HOME_DIR4, "obligations.jsonl");
|
|
58825
58977
|
function ensureDir3() {
|
|
58826
|
-
if (!
|
|
58978
|
+
if (!existsSync12(HOME_DIR4))
|
|
58827
58979
|
mkdirSync8(HOME_DIR4, { recursive: true });
|
|
58828
58980
|
}
|
|
58829
58981
|
function shortId2(claim) {
|
|
58830
58982
|
return `obl-${createHash6("sha256").update(`${claim}\x00${Date.now()}`).digest("hex").slice(0, 12)}`;
|
|
58831
58983
|
}
|
|
58832
58984
|
function loadObligations() {
|
|
58833
|
-
if (!
|
|
58985
|
+
if (!existsSync12(OBLIGATION_PATH))
|
|
58834
58986
|
return [];
|
|
58835
58987
|
try {
|
|
58836
58988
|
const out = [];
|
|
@@ -59833,7 +59985,7 @@ function analyzeJwt(token, opts = {}) {
|
|
|
59833
59985
|
}
|
|
59834
59986
|
|
|
59835
59987
|
// src/enterprise-benchmark.ts
|
|
59836
|
-
import { existsSync as
|
|
59988
|
+
import { existsSync as existsSync13, readFileSync as readFileSync25, readdirSync as readdirSync6, statSync as statSync3 } from "node:fs";
|
|
59837
59989
|
import { join as join23, resolve } from "node:path";
|
|
59838
59990
|
init_complex_bugs();
|
|
59839
59991
|
var ROOT6 = resolve(process.cwd(), "bench", "enterprise");
|
|
@@ -59894,7 +60046,7 @@ function detectFixture(dir) {
|
|
|
59894
60046
|
function runEnterpriseBenchmark() {
|
|
59895
60047
|
const fixtures = [];
|
|
59896
60048
|
for (const fx of ENTERPRISE_FIXTURES) {
|
|
59897
|
-
if (!
|
|
60049
|
+
if (!existsSync13(fx.dir)) {
|
|
59898
60050
|
fixtures.push({ id: fx.id, available: false, detected: 0, expected: fx.expected_vulns, recall: 0 });
|
|
59899
60051
|
continue;
|
|
59900
60052
|
}
|
|
@@ -60318,16 +60470,19 @@ function createServer() {
|
|
|
60318
60470
|
});
|
|
60319
60471
|
server.registerTool("crack_hash", {
|
|
60320
60472
|
title: "Identify + crack a dumped credential hash",
|
|
60321
|
-
description: "CREDENTIAL: when you dump password hashes, EXECUTE this instead of leaving 'crack the hashes' as a recommendation. Identifies the hash type (bcrypt/md5/sha1/sha256/sha512/ntlm) and immediately tries a built-in common-password list offline, then returns the exact hashcat/john command for the full crack. Pass one hash string or a list.",
|
|
60473
|
+
description: "CREDENTIAL: when you dump password hashes, EXECUTE this instead of leaving 'crack the hashes' as a recommendation. Identifies the hash type (bcrypt/md5/sha1/sha256/sha512/ntlm) and immediately tries a built-in common-password list offline, then streams any supplied wordlist (and autoloads seclists/rockyou when present), then returns the exact hashcat/john command for the full crack. Pass one hash string or a list.",
|
|
60322
60474
|
inputSchema: {
|
|
60323
60475
|
hash: string2().describe("The hash string (or a list of hashes, one per line)"),
|
|
60324
|
-
extra: array(string2()).optional().describe("Extra candidate passwords to try (e.g. usernames, target-specific words)")
|
|
60476
|
+
extra: array(string2()).optional().describe("Extra candidate passwords to try (e.g. usernames, target-specific words)"),
|
|
60477
|
+
wordlist: string2().optional().describe("Optional wordlist file path(s) to stream (comma-separated). Autoloads rockyou/seclists if present."),
|
|
60478
|
+
maxCandidates: number2().int().optional().describe("Max wordlist candidates to stream (default 5,000,000)")
|
|
60325
60479
|
}
|
|
60326
|
-
}, async ({ hash, extra }) => {
|
|
60480
|
+
}, async ({ hash, extra, wordlist, maxCandidates }) => {
|
|
60327
60481
|
const hashes = hash.split(/\r?\n/).map((h) => h.trim()).filter(Boolean).slice(0, 50);
|
|
60482
|
+
const wl = wordlist ? wordlist.split(",").map((s) => s.trim()).filter(Boolean) : undefined;
|
|
60328
60483
|
const results = [];
|
|
60329
60484
|
for (const h of hashes) {
|
|
60330
|
-
results.push({ hash: h.slice(0, 24) + (h.length > 24 ? "…" : ""), ...await crackHash(h, extra ?? []) });
|
|
60485
|
+
results.push({ hash: h.slice(0, 24) + (h.length > 24 ? "…" : ""), ...await crackHash(h, extra ?? [], { wordlist: wl, maxCandidates }) });
|
|
60331
60486
|
}
|
|
60332
60487
|
return { content: [{ type: "text", text: JSON.stringify({ hashes_scanned: results.length, results }) }] };
|
|
60333
60488
|
});
|
|
@@ -61934,14 +62089,14 @@ async function serve() {
|
|
|
61934
62089
|
|
|
61935
62090
|
// src/index.ts
|
|
61936
62091
|
init_cli();
|
|
61937
|
-
import { readFileSync as readFileSync31, existsSync as
|
|
62092
|
+
import { readFileSync as readFileSync31, existsSync as existsSync16 } from "node:fs";
|
|
61938
62093
|
import { join as join28 } from "node:path";
|
|
61939
62094
|
import { fileURLToPath as fileURLToPath17 } from "node:url";
|
|
61940
62095
|
var ROOT11 = join28(fileURLToPath17(new URL(".", import.meta.url)), "..");
|
|
61941
62096
|
function readVersion() {
|
|
61942
62097
|
try {
|
|
61943
62098
|
const p = join28(ROOT11, "package.json");
|
|
61944
|
-
if (
|
|
62099
|
+
if (existsSync16(p))
|
|
61945
62100
|
return JSON.parse(readFileSync31(p, "utf8")).version ?? "1.0.0";
|
|
61946
62101
|
} catch {}
|
|
61947
62102
|
return "1.0.0";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "blitzstrike",
|
|
3
|
-
"version": "2.4.
|
|
3
|
+
"version": "2.4.74",
|
|
4
4
|
"description": "Blitz Strike — a universal MCP security-audit toolbelt. BLITZ sweeps the attack surface, EAGLE-EYE traces source-to-sink, STRIKE verifies live. 57 attack chains, 130-tool catalog, intelligence data layer. One server, every agent.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|