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 testYaraSignatureReferenceDeliversFullSignatureToClient(self): signature = "rule foo { condition: true };" blob = signature.encode("utf-8") blob_id = data_store.BLOBS.WriteBlobWithUnknownHash(blob) data_store.REL_DB.WriteGRRUser(username="******") data_store.REL_DB.WriteYaraSignatureReference(blob_id, username="******") args = rdf_memory.YaraProcessScanRequest() args.yara_signature_blob_id = blob_id.AsBytes() shards = [] class FakeYaraProcessScan(action_mocks.ActionMock): def YaraProcessScan( self, args: rdf_memory.YaraProcessScanRequest, ) -> Iterable[rdf_memory.YaraProcessScanResponse]: shards.append(args.signature_shard) return [] self._YaraProcessScan(args, action_mock=FakeYaraProcessScan()) payloads = [_.payload for _ in sorted(shards, key=lambda _: _.index)] self.assertEqual(b"".join(payloads).decode("utf-8"), signature)
def testYaraSignatureReferenceIncorrect(self): data = "This is very confidential and should not leak to the client." blob_id = data_store.BLOBS.WriteBlobWithUnknownHash(data.encode("utf-8")) args = rdf_memory.YaraProcessScanRequest() args.yara_signature_blob_id = blob_id.AsBytes() with self.assertRaisesRegex(RuntimeError, "signature reference"): self._YaraProcessScan(args)
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 testYaraSignatureAndSignatureReference(self): signature = "rule foo { condition: true };" blob = signature.encode("utf-8") blob_id = data_store.BLOBS.WriteBlobWithUnknownHash(blob) data_store.REL_DB.WriteGRRUser(username="******") data_store.REL_DB.WriteYaraSignatureReference(blob_id, username="******") args = rdf_memory.YaraProcessScanRequest() args.yara_signature = signature args.yara_signature_blob_id = blob_id.AsBytes() with self.assertRaisesRegex(RuntimeError, "can't be used together"): self._YaraProcessScan(args)
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 testYaraSignatureReferenceNotExisting(self): args = rdf_memory.YaraProcessScanRequest() args.yara_signature_blob_id = os.urandom(32) with self.assertRaisesRegex(RuntimeError, "signature reference"): self._YaraProcessScan(args)