KillProcessWrapper
A cross-vendor wrapper script that triggers a ‘process kill’ command - i.e executes the proper kill process command according to the vendor: CrowdstrikeFalcon or Cortex XDR. The script will only fail when the kill process action fails for both vendors.
python · Malware Investigation and Response
Details
| ID | KillProcessWrapper |
|---|---|
| Language | python |
| From Version | 6.1.0 |
| Docker Image | demisto/python3:3.12.13.10404775 |
README
A cross-vendor wrapper script that triggers a process kill command - i.e executes the proper kill process command according to the vendor: CrowdstrikeFalcon or Cortex XDR.
The script will only fail when the kill process action fails for both vendors.
Script Data
| Name | Description |
|---|---|
| Script Type | python3 |
| Cortex XSOAR Version | 6.1.0 |
Inputs
| Argument Name | Description |
|---|---|
| endpoint_id | The Endpoint ID in which you would like to kill the given process. |
| process_id | The ID of the process to kill. Either the process_id or the process_name must be specified. |
| process_name | The name of the process to kill. Either the process_id or the process_name must be specified. |
| approve_action | Are you sure you want to kill this process? |
Outputs
| Path | Description | Type |
|---|---|---|
| CrowdStrike.Command.kill | The outputs of the CrowdStrike kill process command. | List |
| CrowdStrike.Command.kill.Error | The status of the CrowdStrike kill process command. | String |
| CrowdStrike.Command.kill.HostID | The endpoint ID of the process. | String |
| CrowdStrike.Command.kill.ProcessID | The ID of the process. | String |
| PaloAltoNetworksXDR.ScriptRun | The outputs of the Cortex XDR kill process command. | List |
| PaloAltoNetworksXDR.ScriptRun.action_id | The ID of the kill process action initiated. | Number |
| PaloAltoNetworksXDR.ScriptRun.endpoints_count | The number of endpoints the action was initiated on. | Number |
| PaloAltoNetworksXDR.ScriptRun.status | The status of the kill process action. | Number |
""" Unit Tests for KillProcessWrapper script. """ import demistomock as demisto import pytest @pytest.mark.parametrize( "endpoint_id, process_id, process_name, expected_commands", [ ("endpoint_id_test", "process_id_test", None, ["cs-falcon-rtr-kill-process"]), ("endpoint_id_test", None, "process_name_test", ["xdr-run-script-kill-process"]), ( "endpoint_id_test", "process_id_test", "process_name_test", ["xdr-run-script-kill-process", "cs-falcon-rtr-kill-process"], ), ], ) def test_create_commands(endpoint_id, process_id, process_name, expected_commands): """ Given: 1. An endpoint ID and a process ID (without a process name). 2. An endpoint ID and a process name (without a process ID). 3. An endpoint ID and a process ID and a process name. When: Running the 'create_commands' function. Then: 1. Verify that the returned command name is the CrowdstrikeFalcon kill process command. 2. Verify that the returned command name is the Cortex XDR kill process command. 3. Verify that the returned command names are both CrowdstrikeFalcon and Cortex XDR kill process commands. """ from KillProcessWrapper import create_commands commands = create_commands(endpoint_id, process_id, process_name) assert commands[0].commands[0] == expected_commands[0] if len(expected_commands) == 2: assert commands[1].commands[0] == expected_commands[1] @pytest.mark.parametrize( "args, expected_err_message", [ ( {"endpoint_id": "", "process_id": "process_id_test", "process_name": "process_name_test", "approve_action": "YES"}, "Endpoint ID was not specified.", ), ( {"endpoint_id": "endpoint_id_test", "process_id": "", "process_name": "", "approve_action": "YES"}, "Process information was not specified - You should provide the process ID or the process name.", ), ], ) def test_missing_arguments(mocker, args, expected_err_message): """ Given: 1. Demisto args object containing an empty string as the endpoint_id argument. An error message about missing endpoint ID. 2. Demisto args object containing an empty string as the process_id and process_name arguments. An error message about missing process information. When: Running the 'main' function. Then: Verify that the expected error message is returned as an error. """ import KillProcessWrapper mocker.patch.object(demisto, "args", return_value=args) return_error_mock = mocker.patch.object(KillProcessWrapper, "return_error") KillProcessWrapper.main() assert return_error_mock.call_count == 1 assert return_error_mock.call_args[0][0] == (f"Failed to execute KillProcessWrapper. Error: {expected_err_message}") @pytest.mark.parametrize("approve_action", ["YES", "NO"]) def test_approve_action_functionality(mocker, approve_action): """ Given: 1. Demisto args object containing an empty string as the endpoint_id argument. An error message about missing endpoint ID. 2. Demisto args object containing an empty string as the process_id and process_name arguments. An error message about missing process information. When: Running the 'main' function. Then: Verify that the expected error message is returned as an error. """ import KillProcessWrapper args = { "endpoint_id": "endpoint_id_test", "process_id": "process_id_test", "process_name": "process_name_test", "approve_action": approve_action, } # Create mockers: mocker.patch.object(demisto, "args", return_value=args) run_killing_process_action_mock = mocker.patch.object(KillProcessWrapper, "run_killing_process_action") return_results_mock = mocker.patch.object(KillProcessWrapper, "return_results") # Execute the main function of the script: KillProcessWrapper.main() # Assertions: if approve_action == "YES": assert run_killing_process_action_mock.call_count == 1 assert return_results_mock.call_count == 1 elif approve_action == "NO": assert run_killing_process_action_mock.call_count == 0 assert return_results_mock.call_count == 1 assert return_results_mock.call_args[0][0].readable_output == "The process was not killed because no approval was given."