Skip to content

Commit 5e1fe67

Browse files
authored
Merge pull request #272 from magicsword-io/yara_update_260313
yara-generator: add validator, bump version & rules
2 parents e473d77 + 799c48b commit 5e1fe67

9 files changed

Lines changed: 37621 additions & 22335 deletions
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
name: Validate Malicious YARA Rules
2+
3+
on:
4+
push:
5+
branches:
6+
- "*"
7+
paths:
8+
- "bin/yara-generator/**"
9+
- "!bin/yara-generator/README.md"
10+
- "yaml/**"
11+
- "detections/yara/**"
12+
pull_request:
13+
branches:
14+
- main
15+
paths:
16+
- "bin/yara-generator/**"
17+
- "!bin/yara-generator/README.md"
18+
- "yaml/**"
19+
- "detections/yara/**"
20+
21+
jobs:
22+
validate-malicious-yara-rules:
23+
runs-on: ubuntu-latest
24+
steps:
25+
- uses: actions/checkout@v2
26+
with:
27+
lfs: true
28+
submodules: true
29+
30+
- name: Set up Python 3.11
31+
uses: actions/setup-python@v4.5.0
32+
with:
33+
python-version: "3.11"
34+
35+
- name: Install YARA
36+
run: sudo apt-get update && sudo apt-get install -y yara
37+
38+
- name: Install validator dependencies
39+
run: python -m pip install -r ./bin/yara-generator/requirements.txt
40+
41+
- name: Validate committed malicious YARA rules
42+
run: >
43+
python ./bin/yara-generator/validate-malicious-rules.py
44+
--skip-generate
45+
--json-output
46+
--output-dir "${RUNNER_TEMP}/yara-malicious-validation"

bin/yara-generator/README.md

Lines changed: 171 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ This YARA rule generator creates YARA rules for the vulnerable / malicious drive
66

77
The generator processes the input samples and extract specific 'VersionInfo' values from the driver's PE headers. This includes e.g., the company name, file version, product version, description and other values. It then creates YARA rules that look for these specific values and uses a condition that's very permissive (`all of them`). This allows us to detect the drivers even if they are embedded in another file or loaded into memory.
88

9-
The rule generator in version 0.4 generates five output files:
9+
The rule generator in version 0.5 generates five output files:
1010

1111
| File Name | Description | Score |
1212
| --- | --- | --- |
@@ -20,27 +20,53 @@ The rule generator in version 0.4 generates five output files:
2020

2121
## Requirements
2222

23-
* [Python 3.10](https://www.python.org/downloads/)
24-
* [Poetry](https://python-poetry.org/docs/#installation)
23+
* [pyenv](https://github.com/pyenv/pyenv)
24+
* Python 3.10+ (tested with Python 3.13.5)
25+
* `pip` (for `pefile` and `pyyaml`)
2526

26-
## Setup
27+
## Setup (pyenv + venv)
2728

28-
1. Install dependencies:
29+
1. Initialize `pyenv` in `zsh`:
2930

31+
```sh
32+
echo 'export PYENV_ROOT="$HOME/.pyenv"' >> ~/.zshrc
33+
echo '[[ -d $PYENV_ROOT/bin ]] && export PATH="$PYENV_ROOT/bin:$PATH"' >> ~/.zshrc
34+
echo 'eval "$(pyenv init - zsh)"' >> ~/.zshrc
35+
exec zsh
3036
```
31-
poetry install
37+
38+
2. Create and activate a project virtual environment:
39+
40+
```sh
41+
cd /path/to/LOLDrivers
42+
pyenv install -s 3.13.5
43+
pyenv local 3.13.5
44+
python -m venv .venv
45+
source .venv/bin/activate # zsh/bash
46+
# source .venv/bin/activate.fish # fish shell
47+
python -m pip install --upgrade pip
48+
python -m pip install -r ./bin/yara-generator/requirements.txt
3249
```
3350

34-
2. Activate the virtual environment:
51+
Shell-agnostic alternative (no activation required):
3552

53+
```sh
54+
cd /path/to/LOLDrivers
55+
python -m venv .venv
56+
./.venv/bin/python -m pip install --upgrade pip
57+
./.venv/bin/python -m pip install -r ./bin/yara-generator/requirements.txt
3658
```
37-
poetry shell
59+
60+
3. Verify dependencies:
61+
62+
```sh
63+
python -c "import yaml, pefile; print('deps-ok')"
3864
```
3965

4066
## Usage
4167

4268
```sh
43-
usage: yara-generator.py [-h] [-d [driver-files ...]] [-y [yaml-files ...]] [-o output-folder] [--debug]
69+
usage: yara-generator.py [-h] [-d [driver-files ...]] [-y [yaml-files ...]] [-f log-file] [-o output-folder] [--debug]
4470

4571
YARA Rule Generator for PE Header Info
4672

@@ -49,38 +75,168 @@ options:
4975
-d [driver-files ...]
5076
Path to driver directories (can be used multiple times)
5177
-y [yaml-files ...] Path to YAML files with information on the drivers (can be used multiple times)
78+
-f log-file Write a log file
5279
-o output-folder Output folder for rules
5380
--debug Debug output
5481
```
5582
83+
### Default paths
84+
85+
If no `-d`, `-y`, or `-o` values are given, defaults are resolved relative to the script location (`bin/yara-generator/`):
86+
87+
* Drivers: `../../drivers/`
88+
* YAML metadata: `../../yaml/`
89+
* Output: `../../detections/yara/`
90+
91+
This means running from the repository root or from the script directory works consistently.
92+
93+
### YAML validation
94+
95+
The generator skips YAML files that are invalid, do not parse to a top-level mapping, or do not contain a `KnownVulnerableSamples` list. Skipped files are reported in the log output.
96+
97+
### Existing rule files
98+
99+
The generator now merges newly generated rules with the existing output files instead of blindly overwriting them.
100+
101+
Rule update behavior:
102+
103+
* If an existing rule has identical detection logic (`strings` and `condition`), the existing rule is kept unchanged. Its original `date` is preserved and no `modified` field is added or updated.
104+
* If an existing rule changes, the original `date` is preserved and a `modified` field is added or updated with the current date.
105+
* If a rule is new, it is added with `date` set to the current date.
106+
* If an older rule exists in the output file but no replacement rule is generated in the current run, the older rule is preserved as-is.
107+
108+
The merge logic also avoids churn from regenerated rules that are semantically identical but would otherwise only differ by the freshly generated `date` value.
109+
56110
## Examples
57111
112+
### Quick start (first run)
113+
114+
```sh
115+
cd /path/to/LOLDrivers
116+
python3 -m venv .venv
117+
./.venv/bin/python -m pip install -r ./bin/yara-generator/requirements.txt
118+
./.venv/bin/python ./bin/yara-generator/yara-generator.py
119+
```
120+
58121
### Working on Linux / macOS
59122
60-
Generate the YARA rules and then use the command line tool YARA to scan the home folder using these rules:
123+
Generate the YARA rules (after setup/dependency install):
61124
62125
```sh
63-
python yara-generator.py -d ../../drivers/
126+
source .venv/bin/activate
127+
python ./bin/yara-generator/yara-generator.py
64128
```
65129
66-
Show debug output while generating the rules
130+
Show debug output while generating the rules:
67131
68132
```sh
69-
python yara-generator.py -d ../../drivers/ --debug
133+
source .venv/bin/activate
134+
python ./bin/yara-generator/yara-generator.py --debug
70135
```
71136
72137
### Working on Windows
73138
74139
Generate the YARA rules and then use the command line tool YARA to scan the drive C: using these rules:
75140
76141
```sh
77-
python yara-generator.py -d ..\..\drivers\
142+
python .\bin\yara-generator\yara-generator.py
78143
```
79144
80145
Show debug output while generating the rules
81146
82147
```sh
83-
python yara-generator.py -d ..\..\drivers\ --debug
148+
python .\bin\yara-generator\yara-generator.py --debug
149+
```
150+
151+
## Troubleshooting
152+
153+
If you see:
154+
155+
```text
156+
ModuleNotFoundError: No module named 'yaml'
157+
```
158+
159+
then dependencies are missing in the active Python environment. Install them in your venv and run again:
160+
161+
```sh
162+
./.venv/bin/python -m pip install -r ./bin/yara-generator/requirements.txt
163+
./.venv/bin/python ./bin/yara-generator/yara-generator.py
164+
```
165+
166+
If you see:
167+
168+
```text
169+
source: Error while reading file '.venv/bin/activate'
170+
```
171+
172+
you are likely using `fish` shell. Use either:
173+
174+
```sh
175+
source .venv/bin/activate.fish
176+
```
177+
178+
or run commands directly with `./.venv/bin/python` (shell-agnostic).
179+
180+
If you see:
181+
182+
```text
183+
error: externally-managed-environment
184+
```
185+
186+
you are installing into system/Homebrew Python. Use the virtualenv interpreter path (`./.venv/bin/python -m pip ...`) instead.
187+
188+
## Validate Rules Against Repo Samples
189+
190+
Automated validation (recommended):
191+
192+
```sh
193+
./.venv/bin/python ./bin/yara-generator/validate-malicious-rules.py
194+
```
195+
196+
Useful options:
197+
198+
```sh
199+
# Reuse existing generated rules (skip regeneration)
200+
./.venv/bin/python ./bin/yara-generator/validate-malicious-rules.py --skip-generate
201+
202+
# Write outputs to a custom folder
203+
./.venv/bin/python ./bin/yara-generator/validate-malicious-rules.py --output-dir /tmp/yara-malicious-validation
204+
```
205+
206+
The script writes hit files and a JSON summary (default: `/tmp/yara-malicious-validation/summary.json`).
207+
It reports `intentionally skipped samples` separately (from `SKIP_DRIVERS`) and excludes them from `missing expected matches`.
208+
It also reports root-cause breakdown for missing matches (`no PE FileInfo`, `insufficient VersionInfo strings`, `no YAML for grouped representative`, `grouped into vulnerable rule`).
209+
When `--skip-generate` is used and no generator log exists yet, the script creates a temporary generator log under the output directory so missing matches can still be classified without rewriting the checked-in rule files.
210+
The script exits with status `2` if `missing_reason_counts.unknown` is greater than `0`, which makes it suitable for CI.
211+
212+
Manual validation commands (equivalent workflow):
213+
214+
Run these commands from the repository root to confirm malicious-driver rules match malicious samples tracked in `yaml/`.
215+
216+
```sh
217+
cd /path/to/LOLDrivers
218+
./.venv/bin/python ./bin/yara-generator/yara-generator.py
219+
```
220+
221+
Scan all driver samples with both malicious rule sets:
222+
223+
```sh
224+
yara -r ./detections/yara/yara-rules_mal_drivers.yar ./drivers > /tmp/yara-mal-hits.txt
225+
yara -r ./detections/yara/other/yara-rules_mal_drivers_strict.yar ./drivers > /tmp/yara-mal-strict-hits.txt
226+
```
227+
228+
Quick hit counts:
229+
230+
```sh
231+
wc -l /tmp/yara-mal-hits.txt /tmp/yara-mal-strict-hits.txt
232+
awk '{print $2}' /tmp/yara-mal-hits.txt | sort -u | wc -l
233+
awk '{print $2}' /tmp/yara-mal-strict-hits.txt | sort -u | wc -l
234+
```
235+
236+
Get a full analytics summary (including missing/extra sets with hash-to-file mapping):
237+
238+
```sh
239+
./.venv/bin/python ./bin/yara-generator/validate-malicious-rules.py --skip-generate --json-output
84240
```
85241
86242
## Example Output

0 commit comments

Comments
 (0)