def testYaraProcessScan_MultipleSignatureShards(self): action_mock = action_mocks.ActionMock(memory_actions.YaraProcessScan) procs = [ p for p in self.procs if p.pid in [101, 102, 103, 104, 105, 106, 107] ] scan_params = { "include_misses_in_results": True, "include_errors_in_results": "ALL_ERRORS", "max_results_per_process": 0, "ignore_grr_process": False, } with test_lib.FakeTime( rdfvalue.RDFDatetime.FromMicrosecondsSinceEpoch(123456789)): matches, errors, misses = self._RunYaraProcessScan( procs, action_mock=action_mock, **scan_params) # Verify scan results. self.assertLen(matches, 2) self.assertLen(errors, 2) self.assertLen(misses, 2) self.assertEqual(matches[0].match[0].rule_name, "test_rule") self.assertEqual(matches[0].match[0].string_matches[0].data, b"1234") flow = data_store.REL_DB.ReadAllFlowObjects( self.client_id, include_child_flows=False)[0] # We expect to have sent 4 YaraProcessScanRequests to the client. self.assertEqual(flow.next_outbound_id, 5) scan_requests = action_mock.recorded_args["YaraProcessScan"] signature_bytes = _TEST_YARA_SIGNATURE.encode("utf-8") expected_requests = [ rdf_memory.YaraProcessScanRequest( signature_shard=rdf_memory.YaraSignatureShard( index=0, payload=signature_bytes[0:30]), num_signature_shards=4, **scan_params), rdf_memory.YaraProcessScanRequest( signature_shard=rdf_memory.YaraSignatureShard( index=1, payload=signature_bytes[30:60]), num_signature_shards=4, **scan_params), rdf_memory.YaraProcessScanRequest( signature_shard=rdf_memory.YaraSignatureShard( index=2, payload=signature_bytes[60:90]), num_signature_shards=4, **scan_params), rdf_memory.YaraProcessScanRequest( signature_shard=rdf_memory.YaraSignatureShard( index=3, payload=signature_bytes[90:]), num_signature_shards=4, **scan_params), ] self.assertCountEqual(scan_requests, expected_requests)
def testSignatureShards(self): requests = [ rdf_memory.YaraProcessScanRequest( signature_shard=rdf_memory.YaraSignatureShard(index=0, payload=b"123"), num_signature_shards=3), rdf_memory.YaraProcessScanRequest( signature_shard=rdf_memory.YaraSignatureShard(index=1, payload=b"456"), num_signature_shards=3), rdf_memory.YaraProcessScanRequest( signature_shard=rdf_memory.YaraSignatureShard(index=2, payload=b"789"), num_signature_shards=3), ] flow_id = "01234567" signature_dir = os.path.join(self.temp_dir, "GRRTest", "Sig_%s" % flow_id) session_id = "C.0123456789abcdef/%s" % flow_id results = self.ExecuteAction(memory.YaraProcessScan, arg=requests[2], session_id=session_id) self.assertLen(results, 1) self.assertIsInstance(results[0], rdf_flows.GrrStatus) self.assertTrue(os.path.isdir(signature_dir)) self.assertCountEqual(os.listdir(signature_dir), ["shard_02_of_03"]) with open(os.path.join(signature_dir, "shard_02_of_03"), "rb") as f: self.assertEqual(f.read(), b"789") results = self.ExecuteAction(memory.YaraProcessScan, arg=requests[0], session_id=session_id) self.assertLen(results, 1) self.assertIsInstance(results[0], rdf_flows.GrrStatus) self.assertCountEqual(os.listdir(signature_dir), ["shard_00_of_03", "shard_02_of_03"]) with open(os.path.join(signature_dir, "shard_00_of_03"), "rb") as f: self.assertEqual(f.read(), b"123") results = self.ExecuteAction(memory.YaraProcessScan, arg=requests[1], session_id=session_id) # We expect at least one YaraProcessScanResponse and a final GrrStatus. self.assertGreater(len(results), 1) self.assertIsInstance(results[0], rdf_memory.YaraProcessScanResponse) self.assertIsInstance(results[-1], rdf_flows.GrrStatus) # The Yara signature provided is invalid, so we expect errors. self.assertNotEmpty(results[0].errors) # Make sure the temporary directory gets deleted when all shards have # been received. self.assertFalse(os.path.exists(signature_dir))
def Start(self): """See base class.""" self._ValidateFlowArgs() if self.client_version < 3306: # TODO(user): Remove when support ends for old clients (Jan 1 2022). self.CallClient( server_stubs.YaraProcessScan, request=self.args, next_state=compatibility.GetName(self.ProcessScanResults)) return signature_bytes = self.args.yara_signature.SerializeToBytes() offsets = range(0, len(signature_bytes), _YARA_SIGNATURE_SHARD_SIZE) for i, offset in enumerate(offsets): client_request = self.args.Copy() # We do not want to send the whole signature to the client, so we clear # the field. client_request.yara_signature = None client_request.signature_shard = rdf_memory.YaraSignatureShard( index=i, payload=signature_bytes[offset:offset + _YARA_SIGNATURE_SHARD_SIZE]) client_request.num_signature_shards = len(offsets) self.CallClient( server_stubs.YaraProcessScan, request=client_request, next_state=compatibility.GetName(self.ProcessScanResults))
def testCmdlineRegex(self): scan_request = rdf_memory.YaraProcessScanRequest( signature_shard=rdf_memory.YaraSignatureShard(index=0, payload=b"123"), num_signature_shards=1, cmdline_regex="svchost.exe -k def") with mock.patch.object( memory.YaraProcessScan, "_GetMatches", return_value=[rdf_memory.YaraMatch()]): results = self.ExecuteAction(memory.YaraProcessScan, arg=scan_request) self.assertLen(results, 2) self.assertLen(results[0].matches, 1) self.assertEqual(results[0].matches[0].process.pid, 1)
def testSignatureShards_Single(self): flow_id = "01234567" signature_dir = os.path.join(self.temp_dir, "GRRTest", "Sig_%s" % flow_id) session_id = "C.0123456789abcdef/%s" % flow_id scan_request = rdf_memory.YaraProcessScanRequest( signature_shard=rdf_memory.YaraSignatureShard(index=0, payload=b"123"), num_signature_shards=1) results = self.ExecuteAction( memory.YaraProcessScan, arg=scan_request, session_id=session_id) # We expect at least one YaraProcessScanResponse and a final GrrStatus. self.assertGreater(len(results), 1) self.assertIsInstance(results[0], rdf_memory.YaraProcessScanResponse) self.assertIsInstance(results[-1], rdf_flows.GrrStatus) # The temporary directory should not get created if there is only one # shard. self.assertFalse(os.path.exists(signature_dir))
def Start(self): """See base class.""" self._ValidateFlowArgs() if self.client_version < 3306: # TODO(user): Remove when support ends for old clients (Jan 1 2022). self.CallClient(server_stubs.YaraProcessScan, request=self.args, next_state=compatibility.GetName( self.ProcessScanResults)) return if self.args.scan_runtime_limit_us: # Back up original runtime limit. Override it for YaraProcessScan action # only. request_data = {"runtime_limit_us": self.rdf_flow.runtime_limit_us} self.rdf_flow.runtime_limit_us = self.args.scan_runtime_limit_us else: request_data = None if self.args.yara_signature: signature_bytes = str(self.args.yara_signature).encode("utf-8") elif self.args.yara_signature_blob_id: blob_id = rdf_objects.BlobID(self.args.yara_signature_blob_id) signature_bytes = data_store.BLOBS.ReadBlob(blob_id) offsets = range(0, len(signature_bytes), _YARA_SIGNATURE_SHARD_SIZE) for i, offset in enumerate(offsets): client_request = self.args.Copy() # We do not want to send the whole signature to the client, so we clear # the field. client_request.yara_signature = None client_request.signature_shard = rdf_memory.YaraSignatureShard( index=i, payload=signature_bytes[offset:offset + _YARA_SIGNATURE_SHARD_SIZE]) client_request.num_signature_shards = len(offsets) self.CallClient(server_stubs.YaraProcessScan, request=client_request, request_data=request_data, next_state=compatibility.GetName( self.ProcessScanResults))