Malspark

Tools

capa and YARA

Where capa and YARA run in an analysis and what they write to the ledger.

capa (FLARE's capability detector) and YARA reach a run in three places, so a run can have their answers even with no static provider at all.

WhereWhat runsWritten to the ledger as
The triage packyara_scan and capa (under the static provider's budget), before any analyst startsthe pack's own entries
The analysis sidecarthe capa and yara_scan tools, which an agent callsthe agent's calls
The capa_yara static providertwo deterministic passes, no tools and no model loopentries under the agent id capa_yara

YARA runs once more, after the report is built: the drafted YARA rule (§10.2) is checked against the sample it was drafted from, through probe rules written from the same string declarations, and what that found is written on the rule's own record (matches_sample, matched_by, sample_strings, sample_not_checked), not to the ledger. See Reporting.

The capa_yara provider

core.static.provider          = capa_yara
core.static.capa.rules_dir    = data/capa-rules
core.static.yara.rules_dir    = data/yara_rules
SettingDefaultNotes
core.static.capa.rules_dirdata/capa-rulescapa's rules.
core.static.capa.signatures_dirdata/capa-signaturescapa's library signatures, loaded where capa itself loads them: for a PE on the vivisect backend.
core.static.capa.timeout_seconds300capa's budget.
core.static.capa.backendautoauto is the backend capa itself picks for the format it detects: its .NET backend for a managed assembly, vivisect for native code. vivisect, pefile or binja is used whatever the format.
core.static.yara.rules_dirdata/yara_rulesThe operator's own rule directory, scanned only by this provider. Its scan runs with no timeout. The drafted YARA rule's check against its sample (§10.2) has its own budget, core.reporting.detection_rule_check_seconds (the former core.static.yara.timeout_seconds, moved on upgrade), and a tool server's call budget is core.mcp.breaker.default_call_timeout_seconds.

Both libraries are optional extras of the package, capa (flare-capa) and yara (yara-python): uv sync --extra capa --extra yara. The backend image installs the capa, yara and tools extras. A missing library costs the provider its evidence, with one warning, rather than failing a job.

capa runs in a child process of its own, under the budget above. The worker's environment is not passed to it: it gets the base environment the tool servers get, and its own run directory as its home. That keeps the worker's credentials out of its environment block only. The child runs as the worker's own user, so it can still read the worker's environment from /proc/<worker pid>/environ; running tools as a user of their own, apart from the worker, is the isolation work that closes that, and it is not done yet.

Its run directory is <staging base>/job-…/capa/run-*, in the job's own staging directory, so the job's teardown removes it however the run ended; a run with no job (a script, an analysis server started by hand) gets a private temporary directory of its own (maljan-capa-*), removed when the run ends. A run with no job whose process was killed outright leaves its directory; the next run with no job removes such directories of the same user once nothing in them has changed for the staging TTL (MALJAN_STAGING_TTL_HOURS, a day by default; zero keeps them). It dies with the process that started it, whether that process is killed, exits or has its process group stopped.

capa's rules and its library-identification signatures are not in the flare-capa package. The backend image fetches both for the flare-capa version uv.lock pins, checks each against its recorded sha256 (the signatures come from flare-capa's own sdist, whose digest is the one uv.lock records), and puts them in data/capa-rules and data/capa-signatures. A stack that bind-mounts its own data/ over the image's, as the shipped compose file does, reads that directory's copies instead: make setup (make external) fetches the same pinned set there (scripts/dev/fetch_capa_data.sh). A directory that is already there is left as it is, and the script says whether it is the pinned version. The rules arrive without their repository's CI folder, so the rule count the connection test gives is the number of rules capa loads.

With the signatures capa identifies library code (the runtime's startup code, statically linked library functions) in a PE it reads with vivisect, and matches no rule in it:

  • A rule that matches only inside library code is no longer reported. That is capa's intended false-positive reduction.
  • A small PE takes about 2 s longer, the time the signatures take to load.
  • The capa answer names the functions it identified under library_functions (each start and name), and their starts stay in function_starts. A run that looked for none says why in their place: no signature directory, or capa loads no signatures for that format and backend.
  • A workstation gets the signatures at its next make setup or make external. capa's answers there then move against runs made before it.

To run without library identification, set core.static.capa.signatures_dir to an empty value or to a path with no directory there. capa runs as before, and its answer says that no signature directory was there.

The rule corpora of the analysis sidecar

The Sigma and YARA corpora the analysis tool server scans with are named in that server's env (Settings → Tool servers → analysis → env):

NameWhat it namesDefault
MALJAN_SIGMA_RULES_DIRDirectory of Sigma rule YAML, loaded recursively.data/sigma_rules
MALJAN_YARA_RULES_DIRThe YARA rule file the scan compiles.data/yara_ttp_rules.yaml

A path that does not exist means an empty corpus and no matches, not a failure. A YARA pattern must be a fact about a sample rather than a word that describes one; how the shipped rules are written, and how a rule asserts nothing when it cannot be that specific, is in Rule corpora.

A rule match is not a claim

A technique that only a deterministic rule asserted, and no analyst claimed, is marked as such in the report's ATT&CK table — "rule match only" with the rule and its string count — and grounds no capability word in the report's prose. capa's place in the triage pack is described in The triage pack.

Edit on GitHub

On this page