Behavior hunting
Creating rules based on file behavior
The vt module provides a comprehensive view of a file, including its static properties, antivirus detection details, and also exposes information about how the file behaves.
To achieve this, we run the executable file through multiple sandbox environments, including our own Jujubox, CAPE, CAPA and other third-party solutions. The behavioral information generated by all those sandboxes is normalized into a common format, and mixed together as if it was generated by a single sandbox. This aggregated behavior report is what the vt module exposes to your rule.
Here are some examples of how this behavioral information can be used:
import "vt"
rule drops_foo_exe {
condition:
for any file_dropped in vt.behaviour.files_dropped : (
file_dropped.path contains "foo.exe"
)
}
import "vt"
rule mutex_hgl345 {
condition:
for any mutex in vt.behaviour.mutexes_created : (
mutex == "HGL345"
)
}
import "vt"
rule persistence_and_self_deletion {
condition:
for any trait in vt.behaviour.traits : ( trait == vt.BehaviourTrait.PERSISTENCE ) and
for any trait in vt.behaviour.traits : ( trait == vt.BehaviourTrait.SELF_DELETE )
}
Fields
The list below describes all the existing behaviour-related fields:
Detection
Field | Type | Description | Example |
---|---|---|---|
vt.behaviour.calls_highlighted | array of strings | API calls that are worth remarking because they are suspicious (e.g. "android.media.AudioRecord.startRecording", "GetTickCount" | |
vt.behaviour.text_highlighted | array of strings | Text that can provide further context about the file, this might be windows titles, dialogs, outputs streams, etc. | |
vt.behaviour.text_decoded | array of strings | Strings that are either encoded or decoded during the observed time frame, we just record the decoded strings in plain form. | |
vt.behaviour.traits | array of integers | List that contains a subset of the values listed in the behaviour traits table. | for any t in vt.behaviour.traits : ( t == vt.BehaviourTrait.LONG_SLEEPS ) |
vt.behaviour.invokes | array of strings | ||
vt.behaviour.verdicts | array of integers | Some sandboxes produce a verdict based on the file behaviour. This list contains one or more of the values listed in the behaviour verdicts table. | for any t in vt.behaviour.verdicts : ( t == vt.BehaviourVerdict.RANSOM ) |
vt.behaviour.verdict_labels | string | List that contains the verdict labels based on the file behaviour sandboxes. | for any label in vt.behaviour.verdict_labels : ( label contains "PDFPhish" ) |
vt.behaviour.mitre_attack_techniques | string | String containing the mitre attack techniques. | for any technique in vt.behaviour.mitre_attack_techniques : ( technique.id == "t1012" ) |
vt.behaviour.mbc[x].id | string | MBC identifier. Check Malware Behavior Catalog for more info. | for any catalog in vt.behaviour.mbc: ( catalog.id == "B0003.003" ) |
vt.behaviour.mbc[x].method | string | Textual description of the method used. | for any catalog in vt.behaviour.mbc: ( catalog.method == "Delayed Execution" ) |
vt.behaviour.mbc[x].objective | string | Textual description of the objective used. | for any catalog in vt.behaviour.mbc: ( catalog.objective == "Anti-Behavioral Analysis" ) |
vt.behaviour.mbc[x].behavior | string | Textual description of the behavior used. | for any catalog in vt.behaviour.mbc: ( catalog.behavior == "Dynamic Analysis Evasion" ) |
Files
Field | Type | Description | Example |
---|---|---|---|
vt.behaviour.files_attribute_changed | array of strings | Paths of the files whose attributes have changed. | for any f in vt.behaviour.files_attribute_changed : ( f contains ".exe" ) |
vt.behaviour.files_copied | array of structs | Structures with information about files that have been copied. | for any f in vt.behaviours.files_copied : ( f.source contains ".exe" and f.destination contains "system32" ) |
vt.behaviour.files_copied[x].source | string | Path where the file was copied from. | |
vt.behaviour.files_copied[x].destination | string | Path where the file was copied to. | |
vt.behaviour.files_deleted | array of strings | Paths of the files that have been deleted. | |
vt.behaviour.files_dropped | array of structs | Structures with information about files that have been dropped. | |
vt.behaviour.files_dropped[x].path | string | Path of the dropped file. | |
vt.behaviour.files_dropped[x].sha256 | string | SHA-256 of the dropped file. | |
vt.behaviour.files_dropped[x].type | integer | Type of the dropped file. | |
vt.behaviour.files_dropped[x].process_name | string | Name of the process that dropped the file. | |
vt.behaviour.files_dropped[x].process_id | string | ID of the process that dropped the file. | |
vt.behaviour.files_opened | array of strings | Paths of the files that have been opened. | |
vt.behaviour.files_written | array of strings | Paths of the files that have been written. |
Network
Field | Type | Description | Example |
---|---|---|---|
vt.behaviour.dns_lookups | array of structs | List of DNS resolutions performed. | |
vt.behaviour.dns_lookups[x].hostname | string | Hostname in the DNS lookup request. | |
vt.behaviour.dns_lookups[x].resolved_ips | array of strings | List of IP address returned for the requested hostname. | |
vt.behaviour.hosts_file | string | Content of the "hosts" file. | |
vt.behaviour.ip_traffic | array of structs | List of established IP connections. | |
vt.behaviour.ip_traffic[x].destination_ip | string | Destination IP address. | |
vt.behaviour.ip_traffic[x].destination_ip_as_int | integer | Destination IP address dotless decimal number notation. | for any t in vt.behaviour.ip_traffic : ( t.destination_ip_as_int == 3941835776 ) |
vt.behaviour.ip_traffic[x].destination_ip_asn | integer | Destination IP Autonomous System Number. | for any t in vt.behaviour.ip_traffic : ( t.destination_ip_asn == 74838 ) |
vt.behaviour.ip_traffic[x].destination_port | integer | Destination port. | |
vt.behaviour.ip_traffic[x].transport_layer_protocol | integer | One of the constants listed in network protocols | |
vt.behaviour.http_conversations | array of structs | List of HTTP requests performed. | |
vt.behaviour.http_conversations[x].url | string | Requested URL. | |
vt.behaviour.http_conversations[x].request_method | integer | One of the constants listed in HTTP methods | for any c in vt.behaviour.http_conversations : ( c.request_method == vt.Http.Method.GET ) |
vt.behaviour.http_conversations[x].request_headers | dictionary | HTTP request headers. Notice that dictionary keys are case-sensitive and therefore request_headers["user-agent"] is not the same than request_headers["User-Agent"]. The header name appears as reported by the sandbox. | for any c in vt.behaviour.http_conversations : ( c.request_headers["user-agent"] == "Moxilla" ) |
vt.behaviour.http_conversations[x].response_headers | dictionary | HTTP response headers. | |
vt.behaviour.http_conversations[x].response_status_code | integer | HTTP status code returned by the server. | |
vt.behaviour.http_conversations[x].response_body_filetype | integer | Type of the response's body, if it was one of the recognizable file types. | |
vt.behaviour.smtp_conversations[x].hostname | string | Host name of the SMTP server. | |
vt.behaviour.smtp_conversations[x].destination_ip | integer | IP address of the SMTP server. | |
vt.behaviour.smtp_conversations[x].destination_port | integer | Port number of the SMTP server (usually 25). | |
vt.behaviour.smtp_conversations[x].smtp_from | string | MAIL FROM: field in the SMTP protocol. | |
vt.behaviour.smtp_conversations[x].smtp_to | array of strings | MAIL TO: field in the SMTP protocol. | |
vt.behaviour.smtp_conversations[x].message_from | array of strings | "from" field in message header. | |
vt.behaviour.smtp_conversations[x].message_to | array of strings | "to" field in message header. | |
vt.behaviour.smtp_conversations[x].message_cc | array of strings | "cc" field in message header. | |
vt.behaviour.smtp_conversations[x].message_bcc | array of strings | "bcc" field in message header. | |
vt.behaviour.smtp_conversations[x].timestamp | string | Message timestamp. Example: "Thu, 16 Jul 2020 6:1:58 GMT". | |
vt.behaviour.smtp_conversations[x].subject | string | Message subject. | |
vt.behaviour.smtp_conversations[x].html_body | string | Message body in HTML form. | |
vt.behaviour.smtp_conversations[x].txt_body | string | Message body in text form. | |
vt.behaviour.smtp_conversations[x].x_mailer | string | Program used for sending the email. Same than "X-Mailer" header. | |
vt.behaviour.tls | array of structs | Contacted domains/IPs certificates. | |
vt.behaviour.tls[x].issuer | dictionary | Certificate issuer information. Keys are certificate fields (C, CN, O, etc.) as strings and values are strings. | for any t in vt.behaviour.tls: ( t.issuer["CN"] == "Foobar" ) |
vt.behaviour.tls[x].ja3 | string | JA3 client fingerprint. | for any t in vt.behaviour.tls: ( t.ja3 == "00112233445566778899aabbccddeeff" ) |
vt.behaviour.tls[x].ja3s | string | JA3S server fingerprint. | for any t in vt.behaviour.tls: ( t.ja3s == "00112233445566778899aabbccddeeff" ) |
vt.behaviour.tls[x].ja4 | string | JA4 client fingerprint. More info in Unveiling Hidden Connections: JA4 Client Fingerprinting on VirusTotal. | for any t in vt.behaviour.tls: ( t.ja4 matches /t10d070600_.*_1a3805c3aa63/ ) |
vt.behaviour.tls[x].serial_number | string | Certificate serial number. | for any t in vt.behaviour.tls: ( t.serial_number == "00112233445566778899aabbccddeeff" ) |
vt.behaviour.tls[x].sni | string | Certificate's server name indication. | for any t in vt.behaviour.tls: ( t.sni matches /example.com/ ) |
vt.behaviour.tls[x].thumbprint | string | Certificate thumbprint. | for any t in vt.behaviour.tls: ( t.thumbprint == "00112233445566778899aabbccddeeff00112233" ) |
vt.behaviour.tls[x].subject | dictionary | Certificate subject information. Same format as issuer field. | for any t in vt.behaviour.tls: ( t.issuer["CN"] == "example.com" ) |
vt.behaviour.tls[x].version | string | TLS version. | for any t in vt.behaviour.tls: ( t.version == "TLS 1.2" ) |
Permissions
Field | Type | Description | Example |
---|---|---|---|
vt.behaviour.permissions_checked | array of structs | Permissions checked by the application. | |
vt.behaviour.permissions_checked[x].permission | string | Permission checked | for any p in vt.behaviour.permissions_checked : ( p.permission == "android.permission.INTERNET" ) |
vt.behaviour.permissions_checked[x].owner | string | ||
vt.behaviour.permissions_requested | array of strings | Permissions requested by the application. | for any p in vt.behaviour.permissions_requested : ( p == "android.permission.BLUETOOTH" ) |
Processes
Field | Type | Description | Example |
---|---|---|---|
vt.behaviour.command_executions | array of strings | Commands executed, including their command-line arguments. | for any cmd in vt.behaviour.command_executions : ( cmd contains "cmd.exe /Q /c" ) |
vt.behaviour.modules_loaded | array of strings | Modules or libraries dynamically loaded (e.g. DLLs loaded with LoadLibrary in Windows, DEX and .class files dynamically loaded in Android) | for any lib in vt.behaviour.modules_loaded : ( lib == "zlib.dll" ) |
vt.behaviour.mutexes_created | array of strings | Mutexes created. | for any mutex in vt.behaviour.mutexes_created : ( mutex contains "HGL345" ) |
vt.behaviour.mutexes_opened | array of strings | Mutexes opened. | |
vt.behaviour.processes_created | array of strings | Processes created. | |
vt.behaviour.processes_injected | array of strings | Processes in which some kind of code was injected. For instance, in Window this is commonly done using CreateRemoteThread. | |
vt.behaviour.processes_killed | array of strings | Processes that were explicitly killed. | |
vt.behaviour.processes_terminated | array of strings | Processes that terminated during the observed time, not necessarily killed. | |
vt.behaviour.signals_hooked | array of strings | Signals hooked. In Windows this includes the windows messages hooked with SetWindowsHook and the string contains both the hook type and the function used (i.e "WH_KEYBOARD - SetWindowsHook") In Android registered receivers are considered hooks. | Windows: for any s in vt.behaviour.signals_hooked : ( s contains "WH_KEYBOARD" ) Android: for any s in vt.behaviour.signals_hooked: ( s == "android.intent.action.PROXY_CHANGE" ) |
vt.behaviour.signals_observed | array of strings | From the signals hooked which were actually observed. |
Services
Field | Type | Description | Example |
---|---|---|---|
vt.behaviour.services_created | array of strings | Services created. In some OSes services are simply any program that runs in the background without user interaction. | for any svc in vt.behaviour.services_created : ( svc == "eckwIIMB") |
vt.behaviour.services_opened | array of strings | Services opened. | |
vt.behaviour.services_started | array of strings | Services started. | |
vt.behaviour.services_stopped | array of strings | Services stopped. |
Registry
Field | Type | Description | Example |
---|---|---|---|
vt.behaviour.registry_keys_deleted | array of strings | Deleted registry keys. | for any key in vt.behaviour.registry_key_deleted : ( key contains "" ) |
vt.behaviour.registry_keys_opened | array of strings | Opened registry keys. | |
vt.behaviour.registry_keys_set | array of structs | Modified registry keys and their new values. | for any r in vt.behaviour.registry_keys_set : ( r.key matches /\windows\currentversion\run/i and r.value contains "VMIntel386.exe" ) |
vt.behaviour.registry_keys_set[x].key | string | Registry key. | |
vt.behaviour.registry_keys_set[x].value | string | New value for registry key. |
Windows specific
Field | Type | Description | Example |
---|---|---|---|
vt.behaviour.windows_hidden | array of strings | Information about windows that have been hidden. The string contains the caption of the hidden Window and the name of the process owning the window. | for any w in vt.behaviour.windows_hidden : ( w contains "cmd.exe /C") |
vt.behaviour.windows_searched | array of strings | Windows that have been searched for (e.g. using FindWindow). The strings can contain the window's name, the window's class name, or both. | for any w in vt.behaviour.windows_searched : ( w contains "BANCO REAL") |
Android specific
Field | Type | Description | Example |
---|---|---|---|
vt.behaviour.services_bound | array of strings | Service binding applies only to Android. A bind operation takes a component, an action, and potentially multiple extras. These are represented as: <component><action><extra> | for any svc in vt.behaviour.services_bound : ( svc contains "gms.analytics.service.START") |
vt.behaviour.shared_preferences_lookups | array of strings | Shared preferences that have been read. | |
vt.behaviour.shared_preferences_sets | array of structs | Shared preferences that have been modified. | |
vt.behaviour.shared_preferences_sets[x].key | string | Shared preference key. | |
vt.behaviour.shared_preferences_sets[x].value | string | New value for preference. | |
vt.behaviour.system_property_lookups | array of strings | System properties that have been read. | |
vt.behaviour.system_property_sets | array of structs | System properties that have been modified. | |
vt.behaviour.system_property_sets[x].key | string | Property key. | |
vt.behaviour.system_property_sets[x].value | string | New value for property. |
Updated 10 days ago