Ejemplo n.º 1
0
    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)
Ejemplo n.º 2
0
    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))
Ejemplo n.º 3
0
  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))
Ejemplo n.º 4
0
  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)
Ejemplo n.º 5
0
  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))
Ejemplo n.º 6
0
    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))