Dactyl is a fast rule engine written in Zig.
Here are the parts of a rule
- Imports (if using regex, etc)
- Metadata
- Strings
- Conditions
Imports allow the use of features disabled by default, for example, to use Regex you must write:
imports: [
"regex"
],
Regex is disabled by default for performance reasons.
Metadata contains the following fields:
- Name
- Author
- Date
- Severity
- Labels
Here is how you would write a metadata statement:
meta: {
name: "Name-Of-Rule",
author: "[User] name or email",
date: "Date of rule creation",
severity: 10, // severity of rule as int/float (i hope decimal numbers aren't too hard for you)
labels: ["ransomware", "wnry", "eternalblue", "apt"]
},
As Dactyl is a pattern matching language, here is how to define strings:
strings: {
$kill_switch: { "text": "www.iuqerfsodpifjposifjposdfjhgosurijfaewrwergwea.com" },
$nocase: { "text": "hEllO", "nocase": true },
$name_1: { "text": "Hello" },
$some_magic: { "hex": "FF 00 10 30 AE AB" },
$some_regex: { "regex": `/\.he(l|l)o$/i` }
},
To execute matching, you need to tell Dactyl what conditions to accept Here is how to define the conditions:
condition: {
any: {
of: ["$some_string", "$maybe_magic"],
any: ["$could", "$be", "$any", "$of", "$these"]
}
}
Here is an example of a working WanaCry rule you can test:
{
imports: [
"regex"
],
meta: {
name: "WannaCry-Ransomware-Dropper",
author: "user@example.com",
date: "2025-12-21",
severity: 10,
labels: ["ransomware", "wnry", "eternalblue", "apt"]
},
strings: {
$kill_switch: { "text": "www.iuqerfsodpifjposifjposdfjhgosurijfaewrwergwea.com" },
$dropper: { "text": "Tasksche.exe", "nocase": true },
$msg_header: { "text": "WanaCrypt0r", "nocase": true },
$btc_1: { "text": "13AM4VW2dhxYgXeQepoHkHSQuy6NgaEb94" },
$btc_2: { "text": "12t9YDPgwueZ9NyMgw519p7AA8isjr6SMw" },
$btc_3: { "text": "115p7UMMngoj1pMvkghijcRdfJNXj6LrLn" },
$wncry_magic: { "hex": "57 41 4E 41 43 52 59 21" },
$ext_regex: { "regex": `/\.wn(cry|ry)$/i` }
},
condition: {
any: {
of: ["$kill_switch", "$wncry_magic"],
any: ["$dropper", "$msg_header", "$btc_1", "$btc_2", "$btc_3"]
}
}
}
Compiling a rule
dactyl <file.dlt> # this command compiles the rules and checks for issuesUsing a rule
dactyl <file.dlt> <sample.exe> # this command will compile the rule then run it on an executableRunning a rule will check the rule against the exe, this is useful when demoing or developing a rule.
Example output:
⌬ Dactyl v0.0.1
────────────────────────────────
MATCH FOUND » WannaCry-Ransomware-Dropper
Time: 87.058ms | Matches: 4
┌─ $dropper at 0xF4D8
0x0000F4D8 74 61 73 6B 73 63 68 65 2E 65 78 65 00 00 00 00 |tasksche.exe....|
0x0000F4E8 54 61 73 6B 53 74 61 72 74 00 00 00 74 2E 77 6E |TaskStart...t.wn|
┌─ $btc_1 at 0xF488
0x0000F488 31 33 41 4D 34 56 57 32 64 68 78 59 67 58 65 51 |13AM4VW2dhxYgXeQ|
0x0000F498 65 70 6F 48 6B 48 53 51 75 79 36 4E 67 61 45 62 |epoHkHSQuy6NgaEb|
┌─ $btc_2 at 0xF464
0x0000F464 31 32 74 39 59 44 50 67 77 75 65 5A 39 4E 79 4D |12t9YDPgwueZ9NyM|
0x0000F474 67 77 35 31 39 70 37 41 41 38 69 73 6A 72 36 53 |gw519p7AA8isjr6S|
┌─ $wncry_magic at 0xEB7C
0x0000EB7C 57 41 4E 41 43 52 59 21 00 00 00 00 25 00 73 00 |WANACRY!....%.s.|
0x0000EB8C 5C 00 25 00 73 00 00 00 43 6C 6F 73 65 48 61 6E |\.%.s...CloseHan|
You can convert YARA to Dactyl like so:
dactyl convert <file.yara> # will parse all rules and create the necessary filesLibrary documentation will be available soon™
These modules are disabled by default, but can be re-enabled via the imports
| disabled module | reason |
|---|---|
| Regex | Performance |
