Skip to main content

Modules

Modules extend the YARA-X rule language with knowledge that the core engine does not have on its own. A plain rule matches on the raw bytes of a file; a module understands structure — the sections of a PE executable, the imports of an ELF binary, the entropy of a byte range, the current time, and so on. Once a module is imported, its fields and functions become available inside a rule's condition.

Modules are written in Rust and ship compiled into the engine, so there is nothing to install. You only need to make a module visible to a rule with the import statement.

import "pe"

rule single_section_executable {
condition:
pe.is_pe and pe.number_of_sections == 1
}
note

The import statement appears at the top of the file, before any rule. Importing a module that a rule never uses is harmless. A rule can import as many modules as it needs.

Built-in modules

YARA-X ships the following modules. The set is verified against the official modules documentation.

ModulePurpose
peParse Windows Portable Executable (PE) files — sections, imports, exports, headers, signatures.
elfParse ELF executables and shared objects (Linux and other Unix-like systems).
machoParse Mach-O binaries used by macOS and iOS, including fat/universal files.
dotnetInspect .NET assembly metadata (streams, GUIDs, type and method tables).
dexParse Android DEX (Dalvik Executable) files.
lnkParse Windows shortcut (.lnk) files.
crxParse Chrome extension (CRX) packages.
mathStatistical and numeric helpers — entropy, mean, deviation, min/max, and more.
hashCompute MD5, SHA-1, SHA-256, CRC32, and a simple 32-bit checksum over byte ranges or strings.
stringString helper functions for use inside conditions.
timeAccess the current time, for time-relative conditions.
consolePrint values to standard output while a rule is evaluated, for debugging.
info

Module availability can depend on how YARA-X was built. Some modules are gated behind Cargo feature flags, so a custom build might exclude one or more of them. The modules listed above are those documented for the standard distribution. Check yr --help and the documentation for the build you are using if a module is missing.

Referencing module fields

After importing a module you reference its members with dot notation: module.field or module.function(args). Fields hold values parsed from the scanned data; functions compute a value on demand.

Some fields are scalars, others are arrays or dictionaries that you index or iterate over. The condition below combines a scalar field, an array element, and a function call from the pe module.

import "pe"

rule example_pe_condition {
meta:
description = "Illustrative example — not a real detection rule"
condition:
pe.is_pe and
pe.number_of_sections > 1 and
pe.sections[0].name == ".text" and
pe.imports("kernel32.dll", "CreateFileW")
}
note

The rule above is illustrative. It demonstrates syntax rather than detecting any specific malware family.

The pe module

The pe module is the most widely used. A few of its commonly referenced members:

MemberKindMeaning
pe.is_pefield (bool)True when the scanned file is a PE.
pe.number_of_sectionsfield (int)Count of sections in the file.
pe.entry_pointfield (int)Entry point as a file offset.
pe.machinefield (int)Target machine type.
pe.timestampfield (int)Build timestamp as a Unix epoch value.
pe.sections[i].namearray fieldName of the i-th section.
pe.imports(dll)functionNumber of functions imported from dll.
pe.imports(dll, func)functionTrue when func is imported from dll.
pe.exports(func)functionTrue when func is exported.
import "pe"

rule control_panel_applet {
condition:
pe.is_pe and pe.exports("CPlApplet")
}

The hash module

The hash module computes cryptographic and non-cryptographic digests. Each function has two forms: one that operates on a byte range of the scanned data (offset, size), and one that operates on a literal string.

FunctionResult
hash.md5(offset, size) / hash.md5(string)MD5 digest (lowercase hex string).
hash.sha1(offset, size) / hash.sha1(string)SHA-1 digest.
hash.sha256(offset, size) / hash.sha256(string)SHA-256 digest.
hash.crc32(offset, size) / hash.crc32(string)CRC32 checksum (integer).
hash.checksum32(offset, size) / hash.checksum32(string)32-bit sum of all bytes.
import "hash"

rule known_file_by_md5 {
condition:
hash.md5(0, filesize) == "feba6c919e3797e7778e8f2e85fa033d"
}
tip

filesize is a built-in constant equal to the size of the data being scanned. Pairing it with an offset of 0 — as in hash.md5(0, filesize) or math.entropy(0, filesize) — applies a function across the whole file.

The math module

The math module provides statistical helpers, most often used to gauge how "random" a byte range looks. High entropy frequently indicates compressed or encrypted content.

FunctionResult
math.entropy(offset, size)Shannon entropy of the byte range (0–8).
math.mean(offset, size)Mean byte value over the range.
math.deviation(offset, size, mean)Average deviation from a given mean.
math.in_range(value, lower, upper)True when value falls within bounds.
math.min(a, b) / math.max(a, b)Smaller / larger of two integers.
import "math"

rule likely_packed {
condition:
math.entropy(0, filesize) >= 7.0
}

The time module

The time module exposes the current time, letting a rule reason about when it runs rather than only what it scans. time.now() returns the current time as a Unix timestamp (seconds since the epoch).

import "pe"
import "time"

rule recently_built_pe {
meta:
description = "Illustrative example — flags PEs built within the last 24 hours"
condition:
pe.is_pe and
(time.now() - pe.timestamp) < 86400
}
note

This rule is illustrative. Compile timestamps are attacker-controlled and unreliable, so a real rule would not depend on pe.timestamp alone.

Inspecting module output

Before writing conditions, it helps to see exactly what a module parses out of a given file. The yr dump command prints a module's structured output for a target so you can discover the available fields and their values.

yr dump --module pe sample.exe

The output mirrors the fields you reference in conditions — sections, imports, headers, and so on — making it a practical way to confirm field names and inspect real values.

Sources