@litko/yara-x 0.1.0
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 +426 -0
- package/index.d.ts +268 -0
- package/index.js +321 -0
- package/package.json +58 -0
package/README.md
ADDED
|
@@ -0,0 +1,426 @@
|
|
|
1
|
+
# @litko/yara-x
|
|
2
|
+
|
|
3
|
+
**v0.1.0**
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- High Performance: Built with [napi-rs](https://napi-rs.com) and [VirusTotal/yara-x](https://github.com/VirusTotal/yara-x)
|
|
8
|
+
- Async Support: First-class support for asynchronous scanning
|
|
9
|
+
- WASM Compilation: Compile rules to WebAssembly for portable execution
|
|
10
|
+
- Zero Dependencies: No external runtime dependencies
|
|
11
|
+
|
|
12
|
+
## Usage
|
|
13
|
+
|
|
14
|
+
### Installation
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
npm install @litko/yara-x
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
### Basic Example
|
|
21
|
+
|
|
22
|
+
```javascript
|
|
23
|
+
import { compile } from "yara-x";
|
|
24
|
+
|
|
25
|
+
// Compile yara rules
|
|
26
|
+
const rules = compile(`
|
|
27
|
+
rule test_rule {
|
|
28
|
+
strings:
|
|
29
|
+
$a = "hello world"
|
|
30
|
+
condition:
|
|
31
|
+
$a
|
|
32
|
+
}
|
|
33
|
+
`);
|
|
34
|
+
|
|
35
|
+
// Scan a buffer
|
|
36
|
+
const buffer = Buffer.from("This is a test with hello world in it");
|
|
37
|
+
const matches = rules.scan(buffer);
|
|
38
|
+
|
|
39
|
+
// Process matches
|
|
40
|
+
if (matches.length > 0) {
|
|
41
|
+
console.log(`Found ${matches.length} matching rules:`);
|
|
42
|
+
matches.forEach((match) => {
|
|
43
|
+
console.log(`- Rule: ${match.ruleIdentifier}`);
|
|
44
|
+
match.matches.forEach((stringMatch) => {
|
|
45
|
+
console.log(
|
|
46
|
+
` * Match at offset ${stringMatch.offset}: ${stringMatch.data}`,
|
|
47
|
+
);
|
|
48
|
+
});
|
|
49
|
+
});
|
|
50
|
+
} else {
|
|
51
|
+
console.log("No matches found");
|
|
52
|
+
}
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
## Scanning Files
|
|
56
|
+
|
|
57
|
+
```javascript
|
|
58
|
+
import { fromFile, compile } from "yara-x";
|
|
59
|
+
import { readFileSync } from "fs";
|
|
60
|
+
|
|
61
|
+
// Load rules from a file
|
|
62
|
+
const rules = fromFile("./rules/malware_rules.yar");
|
|
63
|
+
|
|
64
|
+
try {
|
|
65
|
+
// Scan a file directly
|
|
66
|
+
const matches = rules.scanFile("./samples/suspicious_file.exe");
|
|
67
|
+
|
|
68
|
+
console.log(`Found ${matches.length} matching rules`);
|
|
69
|
+
} catch (error) {
|
|
70
|
+
console.error(`Scanning error: ${error.message}`);
|
|
71
|
+
}
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
## Asynchronous Scanning
|
|
75
|
+
|
|
76
|
+
```javascript
|
|
77
|
+
import { compile } from "yara-x";
|
|
78
|
+
|
|
79
|
+
async function scanLargeFile() {
|
|
80
|
+
const rules = compile(`rule large_file_rule {
|
|
81
|
+
strings:
|
|
82
|
+
$a = "sensitive data"
|
|
83
|
+
condition:
|
|
84
|
+
$a
|
|
85
|
+
}
|
|
86
|
+
`);
|
|
87
|
+
|
|
88
|
+
try {
|
|
89
|
+
// Scan a file asynchronously
|
|
90
|
+
const matches = await rules.scanFileAsync("./samples/large_file.bin");
|
|
91
|
+
console.log(`Found ${matches.length} matching rules`);
|
|
92
|
+
} catch (error) {
|
|
93
|
+
console.error(`Async scanning error: ${error.message}`);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
scanLargeFile();
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
## Variables
|
|
101
|
+
|
|
102
|
+
```javascript
|
|
103
|
+
import { compile } from "yara-x";
|
|
104
|
+
|
|
105
|
+
// Create a scanner with variables
|
|
106
|
+
const rules = compile(
|
|
107
|
+
`
|
|
108
|
+
rule variable_rule {
|
|
109
|
+
condition:
|
|
110
|
+
string_var contains "secret" and int_var > 10
|
|
111
|
+
}
|
|
112
|
+
`,
|
|
113
|
+
{
|
|
114
|
+
defineVariables: {
|
|
115
|
+
string_var: "this is a secret message",
|
|
116
|
+
int_var: "20",
|
|
117
|
+
},
|
|
118
|
+
},
|
|
119
|
+
);
|
|
120
|
+
|
|
121
|
+
// Scan with default variables
|
|
122
|
+
let matches = rules.scan(Buffer.from("test data"));
|
|
123
|
+
console.log(`Matches with default variables: ${matches.length}`);
|
|
124
|
+
|
|
125
|
+
// Override variables at scan time
|
|
126
|
+
matches = rules.scan(Buffer.from("test data"), {
|
|
127
|
+
string_var: "no secrets here",
|
|
128
|
+
int_var: 5, // Note: variables at scan time can be numbers as well
|
|
129
|
+
});
|
|
130
|
+
console.log(`Matches with overridden variables: ${matches.length}`);
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
## WASM Compilation
|
|
134
|
+
|
|
135
|
+
```javascript
|
|
136
|
+
import { compile, compileToWasm } from "yara-x";
|
|
137
|
+
|
|
138
|
+
// Compile rules to WASM
|
|
139
|
+
const rule = `
|
|
140
|
+
rule wasm_test {
|
|
141
|
+
strings:
|
|
142
|
+
$a = "compile to wasm"
|
|
143
|
+
condition:
|
|
144
|
+
$a
|
|
145
|
+
}
|
|
146
|
+
`;
|
|
147
|
+
|
|
148
|
+
// Static compilation
|
|
149
|
+
compileToWasm(rule, "./output/rules.wasm");
|
|
150
|
+
|
|
151
|
+
// Or from a compiled rules instance
|
|
152
|
+
const compiledRules = compile(rule);
|
|
153
|
+
compiledRules.emitWasmFile("./output/instance_rules.wasm");
|
|
154
|
+
|
|
155
|
+
// Async compilation
|
|
156
|
+
await compiledRules.emitWasmFileAsync("./output/async_rules.wasm");
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
## Incremental Rule Building
|
|
160
|
+
|
|
161
|
+
```javascript
|
|
162
|
+
import { create } from "yara-x";
|
|
163
|
+
|
|
164
|
+
// Create an empty scanner
|
|
165
|
+
const scanner = create();
|
|
166
|
+
|
|
167
|
+
// Add rules incrementally
|
|
168
|
+
scanner.addRuleSource(`
|
|
169
|
+
wrule first_rule {
|
|
170
|
+
strings:
|
|
171
|
+
$a = "first pattern"
|
|
172
|
+
condition:
|
|
173
|
+
$a
|
|
174
|
+
}
|
|
175
|
+
`);
|
|
176
|
+
|
|
177
|
+
// Add rules from a file
|
|
178
|
+
scanner.addRuleFile("./rules/more_rules.yar");
|
|
179
|
+
|
|
180
|
+
// Add another rule
|
|
181
|
+
scanner.addRuleSource(`
|
|
182
|
+
rule another_rule {
|
|
183
|
+
strings:
|
|
184
|
+
$a = "another pattern"
|
|
185
|
+
condition:
|
|
186
|
+
$a
|
|
187
|
+
}
|
|
188
|
+
`);
|
|
189
|
+
|
|
190
|
+
// Now scan with all the rules
|
|
191
|
+
const matches = scanner.scan(Buffer.from("test data with first pattern"));
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
## Rule Validation
|
|
195
|
+
|
|
196
|
+
```javascript
|
|
197
|
+
import { validate } from "yara-x";
|
|
198
|
+
|
|
199
|
+
// Validate rules without executing them
|
|
200
|
+
const result = validate(`
|
|
201
|
+
rule valid_rule {
|
|
202
|
+
strings:
|
|
203
|
+
$a = "valid"
|
|
204
|
+
condition:
|
|
205
|
+
$a
|
|
206
|
+
}
|
|
207
|
+
`);
|
|
208
|
+
|
|
209
|
+
if (result.errors.length === 0) {
|
|
210
|
+
console.log("Rules are valid!");
|
|
211
|
+
} else {
|
|
212
|
+
console.error("Rule validation failed:");
|
|
213
|
+
result.errors.forEach((error) => {
|
|
214
|
+
console.error(`- ${error.code}: ${error.message}`);
|
|
215
|
+
});
|
|
216
|
+
}
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
## Advanced Options
|
|
220
|
+
|
|
221
|
+
```javascript
|
|
222
|
+
import { compile } from "yara-x";
|
|
223
|
+
|
|
224
|
+
// Create a scanner with advanced options
|
|
225
|
+
const rules = compile(
|
|
226
|
+
`
|
|
227
|
+
rule advanced_rule {
|
|
228
|
+
strings:
|
|
229
|
+
$a = /hello[[:space:]]world/ // Using POSIX character class
|
|
230
|
+
condition:
|
|
231
|
+
$a and test_var > 10
|
|
232
|
+
}
|
|
233
|
+
`,
|
|
234
|
+
{
|
|
235
|
+
// Define variables
|
|
236
|
+
defineVariables: {
|
|
237
|
+
test_var: "20",
|
|
238
|
+
},
|
|
239
|
+
|
|
240
|
+
// Enable relaxed regular expression syntax
|
|
241
|
+
relaxedReSyntax: true,
|
|
242
|
+
|
|
243
|
+
// Enable condition optimization
|
|
244
|
+
conditionOptimization: true,
|
|
245
|
+
|
|
246
|
+
// Ignore specific modules
|
|
247
|
+
ignoreModules: ["pe"],
|
|
248
|
+
|
|
249
|
+
: // Error on potentially slow patterns
|
|
250
|
+
errorOnSlowPattern: true,
|
|
251
|
+
|
|
252
|
+
// Error on potentially slow loops
|
|
253
|
+
errorOnSlowLoop: true,
|
|
254
|
+
},
|
|
255
|
+
);
|
|
256
|
+
```
|
|
257
|
+
|
|
258
|
+
## Error Handling
|
|
259
|
+
|
|
260
|
+
### Compilation Errors
|
|
261
|
+
|
|
262
|
+
```javascript
|
|
263
|
+
import { compile } from "yara-x";
|
|
264
|
+
|
|
265
|
+
try {
|
|
266
|
+
// This will throw an error due to invalid syntax
|
|
267
|
+
const rules = compile(`
|
|
268
|
+
rule invalid_rule {
|
|
269
|
+
strings:
|
|
270
|
+
$a = "unclosed string
|
|
271
|
+
condition:
|
|
272
|
+
$a
|
|
273
|
+
}
|
|
274
|
+
`);
|
|
275
|
+
} catch (error) {
|
|
276
|
+
console.error(`Compilation error: ${error.message}`);
|
|
277
|
+
// Output: Compilation error: error[E001]: syntax error
|
|
278
|
+
// --> line:3:28
|
|
279
|
+
// |
|
|
280
|
+
// 3 | $a = "unclosed string
|
|
281
|
+
// | ^ expecting `"`, found end of file
|
|
282
|
+
// 278: }
|
|
283
|
+
}
|
|
284
|
+
```
|
|
285
|
+
|
|
286
|
+
### Scanning errors
|
|
287
|
+
|
|
288
|
+
```javascript
|
|
289
|
+
import { compile } from "yara-x";
|
|
290
|
+
|
|
291
|
+
const rules = compile(`
|
|
292
|
+
rule test_rule {
|
|
293
|
+
condition:
|
|
294
|
+
true
|
|
295
|
+
}
|
|
296
|
+
`);
|
|
297
|
+
|
|
298
|
+
try {
|
|
299
|
+
// This will throw if the file doesn't exist
|
|
300
|
+
rules.scanFile("/path/to/nonexistent/file.bin");
|
|
301
|
+
} catch (error) {
|
|
302
|
+
console.error(`Scanning error: ${error.message}`);
|
|
303
|
+
// Output: Scanning error: Error reading file: No such file or directory (os error 2)
|
|
304
|
+
}
|
|
305
|
+
```
|
|
306
|
+
|
|
307
|
+
### Async Errors
|
|
308
|
+
|
|
309
|
+
```javascript
|
|
310
|
+
import { compile, compileToWasm } from "yara-x";
|
|
311
|
+
|
|
312
|
+
async function handleAsyncErrors() {
|
|
313
|
+
const rules = compile(`
|
|
314
|
+
rule test_rule {
|
|
315
|
+
condition:
|
|
316
|
+
true
|
|
317
|
+
}
|
|
318
|
+
`);
|
|
319
|
+
|
|
320
|
+
try {
|
|
321
|
+
await rules.scanFileAsync("/path/to/nonexistent/file.bin");
|
|
322
|
+
} catch (error) {
|
|
323
|
+
console.error(`Async scanning error: ${error.message}`);
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
try {
|
|
327
|
+
await compileToWasm(
|
|
328
|
+
"rule test { condition: true }",
|
|
329
|
+
"/invalid/path/rules.wasm",
|
|
330
|
+
);
|
|
331
|
+
} catch (error) {
|
|
332
|
+
console.error(`WASM compilation error: ${error.message}`);
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
handleAsyncErrors();
|
|
337
|
+
```
|
|
338
|
+
|
|
339
|
+
## Compiler Warnings
|
|
340
|
+
|
|
341
|
+
```javascript
|
|
342
|
+
import { compile } from "yara-x";
|
|
343
|
+
|
|
344
|
+
// Create a scanner with a rule that generates warnings
|
|
345
|
+
const rules = compile(`
|
|
346
|
+
rule warning_rule {
|
|
347
|
+
strings:
|
|
348
|
+
$a = "unused string"
|
|
349
|
+
condition:
|
|
350
|
+
true // Warning: invariant expression
|
|
351
|
+
}
|
|
352
|
+
`);
|
|
353
|
+
|
|
354
|
+
// Get and display warnings
|
|
355
|
+
const warnings = rules.getWarnings();
|
|
356
|
+
if (warnings.length > 0) {
|
|
357
|
+
console.log("Compiler warnings:");
|
|
358
|
+
warnings.forEach((warning) => {
|
|
359
|
+
console.log(`- ${warning.code}: ${warning.message}`);
|
|
360
|
+
});
|
|
361
|
+
}
|
|
362
|
+
```
|
|
363
|
+
|
|
364
|
+
## Performance Benchmarks
|
|
365
|
+
|
|
366
|
+
**Test Setup:**
|
|
367
|
+
|
|
368
|
+
- **Hardware:** MacBook Pro (M3 Max, 36GB RAM)
|
|
369
|
+
- **Test Data:** Generated data of varying sizes (small: 64 bytes, medium: 100KB, large: 10MB). See `__test__/benchmark.mjs` for data generation and benchmarking code.
|
|
370
|
+
- The Large test file (10MB) is auto-generated, to prevent bloating the size of the repository.
|
|
371
|
+
|
|
372
|
+
**Key Metrics (Averages):**
|
|
373
|
+
|
|
374
|
+
| Operation | Average Time | Iterations | p50 | p95 | p99 |
|
|
375
|
+
| :---------------------------------------------- | -----------: | ---------: | -------: | -------: | -------: |
|
|
376
|
+
| Scanner Creation (Simple Rule) | 1.675 ms | 100 | 1.547 ms | 2.318 ms | 2.657 ms |
|
|
377
|
+
| Scanner Creation (Complex Rule) | 1.878 ms | 100 | 1.848 ms | 2.005 ms | 2.865 ms |
|
|
378
|
+
| Scanner Creation (Regex Rule) | 2.447 ms | 100 | 2.444 ms | 2.473 ms | 2.569 ms |
|
|
379
|
+
| Scanner Creation (Multiple Rules) | 1.497 ms | 100 | 1.488 ms | 1.547 ms | 1.819 ms |
|
|
380
|
+
| Scanning Small Data (64 bytes, Simple Rule) | 0.145 ms | 1000 | 0.143 ms | 0.156 ms | 0.169 ms |
|
|
381
|
+
| Scanning Medium Data (100KB, Simple Rule) | 0.151 ms | 100 | 0.146 ms | 0.179 ms | 0.205 ms |
|
|
382
|
+
| Scanning Large Data (10MB, Simple Rule) | 0.347 ms | 10 | 0.340 ms | 0.394 ms | 0.394 ms |
|
|
383
|
+
| Scanning Medium Data (100KB, Complex Rule) | 0.219 ms | 100 | 0.215 ms | 0.254 ms | 0.269 ms |
|
|
384
|
+
| Scanning Medium Data (100KB, Regex Rule) | 0.156 ms | 100 | 0.152 ms | 0.182 ms | 0.210 ms |
|
|
385
|
+
| Scanning Medium Data (100KB, Multiple Rules) | 0.218 ms | 100 | 0.212 ms | 0.261 ms | 0.353 ms |
|
|
386
|
+
| Async Scanning Medium Data (100KB, Simple Rule) | 0.012 ms | 100 | 0.011 ms | 0.016 ms | 0.027ms |
|
|
387
|
+
| Scanning with Variables | 0.143 ms | 1000 | 0.140 ms | 0.155 ms | 0.166 ms |
|
|
388
|
+
| Scanning with Variables (Override at Scan Time) | 0.144 ms | 1000 | 0.142 ms | 0.158 ms | 0.175 ms |
|
|
389
|
+
|
|
390
|
+
# API Reference
|
|
391
|
+
|
|
392
|
+
### Functions
|
|
393
|
+
|
|
394
|
+
- `compile(ruleSource: string, options?: CompilerOptions)` - Compiles yara rules from a string.
|
|
395
|
+
- `compileToWasm(ruleSource: string, outputPath: string, options?: CompilerOptions)` - Compiles yara rules from a string to WASM file.
|
|
396
|
+
- `compileFileToWasm(rulesPath: string, outputPath: string, options?: CompilerOptions)` - Compiles yara rules from a file to WASM file.
|
|
397
|
+
- `validate(ruleSource: string, options?: CompilerOptions)` - Validates yara rules without executing them.
|
|
398
|
+
- `create(options?: CompilerOptions)` - Creates an empty rules scanner to add rules incrementally.
|
|
399
|
+
- `fromFile(rulePath: string, options?: CompilerOptions)` - Compiles yara rules from a file.
|
|
400
|
+
|
|
401
|
+
### yarax Methods
|
|
402
|
+
|
|
403
|
+
- `getWarnings()` - Get compiler warnings.
|
|
404
|
+
- `scan(data: Buffer, variables?: Record<string, string | number>)` - Scan a buffer.
|
|
405
|
+
- `scanFile(filePath: string, variables?: Record<string, string | number>)` - Scan a file.
|
|
406
|
+
- `scanAsync(data: Buffer, variables?: Record<string, object | undefined | null>)` - Scan a buffer asynchronously.
|
|
407
|
+
- `scanFileAsync(filePath: string, variables?: Record<string, object | undefined | null>)` - Scan a file asynchronously.
|
|
408
|
+
- `emitWasmFile(filePath: string)` - Emit compiled rules to WASM file synchronously.
|
|
409
|
+
- `emitWasmFileAsync(filePath: string)` - Emit compiled rules to WASM file asynchronously.
|
|
410
|
+
- `addRuleSource(rules: string)` - Add rules from a string to an existing scanner.
|
|
411
|
+
- `addRuleFile(filePath: string)` - Add rules from a file to an existing scanner.
|
|
412
|
+
|
|
413
|
+
### Rule Validation
|
|
414
|
+
|
|
415
|
+
- `validate(rules: string, options?: CompilerOptions)` - Validate yara rules without executing them.
|
|
416
|
+
|
|
417
|
+
## Licenses
|
|
418
|
+
|
|
419
|
+
This project incorporates code under two distinct licenses:
|
|
420
|
+
|
|
421
|
+
- **MIT License:**
|
|
422
|
+
- The node.js bindings and other code specific to this module are licensed under the MIT license.
|
|
423
|
+
- See `LICENSE-MIT` for the full text.
|
|
424
|
+
- **BSD-3-Clause License:**
|
|
425
|
+
- The included yara-x library is licensed under the BSD-3-Clause license.
|
|
426
|
+
- See `LICENSE-BSD-3-Clause` for the full text.
|
package/index.d.ts
ADDED
|
@@ -0,0 +1,268 @@
|
|
|
1
|
+
/* tslint:disable */
|
|
2
|
+
/* eslint-disable */
|
|
3
|
+
|
|
4
|
+
/* auto-generated by NAPI-RS */
|
|
5
|
+
|
|
6
|
+
/** MatchData struct represents a match found by a YARA rule. */
|
|
7
|
+
export interface MatchData {
|
|
8
|
+
/** The offset of the match in the scanned data. */
|
|
9
|
+
offset: number
|
|
10
|
+
/** The length of the matched data. */
|
|
11
|
+
length: number
|
|
12
|
+
/** The matched data as a string. */
|
|
13
|
+
data: string
|
|
14
|
+
/** The identifier of the pattern that matched. */
|
|
15
|
+
identifier: string
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* RuleMatch struct represents a matching rule found during scanning.
|
|
19
|
+
*
|
|
20
|
+
* See [yara_::Match](https://docs.rs/yara-x/latest/yara_x/struct.Match.html) for more details.
|
|
21
|
+
*/
|
|
22
|
+
export interface RuleMatch {
|
|
23
|
+
/** The identifier of the rule that matched. */
|
|
24
|
+
ruleIdentifier: string
|
|
25
|
+
/** The namespace of the rule that matched. */
|
|
26
|
+
namespace: string
|
|
27
|
+
/** The metadata associated with the rule that matched. */
|
|
28
|
+
meta: object
|
|
29
|
+
/** The tags associated with the rule that matched. */
|
|
30
|
+
tags: Array<string>
|
|
31
|
+
/** The matches found by the rule. */
|
|
32
|
+
matches: Array<MatchData>
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* CompilerOptions struct represents the options for the YARA compiler.
|
|
36
|
+
*
|
|
37
|
+
* See [yara_x::Compiler](https://docs.rs/yara-x/latest/yara_x/struct.Compiler.html) for more
|
|
38
|
+
* details.
|
|
39
|
+
*/
|
|
40
|
+
export interface CompilerOptions {
|
|
41
|
+
/** Defines global variables for the YARA rules. */
|
|
42
|
+
defineVariables?: object
|
|
43
|
+
/** A list of module names to ignore during compilation. */
|
|
44
|
+
ignoreModules?: Array<string>
|
|
45
|
+
/** A list of banned modules that cannot be used in the YARA rules. */
|
|
46
|
+
bannedModules?: Array<BannedModule>
|
|
47
|
+
/** A list of features to enable for the YARA rules. */
|
|
48
|
+
features?: Array<string>
|
|
49
|
+
/** Whether to use relaxed regular expression syntax. */
|
|
50
|
+
relaxedReSyntax?: boolean
|
|
51
|
+
/** Whether to optimize conditions in the YARA rules. */
|
|
52
|
+
conditionOptimization?: boolean
|
|
53
|
+
/** Whether to raise an error on slow patterns. */
|
|
54
|
+
errorOnSlowPattern?: boolean
|
|
55
|
+
/** Whether to raise an error on slow loops. */
|
|
56
|
+
errorOnSlowLoop?: boolean
|
|
57
|
+
}
|
|
58
|
+
/** BannedModule struct represents a module that is banned from being used in YARA rules. */
|
|
59
|
+
export interface BannedModule {
|
|
60
|
+
/** The name of the banned module. */
|
|
61
|
+
name: string
|
|
62
|
+
/** The title of the error message if the module is used. */
|
|
63
|
+
errorTitle: string
|
|
64
|
+
/** The error message if the module is used. */
|
|
65
|
+
errorMessage: string
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* CompilerWarning struct represents a warning generated by the YARA compiler.
|
|
69
|
+
*
|
|
70
|
+
* See [yara_x::CompilerWarning](https://docs.rs/yara-x/latest/yara_x/warnings/enum.Warning.html)
|
|
71
|
+
* for more details.
|
|
72
|
+
*/
|
|
73
|
+
export interface CompilerWarning {
|
|
74
|
+
/** The code of the warning. */
|
|
75
|
+
code: string
|
|
76
|
+
/** The message of the warning. */
|
|
77
|
+
message: string
|
|
78
|
+
/** The source of the warning, if available. */
|
|
79
|
+
source?: string
|
|
80
|
+
/** The line number where the warning occurred, if available. */
|
|
81
|
+
line?: number
|
|
82
|
+
/** The column number where the warning occurred, if available. */
|
|
83
|
+
column?: number
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* CompilerError struct represents an error generated by the YARA compiler.
|
|
87
|
+
*
|
|
88
|
+
* See
|
|
89
|
+
* [yara_x::CompileError](https://docs.rs/yara-x/latest/yara_x/errors/enum.CompileError.html)
|
|
90
|
+
* for more details.
|
|
91
|
+
*/
|
|
92
|
+
export interface CompilerError {
|
|
93
|
+
/** The code of the error. */
|
|
94
|
+
code: string
|
|
95
|
+
/** The message of the error. */
|
|
96
|
+
message: string
|
|
97
|
+
/** The source of the error, if available. */
|
|
98
|
+
source?: string
|
|
99
|
+
/** The line number where the error occurred, if available. */
|
|
100
|
+
line?: number
|
|
101
|
+
/** The column number where the error occurred, if available. */
|
|
102
|
+
column?: number
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* CompileResult struct represents the result of compiling YARA rules.
|
|
106
|
+
* It contains any warnings or errors generated during the compilation process.
|
|
107
|
+
*/
|
|
108
|
+
export interface CompileResult {
|
|
109
|
+
/** Any warnings generated during the compilation process. */
|
|
110
|
+
warnings: Array<CompilerWarning>
|
|
111
|
+
/** Any errors generated during the compilation process. */
|
|
112
|
+
errors: Array<CompilerError>
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* Compiles a YARA rule source string and returns any warnings or errors generated during the
|
|
116
|
+
* compilation process.
|
|
117
|
+
*
|
|
118
|
+
* Exported as `validate` in the NAPI interface.
|
|
119
|
+
*
|
|
120
|
+
* Example
|
|
121
|
+
*
|
|
122
|
+
* ```javascript
|
|
123
|
+
* const { validate } = require('your_yara_module');
|
|
124
|
+
* const result = validate('rule example { strings: $a = "example" condition: $a }');
|
|
125
|
+
* ```
|
|
126
|
+
*/
|
|
127
|
+
export declare function validate(ruleSource: string, options?: CompilerOptions | undefined | null): CompileResult
|
|
128
|
+
/**
|
|
129
|
+
* Compiles a YARA rule source string and returns a YaraX instance with the compiled rules.
|
|
130
|
+
*
|
|
131
|
+
* Exported as `compile` in the NAPI interface.
|
|
132
|
+
*
|
|
133
|
+
* Example
|
|
134
|
+
*
|
|
135
|
+
* ```javascript
|
|
136
|
+
* const { compile } = require('your_yara_module');
|
|
137
|
+
* const yarax = compile('rule example { strings: $a = "example" condition: $a }');
|
|
138
|
+
* ```
|
|
139
|
+
*/
|
|
140
|
+
export declare function compile(ruleSource: string, options?: CompilerOptions | undefined | null): YaraX
|
|
141
|
+
/**
|
|
142
|
+
* Creates a new YaraX instance with empty rules and no source code.
|
|
143
|
+
*
|
|
144
|
+
* Exported as `create` in the NAPI interface.
|
|
145
|
+
*
|
|
146
|
+
* Example
|
|
147
|
+
*
|
|
148
|
+
* ```javascript
|
|
149
|
+
* const { create } = require('your_yara_module');
|
|
150
|
+
* const yarax = create();
|
|
151
|
+
*
|
|
152
|
+
* // Now you can add rules or compile them later
|
|
153
|
+
*
|
|
154
|
+
* yarax.addRuleSource('rule example { strings: $a = "example" condition: $a }');
|
|
155
|
+
* yarax.addRuleFile('path/to/rule_file.yar');
|
|
156
|
+
* yarax.defineVariable('myVar', 'myValue');
|
|
157
|
+
* ```
|
|
158
|
+
*/
|
|
159
|
+
export declare function create(): YaraX
|
|
160
|
+
/**
|
|
161
|
+
* Creates a new YaraX instance from a file containing YARA rules.
|
|
162
|
+
*
|
|
163
|
+
* Exported as `fromFile` in the NAPI interface.
|
|
164
|
+
*
|
|
165
|
+
* Example
|
|
166
|
+
*
|
|
167
|
+
* ```javascript
|
|
168
|
+
* const { fromFile } = require('your_yara_module');
|
|
169
|
+
* const yarax = fromFile('path/to/rule_file.yar');
|
|
170
|
+
* ```
|
|
171
|
+
*/
|
|
172
|
+
export declare function fromFile(rulePath: string, options?: CompilerOptions | undefined | null): YaraX
|
|
173
|
+
/**
|
|
174
|
+
* Compiles a YARA rule source string to a WASM file.
|
|
175
|
+
*
|
|
176
|
+
* Exported as `compileToWasm` in the NAPI interface.
|
|
177
|
+
*
|
|
178
|
+
* Example
|
|
179
|
+
*
|
|
180
|
+
* ```javascript
|
|
181
|
+
* const { compileToWasm } = require('your_yara_module');
|
|
182
|
+
* compileToWasm('rule example { strings: $a = "example" condition: $a }', 'output.wasm');
|
|
183
|
+
* ```
|
|
184
|
+
*/
|
|
185
|
+
export declare function compileToWasm(ruleSource: string, outputPath: string, options?: CompilerOptions | undefined | null): void
|
|
186
|
+
/**
|
|
187
|
+
* Compiles a YARA rule file to a WASM file.
|
|
188
|
+
*
|
|
189
|
+
* Exported as `compileFileToWasm` in the NAPI interface.
|
|
190
|
+
*
|
|
191
|
+
* Example
|
|
192
|
+
*
|
|
193
|
+
* ```javascript
|
|
194
|
+
* const { compileFileToWasm } = require('your_yara_module');
|
|
195
|
+
* compileFileToWasm('path/to/rule_file.yar', 'output.wasm');
|
|
196
|
+
* ```
|
|
197
|
+
*/
|
|
198
|
+
export declare function compileFileToWasm(rulePath: string, outputPath: string, options?: CompilerOptions | undefined | null): void
|
|
199
|
+
/**
|
|
200
|
+
* YaraX struct represents the YARA rules and their associated data.
|
|
201
|
+
* It contains the compiled rules, source code, warnings, and variables.
|
|
202
|
+
*
|
|
203
|
+
* See [yara_x::Rules](https://docs.rs/yara-x/latest/yara_x/struct.Rules.html) for more details.
|
|
204
|
+
*/
|
|
205
|
+
export declare class YaraX {
|
|
206
|
+
getWarnings(): Array<CompilerWarning>
|
|
207
|
+
/**
|
|
208
|
+
* Scans the provided data using the compiled YARA rules.
|
|
209
|
+
* This function takes the scanned data and an optional object of variables,
|
|
210
|
+
* and returns a vector of RuleMatch representing the matching rules found during the scan.
|
|
211
|
+
*/
|
|
212
|
+
scan(data: Buffer, variables?: Record<string, string | number>): Array<RuleMatch>
|
|
213
|
+
/**
|
|
214
|
+
* Scans a file using the compiled YARA rules.
|
|
215
|
+
* This function takes the file path and an optional object of variables,
|
|
216
|
+
* and returns a vector of RuleMatch representing the matching rules found during the scan.
|
|
217
|
+
*/
|
|
218
|
+
scanFile(filePath: string, variables?: Record<string, string | number>): Array<RuleMatch>
|
|
219
|
+
/**
|
|
220
|
+
* Emits a WASM file from the compiled YARA rules.
|
|
221
|
+
* This function takes the output path and writes the compiled rules to a WASM file.
|
|
222
|
+
*/
|
|
223
|
+
emitWasmFile(outputPath: string): void
|
|
224
|
+
/**
|
|
225
|
+
* Scans the provided data asynchronously using the compiled YARA rules.
|
|
226
|
+
* This function takes the scanned data and an optional object of variables,
|
|
227
|
+
* and returns an AsyncTask that will resolve to a vector of RuleMatch representing the matching
|
|
228
|
+
* rules found during the scan.
|
|
229
|
+
*
|
|
230
|
+
* This allows for non-blocking scanning of data, which can be useful for large datasets or
|
|
231
|
+
* performance-critical applications.
|
|
232
|
+
*/
|
|
233
|
+
scanAsync(data: Buffer, variables?: object | undefined | null): Promise<unknown>
|
|
234
|
+
/**
|
|
235
|
+
* Scans a file asynchronously using the compiled YARA rules.
|
|
236
|
+
* This function takes the file path and an optional object of variables,
|
|
237
|
+
* and returns an AsyncTask that will resolve to a vector of RuleMatch representing the matching
|
|
238
|
+
* rules found during the scan.
|
|
239
|
+
*
|
|
240
|
+
* This allows for non-blocking scanning of files, which can be useful for large files or
|
|
241
|
+
* performance-critical applications.
|
|
242
|
+
*/
|
|
243
|
+
scanFileAsync(filePath: string, variables?: object | undefined | null): Promise<unknown>
|
|
244
|
+
/**
|
|
245
|
+
* Emits a WASM file asynchronously from the compiled YARA rules.
|
|
246
|
+
* This function takes the output path
|
|
247
|
+
* and returns an AsyncTask that will resolve when the WASM file is successfully emitted.
|
|
248
|
+
*/
|
|
249
|
+
emitWasmFileAsync(outputPath: string): Promise<unknown>
|
|
250
|
+
/**
|
|
251
|
+
* Adds a rule source to the YARA compiler.
|
|
252
|
+
* This function takes a rule source string,
|
|
253
|
+
* compiles it, and updates the YaraX instance with the new rules.
|
|
254
|
+
*/
|
|
255
|
+
addRuleSource(ruleSource: string): void
|
|
256
|
+
/**
|
|
257
|
+
* Adds a rule file to the YARA compiler.
|
|
258
|
+
* This function takes a file path,
|
|
259
|
+
* reads the file content, and adds it to the YaraX instance.
|
|
260
|
+
*/
|
|
261
|
+
addRuleFile(filePath: string): void
|
|
262
|
+
/**
|
|
263
|
+
* Defines a variable for the YARA compiler.
|
|
264
|
+
* This function takes a variable name and value,
|
|
265
|
+
* and adds it to the YaraX instance.
|
|
266
|
+
*/
|
|
267
|
+
defineVariable(name: string, value: string): void
|
|
268
|
+
}
|
package/index.js
ADDED
|
@@ -0,0 +1,321 @@
|
|
|
1
|
+
/* tslint:disable */
|
|
2
|
+
/* eslint-disable */
|
|
3
|
+
/* prettier-ignore */
|
|
4
|
+
|
|
5
|
+
/* auto-generated by NAPI-RS */
|
|
6
|
+
|
|
7
|
+
const { existsSync, readFileSync } = require('fs')
|
|
8
|
+
const { join } = require('path')
|
|
9
|
+
|
|
10
|
+
const { platform, arch } = process
|
|
11
|
+
|
|
12
|
+
let nativeBinding = null
|
|
13
|
+
let localFileExisted = false
|
|
14
|
+
let loadError = null
|
|
15
|
+
|
|
16
|
+
function isMusl() {
|
|
17
|
+
// For Node 10
|
|
18
|
+
if (!process.report || typeof process.report.getReport !== 'function') {
|
|
19
|
+
try {
|
|
20
|
+
const lddPath = require('child_process').execSync('which ldd').toString().trim()
|
|
21
|
+
return readFileSync(lddPath, 'utf8').includes('musl')
|
|
22
|
+
} catch (e) {
|
|
23
|
+
return true
|
|
24
|
+
}
|
|
25
|
+
} else {
|
|
26
|
+
const { glibcVersionRuntime } = process.report.getReport().header
|
|
27
|
+
return !glibcVersionRuntime
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
switch (platform) {
|
|
32
|
+
case 'android':
|
|
33
|
+
switch (arch) {
|
|
34
|
+
case 'arm64':
|
|
35
|
+
localFileExisted = existsSync(join(__dirname, 'yara-x.android-arm64.node'))
|
|
36
|
+
try {
|
|
37
|
+
if (localFileExisted) {
|
|
38
|
+
nativeBinding = require('./yara-x.android-arm64.node')
|
|
39
|
+
} else {
|
|
40
|
+
nativeBinding = require('@litko/yara-x-android-arm64')
|
|
41
|
+
}
|
|
42
|
+
} catch (e) {
|
|
43
|
+
loadError = e
|
|
44
|
+
}
|
|
45
|
+
break
|
|
46
|
+
case 'arm':
|
|
47
|
+
localFileExisted = existsSync(join(__dirname, 'yara-x.android-arm-eabi.node'))
|
|
48
|
+
try {
|
|
49
|
+
if (localFileExisted) {
|
|
50
|
+
nativeBinding = require('./yara-x.android-arm-eabi.node')
|
|
51
|
+
} else {
|
|
52
|
+
nativeBinding = require('@litko/yara-x-android-arm-eabi')
|
|
53
|
+
}
|
|
54
|
+
} catch (e) {
|
|
55
|
+
loadError = e
|
|
56
|
+
}
|
|
57
|
+
break
|
|
58
|
+
default:
|
|
59
|
+
throw new Error(`Unsupported architecture on Android ${arch}`)
|
|
60
|
+
}
|
|
61
|
+
break
|
|
62
|
+
case 'win32':
|
|
63
|
+
switch (arch) {
|
|
64
|
+
case 'x64':
|
|
65
|
+
localFileExisted = existsSync(
|
|
66
|
+
join(__dirname, 'yara-x.win32-x64-msvc.node')
|
|
67
|
+
)
|
|
68
|
+
try {
|
|
69
|
+
if (localFileExisted) {
|
|
70
|
+
nativeBinding = require('./yara-x.win32-x64-msvc.node')
|
|
71
|
+
} else {
|
|
72
|
+
nativeBinding = require('@litko/yara-x-win32-x64-msvc')
|
|
73
|
+
}
|
|
74
|
+
} catch (e) {
|
|
75
|
+
loadError = e
|
|
76
|
+
}
|
|
77
|
+
break
|
|
78
|
+
case 'ia32':
|
|
79
|
+
localFileExisted = existsSync(
|
|
80
|
+
join(__dirname, 'yara-x.win32-ia32-msvc.node')
|
|
81
|
+
)
|
|
82
|
+
try {
|
|
83
|
+
if (localFileExisted) {
|
|
84
|
+
nativeBinding = require('./yara-x.win32-ia32-msvc.node')
|
|
85
|
+
} else {
|
|
86
|
+
nativeBinding = require('@litko/yara-x-win32-ia32-msvc')
|
|
87
|
+
}
|
|
88
|
+
} catch (e) {
|
|
89
|
+
loadError = e
|
|
90
|
+
}
|
|
91
|
+
break
|
|
92
|
+
case 'arm64':
|
|
93
|
+
localFileExisted = existsSync(
|
|
94
|
+
join(__dirname, 'yara-x.win32-arm64-msvc.node')
|
|
95
|
+
)
|
|
96
|
+
try {
|
|
97
|
+
if (localFileExisted) {
|
|
98
|
+
nativeBinding = require('./yara-x.win32-arm64-msvc.node')
|
|
99
|
+
} else {
|
|
100
|
+
nativeBinding = require('@litko/yara-x-win32-arm64-msvc')
|
|
101
|
+
}
|
|
102
|
+
} catch (e) {
|
|
103
|
+
loadError = e
|
|
104
|
+
}
|
|
105
|
+
break
|
|
106
|
+
default:
|
|
107
|
+
throw new Error(`Unsupported architecture on Windows: ${arch}`)
|
|
108
|
+
}
|
|
109
|
+
break
|
|
110
|
+
case 'darwin':
|
|
111
|
+
localFileExisted = existsSync(join(__dirname, 'yara-x.darwin-universal.node'))
|
|
112
|
+
try {
|
|
113
|
+
if (localFileExisted) {
|
|
114
|
+
nativeBinding = require('./yara-x.darwin-universal.node')
|
|
115
|
+
} else {
|
|
116
|
+
nativeBinding = require('@litko/yara-x-darwin-universal')
|
|
117
|
+
}
|
|
118
|
+
break
|
|
119
|
+
} catch {}
|
|
120
|
+
switch (arch) {
|
|
121
|
+
case 'x64':
|
|
122
|
+
localFileExisted = existsSync(join(__dirname, 'yara-x.darwin-x64.node'))
|
|
123
|
+
try {
|
|
124
|
+
if (localFileExisted) {
|
|
125
|
+
nativeBinding = require('./yara-x.darwin-x64.node')
|
|
126
|
+
} else {
|
|
127
|
+
nativeBinding = require('@litko/yara-x-darwin-x64')
|
|
128
|
+
}
|
|
129
|
+
} catch (e) {
|
|
130
|
+
loadError = e
|
|
131
|
+
}
|
|
132
|
+
break
|
|
133
|
+
case 'arm64':
|
|
134
|
+
localFileExisted = existsSync(
|
|
135
|
+
join(__dirname, 'yara-x.darwin-arm64.node')
|
|
136
|
+
)
|
|
137
|
+
try {
|
|
138
|
+
if (localFileExisted) {
|
|
139
|
+
nativeBinding = require('./yara-x.darwin-arm64.node')
|
|
140
|
+
} else {
|
|
141
|
+
nativeBinding = require('@litko/yara-x-darwin-arm64')
|
|
142
|
+
}
|
|
143
|
+
} catch (e) {
|
|
144
|
+
loadError = e
|
|
145
|
+
}
|
|
146
|
+
break
|
|
147
|
+
default:
|
|
148
|
+
throw new Error(`Unsupported architecture on macOS: ${arch}`)
|
|
149
|
+
}
|
|
150
|
+
break
|
|
151
|
+
case 'freebsd':
|
|
152
|
+
if (arch !== 'x64') {
|
|
153
|
+
throw new Error(`Unsupported architecture on FreeBSD: ${arch}`)
|
|
154
|
+
}
|
|
155
|
+
localFileExisted = existsSync(join(__dirname, 'yara-x.freebsd-x64.node'))
|
|
156
|
+
try {
|
|
157
|
+
if (localFileExisted) {
|
|
158
|
+
nativeBinding = require('./yara-x.freebsd-x64.node')
|
|
159
|
+
} else {
|
|
160
|
+
nativeBinding = require('@litko/yara-x-freebsd-x64')
|
|
161
|
+
}
|
|
162
|
+
} catch (e) {
|
|
163
|
+
loadError = e
|
|
164
|
+
}
|
|
165
|
+
break
|
|
166
|
+
case 'linux':
|
|
167
|
+
switch (arch) {
|
|
168
|
+
case 'x64':
|
|
169
|
+
if (isMusl()) {
|
|
170
|
+
localFileExisted = existsSync(
|
|
171
|
+
join(__dirname, 'yara-x.linux-x64-musl.node')
|
|
172
|
+
)
|
|
173
|
+
try {
|
|
174
|
+
if (localFileExisted) {
|
|
175
|
+
nativeBinding = require('./yara-x.linux-x64-musl.node')
|
|
176
|
+
} else {
|
|
177
|
+
nativeBinding = require('@litko/yara-x-linux-x64-musl')
|
|
178
|
+
}
|
|
179
|
+
} catch (e) {
|
|
180
|
+
loadError = e
|
|
181
|
+
}
|
|
182
|
+
} else {
|
|
183
|
+
localFileExisted = existsSync(
|
|
184
|
+
join(__dirname, 'yara-x.linux-x64-gnu.node')
|
|
185
|
+
)
|
|
186
|
+
try {
|
|
187
|
+
if (localFileExisted) {
|
|
188
|
+
nativeBinding = require('./yara-x.linux-x64-gnu.node')
|
|
189
|
+
} else {
|
|
190
|
+
nativeBinding = require('@litko/yara-x-linux-x64-gnu')
|
|
191
|
+
}
|
|
192
|
+
} catch (e) {
|
|
193
|
+
loadError = e
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
break
|
|
197
|
+
case 'arm64':
|
|
198
|
+
if (isMusl()) {
|
|
199
|
+
localFileExisted = existsSync(
|
|
200
|
+
join(__dirname, 'yara-x.linux-arm64-musl.node')
|
|
201
|
+
)
|
|
202
|
+
try {
|
|
203
|
+
if (localFileExisted) {
|
|
204
|
+
nativeBinding = require('./yara-x.linux-arm64-musl.node')
|
|
205
|
+
} else {
|
|
206
|
+
nativeBinding = require('@litko/yara-x-linux-arm64-musl')
|
|
207
|
+
}
|
|
208
|
+
} catch (e) {
|
|
209
|
+
loadError = e
|
|
210
|
+
}
|
|
211
|
+
} else {
|
|
212
|
+
localFileExisted = existsSync(
|
|
213
|
+
join(__dirname, 'yara-x.linux-arm64-gnu.node')
|
|
214
|
+
)
|
|
215
|
+
try {
|
|
216
|
+
if (localFileExisted) {
|
|
217
|
+
nativeBinding = require('./yara-x.linux-arm64-gnu.node')
|
|
218
|
+
} else {
|
|
219
|
+
nativeBinding = require('@litko/yara-x-linux-arm64-gnu')
|
|
220
|
+
}
|
|
221
|
+
} catch (e) {
|
|
222
|
+
loadError = e
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
break
|
|
226
|
+
case 'arm':
|
|
227
|
+
if (isMusl()) {
|
|
228
|
+
localFileExisted = existsSync(
|
|
229
|
+
join(__dirname, 'yara-x.linux-arm-musleabihf.node')
|
|
230
|
+
)
|
|
231
|
+
try {
|
|
232
|
+
if (localFileExisted) {
|
|
233
|
+
nativeBinding = require('./yara-x.linux-arm-musleabihf.node')
|
|
234
|
+
} else {
|
|
235
|
+
nativeBinding = require('@litko/yara-x-linux-arm-musleabihf')
|
|
236
|
+
}
|
|
237
|
+
} catch (e) {
|
|
238
|
+
loadError = e
|
|
239
|
+
}
|
|
240
|
+
} else {
|
|
241
|
+
localFileExisted = existsSync(
|
|
242
|
+
join(__dirname, 'yara-x.linux-arm-gnueabihf.node')
|
|
243
|
+
)
|
|
244
|
+
try {
|
|
245
|
+
if (localFileExisted) {
|
|
246
|
+
nativeBinding = require('./yara-x.linux-arm-gnueabihf.node')
|
|
247
|
+
} else {
|
|
248
|
+
nativeBinding = require('@litko/yara-x-linux-arm-gnueabihf')
|
|
249
|
+
}
|
|
250
|
+
} catch (e) {
|
|
251
|
+
loadError = e
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
break
|
|
255
|
+
case 'riscv64':
|
|
256
|
+
if (isMusl()) {
|
|
257
|
+
localFileExisted = existsSync(
|
|
258
|
+
join(__dirname, 'yara-x.linux-riscv64-musl.node')
|
|
259
|
+
)
|
|
260
|
+
try {
|
|
261
|
+
if (localFileExisted) {
|
|
262
|
+
nativeBinding = require('./yara-x.linux-riscv64-musl.node')
|
|
263
|
+
} else {
|
|
264
|
+
nativeBinding = require('@litko/yara-x-linux-riscv64-musl')
|
|
265
|
+
}
|
|
266
|
+
} catch (e) {
|
|
267
|
+
loadError = e
|
|
268
|
+
}
|
|
269
|
+
} else {
|
|
270
|
+
localFileExisted = existsSync(
|
|
271
|
+
join(__dirname, 'yara-x.linux-riscv64-gnu.node')
|
|
272
|
+
)
|
|
273
|
+
try {
|
|
274
|
+
if (localFileExisted) {
|
|
275
|
+
nativeBinding = require('./yara-x.linux-riscv64-gnu.node')
|
|
276
|
+
} else {
|
|
277
|
+
nativeBinding = require('@litko/yara-x-linux-riscv64-gnu')
|
|
278
|
+
}
|
|
279
|
+
} catch (e) {
|
|
280
|
+
loadError = e
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
break
|
|
284
|
+
case 's390x':
|
|
285
|
+
localFileExisted = existsSync(
|
|
286
|
+
join(__dirname, 'yara-x.linux-s390x-gnu.node')
|
|
287
|
+
)
|
|
288
|
+
try {
|
|
289
|
+
if (localFileExisted) {
|
|
290
|
+
nativeBinding = require('./yara-x.linux-s390x-gnu.node')
|
|
291
|
+
} else {
|
|
292
|
+
nativeBinding = require('@litko/yara-x-linux-s390x-gnu')
|
|
293
|
+
}
|
|
294
|
+
} catch (e) {
|
|
295
|
+
loadError = e
|
|
296
|
+
}
|
|
297
|
+
break
|
|
298
|
+
default:
|
|
299
|
+
throw new Error(`Unsupported architecture on Linux: ${arch}`)
|
|
300
|
+
}
|
|
301
|
+
break
|
|
302
|
+
default:
|
|
303
|
+
throw new Error(`Unsupported OS: ${platform}, architecture: ${arch}`)
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
if (!nativeBinding) {
|
|
307
|
+
if (loadError) {
|
|
308
|
+
throw loadError
|
|
309
|
+
}
|
|
310
|
+
throw new Error(`Failed to load native binding`)
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
const { YaraX, validate, compile, create, fromFile, compileToWasm, compileFileToWasm } = nativeBinding
|
|
314
|
+
|
|
315
|
+
module.exports.YaraX = YaraX
|
|
316
|
+
module.exports.validate = validate
|
|
317
|
+
module.exports.compile = compile
|
|
318
|
+
module.exports.create = create
|
|
319
|
+
module.exports.fromFile = fromFile
|
|
320
|
+
module.exports.compileToWasm = compileToWasm
|
|
321
|
+
module.exports.compileFileToWasm = compileFileToWasm
|
package/package.json
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@litko/yara-x",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"main": "index.js",
|
|
5
|
+
"types": "index.d.ts",
|
|
6
|
+
"napi": {
|
|
7
|
+
"name": "yara-x",
|
|
8
|
+
"triples": {
|
|
9
|
+
"additional": [
|
|
10
|
+
"x86_64-apple-darwin",
|
|
11
|
+
"aarch64-apple-darwin",
|
|
12
|
+
"x86_64-unknown-linux-gnu",
|
|
13
|
+
"aarch64-unknown-linux-gnu"
|
|
14
|
+
]
|
|
15
|
+
}
|
|
16
|
+
},
|
|
17
|
+
"license": "MIT",
|
|
18
|
+
"devDependencies": {
|
|
19
|
+
"@napi-rs/cli": "^2.18.4",
|
|
20
|
+
"@napi-rs/package-template": "^1.0.0",
|
|
21
|
+
"@types/node": "^22.13.10"
|
|
22
|
+
},
|
|
23
|
+
"engines": {
|
|
24
|
+
"node": ">= 20"
|
|
25
|
+
},
|
|
26
|
+
"publishConfig": {
|
|
27
|
+
"registry": "https://registry.npmjs.org/",
|
|
28
|
+
"access": "public"
|
|
29
|
+
},
|
|
30
|
+
"scripts": {
|
|
31
|
+
"artifacts": "napi artifacts",
|
|
32
|
+
"build": "napi build --platform --release",
|
|
33
|
+
"build:debug": "napi build --platform",
|
|
34
|
+
"universal": "napi universal",
|
|
35
|
+
"version": "napi version",
|
|
36
|
+
"test": "node --test __test__/index.spec.mjs",
|
|
37
|
+
"benchmark": "node __test__/benchmark.mjs"
|
|
38
|
+
},
|
|
39
|
+
"files": [
|
|
40
|
+
"index.js",
|
|
41
|
+
"index.d.ts"
|
|
42
|
+
],
|
|
43
|
+
"keywords": [
|
|
44
|
+
"yara",
|
|
45
|
+
"yara-x",
|
|
46
|
+
"malware",
|
|
47
|
+
"detection",
|
|
48
|
+
"napi-rs",
|
|
49
|
+
"rust"
|
|
50
|
+
],
|
|
51
|
+
"optionalDependencies": {
|
|
52
|
+
"@litko/yara-x-win32-x64-msvc": "0.1.0",
|
|
53
|
+
"@litko/yara-x-darwin-x64": "0.1.0",
|
|
54
|
+
"@litko/yara-x-linux-x64-gnu": "0.1.0",
|
|
55
|
+
"@litko/yara-x-darwin-arm64": "0.1.0",
|
|
56
|
+
"@litko/yara-x-linux-arm64-gnu": "0.1.0"
|
|
57
|
+
}
|
|
58
|
+
}
|