@remnux/mcp-server 0.1.54 → 0.1.55
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/README.md +7 -1
- package/dist/analysis/behavior-prerequisites.d.ts +65 -0
- package/dist/analysis/behavior-prerequisites.d.ts.map +1 -0
- package/dist/analysis/behavior-prerequisites.js +186 -0
- package/dist/analysis/behavior-prerequisites.js.map +1 -0
- package/dist/analysis/file-diff.d.ts +59 -0
- package/dist/analysis/file-diff.d.ts.map +1 -0
- package/dist/analysis/file-diff.js +55 -0
- package/dist/analysis/file-diff.js.map +1 -0
- package/dist/analysis/index.d.ts +1 -1
- package/dist/analysis/index.d.ts.map +1 -1
- package/dist/analysis/index.js +1 -1
- package/dist/analysis/index.js.map +1 -1
- package/dist/analysis/string-usage.d.ts +77 -0
- package/dist/analysis/string-usage.d.ts.map +1 -0
- package/dist/analysis/string-usage.js +130 -0
- package/dist/analysis/string-usage.js.map +1 -0
- package/dist/analysis/summarizer.d.ts +22 -0
- package/dist/analysis/summarizer.d.ts.map +1 -1
- package/dist/analysis/summarizer.js +41 -0
- package/dist/analysis/summarizer.js.map +1 -1
- package/dist/handlers/analyze-file.d.ts.map +1 -1
- package/dist/handlers/analyze-file.js +14 -2
- package/dist/handlers/analyze-file.js.map +1 -1
- package/dist/handlers/check-behavior-prerequisites.d.ts +16 -0
- package/dist/handlers/check-behavior-prerequisites.d.ts.map +1 -0
- package/dist/handlers/check-behavior-prerequisites.js +132 -0
- package/dist/handlers/check-behavior-prerequisites.js.map +1 -0
- package/dist/handlers/compare-files.d.ts +10 -0
- package/dist/handlers/compare-files.d.ts.map +1 -0
- package/dist/handlers/compare-files.js +147 -0
- package/dist/handlers/compare-files.js.map +1 -0
- package/dist/handlers/report.d.ts.map +1 -1
- package/dist/handlers/report.js +11 -0
- package/dist/handlers/report.js.map +1 -1
- package/dist/handlers/verify-string-usage.d.ts +10 -0
- package/dist/handlers/verify-string-usage.d.ts.map +1 -0
- package/dist/handlers/verify-string-usage.js +166 -0
- package/dist/handlers/verify-string-usage.js.map +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +47 -8
- package/dist/index.js.map +1 -1
- package/dist/parsers/capa.d.ts +8 -1
- package/dist/parsers/capa.d.ts.map +1 -1
- package/dist/parsers/capa.js +138 -0
- package/dist/parsers/capa.js.map +1 -1
- package/dist/parsers/imports.d.ts +36 -0
- package/dist/parsers/imports.d.ts.map +1 -0
- package/dist/parsers/imports.js +67 -0
- package/dist/parsers/imports.js.map +1 -0
- package/dist/parsers/r2.d.ts +73 -0
- package/dist/parsers/r2.d.ts.map +1 -0
- package/dist/parsers/r2.js +161 -0
- package/dist/parsers/r2.js.map +1 -0
- package/dist/parsers/types.d.ts +19 -0
- package/dist/parsers/types.d.ts.map +1 -1
- package/dist/report/triage-discipline.d.ts +28 -0
- package/dist/report/triage-discipline.d.ts.map +1 -0
- package/dist/report/triage-discipline.js +49 -0
- package/dist/report/triage-discipline.js.map +1 -0
- package/dist/schemas/tools.d.ts +45 -3
- package/dist/schemas/tools.d.ts.map +1 -1
- package/dist/schemas/tools.js +22 -2
- package/dist/schemas/tools.js.map +1 -1
- package/package.json +1 -1
package/dist/parsers/capa.js
CHANGED
|
@@ -4,6 +4,137 @@
|
|
|
4
4
|
* Extracts capabilities and their associated ATT&CK techniques.
|
|
5
5
|
* Expects JSON output from `capa -j <file>`.
|
|
6
6
|
*/
|
|
7
|
+
/**
|
|
8
|
+
* Map a capa feature-node type to the kind of evidence it represents.
|
|
9
|
+
*
|
|
10
|
+
* Deliberately conservative: only feature types whose evidence kind is
|
|
11
|
+
* unambiguous are mapped. A rule's namespace describes its INTENT
|
|
12
|
+
* (e.g. "collection/*"), not how it matched, so it is NOT used here to infer
|
|
13
|
+
* behavior — conflating the two is exactly the artifact-vs-behavior error this
|
|
14
|
+
* tagging exists to prevent.
|
|
15
|
+
*/
|
|
16
|
+
const FEATURE_EVIDENCE_TYPE = {
|
|
17
|
+
// artifact — data/content patterns present in the binary
|
|
18
|
+
string: "artifact",
|
|
19
|
+
substring: "artifact",
|
|
20
|
+
regex: "artifact",
|
|
21
|
+
bytes: "artifact",
|
|
22
|
+
// behavior — code-level semantics (these feature types occur only in code)
|
|
23
|
+
api: "behavior",
|
|
24
|
+
mnemonic: "behavior",
|
|
25
|
+
number: "behavior",
|
|
26
|
+
offset: "behavior",
|
|
27
|
+
"operand number": "behavior",
|
|
28
|
+
"operand offset": "behavior",
|
|
29
|
+
// structural — binary layout / metadata
|
|
30
|
+
section: "structural",
|
|
31
|
+
export: "structural",
|
|
32
|
+
// linking — imports / library presence
|
|
33
|
+
import: "linking",
|
|
34
|
+
// Intentionally NEUTRAL (no contribution): os, arch, format, match, class,
|
|
35
|
+
// property, namespace, function-name. These are environment guards or
|
|
36
|
+
// ambiguous signals that would dilute the artifact-vs-behavior distinction
|
|
37
|
+
// (e.g. `os: windows` appears in many behavioral rules as a guard).
|
|
38
|
+
};
|
|
39
|
+
/**
|
|
40
|
+
* capa's `characteristic` feature is overloaded: some values describe binary
|
|
41
|
+
* structure, others describe code execution. Map by value; unknown values
|
|
42
|
+
* contribute nothing (conservative — a mislabel is worse than no label).
|
|
43
|
+
*/
|
|
44
|
+
const CHARACTERISTIC_EVIDENCE_TYPE = {
|
|
45
|
+
// structural — file/layout characteristics
|
|
46
|
+
"embedded pe": "structural",
|
|
47
|
+
"mixed mode": "structural",
|
|
48
|
+
"forwarded export": "structural",
|
|
49
|
+
// artifact — string data (constructed in code, but still data)
|
|
50
|
+
"stack string": "artifact",
|
|
51
|
+
// behavior — code-execution characteristics
|
|
52
|
+
loop: "behavior",
|
|
53
|
+
"tight loop": "behavior",
|
|
54
|
+
"recursive call": "behavior",
|
|
55
|
+
nzxor: "behavior",
|
|
56
|
+
"peb access": "behavior",
|
|
57
|
+
"fs access": "behavior",
|
|
58
|
+
"gs access": "behavior",
|
|
59
|
+
"cross section flow": "behavior",
|
|
60
|
+
"indirect call": "behavior",
|
|
61
|
+
"unmanaged call": "behavior",
|
|
62
|
+
};
|
|
63
|
+
/** Stable ordering for the unordered evidence_types set (deterministic output). */
|
|
64
|
+
const EVIDENCE_TYPE_ORDER = ["artifact", "behavior", "structural", "linking"];
|
|
65
|
+
/**
|
|
66
|
+
* Walk a capa match-node tree and collect the feature types of nodes that
|
|
67
|
+
* ACTUALLY matched (success === true). capa includes non-matching branches
|
|
68
|
+
* (the untaken side of an `or`, the inner feature of a satisfied `not`) with
|
|
69
|
+
* success === false; excluding them ensures a rule that fired on a `string`
|
|
70
|
+
* branch is never credited with an unmatched `api` branch.
|
|
71
|
+
*/
|
|
72
|
+
function collectMatchedEvidenceTypes(node, out) {
|
|
73
|
+
if (!node || typeof node !== "object")
|
|
74
|
+
return;
|
|
75
|
+
const n = node;
|
|
76
|
+
const inner = n.node;
|
|
77
|
+
if (n.success === true && inner && typeof inner === "object") {
|
|
78
|
+
const i = inner;
|
|
79
|
+
if (i.type === "feature" && i.feature && typeof i.feature === "object") {
|
|
80
|
+
const f = i.feature;
|
|
81
|
+
const ft = f.type;
|
|
82
|
+
if (typeof ft === "string") {
|
|
83
|
+
if (ft === "characteristic") {
|
|
84
|
+
const val = typeof f.characteristic === "string" ? f.characteristic : "";
|
|
85
|
+
const et = CHARACTERISTIC_EVIDENCE_TYPE[val];
|
|
86
|
+
if (et)
|
|
87
|
+
out.add(et);
|
|
88
|
+
}
|
|
89
|
+
else {
|
|
90
|
+
const et = FEATURE_EVIDENCE_TYPE[ft];
|
|
91
|
+
if (et)
|
|
92
|
+
out.add(et);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
if (Array.isArray(n.children)) {
|
|
98
|
+
for (const c of n.children)
|
|
99
|
+
collectMatchedEvidenceTypes(c, out);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* Derive the evidence_types set for a single capa rule from the feature nodes
|
|
104
|
+
* that actually matched, plus two unambiguous namespace signals. Returns
|
|
105
|
+
* undefined when nothing can be determined (the caller then omits the field).
|
|
106
|
+
* Never throws — a malformed rule yields undefined, never a lost finding.
|
|
107
|
+
*/
|
|
108
|
+
export function deriveEvidenceTypes(rule) {
|
|
109
|
+
try {
|
|
110
|
+
const types = new Set();
|
|
111
|
+
if (Array.isArray(rule.matches)) {
|
|
112
|
+
for (const m of rule.matches) {
|
|
113
|
+
// each match is [address, matchNode]
|
|
114
|
+
if (Array.isArray(m) && m.length >= 2) {
|
|
115
|
+
collectMatchedEvidenceTypes(m[1], types);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
// Namespace carries an unambiguous evidence-kind signal in two cases only.
|
|
120
|
+
const meta = rule.meta;
|
|
121
|
+
if (meta && typeof meta === "object" && !Array.isArray(meta)) {
|
|
122
|
+
const ns = meta.namespace;
|
|
123
|
+
if (typeof ns === "string") {
|
|
124
|
+
if (ns.startsWith("linking/"))
|
|
125
|
+
types.add("linking");
|
|
126
|
+
else if (ns.startsWith("executable/"))
|
|
127
|
+
types.add("structural");
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
if (types.size === 0)
|
|
131
|
+
return undefined;
|
|
132
|
+
return EVIDENCE_TYPE_ORDER.filter((t) => types.has(t));
|
|
133
|
+
}
|
|
134
|
+
catch {
|
|
135
|
+
return undefined;
|
|
136
|
+
}
|
|
137
|
+
}
|
|
7
138
|
export function parseCapaOutput(rawOutput) {
|
|
8
139
|
const result = {
|
|
9
140
|
tool: "capa",
|
|
@@ -38,6 +169,13 @@ export function parseCapaOutput(rawOutput) {
|
|
|
38
169
|
.join(", ");
|
|
39
170
|
}
|
|
40
171
|
}
|
|
172
|
+
// Tag the kind(s) of evidence the rule actually matched on (artifact vs
|
|
173
|
+
// behavior vs structural vs linking). Additive and fail-soft: if this
|
|
174
|
+
// cannot be determined the field is simply omitted — the finding's name
|
|
175
|
+
// and ATT&CK evidence are never affected.
|
|
176
|
+
const evidenceTypes = deriveEvidenceTypes(r);
|
|
177
|
+
if (evidenceTypes)
|
|
178
|
+
finding.evidence_types = evidenceTypes;
|
|
41
179
|
result.findings.push(finding);
|
|
42
180
|
}
|
|
43
181
|
}
|
package/dist/parsers/capa.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"capa.js","sourceRoot":"","sources":["../../src/parsers/capa.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,MAAM,UAAU,eAAe,CAAC,SAAiB;IAC/C,MAAM,MAAM,GAAqB;QAC/B,IAAI,EAAE,MAAM;QACZ,MAAM,EAAE,KAAK;QACb,QAAQ,EAAE,EAAE;QACZ,QAAQ,EAAE,EAAE;QACZ,GAAG,EAAE,SAAS;KACf,CAAC;IAEF,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC;QACnC,MAAM,CAAC,MAAM,GAAG,IAAI,CAAC;QAErB,6BAA6B;QAC7B,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC;QACzB,IAAI,KAAK,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;YAChE,KAAK,MAAM,CAAC,IAAI,EAAE,IAAI,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;gBACjD,IAAI,CAAC,IAAI,IAAI,OAAO,IAAI,KAAK,QAAQ;oBAAE,SAAS;gBAChD,MAAM,CAAC,GAAG,IAA+B,CAAC;gBAC1C,MAAM,IAAI,GAAG,CAAC,CAAC,IAAI,CAAC;gBACpB,MAAM,OAAO,GAAY;oBACvB,WAAW,EAAE,IAAI;oBACjB,QAAQ,EAAE,YAAY;oBACtB,QAAQ,EAAE,MAAM;iBACjB,CAAC;gBAEF,4DAA4D;gBAC5D,IAAI,IAAI,IAAI,OAAO,IAAI,KAAK,QAAQ,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC;oBAC7D,MAAM,CAAC,GAAG,IAA+B,CAAC;oBAC1C,IAAI,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;wBACnD,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC,MAAM;6BACxB,MAAM,CAAC,CAAC,CAAC,EAA+B,EAAE,CAAC,CAAC,IAAI,OAAO,CAAC,KAAK,QAAQ,CAAC;6BACtE,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,CAAC,SAAS,IAAI,GAAG,KAAK,CAAC,CAAC,EAAE,IAAI,GAAG,GAAG,CAAC;6BACpD,IAAI,CAAC,IAAI,CAAC,CAAC;oBAChB,CAAC;gBACH,CAAC;gBAED,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;YAChC,CAAC;QACH,CAAC;QAED,mBAAmB;QACnB,IAAI,IAAI,CAAC,IAAI,IAAI,OAAO,IAAI,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;YAC/C,MAAM,CAAC,QAAQ,CAAC,MAAM,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC;YAC1C,MAAM,CAAC,QAAQ,CAAC,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC;QAChD,CAAC;QAED,yDAAyD;QACzD,IAAI,MAAM,CAAC,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACjC,MAAM,CAAC,QAAQ,CAAC,kBAAkB;gBAChC,mDAAmD;oBACnD,+EAA+E;oBAC/E,4DAA4D;oBAC5D,2DAA2D;oBAC3D,6CAA6C;oBAC7C,0DAA0D;oBAC1D,wEAAwE,CAAC;QAC7E,CAAC;IACH,CAAC;IAAC,MAAM,CAAC;QACP,sCAAsC;IACxC,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC"}
|
|
1
|
+
{"version":3,"file":"capa.js","sourceRoot":"","sources":["../../src/parsers/capa.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Parser for a PE import table from `readpe -i -f json` (pev suite).
|
|
3
|
+
*
|
|
4
|
+
* Produces a structured, queryable view of which APIs a PE statically imports.
|
|
5
|
+
* This is the enabling primitive for check_behavior_prerequisites: knowing the
|
|
6
|
+
* import surface lets us ask "can this binary even call the APIs a behavior
|
|
7
|
+
* requires?" — without conflating "the API is imported" with "the behavior
|
|
8
|
+
* runs".
|
|
9
|
+
*
|
|
10
|
+
* Note on what imports prove: a statically imported API means the binary *can*
|
|
11
|
+
* call it; it is not evidence the call happens on a reachable path. Absence is
|
|
12
|
+
* weaker still — APIs can be resolved at runtime (GetProcAddress + LoadLibrary)
|
|
13
|
+
* or hidden by packing.
|
|
14
|
+
*/
|
|
15
|
+
export interface PeImports {
|
|
16
|
+
/** True when readpe produced valid JSON we could read (even if zero imports). */
|
|
17
|
+
parsed: boolean;
|
|
18
|
+
dlls: Array<{
|
|
19
|
+
dll: string;
|
|
20
|
+
functions: string[];
|
|
21
|
+
}>;
|
|
22
|
+
/** Lowercased imported function names, for case-insensitive lookup. */
|
|
23
|
+
functionSet: Set<string>;
|
|
24
|
+
/** Total number of imported functions across all DLLs. */
|
|
25
|
+
count: number;
|
|
26
|
+
}
|
|
27
|
+
export declare function parsePeImports(readpeJson: string): PeImports;
|
|
28
|
+
/**
|
|
29
|
+
* Whether a required API (given as a base name without the ANSI/Unicode suffix)
|
|
30
|
+
* is present in the import set. Matches the base plus its `...A` / `...W`
|
|
31
|
+
* variants — e.g. required "InternetOpenUrl" is satisfied by "InternetOpenUrlW".
|
|
32
|
+
* We APPEND candidate suffixes rather than stripping, because many genuine API
|
|
33
|
+
* names already end in 'a'/'w' (e.g. "GetClipboardData", "ShowWindow").
|
|
34
|
+
*/
|
|
35
|
+
export declare function apiPresent(requiredBaseName: string, functionSet: Set<string>): boolean;
|
|
36
|
+
//# sourceMappingURL=imports.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"imports.d.ts","sourceRoot":"","sources":["../../src/parsers/imports.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,MAAM,WAAW,SAAS;IACxB,iFAAiF;IACjF,MAAM,EAAE,OAAO,CAAC;IAChB,IAAI,EAAE,KAAK,CAAC;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,EAAE,CAAA;KAAE,CAAC,CAAC;IAClD,uEAAuE;IACvE,WAAW,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IACzB,0DAA0D;IAC1D,KAAK,EAAE,MAAM,CAAC;CACf;AAMD,wBAAgB,cAAc,CAAC,UAAU,EAAE,MAAM,GAAG,SAAS,CAoC5D;AAED;;;;;;GAMG;AACH,wBAAgB,UAAU,CAAC,gBAAgB,EAAE,MAAM,EAAE,WAAW,EAAE,GAAG,CAAC,MAAM,CAAC,GAAG,OAAO,CAGtF"}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Parser for a PE import table from `readpe -i -f json` (pev suite).
|
|
3
|
+
*
|
|
4
|
+
* Produces a structured, queryable view of which APIs a PE statically imports.
|
|
5
|
+
* This is the enabling primitive for check_behavior_prerequisites: knowing the
|
|
6
|
+
* import surface lets us ask "can this binary even call the APIs a behavior
|
|
7
|
+
* requires?" — without conflating "the API is imported" with "the behavior
|
|
8
|
+
* runs".
|
|
9
|
+
*
|
|
10
|
+
* Note on what imports prove: a statically imported API means the binary *can*
|
|
11
|
+
* call it; it is not evidence the call happens on a reachable path. Absence is
|
|
12
|
+
* weaker still — APIs can be resolved at runtime (GetProcAddress + LoadLibrary)
|
|
13
|
+
* or hidden by packing.
|
|
14
|
+
*/
|
|
15
|
+
function emptyImports(parsed) {
|
|
16
|
+
return { parsed, dlls: [], functionSet: new Set(), count: 0 };
|
|
17
|
+
}
|
|
18
|
+
export function parsePeImports(readpeJson) {
|
|
19
|
+
let data;
|
|
20
|
+
try {
|
|
21
|
+
data = JSON.parse(readpeJson);
|
|
22
|
+
}
|
|
23
|
+
catch {
|
|
24
|
+
return emptyImports(false);
|
|
25
|
+
}
|
|
26
|
+
if (!data || typeof data !== "object")
|
|
27
|
+
return emptyImports(false);
|
|
28
|
+
const imported = data["Imported functions"];
|
|
29
|
+
// Valid JSON but no import table (e.g. a PE with no imports) → parsed, empty.
|
|
30
|
+
if (!Array.isArray(imported))
|
|
31
|
+
return emptyImports(true);
|
|
32
|
+
const dlls = [];
|
|
33
|
+
const functionSet = new Set();
|
|
34
|
+
let count = 0;
|
|
35
|
+
for (const lib of imported) {
|
|
36
|
+
if (!lib || typeof lib !== "object")
|
|
37
|
+
continue;
|
|
38
|
+
const l = lib;
|
|
39
|
+
const dll = typeof l.Name === "string" ? l.Name : "";
|
|
40
|
+
const fns = Array.isArray(l.Functions) ? l.Functions : [];
|
|
41
|
+
const names = [];
|
|
42
|
+
for (const fn of fns) {
|
|
43
|
+
if (!fn || typeof fn !== "object")
|
|
44
|
+
continue;
|
|
45
|
+
const name = fn.Name;
|
|
46
|
+
if (typeof name === "string" && name.length > 0) {
|
|
47
|
+
names.push(name);
|
|
48
|
+
functionSet.add(name.toLowerCase());
|
|
49
|
+
count++;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
dlls.push({ dll, functions: names });
|
|
53
|
+
}
|
|
54
|
+
return { parsed: true, dlls, functionSet, count };
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Whether a required API (given as a base name without the ANSI/Unicode suffix)
|
|
58
|
+
* is present in the import set. Matches the base plus its `...A` / `...W`
|
|
59
|
+
* variants — e.g. required "InternetOpenUrl" is satisfied by "InternetOpenUrlW".
|
|
60
|
+
* We APPEND candidate suffixes rather than stripping, because many genuine API
|
|
61
|
+
* names already end in 'a'/'w' (e.g. "GetClipboardData", "ShowWindow").
|
|
62
|
+
*/
|
|
63
|
+
export function apiPresent(requiredBaseName, functionSet) {
|
|
64
|
+
const base = requiredBaseName.toLowerCase();
|
|
65
|
+
return functionSet.has(base) || functionSet.has(base + "a") || functionSet.has(base + "w");
|
|
66
|
+
}
|
|
67
|
+
//# sourceMappingURL=imports.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"imports.js","sourceRoot":"","sources":["../../src/parsers/imports.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAYH,SAAS,YAAY,CAAC,MAAe;IACnC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,EAAE,EAAE,WAAW,EAAE,IAAI,GAAG,EAAE,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC;AAChE,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,UAAkB;IAC/C,IAAI,IAAa,CAAC;IAClB,IAAI,CAAC;QACH,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC;IAChC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,YAAY,CAAC,KAAK,CAAC,CAAC;IAC7B,CAAC;IACD,IAAI,CAAC,IAAI,IAAI,OAAO,IAAI,KAAK,QAAQ;QAAE,OAAO,YAAY,CAAC,KAAK,CAAC,CAAC;IAElE,MAAM,QAAQ,GAAI,IAAgC,CAAC,oBAAoB,CAAC,CAAC;IACzE,8EAA8E;IAC9E,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC;QAAE,OAAO,YAAY,CAAC,IAAI,CAAC,CAAC;IAExD,MAAM,IAAI,GAAgD,EAAE,CAAC;IAC7D,MAAM,WAAW,GAAG,IAAI,GAAG,EAAU,CAAC;IACtC,IAAI,KAAK,GAAG,CAAC,CAAC;IAEd,KAAK,MAAM,GAAG,IAAI,QAAQ,EAAE,CAAC;QAC3B,IAAI,CAAC,GAAG,IAAI,OAAO,GAAG,KAAK,QAAQ;YAAE,SAAS;QAC9C,MAAM,CAAC,GAAG,GAA8B,CAAC;QACzC,MAAM,GAAG,GAAG,OAAO,CAAC,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC;QACrD,MAAM,GAAG,GAAG,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC;QAC1D,MAAM,KAAK,GAAa,EAAE,CAAC;QAC3B,KAAK,MAAM,EAAE,IAAI,GAAG,EAAE,CAAC;YACrB,IAAI,CAAC,EAAE,IAAI,OAAO,EAAE,KAAK,QAAQ;gBAAE,SAAS;YAC5C,MAAM,IAAI,GAAI,EAA8B,CAAC,IAAI,CAAC;YAClD,IAAI,OAAO,IAAI,KAAK,QAAQ,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBAChD,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;gBACjB,WAAW,CAAC,GAAG,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC,CAAC;gBACpC,KAAK,EAAE,CAAC;YACV,CAAC;QACH,CAAC;QACD,IAAI,CAAC,IAAI,CAAC,EAAE,GAAG,EAAE,SAAS,EAAE,KAAK,EAAE,CAAC,CAAC;IACvC,CAAC;IAED,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,WAAW,EAAE,KAAK,EAAE,CAAC;AACpD,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,UAAU,CAAC,gBAAwB,EAAE,WAAwB;IAC3E,MAAM,IAAI,GAAG,gBAAgB,CAAC,WAAW,EAAE,CAAC;IAC5C,OAAO,WAAW,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,WAAW,CAAC,GAAG,CAAC,IAAI,GAAG,GAAG,CAAC,IAAI,WAAW,CAAC,GAAG,CAAC,IAAI,GAAG,GAAG,CAAC,CAAC;AAC7F,CAAC"}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pure parsers for radare2 JSON output (izj/izzj strings, iSj sections, aflj
|
|
3
|
+
* functions, axtj cross-references) plus the marker-split for the batched
|
|
4
|
+
* "Pass 2" command used by verify_string_usage.
|
|
5
|
+
*
|
|
6
|
+
* Every parser is defensive and NEVER throws — malformed/partial r2 output
|
|
7
|
+
* returns an empty result so the classifier can degrade to `unknown` rather
|
|
8
|
+
* than mistaking a parse failure for a real "no xref" answer. Field shapes were
|
|
9
|
+
* captured from radare2 6.1.6; alternative key names seen across versions are
|
|
10
|
+
* tolerated (e.g. function address as `addr` or `offset`).
|
|
11
|
+
*/
|
|
12
|
+
/** Self-generated markers (emitted via `?e`) that delimit the Pass-2 sections. */
|
|
13
|
+
export declare const R2_MARKERS: {
|
|
14
|
+
readonly sections: "__R2MCP_SEC__";
|
|
15
|
+
readonly functions: "__R2MCP_FNS__";
|
|
16
|
+
readonly xref: "__R2MCP_XR__";
|
|
17
|
+
};
|
|
18
|
+
export interface R2String {
|
|
19
|
+
value: string;
|
|
20
|
+
vaddr: number;
|
|
21
|
+
section: string;
|
|
22
|
+
}
|
|
23
|
+
export interface R2Section {
|
|
24
|
+
name: string;
|
|
25
|
+
vaddr: number;
|
|
26
|
+
vaddrEnd: number;
|
|
27
|
+
/** True when the section is executable (perm contains 'x'). */
|
|
28
|
+
exec: boolean;
|
|
29
|
+
}
|
|
30
|
+
export interface R2Function {
|
|
31
|
+
addr: number;
|
|
32
|
+
name: string;
|
|
33
|
+
size: number;
|
|
34
|
+
}
|
|
35
|
+
export interface R2Xref {
|
|
36
|
+
/** Source address of the reference. */
|
|
37
|
+
from: number;
|
|
38
|
+
/** r2 reference type: STRN / DATA / CODE / CALL … */
|
|
39
|
+
type: string;
|
|
40
|
+
/** Containing function address, when r2 attributed one. */
|
|
41
|
+
fcnAddr?: number;
|
|
42
|
+
/** Containing function name, when present. */
|
|
43
|
+
fcnName?: string;
|
|
44
|
+
opcode?: string;
|
|
45
|
+
}
|
|
46
|
+
/** Parse `izj` / `izzj` string output. */
|
|
47
|
+
export declare function parseR2Strings(json: string): R2String[];
|
|
48
|
+
/** Parse `iSj` section output into ranges with an exec flag. */
|
|
49
|
+
export declare function parseR2Sections(json: string): R2Section[];
|
|
50
|
+
/** Parse `aflj` function list (address key is `addr` or `offset` across versions). */
|
|
51
|
+
export declare function parseR2Functions(json: string): R2Function[];
|
|
52
|
+
/** Parse `axtj` cross-reference output for one address. */
|
|
53
|
+
export declare function parseR2Xrefs(json: string): R2Xref[];
|
|
54
|
+
/** Extract the radare2 version string from `?V` output (first matching line). */
|
|
55
|
+
export declare function parseR2Version(text: string): string | undefined;
|
|
56
|
+
export interface SplitR2Output {
|
|
57
|
+
/** True if the connector truncated the output (→ treat as incomplete). */
|
|
58
|
+
truncated: boolean;
|
|
59
|
+
version?: string;
|
|
60
|
+
sectionsJson: string;
|
|
61
|
+
functionsJson: string;
|
|
62
|
+
/** Raw axtj JSON keyed by the queried address marker (hex string as emitted). */
|
|
63
|
+
xrefsByVaddr: Map<string, string>;
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Split the batched Pass-2 stdout on the self-generated markers. The preamble
|
|
67
|
+
* (before the sections marker) carries the `?V` version line; sections sit
|
|
68
|
+
* between the sections and functions markers; functions between the functions
|
|
69
|
+
* marker and the first xref marker; each `__R2MCP_XR__ <addr>` block holds that
|
|
70
|
+
* address's axtj JSON up to the next marker or EOF.
|
|
71
|
+
*/
|
|
72
|
+
export declare function splitMarkedR2Output(stdout: string): SplitR2Output;
|
|
73
|
+
//# sourceMappingURL=r2.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"r2.d.ts","sourceRoot":"","sources":["../../src/parsers/r2.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,kFAAkF;AAClF,eAAO,MAAM,UAAU;;;;CAIb,CAAC;AAKX,MAAM,WAAW,QAAQ;IACvB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,+DAA+D;IAC/D,IAAI,EAAE,OAAO,CAAC;CACf;AAED,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,MAAM;IACrB,uCAAuC;IACvC,IAAI,EAAE,MAAM,CAAC;IACb,qDAAqD;IACrD,IAAI,EAAE,MAAM,CAAC;IACb,2DAA2D;IAC3D,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,8CAA8C;IAC9C,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAeD,0CAA0C;AAC1C,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,QAAQ,EAAE,CAYvD;AAED,gEAAgE;AAChE,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,EAAE,CAiBzD;AAED,sFAAsF;AACtF,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,UAAU,EAAE,CAU3D;AAED,2DAA2D;AAC3D,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,CAgBnD;AAED,iFAAiF;AACjF,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAG/D;AAED,MAAM,WAAW,aAAa;IAC5B,0EAA0E;IAC1E,SAAS,EAAE,OAAO,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,MAAM,CAAC;IACrB,aAAa,EAAE,MAAM,CAAC;IACtB,iFAAiF;IACjF,YAAY,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACnC;AAED;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,MAAM,GAAG,aAAa,CA4CjE"}
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pure parsers for radare2 JSON output (izj/izzj strings, iSj sections, aflj
|
|
3
|
+
* functions, axtj cross-references) plus the marker-split for the batched
|
|
4
|
+
* "Pass 2" command used by verify_string_usage.
|
|
5
|
+
*
|
|
6
|
+
* Every parser is defensive and NEVER throws — malformed/partial r2 output
|
|
7
|
+
* returns an empty result so the classifier can degrade to `unknown` rather
|
|
8
|
+
* than mistaking a parse failure for a real "no xref" answer. Field shapes were
|
|
9
|
+
* captured from radare2 6.1.6; alternative key names seen across versions are
|
|
10
|
+
* tolerated (e.g. function address as `addr` or `offset`).
|
|
11
|
+
*/
|
|
12
|
+
/** Self-generated markers (emitted via `?e`) that delimit the Pass-2 sections. */
|
|
13
|
+
export const R2_MARKERS = {
|
|
14
|
+
sections: "__R2MCP_SEC__",
|
|
15
|
+
functions: "__R2MCP_FNS__",
|
|
16
|
+
xref: "__R2MCP_XR__",
|
|
17
|
+
};
|
|
18
|
+
/** The connector caps stdout at 10MB and appends this sentinel when it does. */
|
|
19
|
+
const TRUNCATION_SENTINEL = "[OUTPUT TRUNCATED";
|
|
20
|
+
function asArray(json) {
|
|
21
|
+
try {
|
|
22
|
+
const data = JSON.parse(json);
|
|
23
|
+
return Array.isArray(data) ? data : [];
|
|
24
|
+
}
|
|
25
|
+
catch {
|
|
26
|
+
return [];
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
function num(v) {
|
|
30
|
+
return typeof v === "number" && Number.isFinite(v) ? v : undefined;
|
|
31
|
+
}
|
|
32
|
+
/** Parse `izj` / `izzj` string output. */
|
|
33
|
+
export function parseR2Strings(json) {
|
|
34
|
+
const out = [];
|
|
35
|
+
for (const e of asArray(json)) {
|
|
36
|
+
if (!e || typeof e !== "object")
|
|
37
|
+
continue;
|
|
38
|
+
const r = e;
|
|
39
|
+
const value = r.string;
|
|
40
|
+
const vaddr = num(r.vaddr);
|
|
41
|
+
if (typeof value === "string" && vaddr !== undefined) {
|
|
42
|
+
out.push({ value, vaddr, section: typeof r.section === "string" ? r.section : "" });
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
return out;
|
|
46
|
+
}
|
|
47
|
+
/** Parse `iSj` section output into ranges with an exec flag. */
|
|
48
|
+
export function parseR2Sections(json) {
|
|
49
|
+
const out = [];
|
|
50
|
+
for (const e of asArray(json)) {
|
|
51
|
+
if (!e || typeof e !== "object")
|
|
52
|
+
continue;
|
|
53
|
+
const r = e;
|
|
54
|
+
const vaddr = num(r.vaddr);
|
|
55
|
+
const vsize = num(r.vsize) ?? 0;
|
|
56
|
+
if (vaddr === undefined)
|
|
57
|
+
continue;
|
|
58
|
+
const perm = typeof r.perm === "string" ? r.perm : "";
|
|
59
|
+
out.push({
|
|
60
|
+
name: typeof r.name === "string" ? r.name : "",
|
|
61
|
+
vaddr,
|
|
62
|
+
vaddrEnd: vaddr + vsize,
|
|
63
|
+
exec: perm.includes("x"),
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
return out;
|
|
67
|
+
}
|
|
68
|
+
/** Parse `aflj` function list (address key is `addr` or `offset` across versions). */
|
|
69
|
+
export function parseR2Functions(json) {
|
|
70
|
+
const out = [];
|
|
71
|
+
for (const e of asArray(json)) {
|
|
72
|
+
if (!e || typeof e !== "object")
|
|
73
|
+
continue;
|
|
74
|
+
const r = e;
|
|
75
|
+
const addr = num(r.addr) ?? num(r.offset);
|
|
76
|
+
if (addr === undefined)
|
|
77
|
+
continue;
|
|
78
|
+
out.push({ addr, name: typeof r.name === "string" ? r.name : "", size: num(r.size) ?? 0 });
|
|
79
|
+
}
|
|
80
|
+
return out;
|
|
81
|
+
}
|
|
82
|
+
/** Parse `axtj` cross-reference output for one address. */
|
|
83
|
+
export function parseR2Xrefs(json) {
|
|
84
|
+
const out = [];
|
|
85
|
+
for (const e of asArray(json)) {
|
|
86
|
+
if (!e || typeof e !== "object")
|
|
87
|
+
continue;
|
|
88
|
+
const r = e;
|
|
89
|
+
const from = num(r.from);
|
|
90
|
+
if (from === undefined)
|
|
91
|
+
continue;
|
|
92
|
+
out.push({
|
|
93
|
+
from,
|
|
94
|
+
type: typeof r.type === "string" ? r.type : "",
|
|
95
|
+
fcnAddr: num(r.fcn_addr),
|
|
96
|
+
fcnName: typeof r.fcn_name === "string" ? r.fcn_name : undefined,
|
|
97
|
+
opcode: typeof r.opcode === "string" ? r.opcode : undefined,
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
return out;
|
|
101
|
+
}
|
|
102
|
+
/** Extract the radare2 version string from `?V` output (first matching line). */
|
|
103
|
+
export function parseR2Version(text) {
|
|
104
|
+
const m = text.match(/radare2\s+(\S+)/i);
|
|
105
|
+
return m ? m[1] : undefined;
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* Split the batched Pass-2 stdout on the self-generated markers. The preamble
|
|
109
|
+
* (before the sections marker) carries the `?V` version line; sections sit
|
|
110
|
+
* between the sections and functions markers; functions between the functions
|
|
111
|
+
* marker and the first xref marker; each `__R2MCP_XR__ <addr>` block holds that
|
|
112
|
+
* address's axtj JSON up to the next marker or EOF.
|
|
113
|
+
*/
|
|
114
|
+
export function splitMarkedR2Output(stdout) {
|
|
115
|
+
const result = {
|
|
116
|
+
truncated: stdout.includes(TRUNCATION_SENTINEL),
|
|
117
|
+
sectionsJson: "",
|
|
118
|
+
functionsJson: "",
|
|
119
|
+
xrefsByVaddr: new Map(),
|
|
120
|
+
};
|
|
121
|
+
const lines = stdout.split("\n");
|
|
122
|
+
let bucket = { kind: "pre" };
|
|
123
|
+
let buf = [];
|
|
124
|
+
const flush = () => {
|
|
125
|
+
const text = buf.join("\n").trim();
|
|
126
|
+
if (bucket.kind === "pre") {
|
|
127
|
+
result.version = parseR2Version(text);
|
|
128
|
+
}
|
|
129
|
+
else if (bucket.kind === "sec") {
|
|
130
|
+
result.sectionsJson = text;
|
|
131
|
+
}
|
|
132
|
+
else if (bucket.kind === "fns") {
|
|
133
|
+
result.functionsJson = text;
|
|
134
|
+
}
|
|
135
|
+
else if (bucket.kind === "xref" && bucket.key) {
|
|
136
|
+
result.xrefsByVaddr.set(bucket.key, text);
|
|
137
|
+
}
|
|
138
|
+
buf = [];
|
|
139
|
+
};
|
|
140
|
+
for (const line of lines) {
|
|
141
|
+
const trimmed = line.trim();
|
|
142
|
+
if (trimmed === R2_MARKERS.sections) {
|
|
143
|
+
flush();
|
|
144
|
+
bucket = { kind: "sec" };
|
|
145
|
+
}
|
|
146
|
+
else if (trimmed === R2_MARKERS.functions) {
|
|
147
|
+
flush();
|
|
148
|
+
bucket = { kind: "fns" };
|
|
149
|
+
}
|
|
150
|
+
else if (trimmed.startsWith(R2_MARKERS.xref + " ")) {
|
|
151
|
+
flush();
|
|
152
|
+
bucket = { kind: "xref", key: trimmed.slice(R2_MARKERS.xref.length + 1).trim() };
|
|
153
|
+
}
|
|
154
|
+
else {
|
|
155
|
+
buf.push(line);
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
flush();
|
|
159
|
+
return result;
|
|
160
|
+
}
|
|
161
|
+
//# sourceMappingURL=r2.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"r2.js","sourceRoot":"","sources":["../../src/parsers/r2.ts"],"names":[],"mappings":"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"}
|
package/dist/parsers/types.d.ts
CHANGED
|
@@ -11,7 +11,26 @@ export interface Finding {
|
|
|
11
11
|
category?: string;
|
|
12
12
|
/** Raw evidence from tool output */
|
|
13
13
|
evidence?: string;
|
|
14
|
+
/**
|
|
15
|
+
* For capability findings (e.g. capa): the kind(s) of evidence the match
|
|
16
|
+
* actually relied on, derived from the feature nodes that matched. An
|
|
17
|
+
* unordered, deduplicated set describing HOW the rule matched — not a verdict
|
|
18
|
+
* on what the sample does. Absent when it cannot be determined (treat absence
|
|
19
|
+
* as "unknown", not "none").
|
|
20
|
+
* - artifact — matched on strings/regex/bytes (data present, not necessarily executed)
|
|
21
|
+
* - behavior — matched on API calls, mnemonics, or other code semantics
|
|
22
|
+
* - structural — matched on sections, file characteristics, format/arch
|
|
23
|
+
* - linking — matched on imports / runtime-linking
|
|
24
|
+
*/
|
|
25
|
+
evidence_types?: EvidenceType[];
|
|
14
26
|
}
|
|
27
|
+
/**
|
|
28
|
+
* The kind of evidence a capability match relied on (see Finding.evidence_types).
|
|
29
|
+
* A `string` artifact match proves the data is present; it does NOT prove the
|
|
30
|
+
* binary executes the corresponding behavior. Only a `behavior` match (API
|
|
31
|
+
* calls, mnemonics) is code-level evidence.
|
|
32
|
+
*/
|
|
33
|
+
export type EvidenceType = "artifact" | "behavior" | "structural" | "linking";
|
|
15
34
|
/** Structured metadata extracted from tool output. */
|
|
16
35
|
export interface ParsedToolOutput {
|
|
17
36
|
/** Tool that produced this output */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/parsers/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,mDAAmD;AACnD,MAAM,WAAW,OAAO;IACtB,wEAAwE;IACxE,WAAW,EAAE,MAAM,CAAC;IACpB,kDAAkD;IAClD,QAAQ,CAAC,EAAE,MAAM,GAAG,KAAK,GAAG,QAAQ,GAAG,MAAM,GAAG,UAAU,CAAC;IAC3D,oEAAoE;IACpE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,oCAAoC;IACpC,QAAQ,CAAC,EAAE,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/parsers/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,mDAAmD;AACnD,MAAM,WAAW,OAAO;IACtB,wEAAwE;IACxE,WAAW,EAAE,MAAM,CAAC;IACpB,kDAAkD;IAClD,QAAQ,CAAC,EAAE,MAAM,GAAG,KAAK,GAAG,QAAQ,GAAG,MAAM,GAAG,UAAU,CAAC;IAC3D,oEAAoE;IACpE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,oCAAoC;IACpC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB;;;;;;;;;;OAUG;IACH,cAAc,CAAC,EAAE,YAAY,EAAE,CAAC;CACjC;AAED;;;;;GAKG;AACH,MAAM,MAAM,YAAY,GAAG,UAAU,GAAG,UAAU,GAAG,YAAY,GAAG,SAAS,CAAC;AAE9E,sDAAsD;AACtD,MAAM,WAAW,gBAAgB;IAC/B,qCAAqC;IACrC,IAAI,EAAE,MAAM,CAAC;IACb,mEAAmE;IACnE,MAAM,EAAE,OAAO,CAAC;IAChB,kCAAkC;IAClC,QAAQ,EAAE,OAAO,EAAE,CAAC;IACpB,+CAA+C;IAC/C,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAClC,yCAAyC;IACzC,GAAG,EAAE,MAAM,CAAC;CACb;AAED,oEAAoE;AACpE,MAAM,MAAM,gBAAgB,GAAG,CAAC,SAAS,EAAE,MAAM,KAAK,gBAAgB,CAAC"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pre-claim triage discipline checklist — server-authored, bundled, offline.
|
|
3
|
+
*
|
|
4
|
+
* This is operational guidance on USING the analysis tools and reasoning about
|
|
5
|
+
* evidence (the gates to pass before asserting a behavioral claim). It is
|
|
6
|
+
* deliberately distinct from the report-WRITING guidelines in
|
|
7
|
+
* content.generated.ts, which are synced from zeltser.com; this content is the
|
|
8
|
+
* same category as the server's other locally-authored guidance (the
|
|
9
|
+
* analyze_file analysis_guidance, the advisories, the suggest_tools hints) and
|
|
10
|
+
* is therefore authored and versioned here.
|
|
11
|
+
*
|
|
12
|
+
* Upgrade path: if this should later be published and reused on zeltser.com, it
|
|
13
|
+
* can graduate to the synced report-guidance pipeline without changing the
|
|
14
|
+
* `triage_checklist` topic's interface. Until then it is bundled and offline —
|
|
15
|
+
* no live network fetch (the server's works-offline guarantee is load-bearing
|
|
16
|
+
* for air-gapped REMnux deployments).
|
|
17
|
+
*/
|
|
18
|
+
export declare const TRIAGE_DISCIPLINE: {
|
|
19
|
+
readonly version: "1.0.0";
|
|
20
|
+
readonly title: "Malware triage discipline — gates to pass before making a claim";
|
|
21
|
+
readonly provenance: "Server-authored operational guidance, bundled and offline (not synced from zeltser.com).";
|
|
22
|
+
readonly core_principle: string;
|
|
23
|
+
readonly before_claiming_a_behavior: readonly ["Are the required APIs imported, or resolvable at runtime (GetProcAddress + LoadLibrary*)? If neither, the behavior is not statically supported.", "If the required APIs are absent but the binary is packed / encrypted / high-entropy, the honest answer is 'indeterminate — unpack first', not 'incapable'. Static absence on an obscured binary proves nothing.", "Are the relevant data artifacts (strings, wallet addresses, regexes) cross-referenced from executable code? Data sitting in .rdata with no code xref is an artifact, not an operational indicator.", "Is the relevant code reachable from the entry point, or only from unused / initializer-only code?", "Did dynamic analysis (emulation, sandbox) actually exercise the suspected path? Static analysis alone cannot confirm a runtime behavior.", "Distinguish 'the code to do X is present' (a capability) from 'the sample does X' (a confirmed behavior). Until confirmed, write 'capable of' or 'consistent with', not 'performs'."];
|
|
24
|
+
readonly for_each_ioc: readonly ["Operationally used (referenced by reachable code, or observed in traffic) vs. vestigial (present in the file but unreferenced)?", "Pyramid-of-Pain tier — trivially changed by the adversary (hash, IP) or costly (tooling, TTP)?", "Pivotable to other samples / campaigns, or unique to this sample?"];
|
|
25
|
+
readonly for_confidence: readonly ["Direct evidence vs. inferential leap — how many assumptions sit between the observation and the claim?", "Single-source vs. corroborated across independent tools or methods.", "Use ICD-203 estimative language; state attribution confidence separately from detection confidence."];
|
|
26
|
+
readonly using_this_server: readonly ["capa findings carry evidence_types (artifact / behavior / structural / linking), and analyze_file returns a capability_evidence field separating behavior_capable from artifact_only — read those before asserting a behavior.", "A YARA family match is resemblance, not identity. A family name in the filename is a lead to test, never a finding.", "When you need behavioral confirmation, plan for emulation (speakeasy) or sandbox detonation rather than inferring it from static artifacts."];
|
|
27
|
+
};
|
|
28
|
+
//# sourceMappingURL=triage-discipline.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"triage-discipline.d.ts","sourceRoot":"","sources":["../../src/report/triage-discipline.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AACH,eAAO,MAAM,iBAAiB;;;;;;;;;CA+BpB,CAAC"}
|