From 6dde963985ffaf08341b401eefc1d058701e2e85 Mon Sep 17 00:00:00 2001 From: Willi Ballenthin Date: Wed, 18 Dec 2024 12:54:11 +0000 Subject: [PATCH] sequence: add sequence address contains the call ids for all the calls within the sequence, so we know where to look for related matched. --- capa/capabilities/dynamic.py | 31 ++- capa/features/address.py | 30 ++- capa/features/freeze/__init__.py | 29 ++- capa/render/proto/__init__.py | 27 +++ capa/render/proto/capa.proto | 10 + capa/render/proto/capa_pb2.py | 301 ++++++++++++++------------- capa/render/proto/capa_pb2.pyi | 45 +++- capa/render/result_document.py | 43 +++- capa/render/verbose.py | 5 +- capa/render/vverbose.py | 14 +- tests/test_dynamic_sequence_scope.py | 148 +++++++++++++ 11 files changed, 521 insertions(+), 162 deletions(-) diff --git a/capa/capabilities/dynamic.py b/capa/capabilities/dynamic.py index 0b56dafd1..83520bd99 100644 --- a/capa/capabilities/dynamic.py +++ b/capa/capabilities/dynamic.py @@ -16,7 +16,7 @@ import capa.render.result_document as rdoc from capa.rules import Scope, RuleSet from capa.engine import FeatureSet, MatchResults -from capa.features.address import _NoAddress +from capa.features.address import DynamicCallAddress, DynamicSequenceAddress, _NoAddress from capa.capabilities.common import Capabilities, find_file_capabilities from capa.features.extractors.base_extractor import CallHandle, ThreadHandle, ProcessHandle, DynamicFeatureExtractor @@ -101,6 +101,7 @@ def find_thread_capabilities( # With this approach, our algorithm performance is independent of SEQUENCE_SIZE. # The naive algorithm, of merging all the trailing feature sets at each call, is dependent upon SEQUENCE_SIZE # (that is, runtime gets slower the larger SEQUENCE_SIZE is). + sequence_call_addresses: collections.deque[DynamicCallAddress] = collections.deque(maxlen=SEQUENCE_SIZE) sequence_feature_sets: collections.deque[FeatureSet] = collections.deque(maxlen=SEQUENCE_SIZE) sequence_features: FeatureSet = collections.defaultdict(set) @@ -108,7 +109,9 @@ def find_thread_capabilities( # so that we can deduplicate long strings of the same matche. last_sequence_matches: set[str] = set() + call_count = 0 for ch in extractor.get_calls(ph, th): + call_count += 1 call_capabilities = find_call_capabilities(ruleset, extractor, ph, th, ch) for feature, vas in call_capabilities.features.items(): features[feature].update(vas) @@ -119,6 +122,12 @@ def find_thread_capabilities( # # sequence scope matching # + sequence_call_addresses.append(ch.address) + # TODO: it would be nice to create this only when needed, since it generates garbage. + sequence_address = DynamicSequenceAddress( + th.address, id=ch.address.id, calls=tuple(address.id for address in sequence_call_addresses) + ) + # As we add items to the end of the deque, overflow and drop the oldest items (at the left end). # While we could rely on `deque.append` with `maxlen` set (which we provide above), # we want to use the dropped item first, to remove the old features, so we manually pop it here. @@ -144,8 +153,10 @@ def find_thread_capabilities( for feature, vas in latest_features.items(): sequence_features[feature].update(vas) - _, smatches = ruleset.match(Scope.SEQUENCE, sequence_features, ch.address) + _, smatches = ruleset.match(Scope.SEQUENCE, sequence_features, sequence_address) + # TODO: if smatches: create the sequence location for rule_name, res in smatches.items(): + # TODO: maybe just garbage collect here better. if rule_name in last_sequence_matches: # don't emit match results for rules seen during the immediately preceeding sequence. # @@ -172,6 +183,14 @@ def find_thread_capabilities( for va, _ in res: capa.engine.index_rule_matches(features, rule, [va]) + logger.debug( + "analyzed thread %d[%d] with %d events, %d features, and %d matches", + th.address.process.pid, + th.address.tid, + call_count, + len(features), + len(matches) + len(sequence_matches) + len(call_matches), + ) return ThreadCapabilities(features, matches, sequence_matches, call_matches) @@ -224,6 +243,13 @@ def find_process_capabilities( process_features[feature].add(va) _, process_matches = ruleset.match(Scope.PROCESS, process_features, ph.address) + + logger.debug( + "analyzed process %d and extracted %d features with %d matches", + ph.address.pid, + len(process_features), + len(process_matches), + ) return ProcessCapabilities(process_matches, thread_matches, sequence_matches, call_matches, len(process_features)) @@ -252,7 +278,6 @@ def find_dynamic_capabilities( address=frz.Address.from_capa(p.address), count=process_capabilities.feature_count ), ) - logger.debug("analyzed %s and extracted %d features", p.address, process_capabilities.feature_count) for rule_name, res in process_capabilities.process_matches.items(): all_process_matches[rule_name].extend(res) diff --git a/capa/features/address.py b/capa/features/address.py index 45c3a600f..b5e6da029 100644 --- a/capa/features/address.py +++ b/capa/features/address.py @@ -104,11 +104,37 @@ def __repr__(self): return f"{self.thread}, call(id: {self.id})" def __hash__(self): - return hash((self.thread, self.id)) + return hash(("call", self.thread, self.id)) def __eq__(self, other): + return isinstance(other, DynamicCallAddress) and (self.thread, self.id) == (other.thread, other.id) + + def __lt__(self, other): assert isinstance(other, DynamicCallAddress) - return (self.thread, self.id) == (other.thread, other.id) + return (self.thread, self.id) < (other.thread, other.id) + + +class DynamicSequenceAddress(Address): + """addresses a sequence in a dynamic execution trace""" + + def __init__(self, thread: ThreadAddress, id: int, calls: tuple[int, ...]): + assert id >= 0 + self.thread = thread + # ID of the call that identifies this sequence + self.id = id + # list of call IDs contained with this sequence. + # not required for identity, because the id + SEQUENCE_SIZE will dictate this. + self.calls = calls + + def __repr__(self): + return f"{self.thread}, sequence(id: {self.id})" + + def __hash__(self): + # calls not required for identity, because the id + SEQUENCE_SIZE will be sufficient. + return hash(("sequence", self.thread, self.id)) + + def __eq__(self, other): + return isinstance(other, DynamicSequenceAddress) and (self.thread, self.id) == (other.thread, other.id) def __lt__(self, other): assert isinstance(other, DynamicCallAddress) diff --git a/capa/features/freeze/__init__.py b/capa/features/freeze/__init__.py index bb6b3ded0..1cdc56f56 100644 --- a/capa/features/freeze/__init__.py +++ b/capa/features/freeze/__init__.py @@ -52,13 +52,23 @@ class AddressType(str, Enum): DN_TOKEN_OFFSET = "dn token offset" PROCESS = "process" THREAD = "thread" + SEQUENCE = "sequence" CALL = "call" NO_ADDRESS = "no address" class Address(HashableModel): type: AddressType - value: Union[int, tuple[int, ...], None] = None # None default value to support deserialization of NO_ADDRESS + value: Union[ + # for absolute, relative, file + int, + # for DNToken, Process, Thread, Call + tuple[int, ...], + # for sequence + tuple[int, int, int, int, tuple[int, ...]], + # for NO_ADDRESS, + None, + ] = None # None default value to support deserialization of NO_ADDRESS @classmethod def from_capa(cls, a: capa.features.address.Address) -> "Address": @@ -86,6 +96,12 @@ def from_capa(cls, a: capa.features.address.Address) -> "Address": elif isinstance(a, capa.features.address.DynamicCallAddress): return cls(type=AddressType.CALL, value=(a.thread.process.ppid, a.thread.process.pid, a.thread.tid, a.id)) + elif isinstance(a, capa.features.address.DynamicSequenceAddress): + return cls( + type=AddressType.SEQUENCE, + value=(a.thread.process.ppid, a.thread.process.pid, a.thread.tid, a.id, a.calls), + ) + elif a == capa.features.address.NO_ADDRESS or isinstance(a, capa.features.address._NoAddress): return cls(type=AddressType.NO_ADDRESS, value=None) @@ -149,6 +165,17 @@ def to_capa(self) -> capa.features.address.Address: id=id_, ) + elif self.type is AddressType.SEQUENCE: + assert isinstance(self.value, tuple) + ppid, pid, tid, id_, calls = self.value + return capa.features.address.DynamicSequenceAddress( + thread=capa.features.address.ThreadAddress( + process=capa.features.address.ProcessAddress(ppid=ppid, pid=pid), tid=tid + ), + id=id_, + calls=calls, + ) + elif self.type is AddressType.NO_ADDRESS: return capa.features.address.NO_ADDRESS diff --git a/capa/render/proto/__init__.py b/capa/render/proto/__init__.py index bf12b5470..e2efc2ac0 100644 --- a/capa/render/proto/__init__.py +++ b/capa/render/proto/__init__.py @@ -135,6 +135,25 @@ def addr_to_pb2(addr: frz.Address) -> capa_pb2.Address: ), ) + elif addr.type is AddressType.SEQUENCE: + assert isinstance(addr.value, tuple) + ppid, pid, tid, id_, calls = addr.value + assert isinstance(ppid, int) + assert isinstance(pid, int) + assert isinstance(tid, int) + assert isinstance(id_, int) + assert isinstance(calls, tuple) + return capa_pb2.Address( + type=capa_pb2.AddressType.ADDRESSTYPE_SEQUENCE, + ppid_pid_tid_id_calls=capa_pb2.Ppid_Pid_Tid_Id_Calls( + ppid=int_to_pb2(ppid), + pid=int_to_pb2(pid), + tid=int_to_pb2(tid), + id=int_to_pb2(id_), + calls=tuple(int_to_pb2(i) for i in calls), + ), + ) + elif addr.type is AddressType.NO_ADDRESS: # value == None, so only set type return capa_pb2.Address(type=capa_pb2.AddressType.ADDRESSTYPE_NO_ADDRESS) @@ -630,6 +649,14 @@ def addr_from_pb2(addr: capa_pb2.Address) -> frz.Address: id_ = int_from_pb2(addr.ppid_pid_tid_id.id) return frz.Address(type=frz.AddressType.CALL, value=(ppid, pid, tid, id_)) + elif addr.type == capa_pb2.AddressType.ADDRESSTYPE_SEQUENCE: + ppid = int_from_pb2(addr.ppid_pid_tid_id_calls.ppid) + pid = int_from_pb2(addr.ppid_pid_tid_id_calls.pid) + tid = int_from_pb2(addr.ppid_pid_tid_id_calls.tid) + id_ = int_from_pb2(addr.ppid_pid_tid_id_calls.id) + calls = tuple(int_from_pb2(i) for i in addr.ppid_pid_tid_id_calls.calls) + return frz.Address(type=frz.AddressType.SEQUENCE, value=(ppid, pid, tid, id_, calls)) + elif addr.type == capa_pb2.AddressType.ADDRESSTYPE_NO_ADDRESS: return frz.Address(type=frz.AddressType.NO_ADDRESS, value=None) diff --git a/capa/render/proto/capa.proto b/capa/render/proto/capa.proto index 5b2c459c7..e147e99e8 100644 --- a/capa/render/proto/capa.proto +++ b/capa/render/proto/capa.proto @@ -16,6 +16,7 @@ message Address { Ppid_Pid ppid_pid = 4; Ppid_Pid_Tid ppid_pid_tid = 5; Ppid_Pid_Tid_Id ppid_pid_tid_id = 6; + Ppid_Pid_Tid_Id_Calls ppid_pid_tid_id_calls = 7; }; } @@ -30,6 +31,7 @@ enum AddressType { ADDRESSTYPE_PROCESS = 7; ADDRESSTYPE_THREAD = 8; ADDRESSTYPE_CALL = 9; + ADDRESSTYPE_SEQUENCE = 10; } message Analysis { @@ -473,6 +475,14 @@ message Ppid_Pid_Tid_Id { Integer id = 4; } +message Ppid_Pid_Tid_Id_Calls { + Integer ppid = 1; + Integer pid = 2; + Integer tid = 3; + Integer id = 4; + repeated Integer calls = 5; +} + message Integer { oneof value { uint64 u = 1; sint64 i = 2; } } // unsigned or signed int message Number { oneof value { uint64 u = 1; sint64 i = 2; double f = 3; } } diff --git a/capa/render/proto/capa_pb2.py b/capa/render/proto/capa_pb2.py index 35d017934..21564b539 100644 --- a/capa/render/proto/capa_pb2.py +++ b/capa/render/proto/capa_pb2.py @@ -1,11 +1,22 @@ # -*- coding: utf-8 -*- # Generated by the protocol buffer compiler. DO NOT EDIT! +# NO CHECKED-IN PROTOBUF GENCODE # source: capa/render/proto/capa.proto +# Protobuf Python Version: 5.28.3 """Generated protocol buffer code.""" from google.protobuf import descriptor as _descriptor from google.protobuf import descriptor_pool as _descriptor_pool +from google.protobuf import runtime_version as _runtime_version from google.protobuf import symbol_database as _symbol_database from google.protobuf.internal import builder as _builder +_runtime_version.ValidateProtobufRuntimeVersion( + _runtime_version.Domain.PUBLIC, + 5, + 28, + 3, + '', + 'capa/render/proto/capa.proto' +) # @@protoc_insertion_point(imports) _sym_db = _symbol_database.Default() @@ -13,159 +24,161 @@ -DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x1c\x63\x61pa/render/proto/capa.proto\x12\rmandiant.capa\"Q\n\nAPIFeature\x12\x0c\n\x04type\x18\x01 \x01(\t\x12\x0b\n\x03\x61pi\x18\x02 \x01(\t\x12\x18\n\x0b\x64\x65scription\x18\x03 \x01(\tH\x00\x88\x01\x01\x42\x0e\n\x0c_description\"\xb3\x02\n\x07\x41\x64\x64ress\x12(\n\x04type\x18\x01 \x01(\x0e\x32\x1a.mandiant.capa.AddressType\x12#\n\x01v\x18\x02 \x01(\x0b\x32\x16.mandiant.capa.IntegerH\x00\x12\x33\n\x0ctoken_offset\x18\x03 \x01(\x0b\x32\x1b.mandiant.capa.Token_OffsetH\x00\x12+\n\x08ppid_pid\x18\x04 \x01(\x0b\x32\x17.mandiant.capa.Ppid_PidH\x00\x12\x33\n\x0cppid_pid_tid\x18\x05 \x01(\x0b\x32\x1b.mandiant.capa.Ppid_Pid_TidH\x00\x12\x39\n\x0fppid_pid_tid_id\x18\x06 \x01(\x0b\x32\x1e.mandiant.capa.Ppid_Pid_Tid_IdH\x00\x42\x07\n\x05value\"\x9c\x02\n\x08\x41nalysis\x12\x0e\n\x06\x66ormat\x18\x01 \x01(\t\x12\x0c\n\x04\x61rch\x18\x02 \x01(\t\x12\n\n\x02os\x18\x03 \x01(\t\x12\x11\n\textractor\x18\x04 \x01(\t\x12\r\n\x05rules\x18\x05 \x03(\t\x12,\n\x0c\x62\x61se_address\x18\x06 \x01(\x0b\x32\x16.mandiant.capa.Address\x12%\n\x06layout\x18\x07 \x01(\x0b\x32\x15.mandiant.capa.Layout\x12\x34\n\x0e\x66\x65\x61ture_counts\x18\x08 \x01(\x0b\x32\x1c.mandiant.capa.FeatureCounts\x12\x39\n\x11library_functions\x18\t \x03(\x0b\x32\x1e.mandiant.capa.LibraryFunction\"S\n\x0b\x41rchFeature\x12\x0c\n\x04type\x18\x01 \x01(\t\x12\x0c\n\x04\x61rch\x18\x02 \x01(\t\x12\x18\n\x0b\x64\x65scription\x18\x03 \x01(\tH\x00\x88\x01\x01\x42\x0e\n\x0c_description\"`\n\nAttackSpec\x12\r\n\x05parts\x18\x01 \x03(\t\x12\x0e\n\x06tactic\x18\x02 \x01(\t\x12\x11\n\ttechnique\x18\x03 \x01(\t\x12\x14\n\x0csubtechnique\x18\x04 \x01(\t\x12\n\n\x02id\x18\x05 \x01(\t\"K\n\x11\x42\x61sicBlockFeature\x12\x0c\n\x04type\x18\x01 \x01(\t\x12\x18\n\x0b\x64\x65scription\x18\x02 \x01(\tH\x00\x88\x01\x01\x42\x0e\n\x0c_description\";\n\x10\x42\x61sicBlockLayout\x12\'\n\x07\x61\x64\x64ress\x18\x01 \x01(\x0b\x32\x16.mandiant.capa.Address\"U\n\x0c\x42ytesFeature\x12\x0c\n\x04type\x18\x01 \x01(\t\x12\r\n\x05\x62ytes\x18\x02 \x01(\t\x12\x18\n\x0b\x64\x65scription\x18\x03 \x01(\tH\x00\x88\x01\x01\x42\x0e\n\x0c_description\"g\n\x15\x43haracteristicFeature\x12\x0c\n\x04type\x18\x01 \x01(\t\x12\x16\n\x0e\x63haracteristic\x18\x02 \x01(\t\x12\x18\n\x0b\x64\x65scription\x18\x03 \x01(\tH\x00\x88\x01\x01\x42\x0e\n\x0c_description\"V\n\x0c\x43lassFeature\x12\x0c\n\x04type\x18\x01 \x01(\t\x12\x0e\n\x06\x63lass_\x18\x02 \x01(\t\x12\x18\n\x0b\x64\x65scription\x18\x03 \x01(\tH\x00\x88\x01\x01\x42\x0e\n\x0c_description\"K\n\x11\x43ompoundStatement\x12\x0c\n\x04type\x18\x01 \x01(\t\x12\x18\n\x0b\x64\x65scription\x18\x02 \x01(\tH\x00\x88\x01\x01\x42\x0e\n\x0c_description\"\xc8\x01\n\x0f\x44ynamicAnalysis\x12\x0e\n\x06\x66ormat\x18\x01 \x01(\t\x12\x0c\n\x04\x61rch\x18\x02 \x01(\t\x12\n\n\x02os\x18\x03 \x01(\t\x12\x11\n\textractor\x18\x04 \x01(\t\x12\r\n\x05rules\x18\x05 \x03(\t\x12,\n\x06layout\x18\x06 \x01(\x0b\x32\x1c.mandiant.capa.DynamicLayout\x12;\n\x0e\x66\x65\x61ture_counts\x18\x07 \x01(\x0b\x32#.mandiant.capa.DynamicFeatureCounts\"[\n\x14\x44ynamicFeatureCounts\x12\x0c\n\x04\x66ile\x18\x01 \x01(\x04\x12\x35\n\tprocesses\x18\x02 \x03(\x0b\x32\".mandiant.capa.ProcessFeatureCount\"@\n\rDynamicLayout\x12/\n\tprocesses\x18\x01 \x03(\x0b\x32\x1c.mandiant.capa.ProcessLayout\"W\n\rExportFeature\x12\x0c\n\x04type\x18\x01 \x01(\t\x12\x0e\n\x06\x65xport\x18\x02 \x01(\t\x12\x18\n\x0b\x64\x65scription\x18\x03 \x01(\tH\x00\x88\x01\x01\x42\x0e\n\x0c_description\"U\n\rFeatureCounts\x12\x0c\n\x04\x66ile\x18\x01 \x01(\x04\x12\x36\n\tfunctions\x18\x02 \x03(\x0b\x32#.mandiant.capa.FunctionFeatureCount\"\xb9\t\n\x0b\x46\x65\x61tureNode\x12\x0c\n\x04type\x18\x01 \x01(\t\x12&\n\x02os\x18\x02 \x01(\x0b\x32\x18.mandiant.capa.OSFeatureH\x00\x12*\n\x04\x61rch\x18\x03 \x01(\x0b\x32\x1a.mandiant.capa.ArchFeatureH\x00\x12.\n\x06\x66ormat\x18\x04 \x01(\x0b\x32\x1c.mandiant.capa.FormatFeatureH\x00\x12,\n\x05match\x18\x05 \x01(\x0b\x32\x1b.mandiant.capa.MatchFeatureH\x00\x12>\n\x0e\x63haracteristic\x18\x06 \x01(\x0b\x32$.mandiant.capa.CharacteristicFeatureH\x00\x12.\n\x06\x65xport\x18\x07 \x01(\x0b\x32\x1c.mandiant.capa.ExportFeatureH\x00\x12/\n\x07import_\x18\x08 \x01(\x0b\x32\x1c.mandiant.capa.ImportFeatureH\x00\x12\x30\n\x07section\x18\t \x01(\x0b\x32\x1d.mandiant.capa.SectionFeatureH\x00\x12;\n\rfunction_name\x18\n \x01(\x0b\x32\".mandiant.capa.FunctionNameFeatureH\x00\x12\x34\n\tsubstring\x18\x0b \x01(\x0b\x32\x1f.mandiant.capa.SubstringFeatureH\x00\x12,\n\x05regex\x18\x0c \x01(\x0b\x32\x1b.mandiant.capa.RegexFeatureH\x00\x12.\n\x06string\x18\r \x01(\x0b\x32\x1c.mandiant.capa.StringFeatureH\x00\x12-\n\x06\x63lass_\x18\x0e \x01(\x0b\x32\x1b.mandiant.capa.ClassFeatureH\x00\x12\x34\n\tnamespace\x18\x0f \x01(\x0b\x32\x1f.mandiant.capa.NamespaceFeatureH\x00\x12(\n\x03\x61pi\x18\x10 \x01(\x0b\x32\x19.mandiant.capa.APIFeatureH\x00\x12\x33\n\tproperty_\x18\x11 \x01(\x0b\x32\x1e.mandiant.capa.PropertyFeatureH\x00\x12.\n\x06number\x18\x12 \x01(\x0b\x32\x1c.mandiant.capa.NumberFeatureH\x00\x12,\n\x05\x62ytes\x18\x13 \x01(\x0b\x32\x1b.mandiant.capa.BytesFeatureH\x00\x12.\n\x06offset\x18\x14 \x01(\x0b\x32\x1c.mandiant.capa.OffsetFeatureH\x00\x12\x32\n\x08mnemonic\x18\x15 \x01(\x0b\x32\x1e.mandiant.capa.MnemonicFeatureH\x00\x12=\n\x0eoperand_number\x18\x16 \x01(\x0b\x32#.mandiant.capa.OperandNumberFeatureH\x00\x12=\n\x0eoperand_offset\x18\x17 \x01(\x0b\x32#.mandiant.capa.OperandOffsetFeatureH\x00\x12\x37\n\x0b\x62\x61sic_block\x18\x18 \x01(\x0b\x32 .mandiant.capa.BasicBlockFeatureH\x00\x42\t\n\x07\x66\x65\x61ture\"W\n\rFormatFeature\x12\x0c\n\x04type\x18\x01 \x01(\t\x12\x0e\n\x06\x66ormat\x18\x02 \x01(\t\x12\x18\n\x0b\x64\x65scription\x18\x03 \x01(\tH\x00\x88\x01\x01\x42\x0e\n\x0c_description\"N\n\x14\x46unctionFeatureCount\x12\'\n\x07\x61\x64\x64ress\x18\x01 \x01(\x0b\x32\x16.mandiant.capa.Address\x12\r\n\x05\x63ount\x18\x02 \x01(\x04\"x\n\x0e\x46unctionLayout\x12\'\n\x07\x61\x64\x64ress\x18\x01 \x01(\x0b\x32\x16.mandiant.capa.Address\x12=\n\x14matched_basic_blocks\x18\x02 \x03(\x0b\x32\x1f.mandiant.capa.BasicBlockLayout\"d\n\x13\x46unctionNameFeature\x12\x0c\n\x04type\x18\x01 \x01(\t\x12\x15\n\rfunction_name\x18\x02 \x01(\t\x12\x18\n\x0b\x64\x65scription\x18\x03 \x01(\tH\x00\x88\x01\x01\x42\x0e\n\x0c_description\"X\n\rImportFeature\x12\x0c\n\x04type\x18\x01 \x01(\t\x12\x0f\n\x07import_\x18\x02 \x01(\t\x12\x18\n\x0b\x64\x65scription\x18\x03 \x01(\tH\x00\x88\x01\x01\x42\x0e\n\x0c_description\":\n\x06Layout\x12\x30\n\tfunctions\x18\x01 \x03(\x0b\x32\x1d.mandiant.capa.FunctionLayout\"H\n\x0fLibraryFunction\x12\'\n\x07\x61\x64\x64ress\x18\x01 \x01(\x0b\x32\x16.mandiant.capa.Address\x12\x0c\n\x04name\x18\x02 \x01(\t\"Y\n\x07MBCSpec\x12\r\n\x05parts\x18\x01 \x03(\t\x12\x11\n\tobjective\x18\x02 \x01(\t\x12\x10\n\x08\x62\x65havior\x18\x03 \x01(\t\x12\x0e\n\x06method\x18\x04 \x01(\t\x12\n\n\x02id\x18\x05 \x01(\t\"\x9a\x01\n\x0cMaecMetadata\x12\x1b\n\x13\x61nalysis_conclusion\x18\x01 \x01(\t\x12\x1e\n\x16\x61nalysis_conclusion_ov\x18\x02 \x01(\t\x12\x16\n\x0emalware_family\x18\x03 \x01(\t\x12\x18\n\x10malware_category\x18\x04 \x01(\t\x12\x1b\n\x13malware_category_ov\x18\x05 \x01(\t\"\xd6\x02\n\x05Match\x12\x0f\n\x07success\x18\x01 \x01(\x08\x12\x31\n\tstatement\x18\x02 \x01(\x0b\x32\x1c.mandiant.capa.StatementNodeH\x00\x12-\n\x07\x66\x65\x61ture\x18\x03 \x01(\x0b\x32\x1a.mandiant.capa.FeatureNodeH\x00\x12&\n\x08\x63hildren\x18\x05 \x03(\x0b\x32\x14.mandiant.capa.Match\x12)\n\tlocations\x18\x06 \x03(\x0b\x32\x16.mandiant.capa.Address\x12\x34\n\x08\x63\x61ptures\x18\x07 \x03(\x0b\x32\".mandiant.capa.Match.CapturesEntry\x1aI\n\rCapturesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\'\n\x05value\x18\x02 \x01(\x0b\x32\x18.mandiant.capa.Addresses:\x02\x38\x01\x42\x06\n\x04node\"U\n\x0cMatchFeature\x12\x0c\n\x04type\x18\x01 \x01(\t\x12\r\n\x05match\x18\x02 \x01(\t\x12\x18\n\x0b\x64\x65scription\x18\x03 \x01(\tH\x00\x88\x01\x01\x42\x0e\n\x0c_description\"\xbc\x02\n\x08Metadata\x12\x11\n\ttimestamp\x18\x01 \x01(\t\x12\x0f\n\x07version\x18\x02 \x01(\t\x12\x0c\n\x04\x61rgv\x18\x03 \x03(\t\x12%\n\x06sample\x18\x04 \x01(\x0b\x32\x15.mandiant.capa.Sample\x12-\n\x08\x61nalysis\x18\x05 \x01(\x0b\x32\x17.mandiant.capa.AnalysisB\x02\x18\x01\x12%\n\x06\x66lavor\x18\x06 \x01(\x0e\x32\x15.mandiant.capa.Flavor\x12\x38\n\x0fstatic_analysis\x18\x07 \x01(\x0b\x32\x1d.mandiant.capa.StaticAnalysisH\x00\x12:\n\x10\x64ynamic_analysis\x18\x08 \x01(\x0b\x32\x1e.mandiant.capa.DynamicAnalysisH\x00\x42\x0b\n\tanalysis2\"[\n\x0fMnemonicFeature\x12\x0c\n\x04type\x18\x01 \x01(\t\x12\x10\n\x08mnemonic\x18\x02 \x01(\t\x12\x18\n\x0b\x64\x65scription\x18\x03 \x01(\tH\x00\x88\x01\x01\x42\x0e\n\x0c_description\"]\n\x10NamespaceFeature\x12\x0c\n\x04type\x18\x01 \x01(\t\x12\x11\n\tnamespace\x18\x02 \x01(\t\x12\x18\n\x0b\x64\x65scription\x18\x03 \x01(\tH\x00\x88\x01\x01\x42\x0e\n\x0c_description\"n\n\rNumberFeature\x12\x0c\n\x04type\x18\x01 \x01(\t\x12%\n\x06number\x18\x02 \x01(\x0b\x32\x15.mandiant.capa.Number\x12\x18\n\x0b\x64\x65scription\x18\x05 \x01(\tH\x00\x88\x01\x01\x42\x0e\n\x0c_description\"O\n\tOSFeature\x12\x0c\n\x04type\x18\x01 \x01(\t\x12\n\n\x02os\x18\x02 \x01(\t\x12\x18\n\x0b\x64\x65scription\x18\x03 \x01(\tH\x00\x88\x01\x01\x42\x0e\n\x0c_description\"o\n\rOffsetFeature\x12\x0c\n\x04type\x18\x01 \x01(\t\x12&\n\x06offset\x18\x02 \x01(\x0b\x32\x16.mandiant.capa.Integer\x12\x18\n\x0b\x64\x65scription\x18\x03 \x01(\tH\x00\x88\x01\x01\x42\x0e\n\x0c_description\"\x8d\x01\n\x14OperandNumberFeature\x12\x0c\n\x04type\x18\x01 \x01(\t\x12\r\n\x05index\x18\x02 \x01(\r\x12.\n\x0eoperand_number\x18\x03 \x01(\x0b\x32\x16.mandiant.capa.Integer\x12\x18\n\x0b\x64\x65scription\x18\x04 \x01(\tH\x00\x88\x01\x01\x42\x0e\n\x0c_description\"\x8d\x01\n\x14OperandOffsetFeature\x12\x0c\n\x04type\x18\x01 \x01(\t\x12\r\n\x05index\x18\x02 \x01(\r\x12.\n\x0eoperand_offset\x18\x03 \x01(\x0b\x32\x16.mandiant.capa.Integer\x12\x18\n\x0b\x64\x65scription\x18\x04 \x01(\tH\x00\x88\x01\x01\x42\x0e\n\x0c_description\"M\n\x13ProcessFeatureCount\x12\'\n\x07\x61\x64\x64ress\x18\x01 \x01(\x0b\x32\x16.mandiant.capa.Address\x12\r\n\x05\x63ount\x18\x02 \x01(\x04\"|\n\rProcessLayout\x12\'\n\x07\x61\x64\x64ress\x18\x01 \x01(\x0b\x32\x16.mandiant.capa.Address\x12\x34\n\x0fmatched_threads\x18\x02 \x03(\x0b\x32\x1b.mandiant.capa.ThreadLayout\x12\x0c\n\x04name\x18\x03 \x01(\t\"|\n\x0fPropertyFeature\x12\x0c\n\x04type\x18\x01 \x01(\t\x12\x11\n\tproperty_\x18\x02 \x01(\t\x12\x13\n\x06\x61\x63\x63\x65ss\x18\x03 \x01(\tH\x00\x88\x01\x01\x12\x18\n\x0b\x64\x65scription\x18\x04 \x01(\tH\x01\x88\x01\x01\x42\t\n\x07_accessB\x0e\n\x0c_description\"\x8d\x01\n\x0eRangeStatement\x12\x0c\n\x04type\x18\x01 \x01(\t\x12\x0b\n\x03min\x18\x02 \x01(\x04\x12\x0b\n\x03max\x18\x03 \x01(\x04\x12)\n\x05\x63hild\x18\x04 \x01(\x0b\x32\x1a.mandiant.capa.FeatureNode\x12\x18\n\x0b\x64\x65scription\x18\x05 \x01(\tH\x00\x88\x01\x01\x42\x0e\n\x0c_description\"U\n\x0cRegexFeature\x12\x0c\n\x04type\x18\x01 \x01(\t\x12\r\n\x05regex\x18\x02 \x01(\t\x12\x18\n\x0b\x64\x65scription\x18\x03 \x01(\tH\x00\x88\x01\x01\x42\x0e\n\x0c_description\"\xba\x01\n\x0eResultDocument\x12%\n\x04meta\x18\x01 \x01(\x0b\x32\x17.mandiant.capa.Metadata\x12\x37\n\x05rules\x18\x02 \x03(\x0b\x32(.mandiant.capa.ResultDocument.RulesEntry\x1aH\n\nRulesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12)\n\x05value\x18\x02 \x01(\x0b\x32\x1a.mandiant.capa.RuleMatches:\x02\x38\x01\"|\n\x0bRuleMatches\x12)\n\x04meta\x18\x01 \x01(\x0b\x32\x1b.mandiant.capa.RuleMetadata\x12\x0e\n\x06source\x18\x02 \x01(\t\x12\x32\n\x07matches\x18\x03 \x03(\x0b\x32!.mandiant.capa.Pair_Address_Match\"\xed\x02\n\x0cRuleMetadata\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x11\n\tnamespace\x18\x02 \x01(\t\x12\x0f\n\x07\x61uthors\x18\x03 \x03(\t\x12\'\n\x05scope\x18\x04 \x01(\x0e\x32\x14.mandiant.capa.ScopeB\x02\x18\x01\x12)\n\x06\x61ttack\x18\x05 \x03(\x0b\x32\x19.mandiant.capa.AttackSpec\x12#\n\x03mbc\x18\x06 \x03(\x0b\x32\x16.mandiant.capa.MBCSpec\x12\x12\n\nreferences\x18\x07 \x03(\t\x12\x10\n\x08\x65xamples\x18\x08 \x03(\t\x12\x13\n\x0b\x64\x65scription\x18\t \x01(\t\x12\x0b\n\x03lib\x18\n \x01(\x08\x12)\n\x04maec\x18\x0b \x01(\x0b\x32\x1b.mandiant.capa.MaecMetadata\x12\x18\n\x10is_subscope_rule\x18\x0c \x01(\x08\x12%\n\x06scopes\x18\r \x01(\x0b\x32\x15.mandiant.capa.Scopes\"A\n\x06Sample\x12\x0b\n\x03md5\x18\x01 \x01(\t\x12\x0c\n\x04sha1\x18\x02 \x01(\t\x12\x0e\n\x06sha256\x18\x03 \x01(\t\x12\x0c\n\x04path\x18\x04 \x01(\t\"v\n\x06Scopes\x12)\n\x06static\x18\x01 \x01(\x0e\x32\x14.mandiant.capa.ScopeH\x00\x88\x01\x01\x12*\n\x07\x64ynamic\x18\x02 \x01(\x0e\x32\x14.mandiant.capa.ScopeH\x01\x88\x01\x01\x42\t\n\x07_staticB\n\n\x08_dynamic\"Y\n\x0eSectionFeature\x12\x0c\n\x04type\x18\x01 \x01(\t\x12\x0f\n\x07section\x18\x02 \x01(\t\x12\x18\n\x0b\x64\x65scription\x18\x03 \x01(\tH\x00\x88\x01\x01\x42\x0e\n\x0c_description\"V\n\rSomeStatement\x12\x0c\n\x04type\x18\x01 \x01(\t\x12\r\n\x05\x63ount\x18\x02 \x01(\r\x12\x18\n\x0b\x64\x65scription\x18\x03 \x01(\tH\x00\x88\x01\x01\x42\x0e\n\x0c_description\"\xf4\x01\n\rStatementNode\x12\x0c\n\x04type\x18\x01 \x01(\t\x12.\n\x05range\x18\x02 \x01(\x0b\x32\x1d.mandiant.capa.RangeStatementH\x00\x12,\n\x04some\x18\x03 \x01(\x0b\x32\x1c.mandiant.capa.SomeStatementH\x00\x12\x34\n\x08subscope\x18\x04 \x01(\x0b\x32 .mandiant.capa.SubscopeStatementH\x00\x12\x34\n\x08\x63ompound\x18\x05 \x01(\x0b\x32 .mandiant.capa.CompoundStatementH\x00\x42\x0b\n\tstatement\"\xae\x02\n\x0eStaticAnalysis\x12\x0e\n\x06\x66ormat\x18\x01 \x01(\t\x12\x0c\n\x04\x61rch\x18\x02 \x01(\t\x12\n\n\x02os\x18\x03 \x01(\t\x12\x11\n\textractor\x18\x04 \x01(\t\x12\r\n\x05rules\x18\x05 \x03(\t\x12,\n\x0c\x62\x61se_address\x18\x06 \x01(\x0b\x32\x16.mandiant.capa.Address\x12+\n\x06layout\x18\x07 \x01(\x0b\x32\x1b.mandiant.capa.StaticLayout\x12:\n\x0e\x66\x65\x61ture_counts\x18\x08 \x01(\x0b\x32\".mandiant.capa.StaticFeatureCounts\x12\x39\n\x11library_functions\x18\t \x03(\x0b\x32\x1e.mandiant.capa.LibraryFunction\"[\n\x13StaticFeatureCounts\x12\x0c\n\x04\x66ile\x18\x01 \x01(\x04\x12\x36\n\tfunctions\x18\x02 \x03(\x0b\x32#.mandiant.capa.FunctionFeatureCount\"@\n\x0cStaticLayout\x12\x30\n\tfunctions\x18\x01 \x03(\x0b\x32\x1d.mandiant.capa.FunctionLayout\"W\n\rStringFeature\x12\x0c\n\x04type\x18\x01 \x01(\t\x12\x0e\n\x06string\x18\x02 \x01(\t\x12\x18\n\x0b\x64\x65scription\x18\x03 \x01(\tH\x00\x88\x01\x01\x42\x0e\n\x0c_description\"p\n\x11SubscopeStatement\x12\x0c\n\x04type\x18\x01 \x01(\t\x12#\n\x05scope\x18\x02 \x01(\x0e\x32\x14.mandiant.capa.Scope\x12\x18\n\x0b\x64\x65scription\x18\x03 \x01(\tH\x00\x88\x01\x01\x42\x0e\n\x0c_description\"]\n\x10SubstringFeature\x12\x0c\n\x04type\x18\x01 \x01(\t\x12\x11\n\tsubstring\x18\x02 \x01(\t\x12\x18\n\x0b\x64\x65scription\x18\x03 \x01(\tH\x00\x88\x01\x01\x42\x0e\n\x0c_description\"C\n\nCallLayout\x12\'\n\x07\x61\x64\x64ress\x18\x01 \x01(\x0b\x32\x16.mandiant.capa.Address\x12\x0c\n\x04name\x18\x02 \x01(\t\"i\n\x0cThreadLayout\x12\'\n\x07\x61\x64\x64ress\x18\x01 \x01(\x0b\x32\x16.mandiant.capa.Address\x12\x30\n\rmatched_calls\x18\x02 \x03(\x0b\x32\x19.mandiant.capa.CallLayout\"4\n\tAddresses\x12\'\n\x07\x61\x64\x64ress\x18\x01 \x03(\x0b\x32\x16.mandiant.capa.Address\"b\n\x12Pair_Address_Match\x12\'\n\x07\x61\x64\x64ress\x18\x01 \x01(\x0b\x32\x16.mandiant.capa.Address\x12#\n\x05match\x18\x02 \x01(\x0b\x32\x14.mandiant.capa.Match\"E\n\x0cToken_Offset\x12%\n\x05token\x18\x01 \x01(\x0b\x32\x16.mandiant.capa.Integer\x12\x0e\n\x06offset\x18\x02 \x01(\x04\"U\n\x08Ppid_Pid\x12$\n\x04ppid\x18\x01 \x01(\x0b\x32\x16.mandiant.capa.Integer\x12#\n\x03pid\x18\x02 \x01(\x0b\x32\x16.mandiant.capa.Integer\"~\n\x0cPpid_Pid_Tid\x12$\n\x04ppid\x18\x01 \x01(\x0b\x32\x16.mandiant.capa.Integer\x12#\n\x03pid\x18\x02 \x01(\x0b\x32\x16.mandiant.capa.Integer\x12#\n\x03tid\x18\x03 \x01(\x0b\x32\x16.mandiant.capa.Integer\"\xa5\x01\n\x0fPpid_Pid_Tid_Id\x12$\n\x04ppid\x18\x01 \x01(\x0b\x32\x16.mandiant.capa.Integer\x12#\n\x03pid\x18\x02 \x01(\x0b\x32\x16.mandiant.capa.Integer\x12#\n\x03tid\x18\x03 \x01(\x0b\x32\x16.mandiant.capa.Integer\x12\"\n\x02id\x18\x04 \x01(\x0b\x32\x16.mandiant.capa.Integer\",\n\x07Integer\x12\x0b\n\x01u\x18\x01 \x01(\x04H\x00\x12\x0b\n\x01i\x18\x02 \x01(\x12H\x00\x42\x07\n\x05value\"8\n\x06Number\x12\x0b\n\x01u\x18\x01 \x01(\x04H\x00\x12\x0b\n\x01i\x18\x02 \x01(\x12H\x00\x12\x0b\n\x01\x66\x18\x03 \x01(\x01H\x00\x42\x07\n\x05value*\x92\x02\n\x0b\x41\x64\x64ressType\x12\x1b\n\x17\x41\x44\x44RESSTYPE_UNSPECIFIED\x10\x00\x12\x18\n\x14\x41\x44\x44RESSTYPE_ABSOLUTE\x10\x01\x12\x18\n\x14\x41\x44\x44RESSTYPE_RELATIVE\x10\x02\x12\x14\n\x10\x41\x44\x44RESSTYPE_FILE\x10\x03\x12\x18\n\x14\x41\x44\x44RESSTYPE_DN_TOKEN\x10\x04\x12\x1f\n\x1b\x41\x44\x44RESSTYPE_DN_TOKEN_OFFSET\x10\x05\x12\x1a\n\x16\x41\x44\x44RESSTYPE_NO_ADDRESS\x10\x06\x12\x17\n\x13\x41\x44\x44RESSTYPE_PROCESS\x10\x07\x12\x16\n\x12\x41\x44\x44RESSTYPE_THREAD\x10\x08\x12\x14\n\x10\x41\x44\x44RESSTYPE_CALL\x10\t*G\n\x06\x46lavor\x12\x16\n\x12\x46LAVOR_UNSPECIFIED\x10\x00\x12\x11\n\rFLAVOR_STATIC\x10\x01\x12\x12\n\x0e\x46LAVOR_DYNAMIC\x10\x02*\xb9\x01\n\x05Scope\x12\x15\n\x11SCOPE_UNSPECIFIED\x10\x00\x12\x0e\n\nSCOPE_FILE\x10\x01\x12\x12\n\x0eSCOPE_FUNCTION\x10\x02\x12\x15\n\x11SCOPE_BASIC_BLOCK\x10\x03\x12\x15\n\x11SCOPE_INSTRUCTION\x10\x04\x12\x11\n\rSCOPE_PROCESS\x10\x05\x12\x10\n\x0cSCOPE_THREAD\x10\x06\x12\x0e\n\nSCOPE_CALL\x10\x07\x12\x12\n\x0eSCOPE_SEQUENCE\x10\x08\x62\x06proto3') +DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x1c\x63\x61pa/render/proto/capa.proto\x12\rmandiant.capa\"Q\n\nAPIFeature\x12\x0c\n\x04type\x18\x01 \x01(\t\x12\x0b\n\x03\x61pi\x18\x02 \x01(\t\x12\x18\n\x0b\x64\x65scription\x18\x03 \x01(\tH\x00\x88\x01\x01\x42\x0e\n\x0c_description\"\xfa\x02\n\x07\x41\x64\x64ress\x12(\n\x04type\x18\x01 \x01(\x0e\x32\x1a.mandiant.capa.AddressType\x12#\n\x01v\x18\x02 \x01(\x0b\x32\x16.mandiant.capa.IntegerH\x00\x12\x33\n\x0ctoken_offset\x18\x03 \x01(\x0b\x32\x1b.mandiant.capa.Token_OffsetH\x00\x12+\n\x08ppid_pid\x18\x04 \x01(\x0b\x32\x17.mandiant.capa.Ppid_PidH\x00\x12\x33\n\x0cppid_pid_tid\x18\x05 \x01(\x0b\x32\x1b.mandiant.capa.Ppid_Pid_TidH\x00\x12\x39\n\x0fppid_pid_tid_id\x18\x06 \x01(\x0b\x32\x1e.mandiant.capa.Ppid_Pid_Tid_IdH\x00\x12\x45\n\x15ppid_pid_tid_id_calls\x18\x07 \x01(\x0b\x32$.mandiant.capa.Ppid_Pid_Tid_Id_CallsH\x00\x42\x07\n\x05value\"\x9c\x02\n\x08\x41nalysis\x12\x0e\n\x06\x66ormat\x18\x01 \x01(\t\x12\x0c\n\x04\x61rch\x18\x02 \x01(\t\x12\n\n\x02os\x18\x03 \x01(\t\x12\x11\n\textractor\x18\x04 \x01(\t\x12\r\n\x05rules\x18\x05 \x03(\t\x12,\n\x0c\x62\x61se_address\x18\x06 \x01(\x0b\x32\x16.mandiant.capa.Address\x12%\n\x06layout\x18\x07 \x01(\x0b\x32\x15.mandiant.capa.Layout\x12\x34\n\x0e\x66\x65\x61ture_counts\x18\x08 \x01(\x0b\x32\x1c.mandiant.capa.FeatureCounts\x12\x39\n\x11library_functions\x18\t \x03(\x0b\x32\x1e.mandiant.capa.LibraryFunction\"S\n\x0b\x41rchFeature\x12\x0c\n\x04type\x18\x01 \x01(\t\x12\x0c\n\x04\x61rch\x18\x02 \x01(\t\x12\x18\n\x0b\x64\x65scription\x18\x03 \x01(\tH\x00\x88\x01\x01\x42\x0e\n\x0c_description\"`\n\nAttackSpec\x12\r\n\x05parts\x18\x01 \x03(\t\x12\x0e\n\x06tactic\x18\x02 \x01(\t\x12\x11\n\ttechnique\x18\x03 \x01(\t\x12\x14\n\x0csubtechnique\x18\x04 \x01(\t\x12\n\n\x02id\x18\x05 \x01(\t\"K\n\x11\x42\x61sicBlockFeature\x12\x0c\n\x04type\x18\x01 \x01(\t\x12\x18\n\x0b\x64\x65scription\x18\x02 \x01(\tH\x00\x88\x01\x01\x42\x0e\n\x0c_description\";\n\x10\x42\x61sicBlockLayout\x12\'\n\x07\x61\x64\x64ress\x18\x01 \x01(\x0b\x32\x16.mandiant.capa.Address\"U\n\x0c\x42ytesFeature\x12\x0c\n\x04type\x18\x01 \x01(\t\x12\r\n\x05\x62ytes\x18\x02 \x01(\t\x12\x18\n\x0b\x64\x65scription\x18\x03 \x01(\tH\x00\x88\x01\x01\x42\x0e\n\x0c_description\"g\n\x15\x43haracteristicFeature\x12\x0c\n\x04type\x18\x01 \x01(\t\x12\x16\n\x0e\x63haracteristic\x18\x02 \x01(\t\x12\x18\n\x0b\x64\x65scription\x18\x03 \x01(\tH\x00\x88\x01\x01\x42\x0e\n\x0c_description\"V\n\x0c\x43lassFeature\x12\x0c\n\x04type\x18\x01 \x01(\t\x12\x0e\n\x06\x63lass_\x18\x02 \x01(\t\x12\x18\n\x0b\x64\x65scription\x18\x03 \x01(\tH\x00\x88\x01\x01\x42\x0e\n\x0c_description\"K\n\x11\x43ompoundStatement\x12\x0c\n\x04type\x18\x01 \x01(\t\x12\x18\n\x0b\x64\x65scription\x18\x02 \x01(\tH\x00\x88\x01\x01\x42\x0e\n\x0c_description\"\xc8\x01\n\x0f\x44ynamicAnalysis\x12\x0e\n\x06\x66ormat\x18\x01 \x01(\t\x12\x0c\n\x04\x61rch\x18\x02 \x01(\t\x12\n\n\x02os\x18\x03 \x01(\t\x12\x11\n\textractor\x18\x04 \x01(\t\x12\r\n\x05rules\x18\x05 \x03(\t\x12,\n\x06layout\x18\x06 \x01(\x0b\x32\x1c.mandiant.capa.DynamicLayout\x12;\n\x0e\x66\x65\x61ture_counts\x18\x07 \x01(\x0b\x32#.mandiant.capa.DynamicFeatureCounts\"[\n\x14\x44ynamicFeatureCounts\x12\x0c\n\x04\x66ile\x18\x01 \x01(\x04\x12\x35\n\tprocesses\x18\x02 \x03(\x0b\x32\".mandiant.capa.ProcessFeatureCount\"@\n\rDynamicLayout\x12/\n\tprocesses\x18\x01 \x03(\x0b\x32\x1c.mandiant.capa.ProcessLayout\"W\n\rExportFeature\x12\x0c\n\x04type\x18\x01 \x01(\t\x12\x0e\n\x06\x65xport\x18\x02 \x01(\t\x12\x18\n\x0b\x64\x65scription\x18\x03 \x01(\tH\x00\x88\x01\x01\x42\x0e\n\x0c_description\"U\n\rFeatureCounts\x12\x0c\n\x04\x66ile\x18\x01 \x01(\x04\x12\x36\n\tfunctions\x18\x02 \x03(\x0b\x32#.mandiant.capa.FunctionFeatureCount\"\xb9\t\n\x0b\x46\x65\x61tureNode\x12\x0c\n\x04type\x18\x01 \x01(\t\x12&\n\x02os\x18\x02 \x01(\x0b\x32\x18.mandiant.capa.OSFeatureH\x00\x12*\n\x04\x61rch\x18\x03 \x01(\x0b\x32\x1a.mandiant.capa.ArchFeatureH\x00\x12.\n\x06\x66ormat\x18\x04 \x01(\x0b\x32\x1c.mandiant.capa.FormatFeatureH\x00\x12,\n\x05match\x18\x05 \x01(\x0b\x32\x1b.mandiant.capa.MatchFeatureH\x00\x12>\n\x0e\x63haracteristic\x18\x06 \x01(\x0b\x32$.mandiant.capa.CharacteristicFeatureH\x00\x12.\n\x06\x65xport\x18\x07 \x01(\x0b\x32\x1c.mandiant.capa.ExportFeatureH\x00\x12/\n\x07import_\x18\x08 \x01(\x0b\x32\x1c.mandiant.capa.ImportFeatureH\x00\x12\x30\n\x07section\x18\t \x01(\x0b\x32\x1d.mandiant.capa.SectionFeatureH\x00\x12;\n\rfunction_name\x18\n \x01(\x0b\x32\".mandiant.capa.FunctionNameFeatureH\x00\x12\x34\n\tsubstring\x18\x0b \x01(\x0b\x32\x1f.mandiant.capa.SubstringFeatureH\x00\x12,\n\x05regex\x18\x0c \x01(\x0b\x32\x1b.mandiant.capa.RegexFeatureH\x00\x12.\n\x06string\x18\r \x01(\x0b\x32\x1c.mandiant.capa.StringFeatureH\x00\x12-\n\x06\x63lass_\x18\x0e \x01(\x0b\x32\x1b.mandiant.capa.ClassFeatureH\x00\x12\x34\n\tnamespace\x18\x0f \x01(\x0b\x32\x1f.mandiant.capa.NamespaceFeatureH\x00\x12(\n\x03\x61pi\x18\x10 \x01(\x0b\x32\x19.mandiant.capa.APIFeatureH\x00\x12\x33\n\tproperty_\x18\x11 \x01(\x0b\x32\x1e.mandiant.capa.PropertyFeatureH\x00\x12.\n\x06number\x18\x12 \x01(\x0b\x32\x1c.mandiant.capa.NumberFeatureH\x00\x12,\n\x05\x62ytes\x18\x13 \x01(\x0b\x32\x1b.mandiant.capa.BytesFeatureH\x00\x12.\n\x06offset\x18\x14 \x01(\x0b\x32\x1c.mandiant.capa.OffsetFeatureH\x00\x12\x32\n\x08mnemonic\x18\x15 \x01(\x0b\x32\x1e.mandiant.capa.MnemonicFeatureH\x00\x12=\n\x0eoperand_number\x18\x16 \x01(\x0b\x32#.mandiant.capa.OperandNumberFeatureH\x00\x12=\n\x0eoperand_offset\x18\x17 \x01(\x0b\x32#.mandiant.capa.OperandOffsetFeatureH\x00\x12\x37\n\x0b\x62\x61sic_block\x18\x18 \x01(\x0b\x32 .mandiant.capa.BasicBlockFeatureH\x00\x42\t\n\x07\x66\x65\x61ture\"W\n\rFormatFeature\x12\x0c\n\x04type\x18\x01 \x01(\t\x12\x0e\n\x06\x66ormat\x18\x02 \x01(\t\x12\x18\n\x0b\x64\x65scription\x18\x03 \x01(\tH\x00\x88\x01\x01\x42\x0e\n\x0c_description\"N\n\x14\x46unctionFeatureCount\x12\'\n\x07\x61\x64\x64ress\x18\x01 \x01(\x0b\x32\x16.mandiant.capa.Address\x12\r\n\x05\x63ount\x18\x02 \x01(\x04\"x\n\x0e\x46unctionLayout\x12\'\n\x07\x61\x64\x64ress\x18\x01 \x01(\x0b\x32\x16.mandiant.capa.Address\x12=\n\x14matched_basic_blocks\x18\x02 \x03(\x0b\x32\x1f.mandiant.capa.BasicBlockLayout\"d\n\x13\x46unctionNameFeature\x12\x0c\n\x04type\x18\x01 \x01(\t\x12\x15\n\rfunction_name\x18\x02 \x01(\t\x12\x18\n\x0b\x64\x65scription\x18\x03 \x01(\tH\x00\x88\x01\x01\x42\x0e\n\x0c_description\"X\n\rImportFeature\x12\x0c\n\x04type\x18\x01 \x01(\t\x12\x0f\n\x07import_\x18\x02 \x01(\t\x12\x18\n\x0b\x64\x65scription\x18\x03 \x01(\tH\x00\x88\x01\x01\x42\x0e\n\x0c_description\":\n\x06Layout\x12\x30\n\tfunctions\x18\x01 \x03(\x0b\x32\x1d.mandiant.capa.FunctionLayout\"H\n\x0fLibraryFunction\x12\'\n\x07\x61\x64\x64ress\x18\x01 \x01(\x0b\x32\x16.mandiant.capa.Address\x12\x0c\n\x04name\x18\x02 \x01(\t\"Y\n\x07MBCSpec\x12\r\n\x05parts\x18\x01 \x03(\t\x12\x11\n\tobjective\x18\x02 \x01(\t\x12\x10\n\x08\x62\x65havior\x18\x03 \x01(\t\x12\x0e\n\x06method\x18\x04 \x01(\t\x12\n\n\x02id\x18\x05 \x01(\t\"\x9a\x01\n\x0cMaecMetadata\x12\x1b\n\x13\x61nalysis_conclusion\x18\x01 \x01(\t\x12\x1e\n\x16\x61nalysis_conclusion_ov\x18\x02 \x01(\t\x12\x16\n\x0emalware_family\x18\x03 \x01(\t\x12\x18\n\x10malware_category\x18\x04 \x01(\t\x12\x1b\n\x13malware_category_ov\x18\x05 \x01(\t\"\xd6\x02\n\x05Match\x12\x0f\n\x07success\x18\x01 \x01(\x08\x12\x31\n\tstatement\x18\x02 \x01(\x0b\x32\x1c.mandiant.capa.StatementNodeH\x00\x12-\n\x07\x66\x65\x61ture\x18\x03 \x01(\x0b\x32\x1a.mandiant.capa.FeatureNodeH\x00\x12&\n\x08\x63hildren\x18\x05 \x03(\x0b\x32\x14.mandiant.capa.Match\x12)\n\tlocations\x18\x06 \x03(\x0b\x32\x16.mandiant.capa.Address\x12\x34\n\x08\x63\x61ptures\x18\x07 \x03(\x0b\x32\".mandiant.capa.Match.CapturesEntry\x1aI\n\rCapturesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\'\n\x05value\x18\x02 \x01(\x0b\x32\x18.mandiant.capa.Addresses:\x02\x38\x01\x42\x06\n\x04node\"U\n\x0cMatchFeature\x12\x0c\n\x04type\x18\x01 \x01(\t\x12\r\n\x05match\x18\x02 \x01(\t\x12\x18\n\x0b\x64\x65scription\x18\x03 \x01(\tH\x00\x88\x01\x01\x42\x0e\n\x0c_description\"\xbc\x02\n\x08Metadata\x12\x11\n\ttimestamp\x18\x01 \x01(\t\x12\x0f\n\x07version\x18\x02 \x01(\t\x12\x0c\n\x04\x61rgv\x18\x03 \x03(\t\x12%\n\x06sample\x18\x04 \x01(\x0b\x32\x15.mandiant.capa.Sample\x12-\n\x08\x61nalysis\x18\x05 \x01(\x0b\x32\x17.mandiant.capa.AnalysisB\x02\x18\x01\x12%\n\x06\x66lavor\x18\x06 \x01(\x0e\x32\x15.mandiant.capa.Flavor\x12\x38\n\x0fstatic_analysis\x18\x07 \x01(\x0b\x32\x1d.mandiant.capa.StaticAnalysisH\x00\x12:\n\x10\x64ynamic_analysis\x18\x08 \x01(\x0b\x32\x1e.mandiant.capa.DynamicAnalysisH\x00\x42\x0b\n\tanalysis2\"[\n\x0fMnemonicFeature\x12\x0c\n\x04type\x18\x01 \x01(\t\x12\x10\n\x08mnemonic\x18\x02 \x01(\t\x12\x18\n\x0b\x64\x65scription\x18\x03 \x01(\tH\x00\x88\x01\x01\x42\x0e\n\x0c_description\"]\n\x10NamespaceFeature\x12\x0c\n\x04type\x18\x01 \x01(\t\x12\x11\n\tnamespace\x18\x02 \x01(\t\x12\x18\n\x0b\x64\x65scription\x18\x03 \x01(\tH\x00\x88\x01\x01\x42\x0e\n\x0c_description\"n\n\rNumberFeature\x12\x0c\n\x04type\x18\x01 \x01(\t\x12%\n\x06number\x18\x02 \x01(\x0b\x32\x15.mandiant.capa.Number\x12\x18\n\x0b\x64\x65scription\x18\x05 \x01(\tH\x00\x88\x01\x01\x42\x0e\n\x0c_description\"O\n\tOSFeature\x12\x0c\n\x04type\x18\x01 \x01(\t\x12\n\n\x02os\x18\x02 \x01(\t\x12\x18\n\x0b\x64\x65scription\x18\x03 \x01(\tH\x00\x88\x01\x01\x42\x0e\n\x0c_description\"o\n\rOffsetFeature\x12\x0c\n\x04type\x18\x01 \x01(\t\x12&\n\x06offset\x18\x02 \x01(\x0b\x32\x16.mandiant.capa.Integer\x12\x18\n\x0b\x64\x65scription\x18\x03 \x01(\tH\x00\x88\x01\x01\x42\x0e\n\x0c_description\"\x8d\x01\n\x14OperandNumberFeature\x12\x0c\n\x04type\x18\x01 \x01(\t\x12\r\n\x05index\x18\x02 \x01(\r\x12.\n\x0eoperand_number\x18\x03 \x01(\x0b\x32\x16.mandiant.capa.Integer\x12\x18\n\x0b\x64\x65scription\x18\x04 \x01(\tH\x00\x88\x01\x01\x42\x0e\n\x0c_description\"\x8d\x01\n\x14OperandOffsetFeature\x12\x0c\n\x04type\x18\x01 \x01(\t\x12\r\n\x05index\x18\x02 \x01(\r\x12.\n\x0eoperand_offset\x18\x03 \x01(\x0b\x32\x16.mandiant.capa.Integer\x12\x18\n\x0b\x64\x65scription\x18\x04 \x01(\tH\x00\x88\x01\x01\x42\x0e\n\x0c_description\"M\n\x13ProcessFeatureCount\x12\'\n\x07\x61\x64\x64ress\x18\x01 \x01(\x0b\x32\x16.mandiant.capa.Address\x12\r\n\x05\x63ount\x18\x02 \x01(\x04\"|\n\rProcessLayout\x12\'\n\x07\x61\x64\x64ress\x18\x01 \x01(\x0b\x32\x16.mandiant.capa.Address\x12\x34\n\x0fmatched_threads\x18\x02 \x03(\x0b\x32\x1b.mandiant.capa.ThreadLayout\x12\x0c\n\x04name\x18\x03 \x01(\t\"|\n\x0fPropertyFeature\x12\x0c\n\x04type\x18\x01 \x01(\t\x12\x11\n\tproperty_\x18\x02 \x01(\t\x12\x13\n\x06\x61\x63\x63\x65ss\x18\x03 \x01(\tH\x00\x88\x01\x01\x12\x18\n\x0b\x64\x65scription\x18\x04 \x01(\tH\x01\x88\x01\x01\x42\t\n\x07_accessB\x0e\n\x0c_description\"\x8d\x01\n\x0eRangeStatement\x12\x0c\n\x04type\x18\x01 \x01(\t\x12\x0b\n\x03min\x18\x02 \x01(\x04\x12\x0b\n\x03max\x18\x03 \x01(\x04\x12)\n\x05\x63hild\x18\x04 \x01(\x0b\x32\x1a.mandiant.capa.FeatureNode\x12\x18\n\x0b\x64\x65scription\x18\x05 \x01(\tH\x00\x88\x01\x01\x42\x0e\n\x0c_description\"U\n\x0cRegexFeature\x12\x0c\n\x04type\x18\x01 \x01(\t\x12\r\n\x05regex\x18\x02 \x01(\t\x12\x18\n\x0b\x64\x65scription\x18\x03 \x01(\tH\x00\x88\x01\x01\x42\x0e\n\x0c_description\"\xba\x01\n\x0eResultDocument\x12%\n\x04meta\x18\x01 \x01(\x0b\x32\x17.mandiant.capa.Metadata\x12\x37\n\x05rules\x18\x02 \x03(\x0b\x32(.mandiant.capa.ResultDocument.RulesEntry\x1aH\n\nRulesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12)\n\x05value\x18\x02 \x01(\x0b\x32\x1a.mandiant.capa.RuleMatches:\x02\x38\x01\"|\n\x0bRuleMatches\x12)\n\x04meta\x18\x01 \x01(\x0b\x32\x1b.mandiant.capa.RuleMetadata\x12\x0e\n\x06source\x18\x02 \x01(\t\x12\x32\n\x07matches\x18\x03 \x03(\x0b\x32!.mandiant.capa.Pair_Address_Match\"\xed\x02\n\x0cRuleMetadata\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x11\n\tnamespace\x18\x02 \x01(\t\x12\x0f\n\x07\x61uthors\x18\x03 \x03(\t\x12\'\n\x05scope\x18\x04 \x01(\x0e\x32\x14.mandiant.capa.ScopeB\x02\x18\x01\x12)\n\x06\x61ttack\x18\x05 \x03(\x0b\x32\x19.mandiant.capa.AttackSpec\x12#\n\x03mbc\x18\x06 \x03(\x0b\x32\x16.mandiant.capa.MBCSpec\x12\x12\n\nreferences\x18\x07 \x03(\t\x12\x10\n\x08\x65xamples\x18\x08 \x03(\t\x12\x13\n\x0b\x64\x65scription\x18\t \x01(\t\x12\x0b\n\x03lib\x18\n \x01(\x08\x12)\n\x04maec\x18\x0b \x01(\x0b\x32\x1b.mandiant.capa.MaecMetadata\x12\x18\n\x10is_subscope_rule\x18\x0c \x01(\x08\x12%\n\x06scopes\x18\r \x01(\x0b\x32\x15.mandiant.capa.Scopes\"A\n\x06Sample\x12\x0b\n\x03md5\x18\x01 \x01(\t\x12\x0c\n\x04sha1\x18\x02 \x01(\t\x12\x0e\n\x06sha256\x18\x03 \x01(\t\x12\x0c\n\x04path\x18\x04 \x01(\t\"v\n\x06Scopes\x12)\n\x06static\x18\x01 \x01(\x0e\x32\x14.mandiant.capa.ScopeH\x00\x88\x01\x01\x12*\n\x07\x64ynamic\x18\x02 \x01(\x0e\x32\x14.mandiant.capa.ScopeH\x01\x88\x01\x01\x42\t\n\x07_staticB\n\n\x08_dynamic\"Y\n\x0eSectionFeature\x12\x0c\n\x04type\x18\x01 \x01(\t\x12\x0f\n\x07section\x18\x02 \x01(\t\x12\x18\n\x0b\x64\x65scription\x18\x03 \x01(\tH\x00\x88\x01\x01\x42\x0e\n\x0c_description\"V\n\rSomeStatement\x12\x0c\n\x04type\x18\x01 \x01(\t\x12\r\n\x05\x63ount\x18\x02 \x01(\r\x12\x18\n\x0b\x64\x65scription\x18\x03 \x01(\tH\x00\x88\x01\x01\x42\x0e\n\x0c_description\"\xf4\x01\n\rStatementNode\x12\x0c\n\x04type\x18\x01 \x01(\t\x12.\n\x05range\x18\x02 \x01(\x0b\x32\x1d.mandiant.capa.RangeStatementH\x00\x12,\n\x04some\x18\x03 \x01(\x0b\x32\x1c.mandiant.capa.SomeStatementH\x00\x12\x34\n\x08subscope\x18\x04 \x01(\x0b\x32 .mandiant.capa.SubscopeStatementH\x00\x12\x34\n\x08\x63ompound\x18\x05 \x01(\x0b\x32 .mandiant.capa.CompoundStatementH\x00\x42\x0b\n\tstatement\"\xae\x02\n\x0eStaticAnalysis\x12\x0e\n\x06\x66ormat\x18\x01 \x01(\t\x12\x0c\n\x04\x61rch\x18\x02 \x01(\t\x12\n\n\x02os\x18\x03 \x01(\t\x12\x11\n\textractor\x18\x04 \x01(\t\x12\r\n\x05rules\x18\x05 \x03(\t\x12,\n\x0c\x62\x61se_address\x18\x06 \x01(\x0b\x32\x16.mandiant.capa.Address\x12+\n\x06layout\x18\x07 \x01(\x0b\x32\x1b.mandiant.capa.StaticLayout\x12:\n\x0e\x66\x65\x61ture_counts\x18\x08 \x01(\x0b\x32\".mandiant.capa.StaticFeatureCounts\x12\x39\n\x11library_functions\x18\t \x03(\x0b\x32\x1e.mandiant.capa.LibraryFunction\"[\n\x13StaticFeatureCounts\x12\x0c\n\x04\x66ile\x18\x01 \x01(\x04\x12\x36\n\tfunctions\x18\x02 \x03(\x0b\x32#.mandiant.capa.FunctionFeatureCount\"@\n\x0cStaticLayout\x12\x30\n\tfunctions\x18\x01 \x03(\x0b\x32\x1d.mandiant.capa.FunctionLayout\"W\n\rStringFeature\x12\x0c\n\x04type\x18\x01 \x01(\t\x12\x0e\n\x06string\x18\x02 \x01(\t\x12\x18\n\x0b\x64\x65scription\x18\x03 \x01(\tH\x00\x88\x01\x01\x42\x0e\n\x0c_description\"p\n\x11SubscopeStatement\x12\x0c\n\x04type\x18\x01 \x01(\t\x12#\n\x05scope\x18\x02 \x01(\x0e\x32\x14.mandiant.capa.Scope\x12\x18\n\x0b\x64\x65scription\x18\x03 \x01(\tH\x00\x88\x01\x01\x42\x0e\n\x0c_description\"]\n\x10SubstringFeature\x12\x0c\n\x04type\x18\x01 \x01(\t\x12\x11\n\tsubstring\x18\x02 \x01(\t\x12\x18\n\x0b\x64\x65scription\x18\x03 \x01(\tH\x00\x88\x01\x01\x42\x0e\n\x0c_description\"C\n\nCallLayout\x12\'\n\x07\x61\x64\x64ress\x18\x01 \x01(\x0b\x32\x16.mandiant.capa.Address\x12\x0c\n\x04name\x18\x02 \x01(\t\"i\n\x0cThreadLayout\x12\'\n\x07\x61\x64\x64ress\x18\x01 \x01(\x0b\x32\x16.mandiant.capa.Address\x12\x30\n\rmatched_calls\x18\x02 \x03(\x0b\x32\x19.mandiant.capa.CallLayout\"4\n\tAddresses\x12\'\n\x07\x61\x64\x64ress\x18\x01 \x03(\x0b\x32\x16.mandiant.capa.Address\"b\n\x12Pair_Address_Match\x12\'\n\x07\x61\x64\x64ress\x18\x01 \x01(\x0b\x32\x16.mandiant.capa.Address\x12#\n\x05match\x18\x02 \x01(\x0b\x32\x14.mandiant.capa.Match\"E\n\x0cToken_Offset\x12%\n\x05token\x18\x01 \x01(\x0b\x32\x16.mandiant.capa.Integer\x12\x0e\n\x06offset\x18\x02 \x01(\x04\"U\n\x08Ppid_Pid\x12$\n\x04ppid\x18\x01 \x01(\x0b\x32\x16.mandiant.capa.Integer\x12#\n\x03pid\x18\x02 \x01(\x0b\x32\x16.mandiant.capa.Integer\"~\n\x0cPpid_Pid_Tid\x12$\n\x04ppid\x18\x01 \x01(\x0b\x32\x16.mandiant.capa.Integer\x12#\n\x03pid\x18\x02 \x01(\x0b\x32\x16.mandiant.capa.Integer\x12#\n\x03tid\x18\x03 \x01(\x0b\x32\x16.mandiant.capa.Integer\"\xa5\x01\n\x0fPpid_Pid_Tid_Id\x12$\n\x04ppid\x18\x01 \x01(\x0b\x32\x16.mandiant.capa.Integer\x12#\n\x03pid\x18\x02 \x01(\x0b\x32\x16.mandiant.capa.Integer\x12#\n\x03tid\x18\x03 \x01(\x0b\x32\x16.mandiant.capa.Integer\x12\"\n\x02id\x18\x04 \x01(\x0b\x32\x16.mandiant.capa.Integer\"\xd2\x01\n\x15Ppid_Pid_Tid_Id_Calls\x12$\n\x04ppid\x18\x01 \x01(\x0b\x32\x16.mandiant.capa.Integer\x12#\n\x03pid\x18\x02 \x01(\x0b\x32\x16.mandiant.capa.Integer\x12#\n\x03tid\x18\x03 \x01(\x0b\x32\x16.mandiant.capa.Integer\x12\"\n\x02id\x18\x04 \x01(\x0b\x32\x16.mandiant.capa.Integer\x12%\n\x05\x63\x61lls\x18\x05 \x03(\x0b\x32\x16.mandiant.capa.Integer\",\n\x07Integer\x12\x0b\n\x01u\x18\x01 \x01(\x04H\x00\x12\x0b\n\x01i\x18\x02 \x01(\x12H\x00\x42\x07\n\x05value\"8\n\x06Number\x12\x0b\n\x01u\x18\x01 \x01(\x04H\x00\x12\x0b\n\x01i\x18\x02 \x01(\x12H\x00\x12\x0b\n\x01\x66\x18\x03 \x01(\x01H\x00\x42\x07\n\x05value*\xac\x02\n\x0b\x41\x64\x64ressType\x12\x1b\n\x17\x41\x44\x44RESSTYPE_UNSPECIFIED\x10\x00\x12\x18\n\x14\x41\x44\x44RESSTYPE_ABSOLUTE\x10\x01\x12\x18\n\x14\x41\x44\x44RESSTYPE_RELATIVE\x10\x02\x12\x14\n\x10\x41\x44\x44RESSTYPE_FILE\x10\x03\x12\x18\n\x14\x41\x44\x44RESSTYPE_DN_TOKEN\x10\x04\x12\x1f\n\x1b\x41\x44\x44RESSTYPE_DN_TOKEN_OFFSET\x10\x05\x12\x1a\n\x16\x41\x44\x44RESSTYPE_NO_ADDRESS\x10\x06\x12\x17\n\x13\x41\x44\x44RESSTYPE_PROCESS\x10\x07\x12\x16\n\x12\x41\x44\x44RESSTYPE_THREAD\x10\x08\x12\x14\n\x10\x41\x44\x44RESSTYPE_CALL\x10\t\x12\x18\n\x14\x41\x44\x44RESSTYPE_SEQUENCE\x10\n*G\n\x06\x46lavor\x12\x16\n\x12\x46LAVOR_UNSPECIFIED\x10\x00\x12\x11\n\rFLAVOR_STATIC\x10\x01\x12\x12\n\x0e\x46LAVOR_DYNAMIC\x10\x02*\xb9\x01\n\x05Scope\x12\x15\n\x11SCOPE_UNSPECIFIED\x10\x00\x12\x0e\n\nSCOPE_FILE\x10\x01\x12\x12\n\x0eSCOPE_FUNCTION\x10\x02\x12\x15\n\x11SCOPE_BASIC_BLOCK\x10\x03\x12\x15\n\x11SCOPE_INSTRUCTION\x10\x04\x12\x11\n\rSCOPE_PROCESS\x10\x05\x12\x10\n\x0cSCOPE_THREAD\x10\x06\x12\x0e\n\nSCOPE_CALL\x10\x07\x12\x12\n\x0eSCOPE_SEQUENCE\x10\x08\x62\x06proto3') _globals = globals() _builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals) _builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'capa.render.proto.capa_pb2', _globals) -if _descriptor._USE_C_DESCRIPTORS == False: - DESCRIPTOR._options = None - _globals['_MATCH_CAPTURESENTRY']._options = None +if not _descriptor._USE_C_DESCRIPTORS: + DESCRIPTOR._loaded_options = None + _globals['_MATCH_CAPTURESENTRY']._loaded_options = None _globals['_MATCH_CAPTURESENTRY']._serialized_options = b'8\001' - _globals['_METADATA'].fields_by_name['analysis']._options = None + _globals['_METADATA'].fields_by_name['analysis']._loaded_options = None _globals['_METADATA'].fields_by_name['analysis']._serialized_options = b'\030\001' - _globals['_RESULTDOCUMENT_RULESENTRY']._options = None + _globals['_RESULTDOCUMENT_RULESENTRY']._loaded_options = None _globals['_RESULTDOCUMENT_RULESENTRY']._serialized_options = b'8\001' - _globals['_RULEMETADATA'].fields_by_name['scope']._options = None + _globals['_RULEMETADATA'].fields_by_name['scope']._loaded_options = None _globals['_RULEMETADATA'].fields_by_name['scope']._serialized_options = b'\030\001' - _globals['_ADDRESSTYPE']._serialized_start=9062 - _globals['_ADDRESSTYPE']._serialized_end=9336 - _globals['_FLAVOR']._serialized_start=9338 - _globals['_FLAVOR']._serialized_end=9409 - _globals['_SCOPE']._serialized_start=9412 - _globals['_SCOPE']._serialized_end=9597 + _globals['_ADDRESSTYPE']._serialized_start=9346 + _globals['_ADDRESSTYPE']._serialized_end=9646 + _globals['_FLAVOR']._serialized_start=9648 + _globals['_FLAVOR']._serialized_end=9719 + _globals['_SCOPE']._serialized_start=9722 + _globals['_SCOPE']._serialized_end=9907 _globals['_APIFEATURE']._serialized_start=47 _globals['_APIFEATURE']._serialized_end=128 _globals['_ADDRESS']._serialized_start=131 - _globals['_ADDRESS']._serialized_end=438 - _globals['_ANALYSIS']._serialized_start=441 - _globals['_ANALYSIS']._serialized_end=725 - _globals['_ARCHFEATURE']._serialized_start=727 - _globals['_ARCHFEATURE']._serialized_end=810 - _globals['_ATTACKSPEC']._serialized_start=812 - _globals['_ATTACKSPEC']._serialized_end=908 - _globals['_BASICBLOCKFEATURE']._serialized_start=910 - _globals['_BASICBLOCKFEATURE']._serialized_end=985 - _globals['_BASICBLOCKLAYOUT']._serialized_start=987 - _globals['_BASICBLOCKLAYOUT']._serialized_end=1046 - _globals['_BYTESFEATURE']._serialized_start=1048 - _globals['_BYTESFEATURE']._serialized_end=1133 - _globals['_CHARACTERISTICFEATURE']._serialized_start=1135 - _globals['_CHARACTERISTICFEATURE']._serialized_end=1238 - _globals['_CLASSFEATURE']._serialized_start=1240 - _globals['_CLASSFEATURE']._serialized_end=1326 - _globals['_COMPOUNDSTATEMENT']._serialized_start=1328 - _globals['_COMPOUNDSTATEMENT']._serialized_end=1403 - _globals['_DYNAMICANALYSIS']._serialized_start=1406 - _globals['_DYNAMICANALYSIS']._serialized_end=1606 - _globals['_DYNAMICFEATURECOUNTS']._serialized_start=1608 - _globals['_DYNAMICFEATURECOUNTS']._serialized_end=1699 - _globals['_DYNAMICLAYOUT']._serialized_start=1701 - _globals['_DYNAMICLAYOUT']._serialized_end=1765 - _globals['_EXPORTFEATURE']._serialized_start=1767 - _globals['_EXPORTFEATURE']._serialized_end=1854 - _globals['_FEATURECOUNTS']._serialized_start=1856 - _globals['_FEATURECOUNTS']._serialized_end=1941 - _globals['_FEATURENODE']._serialized_start=1944 - _globals['_FEATURENODE']._serialized_end=3153 - _globals['_FORMATFEATURE']._serialized_start=3155 - _globals['_FORMATFEATURE']._serialized_end=3242 - _globals['_FUNCTIONFEATURECOUNT']._serialized_start=3244 - _globals['_FUNCTIONFEATURECOUNT']._serialized_end=3322 - _globals['_FUNCTIONLAYOUT']._serialized_start=3324 - _globals['_FUNCTIONLAYOUT']._serialized_end=3444 - _globals['_FUNCTIONNAMEFEATURE']._serialized_start=3446 - _globals['_FUNCTIONNAMEFEATURE']._serialized_end=3546 - _globals['_IMPORTFEATURE']._serialized_start=3548 - _globals['_IMPORTFEATURE']._serialized_end=3636 - _globals['_LAYOUT']._serialized_start=3638 - _globals['_LAYOUT']._serialized_end=3696 - _globals['_LIBRARYFUNCTION']._serialized_start=3698 - _globals['_LIBRARYFUNCTION']._serialized_end=3770 - _globals['_MBCSPEC']._serialized_start=3772 - _globals['_MBCSPEC']._serialized_end=3861 - _globals['_MAECMETADATA']._serialized_start=3864 - _globals['_MAECMETADATA']._serialized_end=4018 - _globals['_MATCH']._serialized_start=4021 - _globals['_MATCH']._serialized_end=4363 - _globals['_MATCH_CAPTURESENTRY']._serialized_start=4282 - _globals['_MATCH_CAPTURESENTRY']._serialized_end=4355 - _globals['_MATCHFEATURE']._serialized_start=4365 - _globals['_MATCHFEATURE']._serialized_end=4450 - _globals['_METADATA']._serialized_start=4453 - _globals['_METADATA']._serialized_end=4769 - _globals['_MNEMONICFEATURE']._serialized_start=4771 - _globals['_MNEMONICFEATURE']._serialized_end=4862 - _globals['_NAMESPACEFEATURE']._serialized_start=4864 - _globals['_NAMESPACEFEATURE']._serialized_end=4957 - _globals['_NUMBERFEATURE']._serialized_start=4959 - _globals['_NUMBERFEATURE']._serialized_end=5069 - _globals['_OSFEATURE']._serialized_start=5071 - _globals['_OSFEATURE']._serialized_end=5150 - _globals['_OFFSETFEATURE']._serialized_start=5152 - _globals['_OFFSETFEATURE']._serialized_end=5263 - _globals['_OPERANDNUMBERFEATURE']._serialized_start=5266 - _globals['_OPERANDNUMBERFEATURE']._serialized_end=5407 - _globals['_OPERANDOFFSETFEATURE']._serialized_start=5410 - _globals['_OPERANDOFFSETFEATURE']._serialized_end=5551 - _globals['_PROCESSFEATURECOUNT']._serialized_start=5553 - _globals['_PROCESSFEATURECOUNT']._serialized_end=5630 - _globals['_PROCESSLAYOUT']._serialized_start=5632 - _globals['_PROCESSLAYOUT']._serialized_end=5756 - _globals['_PROPERTYFEATURE']._serialized_start=5758 - _globals['_PROPERTYFEATURE']._serialized_end=5882 - _globals['_RANGESTATEMENT']._serialized_start=5885 - _globals['_RANGESTATEMENT']._serialized_end=6026 - _globals['_REGEXFEATURE']._serialized_start=6028 - _globals['_REGEXFEATURE']._serialized_end=6113 - _globals['_RESULTDOCUMENT']._serialized_start=6116 - _globals['_RESULTDOCUMENT']._serialized_end=6302 - _globals['_RESULTDOCUMENT_RULESENTRY']._serialized_start=6230 - _globals['_RESULTDOCUMENT_RULESENTRY']._serialized_end=6302 - _globals['_RULEMATCHES']._serialized_start=6304 - _globals['_RULEMATCHES']._serialized_end=6428 - _globals['_RULEMETADATA']._serialized_start=6431 - _globals['_RULEMETADATA']._serialized_end=6796 - _globals['_SAMPLE']._serialized_start=6798 - _globals['_SAMPLE']._serialized_end=6863 - _globals['_SCOPES']._serialized_start=6865 - _globals['_SCOPES']._serialized_end=6983 - _globals['_SECTIONFEATURE']._serialized_start=6985 - _globals['_SECTIONFEATURE']._serialized_end=7074 - _globals['_SOMESTATEMENT']._serialized_start=7076 - _globals['_SOMESTATEMENT']._serialized_end=7162 - _globals['_STATEMENTNODE']._serialized_start=7165 - _globals['_STATEMENTNODE']._serialized_end=7409 - _globals['_STATICANALYSIS']._serialized_start=7412 - _globals['_STATICANALYSIS']._serialized_end=7714 - _globals['_STATICFEATURECOUNTS']._serialized_start=7716 - _globals['_STATICFEATURECOUNTS']._serialized_end=7807 - _globals['_STATICLAYOUT']._serialized_start=7809 - _globals['_STATICLAYOUT']._serialized_end=7873 - _globals['_STRINGFEATURE']._serialized_start=7875 - _globals['_STRINGFEATURE']._serialized_end=7962 - _globals['_SUBSCOPESTATEMENT']._serialized_start=7964 - _globals['_SUBSCOPESTATEMENT']._serialized_end=8076 - _globals['_SUBSTRINGFEATURE']._serialized_start=8078 - _globals['_SUBSTRINGFEATURE']._serialized_end=8171 - _globals['_CALLLAYOUT']._serialized_start=8173 - _globals['_CALLLAYOUT']._serialized_end=8240 - _globals['_THREADLAYOUT']._serialized_start=8242 - _globals['_THREADLAYOUT']._serialized_end=8347 - _globals['_ADDRESSES']._serialized_start=8349 - _globals['_ADDRESSES']._serialized_end=8401 - _globals['_PAIR_ADDRESS_MATCH']._serialized_start=8403 - _globals['_PAIR_ADDRESS_MATCH']._serialized_end=8501 - _globals['_TOKEN_OFFSET']._serialized_start=8503 - _globals['_TOKEN_OFFSET']._serialized_end=8572 - _globals['_PPID_PID']._serialized_start=8574 - _globals['_PPID_PID']._serialized_end=8659 - _globals['_PPID_PID_TID']._serialized_start=8661 - _globals['_PPID_PID_TID']._serialized_end=8787 - _globals['_PPID_PID_TID_ID']._serialized_start=8790 - _globals['_PPID_PID_TID_ID']._serialized_end=8955 - _globals['_INTEGER']._serialized_start=8957 - _globals['_INTEGER']._serialized_end=9001 - _globals['_NUMBER']._serialized_start=9003 - _globals['_NUMBER']._serialized_end=9059 + _globals['_ADDRESS']._serialized_end=509 + _globals['_ANALYSIS']._serialized_start=512 + _globals['_ANALYSIS']._serialized_end=796 + _globals['_ARCHFEATURE']._serialized_start=798 + _globals['_ARCHFEATURE']._serialized_end=881 + _globals['_ATTACKSPEC']._serialized_start=883 + _globals['_ATTACKSPEC']._serialized_end=979 + _globals['_BASICBLOCKFEATURE']._serialized_start=981 + _globals['_BASICBLOCKFEATURE']._serialized_end=1056 + _globals['_BASICBLOCKLAYOUT']._serialized_start=1058 + _globals['_BASICBLOCKLAYOUT']._serialized_end=1117 + _globals['_BYTESFEATURE']._serialized_start=1119 + _globals['_BYTESFEATURE']._serialized_end=1204 + _globals['_CHARACTERISTICFEATURE']._serialized_start=1206 + _globals['_CHARACTERISTICFEATURE']._serialized_end=1309 + _globals['_CLASSFEATURE']._serialized_start=1311 + _globals['_CLASSFEATURE']._serialized_end=1397 + _globals['_COMPOUNDSTATEMENT']._serialized_start=1399 + _globals['_COMPOUNDSTATEMENT']._serialized_end=1474 + _globals['_DYNAMICANALYSIS']._serialized_start=1477 + _globals['_DYNAMICANALYSIS']._serialized_end=1677 + _globals['_DYNAMICFEATURECOUNTS']._serialized_start=1679 + _globals['_DYNAMICFEATURECOUNTS']._serialized_end=1770 + _globals['_DYNAMICLAYOUT']._serialized_start=1772 + _globals['_DYNAMICLAYOUT']._serialized_end=1836 + _globals['_EXPORTFEATURE']._serialized_start=1838 + _globals['_EXPORTFEATURE']._serialized_end=1925 + _globals['_FEATURECOUNTS']._serialized_start=1927 + _globals['_FEATURECOUNTS']._serialized_end=2012 + _globals['_FEATURENODE']._serialized_start=2015 + _globals['_FEATURENODE']._serialized_end=3224 + _globals['_FORMATFEATURE']._serialized_start=3226 + _globals['_FORMATFEATURE']._serialized_end=3313 + _globals['_FUNCTIONFEATURECOUNT']._serialized_start=3315 + _globals['_FUNCTIONFEATURECOUNT']._serialized_end=3393 + _globals['_FUNCTIONLAYOUT']._serialized_start=3395 + _globals['_FUNCTIONLAYOUT']._serialized_end=3515 + _globals['_FUNCTIONNAMEFEATURE']._serialized_start=3517 + _globals['_FUNCTIONNAMEFEATURE']._serialized_end=3617 + _globals['_IMPORTFEATURE']._serialized_start=3619 + _globals['_IMPORTFEATURE']._serialized_end=3707 + _globals['_LAYOUT']._serialized_start=3709 + _globals['_LAYOUT']._serialized_end=3767 + _globals['_LIBRARYFUNCTION']._serialized_start=3769 + _globals['_LIBRARYFUNCTION']._serialized_end=3841 + _globals['_MBCSPEC']._serialized_start=3843 + _globals['_MBCSPEC']._serialized_end=3932 + _globals['_MAECMETADATA']._serialized_start=3935 + _globals['_MAECMETADATA']._serialized_end=4089 + _globals['_MATCH']._serialized_start=4092 + _globals['_MATCH']._serialized_end=4434 + _globals['_MATCH_CAPTURESENTRY']._serialized_start=4353 + _globals['_MATCH_CAPTURESENTRY']._serialized_end=4426 + _globals['_MATCHFEATURE']._serialized_start=4436 + _globals['_MATCHFEATURE']._serialized_end=4521 + _globals['_METADATA']._serialized_start=4524 + _globals['_METADATA']._serialized_end=4840 + _globals['_MNEMONICFEATURE']._serialized_start=4842 + _globals['_MNEMONICFEATURE']._serialized_end=4933 + _globals['_NAMESPACEFEATURE']._serialized_start=4935 + _globals['_NAMESPACEFEATURE']._serialized_end=5028 + _globals['_NUMBERFEATURE']._serialized_start=5030 + _globals['_NUMBERFEATURE']._serialized_end=5140 + _globals['_OSFEATURE']._serialized_start=5142 + _globals['_OSFEATURE']._serialized_end=5221 + _globals['_OFFSETFEATURE']._serialized_start=5223 + _globals['_OFFSETFEATURE']._serialized_end=5334 + _globals['_OPERANDNUMBERFEATURE']._serialized_start=5337 + _globals['_OPERANDNUMBERFEATURE']._serialized_end=5478 + _globals['_OPERANDOFFSETFEATURE']._serialized_start=5481 + _globals['_OPERANDOFFSETFEATURE']._serialized_end=5622 + _globals['_PROCESSFEATURECOUNT']._serialized_start=5624 + _globals['_PROCESSFEATURECOUNT']._serialized_end=5701 + _globals['_PROCESSLAYOUT']._serialized_start=5703 + _globals['_PROCESSLAYOUT']._serialized_end=5827 + _globals['_PROPERTYFEATURE']._serialized_start=5829 + _globals['_PROPERTYFEATURE']._serialized_end=5953 + _globals['_RANGESTATEMENT']._serialized_start=5956 + _globals['_RANGESTATEMENT']._serialized_end=6097 + _globals['_REGEXFEATURE']._serialized_start=6099 + _globals['_REGEXFEATURE']._serialized_end=6184 + _globals['_RESULTDOCUMENT']._serialized_start=6187 + _globals['_RESULTDOCUMENT']._serialized_end=6373 + _globals['_RESULTDOCUMENT_RULESENTRY']._serialized_start=6301 + _globals['_RESULTDOCUMENT_RULESENTRY']._serialized_end=6373 + _globals['_RULEMATCHES']._serialized_start=6375 + _globals['_RULEMATCHES']._serialized_end=6499 + _globals['_RULEMETADATA']._serialized_start=6502 + _globals['_RULEMETADATA']._serialized_end=6867 + _globals['_SAMPLE']._serialized_start=6869 + _globals['_SAMPLE']._serialized_end=6934 + _globals['_SCOPES']._serialized_start=6936 + _globals['_SCOPES']._serialized_end=7054 + _globals['_SECTIONFEATURE']._serialized_start=7056 + _globals['_SECTIONFEATURE']._serialized_end=7145 + _globals['_SOMESTATEMENT']._serialized_start=7147 + _globals['_SOMESTATEMENT']._serialized_end=7233 + _globals['_STATEMENTNODE']._serialized_start=7236 + _globals['_STATEMENTNODE']._serialized_end=7480 + _globals['_STATICANALYSIS']._serialized_start=7483 + _globals['_STATICANALYSIS']._serialized_end=7785 + _globals['_STATICFEATURECOUNTS']._serialized_start=7787 + _globals['_STATICFEATURECOUNTS']._serialized_end=7878 + _globals['_STATICLAYOUT']._serialized_start=7880 + _globals['_STATICLAYOUT']._serialized_end=7944 + _globals['_STRINGFEATURE']._serialized_start=7946 + _globals['_STRINGFEATURE']._serialized_end=8033 + _globals['_SUBSCOPESTATEMENT']._serialized_start=8035 + _globals['_SUBSCOPESTATEMENT']._serialized_end=8147 + _globals['_SUBSTRINGFEATURE']._serialized_start=8149 + _globals['_SUBSTRINGFEATURE']._serialized_end=8242 + _globals['_CALLLAYOUT']._serialized_start=8244 + _globals['_CALLLAYOUT']._serialized_end=8311 + _globals['_THREADLAYOUT']._serialized_start=8313 + _globals['_THREADLAYOUT']._serialized_end=8418 + _globals['_ADDRESSES']._serialized_start=8420 + _globals['_ADDRESSES']._serialized_end=8472 + _globals['_PAIR_ADDRESS_MATCH']._serialized_start=8474 + _globals['_PAIR_ADDRESS_MATCH']._serialized_end=8572 + _globals['_TOKEN_OFFSET']._serialized_start=8574 + _globals['_TOKEN_OFFSET']._serialized_end=8643 + _globals['_PPID_PID']._serialized_start=8645 + _globals['_PPID_PID']._serialized_end=8730 + _globals['_PPID_PID_TID']._serialized_start=8732 + _globals['_PPID_PID_TID']._serialized_end=8858 + _globals['_PPID_PID_TID_ID']._serialized_start=8861 + _globals['_PPID_PID_TID_ID']._serialized_end=9026 + _globals['_PPID_PID_TID_ID_CALLS']._serialized_start=9029 + _globals['_PPID_PID_TID_ID_CALLS']._serialized_end=9239 + _globals['_INTEGER']._serialized_start=9241 + _globals['_INTEGER']._serialized_end=9285 + _globals['_NUMBER']._serialized_start=9287 + _globals['_NUMBER']._serialized_end=9343 # @@protoc_insertion_point(module_scope) diff --git a/capa/render/proto/capa_pb2.pyi b/capa/render/proto/capa_pb2.pyi index c881561a3..9a6eb44b2 100644 --- a/capa/render/proto/capa_pb2.pyi +++ b/capa/render/proto/capa_pb2.pyi @@ -35,6 +35,7 @@ class _AddressTypeEnumTypeWrapper(google.protobuf.internal.enum_type_wrapper._En ADDRESSTYPE_PROCESS: _AddressType.ValueType # 7 ADDRESSTYPE_THREAD: _AddressType.ValueType # 8 ADDRESSTYPE_CALL: _AddressType.ValueType # 9 + ADDRESSTYPE_SEQUENCE: _AddressType.ValueType # 10 class AddressType(_AddressType, metaclass=_AddressTypeEnumTypeWrapper): ... @@ -48,6 +49,7 @@ ADDRESSTYPE_NO_ADDRESS: AddressType.ValueType # 6 ADDRESSTYPE_PROCESS: AddressType.ValueType # 7 ADDRESSTYPE_THREAD: AddressType.ValueType # 8 ADDRESSTYPE_CALL: AddressType.ValueType # 9 +ADDRESSTYPE_SEQUENCE: AddressType.ValueType # 10 global___AddressType = AddressType class _Flavor: @@ -129,6 +131,7 @@ class Address(google.protobuf.message.Message): PPID_PID_FIELD_NUMBER: builtins.int PPID_PID_TID_FIELD_NUMBER: builtins.int PPID_PID_TID_ID_FIELD_NUMBER: builtins.int + PPID_PID_TID_ID_CALLS_FIELD_NUMBER: builtins.int type: global___AddressType.ValueType @property def v(self) -> global___Integer: ... @@ -140,6 +143,8 @@ class Address(google.protobuf.message.Message): def ppid_pid_tid(self) -> global___Ppid_Pid_Tid: ... @property def ppid_pid_tid_id(self) -> global___Ppid_Pid_Tid_Id: ... + @property + def ppid_pid_tid_id_calls(self) -> global___Ppid_Pid_Tid_Id_Calls: ... def __init__( self, *, @@ -149,10 +154,11 @@ class Address(google.protobuf.message.Message): ppid_pid: global___Ppid_Pid | None = ..., ppid_pid_tid: global___Ppid_Pid_Tid | None = ..., ppid_pid_tid_id: global___Ppid_Pid_Tid_Id | None = ..., + ppid_pid_tid_id_calls: global___Ppid_Pid_Tid_Id_Calls | None = ..., ) -> None: ... - def HasField(self, field_name: typing.Literal["ppid_pid", b"ppid_pid", "ppid_pid_tid", b"ppid_pid_tid", "ppid_pid_tid_id", b"ppid_pid_tid_id", "token_offset", b"token_offset", "v", b"v", "value", b"value"]) -> builtins.bool: ... - def ClearField(self, field_name: typing.Literal["ppid_pid", b"ppid_pid", "ppid_pid_tid", b"ppid_pid_tid", "ppid_pid_tid_id", b"ppid_pid_tid_id", "token_offset", b"token_offset", "type", b"type", "v", b"v", "value", b"value"]) -> None: ... - def WhichOneof(self, oneof_group: typing.Literal["value", b"value"]) -> typing.Literal["v", "token_offset", "ppid_pid", "ppid_pid_tid", "ppid_pid_tid_id"] | None: ... + def HasField(self, field_name: typing.Literal["ppid_pid", b"ppid_pid", "ppid_pid_tid", b"ppid_pid_tid", "ppid_pid_tid_id", b"ppid_pid_tid_id", "ppid_pid_tid_id_calls", b"ppid_pid_tid_id_calls", "token_offset", b"token_offset", "v", b"v", "value", b"value"]) -> builtins.bool: ... + def ClearField(self, field_name: typing.Literal["ppid_pid", b"ppid_pid", "ppid_pid_tid", b"ppid_pid_tid", "ppid_pid_tid_id", b"ppid_pid_tid_id", "ppid_pid_tid_id_calls", b"ppid_pid_tid_id_calls", "token_offset", b"token_offset", "type", b"type", "v", b"v", "value", b"value"]) -> None: ... + def WhichOneof(self, oneof_group: typing.Literal["value", b"value"]) -> typing.Literal["v", "token_offset", "ppid_pid", "ppid_pid_tid", "ppid_pid_tid_id", "ppid_pid_tid_id_calls"] | None: ... global___Address = Address @@ -1817,6 +1823,39 @@ class Ppid_Pid_Tid_Id(google.protobuf.message.Message): global___Ppid_Pid_Tid_Id = Ppid_Pid_Tid_Id +@typing.final +class Ppid_Pid_Tid_Id_Calls(google.protobuf.message.Message): + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + PPID_FIELD_NUMBER: builtins.int + PID_FIELD_NUMBER: builtins.int + TID_FIELD_NUMBER: builtins.int + ID_FIELD_NUMBER: builtins.int + CALLS_FIELD_NUMBER: builtins.int + @property + def ppid(self) -> global___Integer: ... + @property + def pid(self) -> global___Integer: ... + @property + def tid(self) -> global___Integer: ... + @property + def id(self) -> global___Integer: ... + @property + def calls(self) -> google.protobuf.internal.containers.RepeatedCompositeFieldContainer[global___Integer]: ... + def __init__( + self, + *, + ppid: global___Integer | None = ..., + pid: global___Integer | None = ..., + tid: global___Integer | None = ..., + id: global___Integer | None = ..., + calls: collections.abc.Iterable[global___Integer] | None = ..., + ) -> None: ... + def HasField(self, field_name: typing.Literal["id", b"id", "pid", b"pid", "ppid", b"ppid", "tid", b"tid"]) -> builtins.bool: ... + def ClearField(self, field_name: typing.Literal["calls", b"calls", "id", b"id", "pid", b"pid", "ppid", b"ppid", "tid", b"tid"]) -> None: ... + +global___Ppid_Pid_Tid_Id_Calls = Ppid_Pid_Tid_Id_Calls + @typing.final class Integer(google.protobuf.message.Message): DESCRIPTOR: google.protobuf.descriptor.Descriptor diff --git a/capa/render/result_document.py b/capa/render/result_document.py index dab639a68..a74f32c6f 100644 --- a/capa/render/result_document.py +++ b/capa/render/result_document.py @@ -22,6 +22,7 @@ from capa.rules import RuleSet from capa.engine import MatchResults from capa.helpers import assert_never, load_json_from_path +from capa.features.address import DynamicCallAddress, DynamicSequenceAddress if TYPE_CHECKING: from capa.capabilities.common import Capabilities @@ -385,7 +386,44 @@ def from_capa( ) for location in result.locations: - children.append(Match.from_capa(rules, capabilities, rule_matches[location])) + + # TODO: assert source and destination rules are sequence scoped + if isinstance(location, capa.features.address.DynamicSequenceAddress): + # sequence scopes can match each other, but they don't strictly contain each other, + # like the way a function contains a basic block. + # so when we have a match within a sequence for another sequence, we need to look + # for all the places it might be found. + + # where the wanted rule *could* be found. + # call ids within the current thread. + sequence_locations = set(location.calls) + + # where the wanted rule *has* been found. + # call ids within the current thread. + match_locations = { + addr.id + for addr in rule_matches.keys() + if isinstance(addr, DynamicSequenceAddress) and addr.thread == location.thread + } + + if not (sequence_locations & match_locations): + breakpoint() + + new_children = [] + for call_id in location.calls: + if match := rule_matches.get(DynamicSequenceAddress(location.thread, call_id, calls=())): + new_children.append(Match.from_capa(rules, capabilities, match)) + elif match := rule_matches.get(DynamicCallAddress(location.thread, call_id)): + new_children.append(Match.from_capa(rules, capabilities, match)) + else: + # there was no match at this call in the given sequence + pass + + assert new_children, "failed to find locations for sequence matching sequence" + children.extend(new_children) + + else: + children.append(Match.from_capa(rules, capabilities, rule_matches[location])) else: # this is a namespace that we're matching # @@ -417,6 +455,9 @@ def from_capa( # in the meantime, the above might be sufficient. rule_matches = dict(capabilities[rule.name]) for location in result.locations: + + # TODO: update here too + # doc[locations] contains all matches for the given namespace. # for example, the feature might be `match: anti-analysis/packer` # which matches against "generic unpacker" and "UPX". diff --git a/capa/render/verbose.py b/capa/render/verbose.py index e8d0266cf..b5d83069c 100644 --- a/capa/render/verbose.py +++ b/capa/render/verbose.py @@ -329,7 +329,10 @@ def render_rules(console: Console, doc: rd.ResultDocument): thread_locations = set() for loc in locations: cloc = loc.to_capa() - assert isinstance(cloc, capa.features.address.DynamicCallAddress) + assert isinstance( + cloc, + (capa.features.address.DynamicCallAddress, capa.features.address.DynamicSequenceAddress), + ) thread_locations.add(frz.Address.from_capa(cloc.thread)) lines = [render_thread(doc.meta.analysis.layout, loc) for loc in thread_locations] diff --git a/capa/render/vverbose.py b/capa/render/vverbose.py index 672e559bf..0322f65cc 100644 --- a/capa/render/vverbose.py +++ b/capa/render/vverbose.py @@ -304,13 +304,13 @@ def render_match( render_match(console, layout, rule, child, indent=indent + 1, mode=child_mode) -def collect_call_locations( +def collect_sequence_locations( match: rd.Match, mode=MODE_SUCCESS, ): """ - Find all the DynamicCallAddress locations in the given match, recursively. - Useful to collect the calls used to match a sequence scoped rule. + Find all the (call, sequence) locations used in a given sequence match, recursively. + Useful to collect the events used to match a sequence scoped rule. """ if isinstance(match.node, rd.StatementNode): if ( @@ -319,13 +319,13 @@ def collect_call_locations( ): child_mode = MODE_FAILURE if mode == MODE_SUCCESS else MODE_SUCCESS for child in match.children: - yield from collect_call_locations(child, child_mode) + yield from collect_sequence_locations(child, child_mode) else: for child in match.children: - yield from collect_call_locations(child, mode) + yield from collect_sequence_locations(child, mode) elif isinstance(match.node, rd.FeatureNode): for location in match.locations: - if location.type != frz.AddressType.CALL: + if location.type not in (frz.AddressType.CALL, frz.AddressType.SEQUENCE): continue if mode == MODE_FAILURE: continue @@ -474,7 +474,7 @@ def render_rules(console: Console, doc: rd.ResultDocument): elif rule.meta.scopes.dynamic == capa.rules.Scope.THREAD: console.write(v.render_thread(doc.meta.analysis.layout, location)) elif rule.meta.scopes.dynamic == capa.rules.Scope.SEQUENCE: - calls = sorted(set(collect_call_locations(match))) + calls = sorted(set(collect_sequence_locations(match))) console.write(hanging_indent(v.render_sequence(doc.meta.analysis.layout, calls), indent=1)) elif rule.meta.scopes.dynamic == capa.rules.Scope.CALL: console.write(hanging_indent(v.render_call(doc.meta.analysis.layout, location), indent=1)) diff --git a/tests/test_dynamic_sequence_scope.py b/tests/test_dynamic_sequence_scope.py index fb4cd7e25..3dc04e241 100644 --- a/tests/test_dynamic_sequence_scope.py +++ b/tests/test_dynamic_sequence_scope.py @@ -36,6 +36,7 @@ import capa.main import capa.rules import capa.capabilities.dynamic +from capa.features.address import DynamicSequenceAddress from capa.features.extractors.base_extractor import ThreadFilter, DynamicFeatureExtractor @@ -181,6 +182,55 @@ def test_dynamic_sequence_scope_length(): assert r.name not in capabilities.matches +# show that the DynamicSequenceAddress has the correct structure. +# temporarily uses a sequence of length 2, for simplicity. +# +# proc: 0000A65749F5902C4D82.exe (ppid=2456, pid=3052) +# thread: 3064 +# call 8: GetSystemTimeAsFileTime() +# call 9: GetSystemInfo() +# call 10: LdrGetDllHandle(1974337536, kernel32.dll) +# call 11: LdrGetProcedureAddress(2010595649, 0, AddVectoredExceptionHandler, 1974337536, kernel32.dll) +# call 12: LdrGetDllHandle(1974337536, kernel32.dll) +# call 13: LdrGetProcedureAddress(2010595072, 0, RemoveVectoredExceptionHandler, 1974337536, kernel32.dll) +# call 14: RtlAddVectoredExceptionHandler(1921490089, 0) +# call 15: GetSystemTime() +# call 16: NtAllocateVirtualMemory(no, 4, 786432, 4784128, 4294967295) +def test_dynamic_sequence_scope_sequence_address(): + extractor = get_0000a657_thread3064() + + rule = textwrap.dedent( + """ + rule: + meta: + name: test rule + scopes: + static: unsupported + dynamic: sequence + features: + - and: + - api: RtlAddVectoredExceptionHandler + """ + ) + + r = capa.rules.Rule.from_yaml(rule) + ruleset = capa.rules.RuleSet([r]) + + # patch SEQUENCE_SIZE since we may use a much larger value in the real world. + from pytest import MonkeyPatch + + with MonkeyPatch.context() as m: + m.setattr(capa.capabilities.dynamic, "SEQUENCE_SIZE", 2) + capabilities = capa.capabilities.dynamic.find_dynamic_capabilities(ruleset, extractor, disable_progress=True) + + assert r.name in capabilities.matches + assert len(capabilities.matches[r.name]) == 1 + address, result = capabilities.matches[r.name][0] + assert isinstance(address, DynamicSequenceAddress) + assert address.id == 14 + assert address.calls == (13, 14) + + # show that you can use a call subscope in sequence rules. # # proc: 0000A65749F5902C4D82.exe (ppid=2456, pid=3052) @@ -364,3 +414,101 @@ def test_dynamic_sequence_multiple_sequences_overlapping_single_event(): assert r.name in capabilities.matches # we only match the first overlapping sequence assert [11] == list(get_call_ids(capabilities.matches[r.name])) + + +# show that you can use match statements in sequence rules. +# +# proc: 0000A65749F5902C4D82.exe (ppid=2456, pid=3052) +# thread: 3064 +# ... +# call 10: LdrGetDllHandle(1974337536, kernel32.dll) +# call 11: LdrGetProcedureAddress(2010595649, 0, AddVectoredExceptionHandler, 1974337536, kernel32.dll) +# call 12: LdrGetDllHandle(1974337536, kernel32.dll) +# call 13: LdrGetProcedureAddress(2010595072, 0, RemoveVectoredExceptionHandler, 1974337536, kernel32.dll) +# ... +def test_dynamic_sequence_scope_match_statements(): + extractor = get_0000a657_thread3064() + + ruleset = capa.rules.RuleSet( + [ + capa.rules.Rule.from_yaml( + textwrap.dedent( + """ + rule: + meta: + name: resolve add VEH + namespace: linking/runtime-linking/veh + scopes: + static: unsupported + dynamic: sequence + features: + - and: + - api: LdrGetDllHandle + - api: LdrGetProcedureAddress + - string: AddVectoredExceptionHandler + """ + ) + ), + capa.rules.Rule.from_yaml( + textwrap.dedent( + """ + rule: + meta: + name: resolve remove VEH + namespace: linking/runtime-linking/veh + scopes: + static: unsupported + dynamic: sequence + features: + - and: + - api: LdrGetDllHandle + - api: LdrGetProcedureAddress + - string: RemoveVectoredExceptionHandler + """ + ) + ), + capa.rules.Rule.from_yaml( + textwrap.dedent( + """ + rule: + meta: + name: resolve add and remove VEH + scopes: + static: unsupported + dynamic: sequence + features: + - and: + - match: resolve add VEH + - match: resolve remove VEH + """ + ) + ), + capa.rules.Rule.from_yaml( + textwrap.dedent( + """ + rule: + meta: + name: has VEH runtime linking + scopes: + static: unsupported + dynamic: sequence + features: + - and: + - match: linking/runtime-linking/veh + """ + ) + ), + ] + ) + + capabilities = capa.capabilities.dynamic.find_dynamic_capabilities(ruleset, extractor, disable_progress=True) + + # basic functionality, already known to work + assert "resolve add VEH" in capabilities.matches + assert "resolve remove VEH" in capabilities.matches + + # requires `match: ` to be working + assert "resolve add and remove VEH" in capabilities.matches + + # requires `match: ` to be working + assert "has VEH runtime linking" in capabilities.matches