def put_file_command(api_client: CBCloudAPI, device_id: str, destination_path: str, file_id: str): session = api_client.select(platform.Device, device_id).lr_session() path = demisto.getFilePath(file_id) session.put_file((path['name'], open(path['path'], 'rb')), destination_path) return f'File: {file_id} is successfully put to the remote destination {destination_path}'
def feed(auth_token): """Create a Feed to use for testing""" cb = CBCloudAPI(url="https://defense-eap01.conferdeploy.net", token=auth_token, org_key="WNEXFKQ7") # Feed Creation feedinfo = { "name": "Temporary BAT Func Test Feed", "owner": "DevRel", "provider_url": "https://developer.carbonblack.com", "summary": "BAT functional test feed", "category": "None", "access": "private" } feed_dict = {"feedinfo": feedinfo, "reports": []} test_feed = cb.create(Feed, feed_dict) try: test_feed.save() except ServerError: for feed in cb.select(Feed): if feed.name == feedinfo["name"]: feed.delete() test_feed.save() yield test_feed delete_feed(auth_token, test_feed._info["id"])
def get_reg_values_command(api_client: CBCloudAPI, device_id: str, reg_path: str, limit: Union[int, str]): """Get the values of the given registry key in the remote device""" session = api_client.select(platform.Device, device_id).lr_session() values = session.list_registry_values(reg_path) if not values: return f'The key: {reg_path} does not contain any value' values, partial_res_msg = get_limited_results(original_results=values, limit=limit) context_entry = dict(key=reg_path, values=values, device_id=device_id) human_readable = [ dict(name=val['registry_name'], type=val['registry_type'], data=val['registry_data']) for val in values ] readable_output = tableToMarkdown( f'Carbon Black Defense Live Response Registry key values{partial_res_msg}', human_readable, headers=['name', 'type', 'data'], headerTransform=string_to_table_header, removeNull=True) return CommandResults( outputs_prefix='CarbonBlackDefenseLR.RegistryValues', outputs_key_field=['device_id', 'key'], outputs=context_entry, readable_output=readable_output, raw_response=values, )
def delete_feed(auth_token, feed_id): """Delete Feed after it's used for testing""" cb = CBCloudAPI(url="https://defense-eap01.conferdeploy.net", token=auth_token, org_key="WNEXFKQ7") feed = cb.select(Feed, feed_id) feed.delete()
def list_processes_command(api_client: CBCloudAPI, device_id: str, limit: Union[int, str]): session = api_client.select(platform.Device, device_id).lr_session() processes = session.list_processes() if not processes: return 'There is no active processes in the remote device' processes, partial_res_msg = get_limited_results( original_results=processes, limit=limit) headers = ['path', 'pid', 'command_line', 'username'] processes_readable = [ dict(path=process['process_path'], pid=process['process_pid'], command_line=process['process_cmdline'], user_name=process['process_username']) for process in processes ] context_entry = dict(device_id=device_id, processes=processes) readable_output = tableToMarkdown( f'Carbon Black Defense Live Response Processes{partial_res_msg}', headers=headers, t=processes_readable, headerTransform=string_to_table_header, removeNull=True) return CommandResults( 'CarbonBlackDefenseLR.Processes', outputs_key_field='device_id', outputs=context_entry, readable_output=readable_output, raw_response=processes, )
def list_directory_command(api_client: CBCloudAPI, device_id: str, directory_path: str, limit: Union[int, str]): """ Get list of directory entries in the remote device :param api_client: The API client :param device_id: The device id :param directory_path: Directory to list. This parameter should end with the path separator :param limit: Limit the result entries count to be the given limit :return: CommandResult represent the API command result :rtype: ``CommandResults`` """ session = api_client.select(platform.Device, device_id).lr_session() items = [ item for item in session.list_directory(directory_path) if item['filename'] not in IGNORED_FILES_IN_DIR ] items, partial_res_msg = get_limited_results(original_results=items, limit=limit) directories_readable = [] context_entry_items = [] headers = ['name', 'type', 'date_modified', 'size'] for item in items: context_entry_items.append(item) directories_readable.append({ 'name': item['filename'], 'type': 'Directory' if item['attributes'] and 'DIRECTORY' in item['attributes'] else 'File', 'date_modified': item['last_write_time'], 'size': item['size'], }) context_entry = dict(content=context_entry_items, device_id=device_id, directory_path=directory_path) readable_output = tableToMarkdown( f'Directory of {directory_path}{partial_res_msg}', t=directories_readable, headers=headers, headerTransform=string_to_table_header, removeNull=True) return CommandResults( outputs_prefix='CarbonBlackDefenseLR.Directory', outputs_key_field=['device_id', 'directory_path'], outputs=context_entry, readable_output=readable_output, raw_response=items, )
def get_reports_from_feed(auth_token, feed_id): """GET to /feed/{feed_id}/reports to verify reports were sent""" cb = CBCloudAPI(url="https://defense-eap01.conferdeploy.net", token=auth_token, org_key="WNEXFKQ7") feed = cb.select(Feed, feed_id) results = {"results": [report._info for report in feed.reports]} return results
def kill_process_command(api_client: CBCloudAPI, device_id: str, pid: Union[int, str]): session = api_client.select(platform.Device, device_id).lr_session() success = session.kill_process(arg_to_number( pid)) # the API returns True if success, False if failure if not success: return_error(f'Can not kill the process: {pid}') return f'The process: {pid} was killed successfully.'
def set_reg_value_command(api_client: CBCloudAPI, device_id: str, reg_path: str, value_data: Any, value_type: str, overwrite: Union[bool, str]): session = api_client.select(platform.Device, device_id).lr_session() session.set_registry_value(reg_path, value_data, overwrite=argToBoolean(overwrite), value_type=value_type) return f'Value was set to the reg key: {reg_path} successfully.'
def get_feed_ids(): """Read and log all the feed IDs from the default server.""" cb = CBCloudAPI() feeds = cb.select(Feed) if not feeds: log.info("No feeds are available for the org key {}".format( cb.credentials.org_key)) else: for feed in feeds: log.info("Feed name: {:<20} \t Feed ID: {:>20}".format( feed.name, feed.id))
def delete_reg_key_command(api_client: CBCloudAPI, device_id: str, reg_path: str, force: Union[bool, str] = False): """Delete a registry key on the remote machine, the key must be without any sub keys""" session = api_client.select(platform.Device, device_id).lr_session() if argToBoolean(force): delete_reg_key_recursive(session, reg_path) else: session.delete_registry_key(reg_path) return f'Registry key: {reg_path} was deleted successfully.'
def get_file_command(api_client: CBCloudAPI, device_id: str, source_path: str, timeout: Union[int, str] = None, delay: Union[float, str] = None): session = api_client.select(platform.Device, device_id).lr_session() if delay: delay = float(delay) file_data = session.get_file(file_name=source_path, timeout=arg_to_number(timeout), delay=delay) file_name = ntpath.split(source_path)[1] return fileResult(file_name, file_data)
def create_process_command(api_client: CBCloudAPI, device_id: str, command_string: str, wait_timeout: Union[int, str] = 30, wait_for_output: Union[bool, str] = True, wait_for_completion: Union[bool, str] = True, **additional_params): # additional_param may include: remote_output_file_name: str, working_directory: str session = api_client.select(platform.Device, device_id).lr_session() process_results_bytes = session.create_process( command_string=command_string, wait_timeout=arg_to_number(wait_timeout), wait_for_output=argToBoolean(wait_for_output), wait_for_completion=argToBoolean(wait_for_completion), **additional_params, ) process_results_str = None if wait_for_output and process_results_bytes: process_results_str = process_results_bytes.decode('utf-8') human_readable = process_results_str else: human_readable = f'Process: {command_string} was successfully executed.' context_output = dict( return_value=process_results_str, device_id=device_id, command_string=command_string, ) return CommandResults( outputs_prefix='CarbonBlackDefenseLR.ExecuteProcess', outputs_key_field=['device_id', 'command_string'], outputs=context_output, readable_output=human_readable, raw_response=process_results_str, )
def list_reg_sub_keys_command(api_client: CBCloudAPI, device_id: str, reg_path: str, limit: Union[int, str]): session = api_client.select(platform.Device, device_id).lr_session() sub_keys = session.list_registry_keys_and_values(reg_path).get( 'sub_keys', []) if not sub_keys: return f'The key: {reg_path} does not contain any sub keys' sub_keys, partial_res_msg = get_limited_results(original_results=sub_keys, limit=limit) context_entry = dict(sub_keys=sub_keys, device_id=device_id, key=reg_path) human_readable = tableToMarkdown( name= f'Carbon Black Defense Live Response Registry sub keys{partial_res_msg}', t=sub_keys, headers=['Sub keys']) return CommandResults( outputs_prefix='CarbonBlackDefenseLR.RegistrySubKeys', outputs_key_field=['device_id', 'key'], outputs=context_entry, readable_output=human_readable, raw_response=sub_keys, )
log.debug(json.dumps(res)) return res elif res["status"] == "error": raise LiveResponseError(res) else: time.sleep(delay) raise TimeoutError(uri=url, message="timeout polling for Live Response") if __name__ == "__main__": from cbc_sdk import CBCloudAPI from cbc_sdk.platform import Device import logging root = logging.getLogger() root.addHandler(logging.StreamHandler()) logging.getLogger("cbc_sdk").setLevel(logging.DEBUG) c = CBCloudAPI() j = GetFileJob(r"c:\test.txt") with c.select(Device, 3).lr_session() as lr_session: file_contents = lr_session.get_file(r"c:\test.txt") future = c.live_response.submit_job(j.run, 3) wait([ future, ]) print(future.result())
def delete_file_command(api_client: CBCloudAPI, device_id: str, source_path: str): session = api_client.select(platform.Device, device_id).lr_session() session.delete_file(filename=source_path) return f'The file: {source_path} was deleted successfully.'
def memdump_command(api_client: CBCloudAPI, device_id: str, target_path: str): session = api_client.select(platform.Device, device_id).lr_session() session.start_memdump(remote_filename=target_path).wait() return f'Memory was successfully dumped to {target_path}.'
def create_reg_key_command(api_client: CBCloudAPI, device_id: str, reg_path: str): session = api_client.select(platform.Device, device_id).lr_session() session.create_registry_key(reg_path) return f'Reg key: {reg_path}, was created successfully.'
def delete_reg_value_command(api_client: CBCloudAPI, device_id: str, reg_path: str): session = api_client.select(platform.Device, device_id).lr_session() session.delete_registry_value(reg_path) return f'Registry value: {reg_path} was deleted successfully.'
class ThreatIntel: """Object handling Threat Intelligence.""" def __init__(self): """Initialize the ThreatIntel class.""" self.cb = CBCloudAPI(timeout=200) def verify_feed_exists(self, feed_id): """Verify that a Feed exists.""" try: feed = self.cb.select(Feed, feed_id) return feed except ApiError: raise ApiError def push_to_cb(self, feed_id, results): """Send result.AnalysisResult Reports or a Report dictionary to a Feed.""" feed = self.verify_feed_exists(feed_id) # will raise an ApiError if the feed cannot be found if not feed: return report_list_to_send = [] reports = [] malformed_reports = [] for result in results: report_dict = {} # convert to a dictionary if necessary if isinstance(result, AnalysisResult): try: report_dict = { "id": str(result.id), "timestamp": int(result.timestamp.timestamp()), "title": str(result.title), "description": str(result.description), "severity": int(result.severity), "iocs_v2": [ioc_v2.as_dict() for ioc_v2 in result.iocs_v2] } except Exception as e: log.error(f"Failed to create a report dictionary from result object. {e}") # no conversion to dictionary needed elif isinstance(result, dict): report_dict = result try: ReportSchema.validate(report_dict) # create Enterprise EDR Report object report = Report(self.cb, initial_data=report_dict, feed_id=feed_id) report_list_to_send.append(report) reports.append(report_dict) except SchemaError as e: log.warning(f"Report Validation failed. Saving report to file for reference. Error: {e}") malformed_reports.append(report_dict) log.debug(f"Num Reports: {len(report_list_to_send)}") try: with open('reports.json', 'w') as f: json.dump(reports, f, indent=4) except Exception as e: log.error(f"Failed to write reports to file: {e}") log.debug("Sending results to Carbon Black Cloud.") if report_list_to_send: try: feed.append_reports(report_list_to_send) log.info(f"Appended {len(report_list_to_send)} reports to Enterprise EDR Feed {feed_id}") except Exception as e: log.debug(f"Failed sending {len(report_list_to_send)} reports: {e}") if malformed_reports: log.warning("Some report(s) failed validation. See malformed_reports.json for reports that failed.") try: with open('malformed_reports.json', 'w') as f: json.dump(malformed_reports, f, indent=4) except Exception as e: log.error(f"Failed to write malformed_reports to file: {e}")
def main(): """Script entry point""" cb = CBCloudAPI(url=url, token=token, org_key=org_key, proxy=proxy, ssl_verify=False) assert type(cb.select(Device).first()) is Device print(f"Successfully fetched Device using proxy: {proxy}")