def Start(self): """The start method.""" binary_urn = rdfvalue.RDFURN(self.args.binary) try: blob_iterator, _ = signed_binary_utils.FetchBlobsForSignedBinary( binary_urn, token=self.token) except signed_binary_utils.SignedBinaryNotFoundError: raise flow.FlowError("Executable binary %s not found." % self.args.binary) try: current_blob = next(blob_iterator) except StopIteration: current_blob = None offset = 0 write_path = "%d" % time.time() while current_blob is not None: try: next_blob = next(blob_iterator) except StopIteration: next_blob = None self.CallClient(server_stubs.ExecuteBinaryCommand, executable=current_blob, more_data=next_blob is not None, args=shlex.split(self.args.command_line), offset=offset, write_path=write_path, next_state="End") offset += len(current_blob.data) current_blob = next_blob
def _GetSignedBinaryMetadata(binary_type, relative_path): """Fetches metadata for the given binary from the datastore. Args: binary_type: ApiGrrBinary.Type of the binary. relative_path: Relative path of the binary, relative to the canonical URN roots for signed binaries (see _GetSignedBlobsRoots()). Returns: An ApiGrrBinary RDFProtoStruct containing metadata for the binary. """ root_urn = _GetSignedBlobsRoots()[binary_type] binary_urn = root_urn.Add(relative_path) blob_iterator, timestamp = signed_binary_utils.FetchBlobsForSignedBinary( binary_urn) binary_size = 0 has_valid_signature = True for blob in blob_iterator: binary_size += len(blob.data) if not has_valid_signature: # No need to check the signature if a previous blob had an invalid # signature. continue try: blob.Verify(config.CONFIG["Client.executable_signing_public_key"]) except rdf_crypto.Error: has_valid_signature = False return ApiGrrBinary(path=relative_path, type=binary_type, size=binary_size, timestamp=timestamp, has_valid_signature=has_valid_signature)
def _BlobIterator(self, binary_urn): try: blob_iterator, _ = signed_binary_utils.FetchBlobsForSignedBinary( binary_urn) except signed_binary_utils.SignedBinaryNotFoundError: raise flow_base.FlowError("%s is not a valid signed binary." % self.args.blob_path) return blob_iterator
def _BlobIterator(self, binary_urn): try: blob_iterator, _ = signed_binary_utils.FetchBlobsForSignedBinary( binary_urn, token=self.token) except signed_binary_utils.SignedBinaryNotFoundError: raise flow.FlowError("Executable binary %s not found." % self.args.binary) return blob_iterator
def testMissingSignedBinary(self): missing_urn = rdfvalue.RDFURN("aff4:/config/executables/not/exist") with self.assertRaises(signed_binary_utils.SignedBinaryNotFoundError): signed_binary_utils.DeleteSignedBinary(missing_urn) with self.assertRaises(signed_binary_utils.SignedBinaryNotFoundError): signed_binary_utils.FetchBlobsForSignedBinary(missing_urn) with self.assertRaises(signed_binary_utils.SignedBinaryNotFoundError): signed_binary_utils.FetchSizeOfSignedBinary(missing_urn)
def _WriteTestBinaryAndGetBlobIterator(self, binary_data, chunk_size): binary_urn = rdfvalue.RDFURN("aff4:/config/executables/foo") signed_binary_utils.WriteSignedBinary(binary_urn, binary_data, private_key=self._private_key, public_key=self._public_key, chunk_size=chunk_size) blob_iterator, _ = signed_binary_utils.FetchBlobsForSignedBinary( binary_urn) return blob_iterator
def Handle(self, args, token=None): root_urn = _GetSignedBlobsRoots()[args.type] binary_urn = root_urn.Add(args.path) binary_size = signed_binary_utils.FetchSizeOfSignedBinary(binary_urn) blob_iterator, _ = signed_binary_utils.FetchBlobsForSignedBinary(binary_urn) chunk_iterator = signed_binary_utils.StreamSignedBinaryContents( blob_iterator, chunk_size=self.CHUNK_SIZE) return api_call_handler_base.ApiBinaryStream( filename=binary_urn.Basename(), content_generator=chunk_iterator, content_length=binary_size)
def testWriteSignedBinaryBlobs(self): test_urn = rdfvalue.RDFURN("aff4:/config/executables/foo") test_blobs = [ rdf_crypto.SignedBlob().Sign(b"\x00\x11\x22", self._private_key), rdf_crypto.SignedBlob().Sign(b"\x33\x44\x55", self._private_key), rdf_crypto.SignedBlob().Sign(b"\x66\x77\x88", self._private_key), rdf_crypto.SignedBlob().Sign(b"\x99", self._private_key) ] signed_binary_utils.WriteSignedBinaryBlobs(test_urn, test_blobs) blobs_iterator, timestamp = signed_binary_utils.FetchBlobsForSignedBinary( test_urn) self.assertGreater(timestamp.AsMicrosecondsSinceEpoch(), 0) self.assertCountEqual(list(blobs_iterator), test_blobs)
def testExecuteLargeBinaries(self): client_mock = action_mocks.ActionMock(standard.ExecuteBinaryCommand) code = b"I am a large binary file" * 100 upload_path = signed_binary_utils.GetAFF4ExecutablesRoot().Add( config.CONFIG["Client.platform"]).Add("test.exe") maintenance_utils.UploadSignedConfigBlob(code, aff4_path=upload_path, limit=100, token=self.token) binary_urn = rdfvalue.RDFURN(upload_path) binary_size = signed_binary_utils.FetchSizeOfSignedBinary( binary_urn, token=self.token) blob_iterator, _ = signed_binary_utils.FetchBlobsForSignedBinary( binary_urn, token=self.token) # Total size is 2400. self.assertEqual(binary_size, 2400) # There should be 24 parts to this binary. self.assertLen(list(blob_iterator), 24) # This flow has an acl, the user needs to be admin. acl_test_lib.CreateAdminUser(self.token.username) with utils.Stubber(subprocess, "Popen", client_test_lib.Popen): flow_test_lib.TestFlowHelper(compatibility.GetName( administrative.LaunchBinary), client_mock, client_id=self.SetupClient(0), binary=upload_path, command_line="--value 356", token=self.token) # Check that the executable file contains the code string. self.assertEqual(client_test_lib.Popen.binary, code) # At this point, the actual binary should have been cleaned up by the # client action so it should not exist. self.assertRaises(IOError, open, client_test_lib.Popen.running_args[0]) # Check the binary was run with the correct command line. self.assertEqual(client_test_lib.Popen.running_args[1], "--value") self.assertEqual(client_test_lib.Popen.running_args[2], "356") # Check the command was in the tmp file. self.assertStartsWith(client_test_lib.Popen.running_args[0], config.CONFIG["Client.tempdir_roots"][0])
def Start(self): """The start method.""" python_hack_urn = signed_binary_utils.GetAFF4PythonHackRoot().Add( self.args.hack_name) try: blob_iterator, _ = signed_binary_utils.FetchBlobsForSignedBinary( python_hack_urn) except signed_binary_utils.SignedBinaryNotFoundError: raise flow_base.FlowError("Python hack %s not found." % self.args.hack_name) # TODO(amoser): This will break if someone wants to execute lots of Python. for python_blob in blob_iterator: self.CallClient(server_stubs.ExecutePython, python_code=python_blob, py_args=self.args.py_args, next_state="Done")
def testUploadPythonHack(self): with utils.TempDirectory() as dir_path: python_hack_path = os.path.join(dir_path, "hello_world.py") with open(python_hack_path, "wb") as f: f.write(b"print('Hello, world!')") config_updater_util.UploadSignedBinary( python_hack_path, rdf_objects.SignedBinaryID.BinaryType.PYTHON_HACK, "linux", upload_subdirectory="test") python_hack_urn = rdfvalue.RDFURN( "aff4:/config/python_hacks/linux/test/hello_world.py") blob_iterator, _ = signed_binary_utils.FetchBlobsForSignedBinary( python_hack_urn) uploaded_blobs = list( signed_binary_utils.StreamSignedBinaryContents(blob_iterator)) uploaded_content = b"".join(uploaded_blobs) self.assertEqual(uploaded_content, b"print('Hello, world!')")
def testUploadExecutable(self): with utils.TempDirectory() as dir_path: executable_path = os.path.join(dir_path, "foo.exe") with open(executable_path, "wb") as f: f.write(b"\xaa\xbb\xcc\xdd") config_updater_util.UploadSignedBinary( executable_path, rdf_objects.SignedBinaryID.BinaryType.EXECUTABLE, "windows", upload_subdirectory="anti-malware/registry-tools") executable_urn = rdfvalue.RDFURN( "aff4:/config/executables/windows/anti-malware/registry-tools/" "foo.exe") blob_iterator, _ = signed_binary_utils.FetchBlobsForSignedBinary( executable_urn) uploaded_blobs = list( signed_binary_utils.StreamSignedBinaryContents(blob_iterator)) uploaded_content = b"".join(uploaded_blobs) self.assertEqual(uploaded_content, b"\xaa\xbb\xcc\xdd")
def testWriteSignedBinary(self): binary_data = b"\x00\x11\x22\x33\x44\x55\x66\x77\x88\x99" # 10 bytes. test_urn = rdfvalue.RDFURN("aff4:/config/executables/foo") signed_binary_utils.WriteSignedBinary(test_urn, binary_data, private_key=self._private_key, public_key=self._public_key, chunk_size=3) blobs_iterator, timestamp = signed_binary_utils.FetchBlobsForSignedBinary( test_urn) self.assertGreater(timestamp.AsMicrosecondsSinceEpoch(), 0) self.assertIsInstance(blobs_iterator, collections.Iterator) # We expect blobs to have at most 3 contiguous bytes of data. expected_blobs = [ rdf_crypto.SignedBlob().Sign(b"\x00\x11\x22", self._private_key), rdf_crypto.SignedBlob().Sign(b"\x33\x44\x55", self._private_key), rdf_crypto.SignedBlob().Sign(b"\x66\x77\x88", self._private_key), rdf_crypto.SignedBlob().Sign(b"\x99", self._private_key) ] self.assertCountEqual(list(blobs_iterator), expected_blobs)
def testUpdateClient(self): client_mock = action_mocks.UpdateAgentClientMock() fake_installer = b"FakeGRRDebInstaller" * 20 upload_path = signed_binary_utils.GetAFF4ExecutablesRoot().Add( config.CONFIG["Client.platform"]).Add("test.deb") maintenance_utils.UploadSignedConfigBlob(fake_installer, aff4_path=upload_path, limit=100) blob_list, _ = signed_binary_utils.FetchBlobsForSignedBinary( upload_path) self.assertLen(list(blob_list), 4) acl_test_lib.CreateAdminUser(self.token.username) flow_test_lib.TestFlowHelper(administrative.UpdateClient.__name__, client_mock, client_id=self.SetupClient(0, system=""), blob_path=upload_path, token=self.token) self.assertEqual(client_mock.GetDownloadedFileContents(), fake_installer)
def Start(self): """Start.""" binary_path = self.args.blob_path if not binary_path: raise flow.FlowError("Please specify an installer binary.") binary_urn = rdfvalue.RDFURN(binary_path) try: blob_iterator, _ = signed_binary_utils.FetchBlobsForSignedBinary( binary_urn, token=self.token) except signed_binary_utils.SignedBinaryNotFoundError: raise flow.FlowError("%s is not a valid signed binary." % binary_path) offset = 0 write_path = "%d_%s" % (time.time(), binary_urn.Basename()) try: current_blob = next(blob_iterator) except StopIteration: current_blob = None while current_blob is not None: try: next_blob = next(blob_iterator) except StopIteration: next_blob = None more_data = next_blob is not None self.CallClient(server_stubs.UpdateAgent, executable=current_blob, more_data=more_data, offset=offset, write_path=write_path, next_state=("CheckUpdateAgent" if more_data else "Interrogate"), use_client_env=False) offset += len(current_blob.data) current_blob = next_blob