Skip to content

YARA on VirusTotal: Livehunt and Retrohunt

How YARA is used on VirusTotal: Livehunt for new submissions, Retrohunt over past files, the vt module, and how to test rules locally before running them there.

Published 3 min read

VirusTotal, where YARA was born, is also one of the main places where YARA rules run at scale. Its hunting features let analysts apply rules to the constant stream of submitted files and to a window of past submissions. This guide summarises how they relate to rules you write and test locally. Feature names and limits are VirusTotal's; check its documentation for the current details of your subscription.

Crowdsourced YARA rules

VirusTotal also runs a selection of public rule sets against every file and shows matching "crowdsourced" rules on file reports, with a link to the rule's source. Many of those rules come from the same repositories mirrored in this library.

Livehunt

Livehunt runs a set of your rules against new files as they are submitted and notifies you on matches. Typical uses:

  • tracking a malware family or a threat actor's tooling over time;
  • watching for new variants of a sample from your own incident;
  • monitoring for files that mention your organisation, domains or code-signing certificates.

Because Livehunt runs on a huge volume, it rewards the same qualities as any production rule: strong atoms, cheap guards, no whole-file loops (see performance).

Retrohunt

Retrohunt applies rules to files submitted in the past, within a retention window. It is the natural next step after writing a rule from an incident sample: "has this appeared before, and where?" Results often reveal older builds, related tools or earlier campaign activity. VirusTotal runs YARA-X in production for these features, so rules that compile cleanly with YARA-X — as tested in the editor — behave as expected there.

The vt module

In Livehunt, the vt module exposes metadata about the submission — for example information about the file, how it was submitted, and results from VirusTotal's analyses — so rules can combine content patterns with context. Outside VirusTotal the module compiles but its fields are undefined, so conditions that depend on them are false. Keep content logic and vt logic clearly separated, so the content part stays testable locally.

import "vt"

rule VT_Context_Example
{
    meta:
        description = "Content check that also compiles locally; vt fields are only set on VirusTotal"
    strings:
        $a = "ExampleImplantConfig" ascii
    condition:
        $a and filesize < 5MB
}

Differences from local scanning

  • Corpus. VirusTotal sees files from the whole world; a rule that is quiet on your goodware may still match legitimate software somewhere. Expect some noise and refine.
  • Volume and quotas. Match notifications and retrohunt jobs are limited by your plan. Precise rules save both.
  • Context. Metadata from the vt module has no local equivalent.
  • Engine. Hunting runs on YARA-X; features that only exist in YARA 4.x should be avoided.

Good practice

  1. Develop and test the content part locally: the online editor compiles with YARA-X and tests against samples without uploading them.
  2. Check performance with the linter before deploying a hunting rule.
  3. Start Livehunt rules narrowly, then widen; start Retrohunt with the most specific version of a rule.
  4. Document each hunting rule (purpose, owner, date) so notification rules can be retired when no longer useful.
  5. Remember the licences of any public rules you reuse (see public rule sets).

yararules.org is an independent project and is not affiliated with VirusTotal or Google.

FAQ

What is VirusTotal Livehunt?
A VirusTotal feature that runs your YARA rules against files as they are submitted and notifies you when one matches.
What is Retrohunt?
A VirusTotal feature that runs YARA rules over a historical window of previously submitted files, to find older samples of a family.
Can I use the vt module outside VirusTotal?
It compiles with YARA-X, but its fields are only populated by VirusTotal's infrastructure. Locally the fields are undefined, so conditions that depend on them do not match.