@bengabay94/mrzero 0.1.0-alpha.1
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/LICENSE +21 -0
- package/README.md +246 -0
- package/agents/MrZeroEnvBuilder.md +155 -0
- package/agents/MrZeroExploitDeveloper.md +263 -0
- package/agents/MrZeroMapperOS.md +179 -0
- package/agents/MrZeroVulnHunterOS.md +172 -0
- package/dist/commands/check.d.ts +6 -0
- package/dist/commands/check.d.ts.map +1 -0
- package/dist/commands/check.js +205 -0
- package/dist/commands/check.js.map +1 -0
- package/dist/commands/install.d.ts +10 -0
- package/dist/commands/install.d.ts.map +1 -0
- package/dist/commands/install.js +256 -0
- package/dist/commands/install.js.map +1 -0
- package/dist/commands/uninstall.d.ts +8 -0
- package/dist/commands/uninstall.d.ts.map +1 -0
- package/dist/commands/uninstall.js +123 -0
- package/dist/commands/uninstall.js.map +1 -0
- package/dist/config/agents.d.ts +20 -0
- package/dist/config/agents.d.ts.map +1 -0
- package/dist/config/agents.js +88 -0
- package/dist/config/agents.js.map +1 -0
- package/dist/config/mcp-servers.d.ts +16 -0
- package/dist/config/mcp-servers.d.ts.map +1 -0
- package/dist/config/mcp-servers.js +72 -0
- package/dist/config/mcp-servers.js.map +1 -0
- package/dist/config/tools.d.ts +15 -0
- package/dist/config/tools.d.ts.map +1 -0
- package/dist/config/tools.js +130 -0
- package/dist/config/tools.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +35 -0
- package/dist/index.js.map +1 -0
- package/dist/installer/detector.d.ts +52 -0
- package/dist/installer/detector.d.ts.map +1 -0
- package/dist/installer/detector.js +381 -0
- package/dist/installer/detector.js.map +1 -0
- package/dist/installer/docker.d.ts +8 -0
- package/dist/installer/docker.d.ts.map +1 -0
- package/dist/installer/docker.js +197 -0
- package/dist/installer/docker.js.map +1 -0
- package/dist/installer/mcp.d.ts +11 -0
- package/dist/installer/mcp.d.ts.map +1 -0
- package/dist/installer/mcp.js +317 -0
- package/dist/installer/mcp.js.map +1 -0
- package/dist/installer/platforms.d.ts +7 -0
- package/dist/installer/platforms.d.ts.map +1 -0
- package/dist/installer/platforms.js +254 -0
- package/dist/installer/platforms.js.map +1 -0
- package/dist/installer/python.d.ts +5 -0
- package/dist/installer/python.d.ts.map +1 -0
- package/dist/installer/python.js +65 -0
- package/dist/installer/python.js.map +1 -0
- package/dist/installer/ruby.d.ts +5 -0
- package/dist/installer/ruby.d.ts.map +1 -0
- package/dist/installer/ruby.js +80 -0
- package/dist/installer/ruby.js.map +1 -0
- package/dist/utils/logger.d.ts +16 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/logger.js +46 -0
- package/dist/utils/logger.js.map +1 -0
- package/dist/utils/platform.d.ts +18 -0
- package/dist/utils/platform.d.ts.map +1 -0
- package/dist/utils/platform.js +110 -0
- package/dist/utils/platform.js.map +1 -0
- package/dist/utils/shell.d.ts +14 -0
- package/dist/utils/shell.d.ts.map +1 -0
- package/dist/utils/shell.js +45 -0
- package/dist/utils/shell.js.map +1 -0
- package/docker/Dockerfile +118 -0
- package/package.json +56 -0
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export interface ToolConfig {
|
|
2
|
+
name: string;
|
|
3
|
+
displayName: string;
|
|
4
|
+
description: string;
|
|
5
|
+
installMethod: 'docker' | 'uv' | 'gem' | 'apt' | 'manual';
|
|
6
|
+
checkCommand?: string;
|
|
7
|
+
installCommand?: string;
|
|
8
|
+
wrapperName?: string;
|
|
9
|
+
}
|
|
10
|
+
export declare const DOCKER_TOOLS: Record<string, ToolConfig>;
|
|
11
|
+
export declare const PYTHON_TOOLS: Record<string, ToolConfig>;
|
|
12
|
+
export declare const RUBY_TOOLS: Record<string, ToolConfig>;
|
|
13
|
+
export declare const SYSTEM_TOOLS: Record<string, ToolConfig>;
|
|
14
|
+
export declare const DOCKER_IMAGE = "ghcr.io/bengabay1994/mrzero-tools:latest";
|
|
15
|
+
//# sourceMappingURL=tools.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tools.d.ts","sourceRoot":"","sources":["../../src/config/tools.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,aAAa,EAAE,QAAQ,GAAG,IAAI,GAAG,KAAK,GAAG,KAAK,GAAG,QAAQ,CAAC;IAC1D,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,eAAO,MAAM,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,UAAU,CAuEnD,CAAC;AAEF,eAAO,MAAM,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,UAAU,CAiBnD,CAAC;AAEF,eAAO,MAAM,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,UAAU,CASjD,CAAC;AAEF,eAAO,MAAM,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,UAAU,CAwBnD,CAAC;AAEF,eAAO,MAAM,YAAY,6CAA6C,CAAC"}
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.DOCKER_IMAGE = exports.SYSTEM_TOOLS = exports.RUBY_TOOLS = exports.PYTHON_TOOLS = exports.DOCKER_TOOLS = void 0;
|
|
4
|
+
exports.DOCKER_TOOLS = {
|
|
5
|
+
opengrep: {
|
|
6
|
+
name: 'opengrep',
|
|
7
|
+
displayName: 'Opengrep',
|
|
8
|
+
description: 'Pattern-based code analysis for vulnerability detection',
|
|
9
|
+
installMethod: 'docker',
|
|
10
|
+
wrapperName: 'opengrep',
|
|
11
|
+
},
|
|
12
|
+
gitleaks: {
|
|
13
|
+
name: 'gitleaks',
|
|
14
|
+
displayName: 'Gitleaks',
|
|
15
|
+
description: 'Scanning for hardcoded secrets and sensitive data',
|
|
16
|
+
installMethod: 'docker',
|
|
17
|
+
wrapperName: 'gitleaks',
|
|
18
|
+
},
|
|
19
|
+
codeql: {
|
|
20
|
+
name: 'codeql',
|
|
21
|
+
displayName: 'CodeQL',
|
|
22
|
+
description: 'Deep semantic code analysis and taint tracking',
|
|
23
|
+
installMethod: 'docker',
|
|
24
|
+
wrapperName: 'codeql',
|
|
25
|
+
},
|
|
26
|
+
joern: {
|
|
27
|
+
name: 'joern',
|
|
28
|
+
displayName: 'Joern',
|
|
29
|
+
description: 'Code property graph analysis for security flaws',
|
|
30
|
+
installMethod: 'docker',
|
|
31
|
+
wrapperName: 'joern',
|
|
32
|
+
},
|
|
33
|
+
infer: {
|
|
34
|
+
name: 'infer',
|
|
35
|
+
displayName: 'Infer',
|
|
36
|
+
description: 'Static analysis for memory safety issues',
|
|
37
|
+
installMethod: 'docker',
|
|
38
|
+
wrapperName: 'infer',
|
|
39
|
+
},
|
|
40
|
+
bearer: {
|
|
41
|
+
name: 'bearer',
|
|
42
|
+
displayName: 'Bearer',
|
|
43
|
+
description: 'Security and privacy scanning for sensitive data flows',
|
|
44
|
+
installMethod: 'docker',
|
|
45
|
+
wrapperName: 'bearer',
|
|
46
|
+
},
|
|
47
|
+
slither: {
|
|
48
|
+
name: 'slither',
|
|
49
|
+
displayName: 'Slither',
|
|
50
|
+
description: 'Solidity smart contract analysis',
|
|
51
|
+
installMethod: 'docker',
|
|
52
|
+
wrapperName: 'slither',
|
|
53
|
+
},
|
|
54
|
+
trivy: {
|
|
55
|
+
name: 'trivy',
|
|
56
|
+
displayName: 'Trivy',
|
|
57
|
+
description: 'Dependency and container vulnerability scanning',
|
|
58
|
+
installMethod: 'docker',
|
|
59
|
+
wrapperName: 'trivy',
|
|
60
|
+
},
|
|
61
|
+
linguist: {
|
|
62
|
+
name: 'linguist',
|
|
63
|
+
displayName: 'Linguist',
|
|
64
|
+
description: 'Language detection and codebase composition analysis',
|
|
65
|
+
installMethod: 'docker',
|
|
66
|
+
wrapperName: 'linguist',
|
|
67
|
+
},
|
|
68
|
+
'tree-sitter': {
|
|
69
|
+
name: 'tree-sitter',
|
|
70
|
+
displayName: 'Tree-sitter',
|
|
71
|
+
description: 'Syntax tree parsing for code understanding',
|
|
72
|
+
installMethod: 'docker',
|
|
73
|
+
wrapperName: 'tree-sitter',
|
|
74
|
+
},
|
|
75
|
+
};
|
|
76
|
+
exports.PYTHON_TOOLS = {
|
|
77
|
+
pwntools: {
|
|
78
|
+
name: 'pwntools',
|
|
79
|
+
displayName: 'pwntools',
|
|
80
|
+
description: 'CTF framework and exploit development library',
|
|
81
|
+
installMethod: 'uv',
|
|
82
|
+
checkCommand: 'python3 -c "import pwn"',
|
|
83
|
+
installCommand: 'uv pip install pwntools',
|
|
84
|
+
},
|
|
85
|
+
ropper: {
|
|
86
|
+
name: 'ropper',
|
|
87
|
+
displayName: 'Ropper',
|
|
88
|
+
description: 'ROP gadget finder and binary analysis',
|
|
89
|
+
installMethod: 'uv',
|
|
90
|
+
checkCommand: 'ropper --version',
|
|
91
|
+
installCommand: 'uv pip install ropper',
|
|
92
|
+
},
|
|
93
|
+
};
|
|
94
|
+
exports.RUBY_TOOLS = {
|
|
95
|
+
one_gadget: {
|
|
96
|
+
name: 'one_gadget',
|
|
97
|
+
displayName: 'one_gadget',
|
|
98
|
+
description: 'Find one-shot RCE gadgets in libc',
|
|
99
|
+
installMethod: 'gem',
|
|
100
|
+
checkCommand: 'one_gadget --version',
|
|
101
|
+
installCommand: 'gem install one_gadget',
|
|
102
|
+
},
|
|
103
|
+
};
|
|
104
|
+
exports.SYSTEM_TOOLS = {
|
|
105
|
+
docker: {
|
|
106
|
+
name: 'docker',
|
|
107
|
+
displayName: 'Docker',
|
|
108
|
+
description: 'Container runtime for isolated tools',
|
|
109
|
+
installMethod: 'manual',
|
|
110
|
+
checkCommand: 'docker --version',
|
|
111
|
+
},
|
|
112
|
+
gdb: {
|
|
113
|
+
name: 'gdb',
|
|
114
|
+
displayName: 'GDB',
|
|
115
|
+
description: 'GNU Debugger',
|
|
116
|
+
installMethod: 'apt',
|
|
117
|
+
checkCommand: 'gdb --version',
|
|
118
|
+
installCommand: 'sudo apt-get install -y gdb',
|
|
119
|
+
},
|
|
120
|
+
checksec: {
|
|
121
|
+
name: 'checksec',
|
|
122
|
+
displayName: 'checksec',
|
|
123
|
+
description: 'Check binary security features',
|
|
124
|
+
installMethod: 'apt',
|
|
125
|
+
checkCommand: 'checksec --version',
|
|
126
|
+
installCommand: 'sudo apt-get install -y checksec',
|
|
127
|
+
},
|
|
128
|
+
};
|
|
129
|
+
exports.DOCKER_IMAGE = 'ghcr.io/bengabay1994/mrzero-tools:latest';
|
|
130
|
+
//# sourceMappingURL=tools.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tools.js","sourceRoot":"","sources":["../../src/config/tools.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":""}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";
|
|
3
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
+
const commander_1 = require("commander");
|
|
5
|
+
const install_js_1 = require("./commands/install.js");
|
|
6
|
+
const check_js_1 = require("./commands/check.js");
|
|
7
|
+
const uninstall_js_1 = require("./commands/uninstall.js");
|
|
8
|
+
const program = new commander_1.Command();
|
|
9
|
+
program
|
|
10
|
+
.name('mrzero')
|
|
11
|
+
.description('AI-powered security research agents for vulnerability hunting and exploit development')
|
|
12
|
+
.version('1.0.0');
|
|
13
|
+
program
|
|
14
|
+
.command('install')
|
|
15
|
+
.description('Install MrZero agents and tools')
|
|
16
|
+
.option('-a, --agent <agents...>', 'Specific agents to install tools for')
|
|
17
|
+
.option('-p, --platform <platforms...>', 'Target platforms (claude-code, opencode)')
|
|
18
|
+
.option('--skip-docker', 'Skip Docker image pull/build')
|
|
19
|
+
.option('--skip-mcp', 'Skip MCP server installation')
|
|
20
|
+
.option('-y, --yes', 'Skip confirmation prompts')
|
|
21
|
+
.action(install_js_1.installCommand);
|
|
22
|
+
program
|
|
23
|
+
.command('check')
|
|
24
|
+
.description('Check installation status of MrZero tools')
|
|
25
|
+
.option('-v, --verbose', 'Show detailed information')
|
|
26
|
+
.action(check_js_1.checkCommand);
|
|
27
|
+
program
|
|
28
|
+
.command('uninstall')
|
|
29
|
+
.description('Uninstall MrZero tools and configurations')
|
|
30
|
+
.option('--keep-agents', 'Keep agent files in platform configs')
|
|
31
|
+
.option('--keep-docker', 'Keep Docker image')
|
|
32
|
+
.option('-y, --yes', 'Skip confirmation prompts')
|
|
33
|
+
.action(uninstall_js_1.uninstallCommand);
|
|
34
|
+
program.parse();
|
|
35
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AAEA,yCAAoC;AACpC,sDAAuD;AACvD,kDAAmD;AACnD,0DAA2D;AAE3D,MAAM,OAAO,GAAG,IAAI,mBAAO,EAAE,CAAC;AAE9B,OAAO;KACJ,IAAI,CAAC,QAAQ,CAAC;KACd,WAAW,CAAC,uFAAuF,CAAC;KACpG,OAAO,CAAC,OAAO,CAAC,CAAC;AAEpB,OAAO;KACJ,OAAO,CAAC,SAAS,CAAC;KAClB,WAAW,CAAC,iCAAiC,CAAC;KAC9C,MAAM,CAAC,yBAAyB,EAAE,sCAAsC,CAAC;KACzE,MAAM,CAAC,+BAA+B,EAAE,0CAA0C,CAAC;KACnF,MAAM,CAAC,eAAe,EAAE,8BAA8B,CAAC;KACvD,MAAM,CAAC,YAAY,EAAE,8BAA8B,CAAC;KACpD,MAAM,CAAC,WAAW,EAAE,2BAA2B,CAAC;KAChD,MAAM,CAAC,2BAAc,CAAC,CAAC;AAE1B,OAAO;KACJ,OAAO,CAAC,OAAO,CAAC;KAChB,WAAW,CAAC,2CAA2C,CAAC;KACxD,MAAM,CAAC,eAAe,EAAE,2BAA2B,CAAC;KACpD,MAAM,CAAC,uBAAY,CAAC,CAAC;AAExB,OAAO;KACJ,OAAO,CAAC,WAAW,CAAC;KACpB,WAAW,CAAC,2CAA2C,CAAC;KACxD,MAAM,CAAC,eAAe,EAAE,sCAAsC,CAAC;KAC/D,MAAM,CAAC,eAAe,EAAE,mBAAmB,CAAC;KAC5C,MAAM,CAAC,WAAW,EAAE,2BAA2B,CAAC;KAChD,MAAM,CAAC,+BAAgB,CAAC,CAAC;AAE5B,OAAO,CAAC,KAAK,EAAE,CAAC"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
export interface SystemInfo {
|
|
2
|
+
os: string;
|
|
3
|
+
osVersion: string;
|
|
4
|
+
arch: string;
|
|
5
|
+
docker: {
|
|
6
|
+
installed: boolean;
|
|
7
|
+
version?: string;
|
|
8
|
+
};
|
|
9
|
+
python: {
|
|
10
|
+
installed: boolean;
|
|
11
|
+
version?: string;
|
|
12
|
+
};
|
|
13
|
+
uv: {
|
|
14
|
+
installed: boolean;
|
|
15
|
+
version?: string;
|
|
16
|
+
};
|
|
17
|
+
ruby: {
|
|
18
|
+
installed: boolean;
|
|
19
|
+
version?: string;
|
|
20
|
+
};
|
|
21
|
+
git: {
|
|
22
|
+
installed: boolean;
|
|
23
|
+
version?: string;
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
export interface ToolStatus {
|
|
27
|
+
name: string;
|
|
28
|
+
installed: boolean;
|
|
29
|
+
version?: string;
|
|
30
|
+
path?: string;
|
|
31
|
+
method?: string;
|
|
32
|
+
}
|
|
33
|
+
export declare function detectSystemInfo(): Promise<SystemInfo>;
|
|
34
|
+
export declare function detectGdb(): Promise<ToolStatus>;
|
|
35
|
+
export declare function detectPwndbg(): Promise<ToolStatus>;
|
|
36
|
+
export declare function detectGhidra(): Promise<ToolStatus>;
|
|
37
|
+
export declare function detectMetasploit(): Promise<ToolStatus>;
|
|
38
|
+
export declare function detectIdaPro(): Promise<ToolStatus>;
|
|
39
|
+
export declare function detectIdaFree(): Promise<ToolStatus>;
|
|
40
|
+
export declare function detectPythonPackage(packageName: string): Promise<ToolStatus>;
|
|
41
|
+
export declare function detectRubyGem(gemName: string): Promise<ToolStatus>;
|
|
42
|
+
export declare function detectDockerImage(imageName: string): Promise<boolean>;
|
|
43
|
+
export declare function detectWrapper(wrapperName: string): Promise<boolean>;
|
|
44
|
+
export declare function detectNativeTool(toolName: string): Promise<ToolStatus>;
|
|
45
|
+
export interface DockerToolStatus {
|
|
46
|
+
name: string;
|
|
47
|
+
wrapperInstalled: boolean;
|
|
48
|
+
nativeInstalled: boolean;
|
|
49
|
+
nativePath?: string;
|
|
50
|
+
}
|
|
51
|
+
export declare function detectDockerTool(toolName: string): Promise<DockerToolStatus>;
|
|
52
|
+
//# sourceMappingURL=detector.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"detector.d.ts","sourceRoot":"","sources":["../../src/installer/detector.ts"],"names":[],"mappings":"AAMA,MAAM,WAAW,UAAU;IACzB,EAAE,EAAE,MAAM,CAAC;IACX,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE;QAAE,SAAS,EAAE,OAAO,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IACjD,MAAM,EAAE;QAAE,SAAS,EAAE,OAAO,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IACjD,EAAE,EAAE;QAAE,SAAS,EAAE,OAAO,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAC7C,IAAI,EAAE;QAAE,SAAS,EAAE,OAAO,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAC/C,GAAG,EAAE;QAAE,SAAS,EAAE,OAAO,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;CAC/C;AAED,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,OAAO,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,wBAAsB,gBAAgB,IAAI,OAAO,CAAC,UAAU,CAAC,CAqB5D;AA4DD,wBAAsB,SAAS,IAAI,OAAO,CAAC,UAAU,CAAC,CAOrD;AAGD,wBAAsB,YAAY,IAAI,OAAO,CAAC,UAAU,CAAC,CA6CxD;AAGD,wBAAsB,YAAY,IAAI,OAAO,CAAC,UAAU,CAAC,CAmCxD;AAGD,wBAAsB,gBAAgB,IAAI,OAAO,CAAC,UAAU,CAAC,CAqB5D;AAGD,wBAAsB,YAAY,IAAI,OAAO,CAAC,UAAU,CAAC,CAsDxD;AAGD,wBAAsB,aAAa,IAAI,OAAO,CAAC,UAAU,CAAC,CA8BzD;AAGD,wBAAsB,mBAAmB,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC,CAMlF;AAGD,wBAAsB,aAAa,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC,CAMxE;AAGD,wBAAsB,iBAAiB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAG3E;AAGD,wBAAsB,aAAa,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAqBzE;AAGD,wBAAsB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC,CAY5E;AAGD,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,gBAAgB,EAAE,OAAO,CAAC;IAC1B,eAAe,EAAE,OAAO,CAAC;IACzB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,wBAAsB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAUlF"}
|
|
@@ -0,0 +1,381 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.detectSystemInfo = detectSystemInfo;
|
|
37
|
+
exports.detectGdb = detectGdb;
|
|
38
|
+
exports.detectPwndbg = detectPwndbg;
|
|
39
|
+
exports.detectGhidra = detectGhidra;
|
|
40
|
+
exports.detectMetasploit = detectMetasploit;
|
|
41
|
+
exports.detectIdaPro = detectIdaPro;
|
|
42
|
+
exports.detectIdaFree = detectIdaFree;
|
|
43
|
+
exports.detectPythonPackage = detectPythonPackage;
|
|
44
|
+
exports.detectRubyGem = detectRubyGem;
|
|
45
|
+
exports.detectDockerImage = detectDockerImage;
|
|
46
|
+
exports.detectWrapper = detectWrapper;
|
|
47
|
+
exports.detectNativeTool = detectNativeTool;
|
|
48
|
+
exports.detectDockerTool = detectDockerTool;
|
|
49
|
+
const fs = __importStar(require("fs"));
|
|
50
|
+
const path = __importStar(require("path"));
|
|
51
|
+
const os = __importStar(require("os"));
|
|
52
|
+
const shell_js_1 = require("../utils/shell.js");
|
|
53
|
+
const platform_js_1 = require("../utils/platform.js");
|
|
54
|
+
async function detectSystemInfo() {
|
|
55
|
+
const [docker, python, uv, ruby, git] = await Promise.all([
|
|
56
|
+
detectDocker(),
|
|
57
|
+
detectPython(),
|
|
58
|
+
detectUv(),
|
|
59
|
+
detectRuby(),
|
|
60
|
+
detectGit(),
|
|
61
|
+
]);
|
|
62
|
+
const distro = await detectLinuxDistro();
|
|
63
|
+
return {
|
|
64
|
+
os: os.platform(),
|
|
65
|
+
osVersion: distro || os.release(),
|
|
66
|
+
arch: os.arch(),
|
|
67
|
+
docker,
|
|
68
|
+
python,
|
|
69
|
+
uv,
|
|
70
|
+
ruby,
|
|
71
|
+
git,
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
async function detectDocker() {
|
|
75
|
+
const result = await (0, shell_js_1.exec)('docker --version');
|
|
76
|
+
if (result.code === 0) {
|
|
77
|
+
const match = result.stdout.match(/Docker version ([\d.]+)/);
|
|
78
|
+
return { installed: true, version: match?.[1] };
|
|
79
|
+
}
|
|
80
|
+
return { installed: false };
|
|
81
|
+
}
|
|
82
|
+
async function detectPython() {
|
|
83
|
+
const result = await (0, shell_js_1.exec)('python3 --version');
|
|
84
|
+
if (result.code === 0) {
|
|
85
|
+
const match = result.stdout.match(/Python ([\d.]+)/);
|
|
86
|
+
return { installed: true, version: match?.[1] };
|
|
87
|
+
}
|
|
88
|
+
return { installed: false };
|
|
89
|
+
}
|
|
90
|
+
async function detectUv() {
|
|
91
|
+
const result = await (0, shell_js_1.exec)('uv --version');
|
|
92
|
+
if (result.code === 0) {
|
|
93
|
+
const match = result.stdout.match(/uv ([\d.]+)/);
|
|
94
|
+
return { installed: true, version: match?.[1] };
|
|
95
|
+
}
|
|
96
|
+
return { installed: false };
|
|
97
|
+
}
|
|
98
|
+
async function detectRuby() {
|
|
99
|
+
const result = await (0, shell_js_1.exec)('ruby --version');
|
|
100
|
+
if (result.code === 0) {
|
|
101
|
+
const match = result.stdout.match(/ruby ([\d.]+)/);
|
|
102
|
+
return { installed: true, version: match?.[1] };
|
|
103
|
+
}
|
|
104
|
+
return { installed: false };
|
|
105
|
+
}
|
|
106
|
+
async function detectGit() {
|
|
107
|
+
const result = await (0, shell_js_1.exec)('git --version');
|
|
108
|
+
if (result.code === 0) {
|
|
109
|
+
const match = result.stdout.match(/git version ([\d.]+)/);
|
|
110
|
+
return { installed: true, version: match?.[1] };
|
|
111
|
+
}
|
|
112
|
+
return { installed: false };
|
|
113
|
+
}
|
|
114
|
+
async function detectLinuxDistro() {
|
|
115
|
+
try {
|
|
116
|
+
const releaseFile = '/etc/os-release';
|
|
117
|
+
if (fs.existsSync(releaseFile)) {
|
|
118
|
+
const content = fs.readFileSync(releaseFile, 'utf-8');
|
|
119
|
+
const nameMatch = content.match(/^PRETTY_NAME="?([^"\n]+)"?/m);
|
|
120
|
+
return nameMatch?.[1] || null;
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
catch { }
|
|
124
|
+
return null;
|
|
125
|
+
}
|
|
126
|
+
// GDB detection
|
|
127
|
+
async function detectGdb() {
|
|
128
|
+
const result = await (0, shell_js_1.exec)('gdb --version');
|
|
129
|
+
if (result.code === 0) {
|
|
130
|
+
const match = result.stdout.match(/GNU gdb[^\d]*([\d.]+)/);
|
|
131
|
+
return { name: 'gdb', installed: true, version: match?.[1] };
|
|
132
|
+
}
|
|
133
|
+
return { name: 'gdb', installed: false };
|
|
134
|
+
}
|
|
135
|
+
// pwndbg detection - multiple methods
|
|
136
|
+
async function detectPwndbg() {
|
|
137
|
+
// Method 1: Check for standalone pwndbg binary
|
|
138
|
+
if (await (0, shell_js_1.commandExists)('pwndbg')) {
|
|
139
|
+
const result = await (0, shell_js_1.exec)('which pwndbg');
|
|
140
|
+
return { name: 'pwndbg', installed: true, method: 'binary', path: result.stdout.trim() };
|
|
141
|
+
}
|
|
142
|
+
// Method 2: Check .gdbinit for pwndbg source line
|
|
143
|
+
const gdbinit = path.join((0, platform_js_1.getHomeDir)(), '.gdbinit');
|
|
144
|
+
if (fs.existsSync(gdbinit)) {
|
|
145
|
+
const content = fs.readFileSync(gdbinit, 'utf-8');
|
|
146
|
+
const match = content.match(/source\s+(.+pwndbg[^\s]*gdbinit\.py)/i);
|
|
147
|
+
if (match) {
|
|
148
|
+
return { name: 'pwndbg', installed: true, method: 'gdbinit-source', path: match[1] };
|
|
149
|
+
}
|
|
150
|
+
if (content.toLowerCase().includes('pwndbg')) {
|
|
151
|
+
return { name: 'pwndbg', installed: true, method: 'gdbinit-reference' };
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
// Method 3: Run gdb and check if pwndbg banner appears
|
|
155
|
+
try {
|
|
156
|
+
const result = await (0, shell_js_1.exec)('echo "quit" | gdb -q 2>&1', { timeout: 5000 });
|
|
157
|
+
const output = result.stdout + result.stderr;
|
|
158
|
+
if (output.toLowerCase().includes('pwndbg')) {
|
|
159
|
+
return { name: 'pwndbg', installed: true, method: 'gdb-plugin' };
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
catch { }
|
|
163
|
+
// Method 4: Check common installation paths
|
|
164
|
+
const commonPaths = [
|
|
165
|
+
path.join((0, platform_js_1.getHomeDir)(), '.pwndbg', 'gdbinit.py'),
|
|
166
|
+
path.join((0, platform_js_1.getHomeDir)(), 'pwndbg', 'gdbinit.py'),
|
|
167
|
+
'/opt/pwndbg/gdbinit.py',
|
|
168
|
+
path.join((0, platform_js_1.getHomeDir)(), 'Desktop', 'repos', 'pwndbg', 'gdbinit.py'),
|
|
169
|
+
path.join((0, platform_js_1.getHomeDir)(), 'tools', 'pwndbg', 'gdbinit.py'),
|
|
170
|
+
];
|
|
171
|
+
for (const p of commonPaths) {
|
|
172
|
+
if (fs.existsSync(p)) {
|
|
173
|
+
return { name: 'pwndbg', installed: true, method: 'common-path', path: p };
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
return { name: 'pwndbg', installed: false };
|
|
177
|
+
}
|
|
178
|
+
// Ghidra detection
|
|
179
|
+
async function detectGhidra() {
|
|
180
|
+
// Check for ghidraRun in PATH
|
|
181
|
+
if (await (0, shell_js_1.commandExists)('ghidraRun')) {
|
|
182
|
+
const result = await (0, shell_js_1.exec)('which ghidraRun');
|
|
183
|
+
return { name: 'ghidra', installed: true, path: result.stdout.trim() };
|
|
184
|
+
}
|
|
185
|
+
// Check common installation paths
|
|
186
|
+
const commonPaths = [
|
|
187
|
+
'/opt/ghidra',
|
|
188
|
+
'/opt/ghidra_*',
|
|
189
|
+
path.join((0, platform_js_1.getHomeDir)(), 'ghidra'),
|
|
190
|
+
path.join((0, platform_js_1.getHomeDir)(), 'ghidra_*'),
|
|
191
|
+
'/usr/local/ghidra',
|
|
192
|
+
'/usr/share/ghidra',
|
|
193
|
+
];
|
|
194
|
+
for (const pattern of commonPaths) {
|
|
195
|
+
if (pattern.includes('*')) {
|
|
196
|
+
// Glob pattern
|
|
197
|
+
const dir = path.dirname(pattern);
|
|
198
|
+
const base = path.basename(pattern).replace('*', '');
|
|
199
|
+
if (fs.existsSync(dir)) {
|
|
200
|
+
const entries = fs.readdirSync(dir);
|
|
201
|
+
const match = entries.find((e) => e.startsWith(base));
|
|
202
|
+
if (match) {
|
|
203
|
+
return { name: 'ghidra', installed: true, path: path.join(dir, match) };
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
else if (fs.existsSync(pattern)) {
|
|
208
|
+
return { name: 'ghidra', installed: true, path: pattern };
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
return { name: 'ghidra', installed: false };
|
|
212
|
+
}
|
|
213
|
+
// Metasploit detection
|
|
214
|
+
async function detectMetasploit() {
|
|
215
|
+
if (await (0, shell_js_1.commandExists)('msfconsole')) {
|
|
216
|
+
const result = await (0, shell_js_1.exec)('msfconsole --version 2>/dev/null || echo ""');
|
|
217
|
+
const match = result.stdout.match(/Framework Version: ([\d.]+)/);
|
|
218
|
+
return { name: 'metasploit', installed: true, version: match?.[1] };
|
|
219
|
+
}
|
|
220
|
+
// Check common paths
|
|
221
|
+
const commonPaths = [
|
|
222
|
+
'/opt/metasploit-framework',
|
|
223
|
+
'/usr/share/metasploit-framework',
|
|
224
|
+
path.join((0, platform_js_1.getHomeDir)(), 'metasploit-framework'),
|
|
225
|
+
];
|
|
226
|
+
for (const p of commonPaths) {
|
|
227
|
+
if (fs.existsSync(p)) {
|
|
228
|
+
return { name: 'metasploit', installed: true, path: p };
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
return { name: 'metasploit', installed: false };
|
|
232
|
+
}
|
|
233
|
+
// IDA Pro detection - distinguishes between Pro and Free versions
|
|
234
|
+
async function detectIdaPro() {
|
|
235
|
+
// IDA Pro has idat64 (text mode batch processing) which IDA Free does NOT have
|
|
236
|
+
// This is the key differentiator between Pro and Free
|
|
237
|
+
if (await (0, shell_js_1.commandExists)('idat64')) {
|
|
238
|
+
const result = await (0, shell_js_1.exec)('which idat64');
|
|
239
|
+
return { name: 'ida-pro', installed: true, method: 'pro', path: result.stdout.trim() };
|
|
240
|
+
}
|
|
241
|
+
// Check common installation paths for IDA Pro specific indicators
|
|
242
|
+
const proPaths = [
|
|
243
|
+
'/opt/idapro',
|
|
244
|
+
'/opt/ida-pro',
|
|
245
|
+
path.join((0, platform_js_1.getHomeDir)(), 'idapro'),
|
|
246
|
+
path.join((0, platform_js_1.getHomeDir)(), 'ida-pro'),
|
|
247
|
+
];
|
|
248
|
+
for (const p of proPaths) {
|
|
249
|
+
if (fs.existsSync(p)) {
|
|
250
|
+
// Check if idat64 exists in this directory (Pro indicator)
|
|
251
|
+
const idat64Path = path.join(p, 'idat64');
|
|
252
|
+
if (fs.existsSync(idat64Path)) {
|
|
253
|
+
return { name: 'ida-pro', installed: true, method: 'pro', path: p };
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
// Check for generic IDA paths but verify it's Pro version
|
|
258
|
+
const genericPaths = [
|
|
259
|
+
'/opt/ida*',
|
|
260
|
+
path.join((0, platform_js_1.getHomeDir)(), 'ida*'),
|
|
261
|
+
];
|
|
262
|
+
for (const pattern of genericPaths) {
|
|
263
|
+
const dir = path.dirname(pattern);
|
|
264
|
+
const base = path.basename(pattern).replace('*', '');
|
|
265
|
+
if (fs.existsSync(dir)) {
|
|
266
|
+
try {
|
|
267
|
+
const entries = fs.readdirSync(dir);
|
|
268
|
+
for (const entry of entries) {
|
|
269
|
+
if (entry.toLowerCase().startsWith(base.toLowerCase())) {
|
|
270
|
+
const fullPath = path.join(dir, entry);
|
|
271
|
+
// Check if idat64 exists (Pro indicator)
|
|
272
|
+
const idat64Path = path.join(fullPath, 'idat64');
|
|
273
|
+
if (fs.existsSync(idat64Path)) {
|
|
274
|
+
return { name: 'ida-pro', installed: true, method: 'pro', path: fullPath };
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
catch { }
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
// IDA Pro not found (IDA Free may be installed but we don't detect that here)
|
|
283
|
+
return { name: 'ida-pro', installed: false };
|
|
284
|
+
}
|
|
285
|
+
// IDA Free detection (separate from Pro)
|
|
286
|
+
async function detectIdaFree() {
|
|
287
|
+
// Check for ida64 binary (present in both Free and Pro, but we check this after Pro detection fails)
|
|
288
|
+
if (await (0, shell_js_1.commandExists)('ida64')) {
|
|
289
|
+
const result = await (0, shell_js_1.exec)('which ida64');
|
|
290
|
+
return { name: 'ida-free', installed: true, path: result.stdout.trim() };
|
|
291
|
+
}
|
|
292
|
+
// Check common installation paths for IDA Free
|
|
293
|
+
const freePaths = [
|
|
294
|
+
'/opt/idafree*',
|
|
295
|
+
'/opt/ida-free*',
|
|
296
|
+
path.join((0, platform_js_1.getHomeDir)(), 'idafree*'),
|
|
297
|
+
path.join((0, platform_js_1.getHomeDir)(), 'ida-free*'),
|
|
298
|
+
];
|
|
299
|
+
for (const pattern of freePaths) {
|
|
300
|
+
const dir = path.dirname(pattern);
|
|
301
|
+
const base = path.basename(pattern).replace('*', '');
|
|
302
|
+
if (fs.existsSync(dir)) {
|
|
303
|
+
try {
|
|
304
|
+
const entries = fs.readdirSync(dir);
|
|
305
|
+
const match = entries.find((e) => e.toLowerCase().startsWith(base.toLowerCase()));
|
|
306
|
+
if (match) {
|
|
307
|
+
return { name: 'ida-free', installed: true, path: path.join(dir, match) };
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
catch { }
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
return { name: 'ida-free', installed: false };
|
|
314
|
+
}
|
|
315
|
+
// Check if a Python package is installed
|
|
316
|
+
async function detectPythonPackage(packageName) {
|
|
317
|
+
const result = await (0, shell_js_1.exec)(`python3 -c "import ${packageName.replace('-', '_')}" 2>&1`);
|
|
318
|
+
if (result.code === 0) {
|
|
319
|
+
return { name: packageName, installed: true };
|
|
320
|
+
}
|
|
321
|
+
return { name: packageName, installed: false };
|
|
322
|
+
}
|
|
323
|
+
// Check if a Ruby gem is installed
|
|
324
|
+
async function detectRubyGem(gemName) {
|
|
325
|
+
const result = await (0, shell_js_1.exec)(`gem list -i ${gemName}`);
|
|
326
|
+
if (result.code === 0 && result.stdout.includes('true')) {
|
|
327
|
+
return { name: gemName, installed: true };
|
|
328
|
+
}
|
|
329
|
+
return { name: gemName, installed: false };
|
|
330
|
+
}
|
|
331
|
+
// Check if Docker image exists
|
|
332
|
+
async function detectDockerImage(imageName) {
|
|
333
|
+
const result = await (0, shell_js_1.exec)(`docker image inspect ${imageName} 2>/dev/null`);
|
|
334
|
+
return result.code === 0;
|
|
335
|
+
}
|
|
336
|
+
// Check if CLI wrapper exists in ~/.local/bin
|
|
337
|
+
async function detectWrapper(wrapperName) {
|
|
338
|
+
const wrapperPath = path.join((0, platform_js_1.getHomeDir)(), '.local', 'bin', wrapperName);
|
|
339
|
+
if (!fs.existsSync(wrapperPath)) {
|
|
340
|
+
return false;
|
|
341
|
+
}
|
|
342
|
+
// Check if it's actually our MrZero wrapper (contains our Docker image reference)
|
|
343
|
+
try {
|
|
344
|
+
const stats = fs.lstatSync(wrapperPath);
|
|
345
|
+
// If it's a symlink, it's not our wrapper
|
|
346
|
+
if (stats.isSymbolicLink()) {
|
|
347
|
+
return false;
|
|
348
|
+
}
|
|
349
|
+
// Read the file and check if it contains our Docker image marker
|
|
350
|
+
const content = fs.readFileSync(wrapperPath, 'utf-8');
|
|
351
|
+
return content.includes('mrzero') || content.includes('MRZERO');
|
|
352
|
+
}
|
|
353
|
+
catch {
|
|
354
|
+
return false;
|
|
355
|
+
}
|
|
356
|
+
}
|
|
357
|
+
// Check if a native CLI tool is installed (not wrapper, actual tool in PATH)
|
|
358
|
+
async function detectNativeTool(toolName) {
|
|
359
|
+
const result = await (0, shell_js_1.exec)(`which ${toolName} 2>/dev/null`);
|
|
360
|
+
if (result.code === 0) {
|
|
361
|
+
const toolPath = result.stdout.trim();
|
|
362
|
+
return {
|
|
363
|
+
name: toolName,
|
|
364
|
+
installed: true,
|
|
365
|
+
path: toolPath,
|
|
366
|
+
method: 'native'
|
|
367
|
+
};
|
|
368
|
+
}
|
|
369
|
+
return { name: toolName, installed: false };
|
|
370
|
+
}
|
|
371
|
+
async function detectDockerTool(toolName) {
|
|
372
|
+
const wrapperInstalled = await detectWrapper(toolName);
|
|
373
|
+
const nativeStatus = await detectNativeTool(toolName);
|
|
374
|
+
return {
|
|
375
|
+
name: toolName,
|
|
376
|
+
wrapperInstalled,
|
|
377
|
+
nativeInstalled: nativeStatus.installed,
|
|
378
|
+
nativePath: nativeStatus.installed ? nativeStatus.path : undefined,
|
|
379
|
+
};
|
|
380
|
+
}
|
|
381
|
+
//# sourceMappingURL=detector.js.map
|