Examples of network hunting using Livehunt
Examples of network hunting using Livehunt
Uncover new artifacts and infrastructure related to a known campaign
New Files downloaded from URLs with a pattern
Matches: FILE
import "vt"
rule NewFileDownloadedFromUrlMatchingExpression {
meta:
description = "New Files downloaded from URLs with a pattern"
author = "virustotal"
target_entity = "file"
condition:
vt.metadata.new_file and
vt.metadata.itw.url.raw matches /example[.]com\/foo\/.*/
}
⚠️ Finetuned alternatives to regexps matching:
vt.metadata.itw.url.raw icontains "example.com/foo"
vt.metadata.itw.domain.root == "example.com" and vt.metadata.itw.url.path istartswith "/foo"
(for every domain or subdomain of example.com including itself)vt.metadata.itw.domain.raw iendswith ".example.com" and vt.metadata.itw.url.path istartswith "/foo"
(for only example.com subdomains)
New PE files downloaded from URLs with a pattern
Matches: FILE
import "vt"
rule NewExesDownloadedFromSomeURLPattern {
meta:
description = "New PE files downloaded from URLs with a pattern"
author = "virustotal"
target_entity = "file"
condition:
vt.metadata.new_file and
vt.metadata.itw.url.raw matches /example.com\/foo\/.*/ and
vt.metadata.file_type == vt.FileType.PE_EXE
}
URLs matching a pattern that downloads a PE file for first time
Matches: URL
import "vt"
rule UrlsMatchingExpressionDownloadingNewFiles {
meta:
description = "URLs matching a pattern that downloads a PE file for first time"
author = "virustotal"
target_entity = "url"
condition:
vt.net.url.downloaded_file.new_for_url and
vt.net.url.raw matches /example[.]com\/foo\/.*/ and
vt.net.url.downloaded_file.file_type == vt.FileType.PE_EXE
}
⚠️ Notice that vt.net.url.downloaded_file.new_for_url
matches once the file
haven't been previously downloaded from that particular URL, it may already be
known in VT.
New URLs serving certain hash
Matches: URL
import "vt"
rule NewURLsServingThisFile {
meta:
description = "New URLs serving certain hash"
author = "virustotal"
target_entity = "url"
condition:
vt.net.url.new_url and
vt.net.url.downloaded_file.sha256 == "<sha256>"
}
New URL with a pattern serving a new file
Matches: URL
import "vt"
rule NewURLsServingANewFile {
meta:
description = "New URL with a pattern serving a new file"
author = "virustotal"
target_entity = "url"
condition:
vt.net.url.new_url and
vt.net.url.downloaded_file.new_for_vt and // For VT
vt.net.url.raw icontains "example.com/foo/"
}
URLs matching a string in its content and served for first time
Matches: URL
⚠️ The content will be new for that particular URL, alternatively you can use vt.net.url.downloaded_file.new_for_vt
to check if it's first time seen in the whole VT collection.
import "vt"
rule URLsMatchingContent {
meta:
description = "URLs matching a string in its content and served for first time"
author = "virustotal"
target_entity = "url"
strings:
$cmdlet_str = "CmdletBinding" nocase
condition:
vt.net.url.downloaded_file.new_for_url and
$cmdlet_str
}
New URLs matching certain strings in its content
Matches: URL
import "vt"
rule NewURLsServingFileContentMatchingConditions {
meta:
description = "New URLs matching certain strings in its content"
author = "virustotal"
target_entity = "url"
strings:
$foo = "foo"
$bar = "bar"
condition:
vt.net.url.new_url and
all of them
}
New Domains having communicating files detected
Matches: DOMAIN
⚠️ vt.net.domain.communicating_file.*
refers to a File behavioural analysis that reported this Domain (or URL domain) as part of its indicators.
import "vt"
rule NewCommunicatingDomainForDetectedFiles {
meta:
description = "New Domains having communicating files detected"
author = "virustotal"
target_entity = "domain"
condition:
vt.net.domain.new_domain and
// communicating_file.* refers to a File behavioural analysis that reported this Domain (or URL domain).
vt.net.domain.communicating_file.analysis_stats.malicious > 2
}
New Domains having a specific communicating file
Matches: DOMAIN
⚠️ vt.net.domain.communicating_file.*
refers to a File behavioural analysis that reported this Domain (or URL domain) as part of its indicators.
import "vt"
rule NewCommunicatingDomainForSpecificFile {
meta:
description = "New Domains having a specific communicating file"
author = "virustotal"
target_entity = "domain"
condition:
vt.net.domain.new_domain and
// communicating_file.* refers to a File behavioural analysis that reported this Domain (or URL domain).
vt.net.domain.communicating_file.sha256 == "<sha256>"
}
New Domains reported for a subsequent File behaviour analyses
Matches: DOMAIN
import "vt"
rule EveryCommunicatingDomainForSpecificFile {
meta:
description = "New Domains reported for a subsequent File behaviour analyses"
author = "virustotal"
target_entity = "domain"
condition:
vt.net.domain.communicating_file.sha256 == "<sha256>"
}
⚠️ Fixing communicating_file
to a certain hash means that once VT receives a new behavioural report over that file you will be notified.
New Domains observed in behaviour analyses of files with detections
Matches: DOMAIN
import "vt"
rule CommunicatingDomainForDetectedFiles {
meta:
description = "New Domains observed in behaviour analyses of files with detections"
author = "virustotal"
target_entity = "domain"
condition:
vt.net.domain.new_domain and
vt.net.domain.communicating_file.analysis_stats.malicious >= 2
}
Domains observed from detected samples behaviours
Matches: DOMAIN
import "vt"
rule DomainsContactedByADetectedFile {
meta:
description = "Domains observed from detected samples behaviours"
author = "virustotal"
target_entity = "domain"
condition:
vt.net.domain.communicating_file.analysis_stats.malicious >= 2
}
IP addresses observed from detected samples behaviours
Matches: IP
import "vt"
rule IpsContactedByADetectedFile {
meta:
description = "IP addresses observed from detected samples behaviours"
author = "virustotal"
target_entity = "ip_address"
condition:
vt.net.ip.communicating_file.analysis_stats.malicious >= 2
}
New URLs under a specific domain
Matches: URL
import "vt"
rule newURLsUnderDomain {
meta:
description = "New URLs under a specific domain"
author = "virustotal"
target_entity = "url"
condition:
vt.net.url.new_url
and vt.net.domain.raw == "example.com"
}
New URLs in subdomains
Matches: URL
import "vt"
rule newURLsInSubDomains {
meta:
description = "New URLs in subdomains"
author = "virustotal"
target_entity = "url"
condition:
vt.net.url.new_url
and vt.net.domain.raw endswith ".example.com"
}
Root domain appearing in a sample behavior for first time
Matches: DOMAIN
import "vt"
rule newDomainRelationshipForIOC {
meta:
description = "Root domain appearing in a sample behavior for first time"
author = "virustotal"
target_entity = "domain"
condition:
vt.net.domain.root == "example.com" and
vt.net.domain.communicating_file.new_for_domain
}
IP addresses range appearing in a sample behavior for first time
Matches: IP
import "vt"
rule newIPRelationshipForIOC {
meta:
description = "IP addresses range appearing in a sample behavior for first time"
author = "virustotal"
target_entity = "ip_address"
condition:
vt.net.ip.communicating_file.new_for_ip and
vt.net.ip.ip_as_int >= 3941835776 and vt.net.ip.ip_as_int < 3941836800 // 234.243.166.33/22
}
Unearth malicious infrastructure being used by certain malware toolkits
URLs with pattern and a set of query params
Matches: URL
⚠️ URL matching can be fine-tuned, for example: vt.net.domain.root == "example.com" and vt.net.url.path istartswith "/foo"
import "vt"
rule paramsOverURL {
meta:
description = "URLs with pattern and a set of query params"
author = "virustotal"
target_entity = "url"
condition:
vt.net.url.raw matches /example[.]com/ and
for any key, value in vt.net.url.params: (
key == "foo" and
value icontains "bar"
)
}
URL subdomains matching certain GET params
Matches: URL
import "vt"
rule paramsOverSubDomain {
meta:
description = "URL subdomains matching certain GET params"
author = "virustotal"
target_entity = "url"
condition:
vt.net.domain.root == "example.com" and
// vt.net.domain.raw != "example.com" and // enable to skip naked domain matches
for any key, value in vt.net.url.params: (
key == "foo" and
value icontains"bar"
)
}
New Files serverd from a domain matching certain JARM
Matches: FILE
import "vt"
rule NewDownloadedFilesJarmMatching {
meta:
description = "New Files serverd from a domain matching certain JARM"
author = "virustotal"
target_entity = "file"
condition:
vt.metadata.new_file and
vt.metadata.itw.domain.jarm == "00112233445566778899AABBCCDDEEFF"
}
New domains with a specific JARM
Matches: DOMAIN
import "vt"
rule NewDomainJarmMatching {
meta:
description = "New domains with a specific JARM"
author = "virustotal"
target_entity = "domain"
condition:
vt.net.domain.new_domain and
vt.net.domain.jarm == "00112233445566778899AABBCCDDEEFF"
}
IP addresses with SSL/TLS serving with a specific JARM
Matches: IP
import "vt"
rule IPJarmMatching {
meta:
description = "IP addresses with SSL/TLS serving with a specific JARM"
author = "virustotal"
target_entity = "ip_address"
condition:
vt.net.ip.jarm == "00112233445566778899AABBCCDDEEFF"
}
New URLs with certain SSL certificate subject
Matches: URL
import "vt"
rule sslCertificateAttributeMatching {
meta:
description = "New URLs with certain SSL certificate subject"
author = "virustotal"
target_entity = "url"
condition:
vt.net.url.new_url and
vt.net.domain.https_certificate.subject.common_name == "*.example.com"
}
URLs with a certain set and amount of HTTP headers
Matches: URL
import "vt"
rule missingAndContainedHTTPHeaders {
meta:
description = "URLs with a certain set and amount of HTTP headers"
author = "virustotal"
target_entity = "url"
condition:
vt.net.url.number_of_response_headers == 4 and
for all name, value in vt.net.url.response_headers : (
name != "Content-Encoding"
) and
for any name, value in vt.net.url.response_headers : (
name == "Foo" and value == "Bar"
)
}
URLs with a certain cookie name
Matches: URL
import "vt"
rule cookieWithName {
meta:
description = "URLs with a certain cookie name"
author = "virustotal"
target_entity = "url"
condition:
for any name, value in vt.net.url.cookies : (
name == "SuspiciousCookie"
)
}
New URLs serving content strings and URLscanner detections
Matches: URL
import "vt"
rule MatchHTTPResponseContentAndAnalysis {
meta:
description = "New URLs serving content strings and URLscanner detections"
author = "virustotal"
target_entity = "url"
strings:
$html = "<HTML "
$bar = "bar"
condition:
vt.net.url.new_url
and vt.net.url.analysis_stats.malicious > 1
and $html at 0 and $bar
}
New URLs with URLscanner detections matching potentially malicious HTML/JS strings
Matches: URL
import "vt"
rule MatchEmbeddedJavascriptContent {
meta:
description = "New URLs with URLscanner detections matching potentially malicious HTML/JS strings"
author = "virustotal"
target_entity = "url"
strings:
$html = "<HTML " nocase
$js_script = "script" nocase
$js_unescape = "unescape" nocase
$js_parseint = "parseint" nocase
$js_fromcharcode = "fromcharcode" nocase
condition:
vt.net.url.new_url and
vt.net.url.analysis_stats.malicious > 1 and
$html at 0 and $js_script and
($js_unescape or $js_parseint or $js_fromcharcode)
}
URLs serving strings seen in VT for first time
Matches: URL
import "vt"
rule MatchHTTPResponseContentFirstSeen {
meta:
description = "URLs serving strings seen in VT for first time"
author = "virustotal"
target_entity = "url"
strings:
$securestring_str = "ConvertFrom-SecureString" nocase
condition:
vt.net.url.downloaded_file.new_for_vt and
$securestring_str
}
URLs serving potential PowerShell content
Matches: URL
⚠️ Useful for filetypes that are not automatically submmited to VT (list).
import "vt"
rule MatchPowerShellContent {
meta:
description = "URLs serving potential PowerShell content"
author = "virustotal"
target_entity = "url"
strings:
$mz_header = { 4d 5a 90 }
$cmdlet_str = "CmdletBinding" nocase
$securestring_str = "ConvertFrom-SecureString" nocase
condition:
not ($mz_header at 0) and
($cmdlet_str or $securestring_str)
}
URLs serving new potential PowerShell content
Matches: URL
⚠️ Useful for filetypes that are not automatically submmited to VT (list).
import "vt"
rule MatchNewServedPowerShellContent {
meta:
description = "URLs serving new potential PowerShell content"
author = "virustotal"
target_entity = "url"
strings:
$mz_header = { 4d 5a 90 }
$cmdlet_str = "CmdletBinding" nocase
$securestring_str = "ConvertFrom-SecureString" nocase
condition:
vt.net.url.downloaded_file.new_for_url and
not ($mz_header at 0) and
($cmdlet_str or $securestring_str)
}
Domains with certain DNS records
Matches: DOMAIN
import "vt"
rule dnsRecord {
meta:
description = "Domains with certain DNS records"
author = "virustotal"
target_entity = "domain"
condition:
for any record in vt.net.domain.dns_records : (
record.type == "TXT" and
record.value istartswith "v=spf1 include:"
)
}
Track specific threat actors and their newly created infrastructure
URLs with a certain set of HTML meta tags
Matches: URL
import "vt"
rule htmlMetaTags {
meta:
description = "URLs with a certain set of HTML meta tags"
author = "virustotal"
target_entity = "url"
condition:
for any entry in vt.net.url.html_meta_tags : (
entry.key == "generator" and
for any value in entry.values : (
value startswith "Foo"
) and
for any value in entry.values : (
value startswith "Bar"
)
)
}
URLs with a combination of tracker and tracker id
Matches: URL
import "vt"
rule newURLsUsingSpecificTracker {
meta:
description = "URLs with a combination of tracker and tracker id"
author = "virustotal"
target_entity = "url"
condition:
for any tracker in vt.net.url.trackers : (
tracker.name == "Google Analytics" and
tracker.id == "Foo"
)
}
Domains matching Whois key/values
Matches: DOMAIN
⚠️ This will notify new and updated Whois records.
import "vt"
rule WhoisProperties {
meta:
description = "Domains matching Whois key/values"
author = "virustotal"
target_entity = "domain"
condition:
for any key, value in vt.net.domain.whois : (
key == "Foo" and
value == "Bar"
)
}
Domains serving HTTPS with certain a certificate thumbprint
Matches: DOMAIN
⚠️ To match other HTTPS certificate fields check cert struct.
import "vt"
rule httpsCertificate {
meta:
description = "Domains serving HTTPS with certain a certificate thumbprint"
author = "virustotal"
target_entity = "domain"
vt.net.domain.https_certificate.thumbprint == "AABBCCDD"
}
Identify supply chain risk, mainly phishing, against my identity provider or specific companies
URLs containing certain HTML title and serving a favicon dhash
Matches: URL
⚠️ To obtain a dhash check: obtaining a domain favicon dhash.
import "vt"
rule URLsWithMyFavIcon {
meta:
description = "URLs containing certain HTML title and serving a favicon dhash"
author = "virustotal"
target_entity = "url"
condition:
(vt.net.url.html_title contains "Example Bank" or
vt.net.url.favicon.dhash == "5a923260c3c8708f") and
not vt.net.url.raw istartswith "https://www.example-bank.com/"
}
URLs matching string in its URL excluding the canonical URL
Matches: URL
import "vt"
rule URLHostingPhishing {
meta:
description = "URLs matching string in its URL excluding the canonical URL"
author = "virustotal"
target_entity = "url"
condition:
vt.net.url.raw contains "example-bank" and
vt.net.domain.root != "example-bank.com"
}
⚠️ Notice how vt.net.domain.root
condition excludes the root domain and all its possible subdomains.
Attack surface/infrastructure management
Files with positives downloaded from a certain IP range
Matches: FILE
⚠️ To convert an IP range to Integer match you can check: generating IP integer range.
import "vt"
rule maliciousFilesFromMyIPRange {
meta:
description = "Files with positives downloaded from a certain IP range"
author = "virustotal"
target_entity = "file"
condition:
vt.metadata.analysis_stats.malicious > 1 and
vt.metadata.itw.ip.ip_as_int >= 3941835776 and vt.metadata.itw.ip.ip_as_int < 3941836800 // 234.243.166.33/22
}
Files with positives downloaded from a certain URLs
Matches: FILE
import "vt"
rule maliciousFilesFromMyURLs {
meta:
description = "Files with positives downloaded from a certain URLs"
author = "virustotal"
target_entity = "file"
condition:
vt.metadata.analysis_stats.malicious > 1 and
vt.metadata.itw.url.raw matches /mydomain[.]com/
}
IP addresses marked as malicious in an IP range
Matches: IP
⚠️ To convert an IP range to Integer match you can check: generating IP integer range.
import "vt"
rule IPMarkedAsMaliciousFromMyIPRange {
meta:
description = "IP addresses marked as malicious in an IP range"
author = "virustotal"
target_entity = "ip_address"
condition:
vt.net.ip.analysis_stats.malicious > 1 and
vt.net.ip.ip_as_int >= 3941835776 and vt.net.ip.ip_as_int < 3941836800 // 234.243.166.33/22
}
IP addresses serving malicious files
Matches: IP
Useful to monitor your own infrastructure.
import "vt"
rule IPServesMaliciousFile {
meta:
description = "IP addresses serving malicious files"
author = "virustotal"
target_entity = "ip_address"
condition:
vt.net.ip.raw matches /ˆ11\.22\.33\./ and
vt.net.ip.downloaded_file.analysis_stats.malicious > 2
}
Domain serving malicious files
Matches: DOMAIN
Useful to monitor your own infrastructure.
import "vt"
rule DomainServesMaliciousFile {
meta:
description = "Domain serving malicious files"
author = "virustotal"
target_entity = "domain"
condition:
vt.net.domain.raw iendswith "drive.google.com" and
vt.net.domain.downloaded_file.analysis_stats.malicious > 2
}
False positives related to your internet-exposed assets
Files with positives downloaded from a certain Domain
Matches: DOMAIN
import "vt"
rule falsePositivesFromMyDomain {
meta:
description = "Files with positives downloaded from a certain Domain"
author = "virustotal"
target_entity = "domain"
condition:
vt.net.domain.raw == "example.com" and
vt.net.domain.analysis_stats.malicious > 0
}
Updated about 1 year ago