@jshookmcp/jshook 0.1.5 → 0.1.6
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 +661 -661
- package/README.md +72 -40
- package/README.zh.md +77 -40
- package/dist/constants.d.ts +1 -0
- package/dist/constants.js +13 -1
- package/dist/modules/analyzer/IntelligentAnalyzer.js +19 -11
- package/dist/modules/browser/BrowserModeManager.d.ts +5 -0
- package/dist/modules/browser/BrowserModeManager.js +96 -10
- package/dist/modules/browser/CamoufoxBrowserManager.d.ts +4 -0
- package/dist/modules/browser/CamoufoxBrowserManager.js +64 -3
- package/dist/modules/browser/TabRegistry.js +3 -2
- package/dist/modules/browser/UnifiedBrowserManager.d.ts +5 -0
- package/dist/modules/browser/UnifiedBrowserManager.js +62 -9
- package/dist/modules/captcha/AICaptchaDetector.js +185 -185
- package/dist/modules/debugger/DebuggerSessionManager.d.ts +4 -0
- package/dist/modules/debugger/DebuggerSessionManager.js +29 -19
- package/dist/modules/debugger/ScriptManager.impl.class.d.ts +4 -0
- package/dist/modules/debugger/ScriptManager.impl.class.js +46 -21
- package/dist/modules/emulator/EnvironmentEmulator.js +2 -2
- package/dist/modules/monitor/NetworkMonitor.impl.d.ts +1 -0
- package/dist/modules/monitor/NetworkMonitor.impl.js +22 -15
- package/dist/modules/monitor/PerformanceMonitor.js +64 -32
- package/dist/modules/process/LinuxProcessManager.d.ts +3 -1
- package/dist/modules/process/LinuxProcessManager.js +7 -3
- package/dist/modules/process/MacProcessManager.d.ts +3 -1
- package/dist/modules/process/MacProcessManager.js +32 -28
- package/dist/modules/process/ProcessManager.impl.d.ts +5 -1
- package/dist/modules/process/ProcessManager.impl.js +54 -13
- package/dist/modules/process/index.d.ts +3 -1
- package/dist/modules/process/index.js +2 -2
- package/dist/modules/process/memory/AuditTrail.d.ts +25 -0
- package/dist/modules/process/memory/AuditTrail.js +44 -0
- package/dist/modules/process/memory/availability.js +49 -49
- package/dist/modules/process/memory/injector.js +185 -185
- package/dist/modules/process/memory/linux/mapsParser.d.ts +16 -0
- package/dist/modules/process/memory/linux/mapsParser.js +28 -0
- package/dist/modules/process/memory/reader.js +50 -50
- package/dist/modules/process/memory/regions.enumerate.js +45 -1
- package/dist/modules/process/memory/regions.protection.js +48 -2
- package/dist/modules/process/memory/scanner.d.ts +4 -1
- package/dist/modules/process/memory/scanner.js +383 -182
- package/dist/modules/process/memory/writer.js +54 -54
- package/dist/native/NativeMemoryManager.impl.d.ts +4 -0
- package/dist/native/NativeMemoryManager.impl.js +72 -24
- package/dist/native/NativeMemoryManager.utils.d.ts +1 -0
- package/dist/native/NativeMemoryManager.utils.js +44 -1
- package/dist/native/scripts/linux/enum-windows.sh +12 -12
- package/dist/native/scripts/macos/enum-windows.applescript +22 -22
- package/dist/native/scripts/windows/enum-windows-by-class.ps1 +51 -51
- package/dist/native/scripts/windows/enum-windows.ps1 +44 -44
- package/dist/native/scripts/windows/inject-dll.ps1 +21 -21
- package/dist/server/MCPServer.search.d.ts +3 -0
- package/dist/server/MCPServer.search.js +21 -2
- package/dist/server/ToolCallContextGuard.d.ts +2 -0
- package/dist/server/ToolCallContextGuard.js +29 -14
- package/dist/server/ToolSearch.js +11 -5
- package/dist/server/domains/browser/definitions.tools.page-core.js +53 -53
- package/dist/server/domains/browser/definitions.tools.runtime.js +40 -40
- package/dist/server/domains/browser/definitions.tools.security.js +76 -76
- package/dist/server/domains/browser/handlers/tab-workflow.js +6 -4
- package/dist/server/domains/maintenance/handlers.extensions.js +46 -26
- package/dist/server/domains/process/definitions.js +20 -7
- package/dist/server/domains/process/handlers.impl.core.runtime.base.d.ts +35 -0
- package/dist/server/domains/process/handlers.impl.core.runtime.base.js +107 -1
- package/dist/server/domains/process/handlers.impl.core.runtime.inject.js +111 -2
- package/dist/server/domains/process/handlers.impl.core.runtime.memory.d.ts +9 -0
- package/dist/server/domains/process/handlers.impl.core.runtime.memory.js +282 -31
- package/dist/server/domains/process/manifest.js +1 -0
- package/dist/server/domains/transform/handlers.impl.transform-base.js +102 -102
- package/dist/server/domains/workflow/handlers.impl.workflow-api.js +14 -4
- package/dist/server/domains/workflow/handlers.impl.workflow-base.js +51 -51
- package/dist/server/registry/discovery.js +17 -12
- package/dist/server/registry/index.js +10 -2
- package/dist/utils/TokenBudgetManager.d.ts +1 -0
- package/dist/utils/TokenBudgetManager.js +22 -0
- package/package.json +5 -1
- package/src/native/scripts/linux/enum-windows.sh +12 -12
- package/src/native/scripts/macos/enum-windows.applescript +22 -22
- package/src/native/scripts/windows/enum-windows-by-class.ps1 +51 -51
- package/src/native/scripts/windows/enum-windows.ps1 +44 -44
- package/src/native/scripts/windows/inject-dll.ps1 +21 -21
|
@@ -14,14 +14,67 @@ function normalizePatternType(value) {
|
|
|
14
14
|
}
|
|
15
15
|
return 'hex';
|
|
16
16
|
}
|
|
17
|
+
function getOptionalPid(value) {
|
|
18
|
+
const pid = Number(value);
|
|
19
|
+
return Number.isInteger(pid) && pid > 0 ? pid : undefined;
|
|
20
|
+
}
|
|
21
|
+
function getOptionalString(value) {
|
|
22
|
+
return typeof value === 'string' && value.length > 0 ? value : undefined;
|
|
23
|
+
}
|
|
24
|
+
function getOptionalPositiveNumber(value) {
|
|
25
|
+
const size = Number(value);
|
|
26
|
+
return Number.isFinite(size) && size > 0 ? size : undefined;
|
|
27
|
+
}
|
|
28
|
+
function getWriteSize(data, encoding) {
|
|
29
|
+
if (encoding === 'hex') {
|
|
30
|
+
const normalized = data.replace(/\s+/g, '');
|
|
31
|
+
return Math.ceil(normalized.length / 2);
|
|
32
|
+
}
|
|
33
|
+
return Buffer.from(data, 'base64').length;
|
|
34
|
+
}
|
|
17
35
|
export class ProcessToolHandlersMemory extends ProcessToolHandlersBase {
|
|
36
|
+
async safeBuildMemoryDiagnostics(input) {
|
|
37
|
+
try {
|
|
38
|
+
return await this.buildMemoryDiagnostics(input);
|
|
39
|
+
}
|
|
40
|
+
catch (diagnosticError) {
|
|
41
|
+
logger.warn('Memory diagnostics generation failed:', diagnosticError);
|
|
42
|
+
return undefined;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
recordMemoryAudit(entry) {
|
|
46
|
+
try {
|
|
47
|
+
this.auditTrail.record(entry);
|
|
48
|
+
}
|
|
49
|
+
catch (auditError) {
|
|
50
|
+
logger.warn('Memory audit trail recording failed:', auditError);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
18
53
|
async handleMemoryRead(args) {
|
|
54
|
+
const startedAt = Date.now();
|
|
19
55
|
try {
|
|
20
56
|
const pid = validatePid(args.pid);
|
|
21
57
|
const address = requireString(args.address, 'address');
|
|
22
58
|
const size = requirePositiveNumber(args.size, 'size');
|
|
23
59
|
const availability = await this.memoryManager.checkAvailability();
|
|
24
60
|
if (!availability.available) {
|
|
61
|
+
const errorMessage = availability.reason ?? 'Memory operations not available';
|
|
62
|
+
const diagnostics = await this.safeBuildMemoryDiagnostics({
|
|
63
|
+
pid,
|
|
64
|
+
address,
|
|
65
|
+
size,
|
|
66
|
+
operation: 'memory_read',
|
|
67
|
+
error: errorMessage,
|
|
68
|
+
});
|
|
69
|
+
this.recordMemoryAudit({
|
|
70
|
+
operation: 'memory_read',
|
|
71
|
+
pid,
|
|
72
|
+
address,
|
|
73
|
+
size,
|
|
74
|
+
result: 'failure',
|
|
75
|
+
error: errorMessage,
|
|
76
|
+
durationMs: Date.now() - startedAt,
|
|
77
|
+
});
|
|
25
78
|
return {
|
|
26
79
|
content: [
|
|
27
80
|
{
|
|
@@ -34,38 +87,82 @@ export class ProcessToolHandlersMemory extends ProcessToolHandlersBase {
|
|
|
34
87
|
requestedAddress: address,
|
|
35
88
|
requestedSize: size,
|
|
36
89
|
pid,
|
|
90
|
+
diagnostics,
|
|
37
91
|
}, null, 2),
|
|
38
92
|
},
|
|
39
93
|
],
|
|
40
94
|
};
|
|
41
95
|
}
|
|
42
96
|
const result = await this.memoryManager.readMemory(pid, address, size);
|
|
97
|
+
const diagnostics = !result.success
|
|
98
|
+
? await this.safeBuildMemoryDiagnostics({
|
|
99
|
+
pid,
|
|
100
|
+
address,
|
|
101
|
+
size,
|
|
102
|
+
operation: 'memory_read',
|
|
103
|
+
error: result.error,
|
|
104
|
+
})
|
|
105
|
+
: undefined;
|
|
106
|
+
this.recordMemoryAudit({
|
|
107
|
+
operation: 'memory_read',
|
|
108
|
+
pid,
|
|
109
|
+
address,
|
|
110
|
+
size,
|
|
111
|
+
result: result.success ? 'success' : 'failure',
|
|
112
|
+
error: result.error,
|
|
113
|
+
durationMs: Date.now() - startedAt,
|
|
114
|
+
});
|
|
115
|
+
const payload = {
|
|
116
|
+
success: result.success,
|
|
117
|
+
data: result.data,
|
|
118
|
+
error: result.error,
|
|
119
|
+
pid,
|
|
120
|
+
address,
|
|
121
|
+
size,
|
|
122
|
+
platform: this.platform,
|
|
123
|
+
};
|
|
124
|
+
if (!result.success) {
|
|
125
|
+
payload.diagnostics = diagnostics;
|
|
126
|
+
}
|
|
43
127
|
return {
|
|
44
128
|
content: [
|
|
45
129
|
{
|
|
46
130
|
type: 'text',
|
|
47
|
-
text: JSON.stringify(
|
|
48
|
-
success: result.success,
|
|
49
|
-
data: result.data,
|
|
50
|
-
error: result.error,
|
|
51
|
-
pid,
|
|
52
|
-
address,
|
|
53
|
-
size,
|
|
54
|
-
platform: this.platform,
|
|
55
|
-
}, null, 2),
|
|
131
|
+
text: JSON.stringify(payload, null, 2),
|
|
56
132
|
},
|
|
57
133
|
],
|
|
58
134
|
};
|
|
59
135
|
}
|
|
60
136
|
catch (error) {
|
|
61
137
|
logger.error('Memory read failed:', error);
|
|
138
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
139
|
+
const pid = getOptionalPid(args.pid);
|
|
140
|
+
const address = getOptionalString(args.address);
|
|
141
|
+
const size = getOptionalPositiveNumber(args.size);
|
|
142
|
+
const diagnostics = await this.safeBuildMemoryDiagnostics({
|
|
143
|
+
pid,
|
|
144
|
+
address,
|
|
145
|
+
size,
|
|
146
|
+
operation: 'memory_read',
|
|
147
|
+
error: errorMessage,
|
|
148
|
+
});
|
|
149
|
+
this.recordMemoryAudit({
|
|
150
|
+
operation: 'memory_read',
|
|
151
|
+
pid: pid ?? null,
|
|
152
|
+
address: address ?? null,
|
|
153
|
+
size: size ?? null,
|
|
154
|
+
result: 'failure',
|
|
155
|
+
error: errorMessage,
|
|
156
|
+
durationMs: Date.now() - startedAt,
|
|
157
|
+
});
|
|
62
158
|
return {
|
|
63
159
|
content: [
|
|
64
160
|
{
|
|
65
161
|
type: 'text',
|
|
66
162
|
text: JSON.stringify({
|
|
67
163
|
success: false,
|
|
68
|
-
error:
|
|
164
|
+
error: errorMessage,
|
|
165
|
+
diagnostics,
|
|
69
166
|
}, null, 2),
|
|
70
167
|
},
|
|
71
168
|
],
|
|
@@ -73,13 +170,32 @@ export class ProcessToolHandlersMemory extends ProcessToolHandlersBase {
|
|
|
73
170
|
}
|
|
74
171
|
}
|
|
75
172
|
async handleMemoryWrite(args) {
|
|
173
|
+
const startedAt = Date.now();
|
|
76
174
|
try {
|
|
77
175
|
const pid = validatePid(args.pid);
|
|
78
176
|
const address = requireString(args.address, 'address');
|
|
79
177
|
const data = requireString(args.data, 'data');
|
|
80
178
|
const encoding = args.encoding || 'hex';
|
|
179
|
+
const size = getWriteSize(data, encoding);
|
|
81
180
|
const availability = await this.memoryManager.checkAvailability();
|
|
82
181
|
if (!availability.available) {
|
|
182
|
+
const errorMessage = availability.reason ?? 'Memory operations not available';
|
|
183
|
+
const diagnostics = await this.safeBuildMemoryDiagnostics({
|
|
184
|
+
pid,
|
|
185
|
+
address,
|
|
186
|
+
size,
|
|
187
|
+
operation: 'memory_write',
|
|
188
|
+
error: errorMessage,
|
|
189
|
+
});
|
|
190
|
+
this.recordMemoryAudit({
|
|
191
|
+
operation: 'memory_write',
|
|
192
|
+
pid,
|
|
193
|
+
address,
|
|
194
|
+
size,
|
|
195
|
+
result: 'failure',
|
|
196
|
+
error: errorMessage,
|
|
197
|
+
durationMs: Date.now() - startedAt,
|
|
198
|
+
});
|
|
83
199
|
return {
|
|
84
200
|
content: [
|
|
85
201
|
{
|
|
@@ -93,39 +209,85 @@ export class ProcessToolHandlersMemory extends ProcessToolHandlersBase {
|
|
|
93
209
|
dataLength: data != null ? data.length : 0,
|
|
94
210
|
encoding,
|
|
95
211
|
pid,
|
|
212
|
+
diagnostics,
|
|
96
213
|
}, null, 2),
|
|
97
214
|
},
|
|
98
215
|
],
|
|
99
216
|
};
|
|
100
217
|
}
|
|
101
218
|
const result = await this.memoryManager.writeMemory(pid, address, data, encoding);
|
|
219
|
+
const diagnostics = !result.success
|
|
220
|
+
? await this.safeBuildMemoryDiagnostics({
|
|
221
|
+
pid,
|
|
222
|
+
address,
|
|
223
|
+
size,
|
|
224
|
+
operation: 'memory_write',
|
|
225
|
+
error: result.error,
|
|
226
|
+
})
|
|
227
|
+
: undefined;
|
|
228
|
+
this.recordMemoryAudit({
|
|
229
|
+
operation: 'memory_write',
|
|
230
|
+
pid,
|
|
231
|
+
address,
|
|
232
|
+
size,
|
|
233
|
+
result: result.success ? 'success' : 'failure',
|
|
234
|
+
error: result.error,
|
|
235
|
+
durationMs: Date.now() - startedAt,
|
|
236
|
+
});
|
|
237
|
+
const payload = {
|
|
238
|
+
success: result.success,
|
|
239
|
+
bytesWritten: result.bytesWritten,
|
|
240
|
+
error: result.error,
|
|
241
|
+
pid,
|
|
242
|
+
address,
|
|
243
|
+
dataLength: data.length,
|
|
244
|
+
encoding,
|
|
245
|
+
platform: this.platform,
|
|
246
|
+
};
|
|
247
|
+
if (!result.success) {
|
|
248
|
+
payload.diagnostics = diagnostics;
|
|
249
|
+
}
|
|
102
250
|
return {
|
|
103
251
|
content: [
|
|
104
252
|
{
|
|
105
253
|
type: 'text',
|
|
106
|
-
text: JSON.stringify(
|
|
107
|
-
success: result.success,
|
|
108
|
-
bytesWritten: result.bytesWritten,
|
|
109
|
-
error: result.error,
|
|
110
|
-
pid,
|
|
111
|
-
address,
|
|
112
|
-
dataLength: data.length,
|
|
113
|
-
encoding,
|
|
114
|
-
platform: this.platform,
|
|
115
|
-
}, null, 2),
|
|
254
|
+
text: JSON.stringify(payload, null, 2),
|
|
116
255
|
},
|
|
117
256
|
],
|
|
118
257
|
};
|
|
119
258
|
}
|
|
120
259
|
catch (error) {
|
|
121
260
|
logger.error('Memory write failed:', error);
|
|
261
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
262
|
+
const pid = getOptionalPid(args.pid);
|
|
263
|
+
const address = getOptionalString(args.address);
|
|
264
|
+
const data = getOptionalString(args.data);
|
|
265
|
+
const encoding = args.encoding || 'hex';
|
|
266
|
+
const size = data ? getWriteSize(data, encoding) : undefined;
|
|
267
|
+
const diagnostics = await this.safeBuildMemoryDiagnostics({
|
|
268
|
+
pid,
|
|
269
|
+
address,
|
|
270
|
+
size,
|
|
271
|
+
operation: 'memory_write',
|
|
272
|
+
error: errorMessage,
|
|
273
|
+
});
|
|
274
|
+
this.recordMemoryAudit({
|
|
275
|
+
operation: 'memory_write',
|
|
276
|
+
pid: pid ?? null,
|
|
277
|
+
address: address ?? null,
|
|
278
|
+
size: size ?? null,
|
|
279
|
+
result: 'failure',
|
|
280
|
+
error: errorMessage,
|
|
281
|
+
durationMs: Date.now() - startedAt,
|
|
282
|
+
});
|
|
122
283
|
return {
|
|
123
284
|
content: [
|
|
124
285
|
{
|
|
125
286
|
type: 'text',
|
|
126
287
|
text: JSON.stringify({
|
|
127
288
|
success: false,
|
|
128
|
-
error:
|
|
289
|
+
error: errorMessage,
|
|
290
|
+
diagnostics,
|
|
129
291
|
}, null, 2),
|
|
130
292
|
},
|
|
131
293
|
],
|
|
@@ -133,12 +295,28 @@ export class ProcessToolHandlersMemory extends ProcessToolHandlersBase {
|
|
|
133
295
|
}
|
|
134
296
|
}
|
|
135
297
|
async handleMemoryScan(args) {
|
|
298
|
+
const startedAt = Date.now();
|
|
136
299
|
try {
|
|
137
300
|
const pid = validatePid(args.pid);
|
|
138
301
|
const pattern = requireString(args.pattern, 'pattern');
|
|
139
302
|
const patternType = normalizePatternType(args.patternType);
|
|
140
303
|
const availability = await this.memoryManager.checkAvailability();
|
|
141
304
|
if (!availability.available) {
|
|
305
|
+
const errorMessage = availability.reason ?? 'Memory operations not available';
|
|
306
|
+
const diagnostics = await this.safeBuildMemoryDiagnostics({
|
|
307
|
+
pid,
|
|
308
|
+
operation: 'memory_scan',
|
|
309
|
+
error: errorMessage,
|
|
310
|
+
});
|
|
311
|
+
this.recordMemoryAudit({
|
|
312
|
+
operation: 'memory_scan',
|
|
313
|
+
pid,
|
|
314
|
+
address: null,
|
|
315
|
+
size: null,
|
|
316
|
+
result: 'failure',
|
|
317
|
+
error: errorMessage,
|
|
318
|
+
durationMs: Date.now() - startedAt,
|
|
319
|
+
});
|
|
142
320
|
return {
|
|
143
321
|
content: [
|
|
144
322
|
{
|
|
@@ -151,43 +329,116 @@ export class ProcessToolHandlersMemory extends ProcessToolHandlersBase {
|
|
|
151
329
|
requestedPattern: pattern,
|
|
152
330
|
patternType,
|
|
153
331
|
pid,
|
|
332
|
+
diagnostics,
|
|
154
333
|
}, null, 2),
|
|
155
334
|
},
|
|
156
335
|
],
|
|
157
336
|
};
|
|
158
337
|
}
|
|
159
338
|
const result = await this.memoryManager.scanMemory(pid, pattern, patternType);
|
|
339
|
+
const diagnostics = !result.success
|
|
340
|
+
? await this.safeBuildMemoryDiagnostics({
|
|
341
|
+
pid,
|
|
342
|
+
operation: 'memory_scan',
|
|
343
|
+
error: result.error,
|
|
344
|
+
})
|
|
345
|
+
: undefined;
|
|
346
|
+
this.recordMemoryAudit({
|
|
347
|
+
operation: 'memory_scan',
|
|
348
|
+
pid,
|
|
349
|
+
address: null,
|
|
350
|
+
size: null,
|
|
351
|
+
result: result.success ? 'success' : 'failure',
|
|
352
|
+
error: result.error,
|
|
353
|
+
durationMs: Date.now() - startedAt,
|
|
354
|
+
});
|
|
355
|
+
const payload = {
|
|
356
|
+
success: result.success,
|
|
357
|
+
addresses: result.addresses,
|
|
358
|
+
error: result.error,
|
|
359
|
+
pid,
|
|
360
|
+
pattern,
|
|
361
|
+
patternType,
|
|
362
|
+
platform: this.platform,
|
|
363
|
+
};
|
|
364
|
+
if (!result.success) {
|
|
365
|
+
payload.diagnostics = diagnostics;
|
|
366
|
+
}
|
|
160
367
|
return {
|
|
161
368
|
content: [
|
|
162
369
|
{
|
|
163
370
|
type: 'text',
|
|
164
|
-
text: JSON.stringify(
|
|
165
|
-
success: result.success,
|
|
166
|
-
addresses: result.addresses,
|
|
167
|
-
error: result.error,
|
|
168
|
-
pid,
|
|
169
|
-
pattern,
|
|
170
|
-
patternType,
|
|
171
|
-
platform: this.platform,
|
|
172
|
-
}, null, 2),
|
|
371
|
+
text: JSON.stringify(payload, null, 2),
|
|
173
372
|
},
|
|
174
373
|
],
|
|
175
374
|
};
|
|
176
375
|
}
|
|
177
376
|
catch (error) {
|
|
178
377
|
logger.error('Memory scan failed:', error);
|
|
378
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
379
|
+
const pid = getOptionalPid(args.pid);
|
|
380
|
+
const diagnostics = await this.safeBuildMemoryDiagnostics({
|
|
381
|
+
pid,
|
|
382
|
+
operation: 'memory_scan',
|
|
383
|
+
error: errorMessage,
|
|
384
|
+
});
|
|
385
|
+
this.recordMemoryAudit({
|
|
386
|
+
operation: 'memory_scan',
|
|
387
|
+
pid: pid ?? null,
|
|
388
|
+
address: null,
|
|
389
|
+
size: null,
|
|
390
|
+
result: 'failure',
|
|
391
|
+
error: errorMessage,
|
|
392
|
+
durationMs: Date.now() - startedAt,
|
|
393
|
+
});
|
|
179
394
|
return {
|
|
180
395
|
content: [
|
|
181
396
|
{
|
|
182
397
|
type: 'text',
|
|
183
398
|
text: JSON.stringify({
|
|
184
399
|
success: false,
|
|
185
|
-
error:
|
|
400
|
+
error: errorMessage,
|
|
401
|
+
diagnostics,
|
|
402
|
+
}, null, 2),
|
|
403
|
+
},
|
|
404
|
+
],
|
|
405
|
+
};
|
|
406
|
+
}
|
|
407
|
+
}
|
|
408
|
+
async handleMemoryAuditExport(args) {
|
|
409
|
+
try {
|
|
410
|
+
const exportedJson = this.auditTrail.exportJson();
|
|
411
|
+
const entries = JSON.parse(exportedJson);
|
|
412
|
+
const clear = args.clear === true;
|
|
413
|
+
const count = this.auditTrail.size();
|
|
414
|
+
if (clear) {
|
|
415
|
+
this.auditTrail.clear();
|
|
416
|
+
}
|
|
417
|
+
return {
|
|
418
|
+
content: [
|
|
419
|
+
{
|
|
420
|
+
type: 'text',
|
|
421
|
+
text: JSON.stringify({
|
|
422
|
+
success: true,
|
|
423
|
+
count,
|
|
424
|
+
cleared: clear,
|
|
425
|
+
entries,
|
|
186
426
|
}, null, 2),
|
|
187
427
|
},
|
|
188
428
|
],
|
|
189
429
|
};
|
|
190
430
|
}
|
|
431
|
+
catch (error) {
|
|
432
|
+
logger.error('Memory audit export failed:', error);
|
|
433
|
+
return {
|
|
434
|
+
content: [
|
|
435
|
+
{
|
|
436
|
+
type: 'text',
|
|
437
|
+
text: JSON.stringify({ success: false, error: error instanceof Error ? error.message : String(error) }, null, 2),
|
|
438
|
+
},
|
|
439
|
+
],
|
|
440
|
+
};
|
|
441
|
+
}
|
|
191
442
|
}
|
|
192
443
|
async handleMemoryCheckProtection(args) {
|
|
193
444
|
try {
|
|
@@ -36,6 +36,7 @@ const manifest = {
|
|
|
36
36
|
{ tool: t('memory_batch_write'), domain: DOMAIN, bind: b((h, a) => h.handleMemoryBatchWrite(a)) },
|
|
37
37
|
{ tool: t('memory_dump_region'), domain: DOMAIN, bind: b((h, a) => h.handleMemoryDumpRegion(a)) },
|
|
38
38
|
{ tool: t('memory_list_regions'), domain: DOMAIN, bind: b((h, a) => h.handleMemoryListRegions(a)) },
|
|
39
|
+
{ tool: t('memory_audit_export'), domain: DOMAIN, bind: b((h, a) => h.handleMemoryAuditExport(a)) },
|
|
39
40
|
{ tool: t('inject_dll'), domain: DOMAIN, bind: b((h, a) => h.handleInjectDll(a)) },
|
|
40
41
|
{ tool: t('module_inject_dll'), domain: DOMAIN, bind: b((h, a) => h.handleInjectDll(a)) },
|
|
41
42
|
{ tool: t('inject_shellcode'), domain: DOMAIN, bind: b((h, a) => h.handleInjectShellcode(a)) },
|
|
@@ -28,98 +28,98 @@ export const CRYPTO_KEYWORDS = [
|
|
|
28
28
|
'aes',
|
|
29
29
|
'rsa',
|
|
30
30
|
];
|
|
31
|
-
const CRYPTO_TEST_WORKER_SCRIPT = `
|
|
32
|
-
const __bootstrap = async () => {
|
|
33
|
-
const [workerThreads, vm, perfHooks] = await Promise.all([
|
|
34
|
-
import('node:worker_threads'),
|
|
35
|
-
import('node:vm'),
|
|
36
|
-
import('node:perf_hooks'),
|
|
37
|
-
]);
|
|
38
|
-
|
|
39
|
-
const parentPort = workerThreads.parentPort;
|
|
40
|
-
const performance = perfHooks.performance;
|
|
41
|
-
|
|
42
|
-
if (!parentPort) {
|
|
43
|
-
throw new Error('worker parentPort is unavailable');
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
function normalizeOutput(value) {
|
|
47
|
-
if (value === undefined) return '__undefined__';
|
|
48
|
-
if (value === null) return 'null';
|
|
49
|
-
if (typeof value === 'string') return value;
|
|
50
|
-
if (typeof value === 'number' || typeof value === 'boolean' || typeof value === 'bigint') return String(value);
|
|
51
|
-
try { return JSON.stringify(value); } catch { return String(value); }
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
parentPort.on('message', async (msg) => {
|
|
55
|
-
const { jobId, payload } = msg;
|
|
56
|
-
try {
|
|
57
|
-
const { code, functionName, testInputs } = payload;
|
|
58
|
-
const sandbox = {
|
|
59
|
-
console: { log() {}, warn() {}, error() {} },
|
|
60
|
-
Buffer,
|
|
61
|
-
TextEncoder,
|
|
62
|
-
TextDecoder,
|
|
63
|
-
atob: (v) => Buffer.from(String(v), 'base64').toString('binary'),
|
|
64
|
-
btoa: (v) => Buffer.from(String(v), 'binary').toString('base64'),
|
|
65
|
-
};
|
|
66
|
-
sandbox.globalThis = sandbox;
|
|
67
|
-
const context = vm.createContext(sandbox);
|
|
68
|
-
|
|
69
|
-
const isValidIdentifier = /^[A-Za-z_$][A-Za-z0-9_$]*$/.test(functionName);
|
|
70
|
-
const bindCode = isValidIdentifier
|
|
71
|
-
? "\\n;globalThis.__targetFn = (typeof " + functionName + " !== 'undefined' ? " + functionName + " : globalThis[" + JSON.stringify(functionName) + "]);"
|
|
72
|
-
: "\\n;globalThis.__targetFn = globalThis[" + JSON.stringify(functionName) + "];";
|
|
73
|
-
|
|
74
|
-
const script = new vm.Script(code + bindCode, { timeout: 5000 });
|
|
75
|
-
script.runInContext(context, { timeout: 5000 });
|
|
76
|
-
|
|
77
|
-
const targetFn = context.__targetFn;
|
|
78
|
-
if (typeof targetFn !== 'function') {
|
|
79
|
-
throw new Error("Function not found or not callable: " + functionName);
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
const rows = [];
|
|
83
|
-
for (const input of testInputs) {
|
|
84
|
-
const started = performance.now();
|
|
85
|
-
try {
|
|
86
|
-
const raw = targetFn(input);
|
|
87
|
-
const resolved = raw && typeof raw.then === 'function' ? await raw : raw;
|
|
88
|
-
rows.push({
|
|
89
|
-
input,
|
|
90
|
-
output: normalizeOutput(resolved),
|
|
91
|
-
duration: Number((performance.now() - started).toFixed(3)),
|
|
92
|
-
});
|
|
93
|
-
} catch (err) {
|
|
94
|
-
rows.push({
|
|
95
|
-
input,
|
|
96
|
-
output: '',
|
|
97
|
-
error: err && err.message ? err.message : String(err),
|
|
98
|
-
duration: Number((performance.now() - started).toFixed(3)),
|
|
99
|
-
});
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
parentPort.postMessage({ jobId, ok: true, result: { ok: true, results: rows } });
|
|
104
|
-
} catch (error) {
|
|
105
|
-
parentPort.postMessage({
|
|
106
|
-
jobId,
|
|
107
|
-
ok: true,
|
|
108
|
-
result: {
|
|
109
|
-
ok: false,
|
|
110
|
-
error: error && error.message ? error.message : String(error),
|
|
111
|
-
results: [],
|
|
112
|
-
},
|
|
113
|
-
});
|
|
114
|
-
}
|
|
115
|
-
});
|
|
116
|
-
};
|
|
117
|
-
|
|
118
|
-
__bootstrap().catch((error) => {
|
|
119
|
-
if (typeof console !== 'undefined' && typeof console.error === 'function') {
|
|
120
|
-
console.error('crypto harness worker bootstrap failed:', error && error.message ? error.message : String(error));
|
|
121
|
-
}
|
|
122
|
-
});
|
|
31
|
+
const CRYPTO_TEST_WORKER_SCRIPT = `
|
|
32
|
+
const __bootstrap = async () => {
|
|
33
|
+
const [workerThreads, vm, perfHooks] = await Promise.all([
|
|
34
|
+
import('node:worker_threads'),
|
|
35
|
+
import('node:vm'),
|
|
36
|
+
import('node:perf_hooks'),
|
|
37
|
+
]);
|
|
38
|
+
|
|
39
|
+
const parentPort = workerThreads.parentPort;
|
|
40
|
+
const performance = perfHooks.performance;
|
|
41
|
+
|
|
42
|
+
if (!parentPort) {
|
|
43
|
+
throw new Error('worker parentPort is unavailable');
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
function normalizeOutput(value) {
|
|
47
|
+
if (value === undefined) return '__undefined__';
|
|
48
|
+
if (value === null) return 'null';
|
|
49
|
+
if (typeof value === 'string') return value;
|
|
50
|
+
if (typeof value === 'number' || typeof value === 'boolean' || typeof value === 'bigint') return String(value);
|
|
51
|
+
try { return JSON.stringify(value); } catch { return String(value); }
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
parentPort.on('message', async (msg) => {
|
|
55
|
+
const { jobId, payload } = msg;
|
|
56
|
+
try {
|
|
57
|
+
const { code, functionName, testInputs } = payload;
|
|
58
|
+
const sandbox = {
|
|
59
|
+
console: { log() {}, warn() {}, error() {} },
|
|
60
|
+
Buffer,
|
|
61
|
+
TextEncoder,
|
|
62
|
+
TextDecoder,
|
|
63
|
+
atob: (v) => Buffer.from(String(v), 'base64').toString('binary'),
|
|
64
|
+
btoa: (v) => Buffer.from(String(v), 'binary').toString('base64'),
|
|
65
|
+
};
|
|
66
|
+
sandbox.globalThis = sandbox;
|
|
67
|
+
const context = vm.createContext(sandbox);
|
|
68
|
+
|
|
69
|
+
const isValidIdentifier = /^[A-Za-z_$][A-Za-z0-9_$]*$/.test(functionName);
|
|
70
|
+
const bindCode = isValidIdentifier
|
|
71
|
+
? "\\n;globalThis.__targetFn = (typeof " + functionName + " !== 'undefined' ? " + functionName + " : globalThis[" + JSON.stringify(functionName) + "]);"
|
|
72
|
+
: "\\n;globalThis.__targetFn = globalThis[" + JSON.stringify(functionName) + "];";
|
|
73
|
+
|
|
74
|
+
const script = new vm.Script(code + bindCode, { timeout: 5000 });
|
|
75
|
+
script.runInContext(context, { timeout: 5000 });
|
|
76
|
+
|
|
77
|
+
const targetFn = context.__targetFn;
|
|
78
|
+
if (typeof targetFn !== 'function') {
|
|
79
|
+
throw new Error("Function not found or not callable: " + functionName);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
const rows = [];
|
|
83
|
+
for (const input of testInputs) {
|
|
84
|
+
const started = performance.now();
|
|
85
|
+
try {
|
|
86
|
+
const raw = targetFn(input);
|
|
87
|
+
const resolved = raw && typeof raw.then === 'function' ? await raw : raw;
|
|
88
|
+
rows.push({
|
|
89
|
+
input,
|
|
90
|
+
output: normalizeOutput(resolved),
|
|
91
|
+
duration: Number((performance.now() - started).toFixed(3)),
|
|
92
|
+
});
|
|
93
|
+
} catch (err) {
|
|
94
|
+
rows.push({
|
|
95
|
+
input,
|
|
96
|
+
output: '',
|
|
97
|
+
error: err && err.message ? err.message : String(err),
|
|
98
|
+
duration: Number((performance.now() - started).toFixed(3)),
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
parentPort.postMessage({ jobId, ok: true, result: { ok: true, results: rows } });
|
|
104
|
+
} catch (error) {
|
|
105
|
+
parentPort.postMessage({
|
|
106
|
+
jobId,
|
|
107
|
+
ok: true,
|
|
108
|
+
result: {
|
|
109
|
+
ok: false,
|
|
110
|
+
error: error && error.message ? error.message : String(error),
|
|
111
|
+
results: [],
|
|
112
|
+
},
|
|
113
|
+
});
|
|
114
|
+
}
|
|
115
|
+
});
|
|
116
|
+
};
|
|
117
|
+
|
|
118
|
+
__bootstrap().catch((error) => {
|
|
119
|
+
if (typeof console !== 'undefined' && typeof console.error === 'function') {
|
|
120
|
+
console.error('crypto harness worker bootstrap failed:', error && error.message ? error.message : String(error));
|
|
121
|
+
}
|
|
122
|
+
});
|
|
123
123
|
`;
|
|
124
124
|
export class TransformToolHandlersBase {
|
|
125
125
|
collector;
|
|
@@ -333,16 +333,16 @@ export class TransformToolHandlersBase {
|
|
|
333
333
|
return /^[A-Za-z_$][A-Za-z0-9_$]*$/.test(value);
|
|
334
334
|
}
|
|
335
335
|
buildCryptoPolyfills() {
|
|
336
|
-
return `
|
|
337
|
-
const __textEncoder = typeof TextEncoder !== 'undefined' ? new TextEncoder() : null;
|
|
338
|
-
const __textDecoder = typeof TextDecoder !== 'undefined' ? new TextDecoder() : null;
|
|
339
|
-
|
|
340
|
-
if (typeof globalThis.atob === 'undefined') {
|
|
341
|
-
globalThis.atob = (value) => Buffer.from(String(value), 'base64').toString('binary');
|
|
342
|
-
}
|
|
343
|
-
if (typeof globalThis.btoa === 'undefined') {
|
|
344
|
-
globalThis.btoa = (value) => Buffer.from(String(value), 'binary').toString('base64');
|
|
345
|
-
}
|
|
336
|
+
return `
|
|
337
|
+
const __textEncoder = typeof TextEncoder !== 'undefined' ? new TextEncoder() : null;
|
|
338
|
+
const __textDecoder = typeof TextDecoder !== 'undefined' ? new TextDecoder() : null;
|
|
339
|
+
|
|
340
|
+
if (typeof globalThis.atob === 'undefined') {
|
|
341
|
+
globalThis.atob = (value) => Buffer.from(String(value), 'base64').toString('binary');
|
|
342
|
+
}
|
|
343
|
+
if (typeof globalThis.btoa === 'undefined') {
|
|
344
|
+
globalThis.btoa = (value) => Buffer.from(String(value), 'binary').toString('base64');
|
|
345
|
+
}
|
|
346
346
|
`.trim();
|
|
347
347
|
}
|
|
348
348
|
async runCryptoHarness(code, functionName, testInputs) {
|