├── .gitignore ├── LICENSE ├── README.md ├── Win_Hunting.cfg ├── alert_bulk_resolve.py ├── alert_search.py ├── auto_blacklist_from_watchlist.conf.example ├── auto_blacklist_from_watchlist.py ├── auto_isolate_from_watchlist.conf.example ├── auto_isolate_from_watchlist.py ├── binary_download.py ├── binary_export.py ├── binary_search.py ├── bit9_platform_server_config.py ├── cb-dns-exfil.py ├── cb-powershell-decode.py ├── check_ioc.py ├── cmd_exe_filemods.py ├── data ├── autoruns_regexes.txt ├── mandiant-domains.txt └── mandiant-md5s.txt ├── del_file.py ├── download_all_files_with_extension.py ├── download_sensor_installer.py ├── englishwords.freq ├── enumerate_usb_devices.py ├── event_add.py ├── event_by_process_id.py ├── event_del.py ├── event_export.py ├── event_info.py ├── event_update.py ├── extract_indicators.py ├── facets.py ├── feed_action_add.py ├── feed_action_del.py ├── feed_action_enum.py ├── feed_action_update.py ├── feed_add.py ├── feed_cert.py ├── feed_del.py ├── feed_enum.py ├── feed_info.py ├── feed_ioc_cleaner ├── bad_iocs.txt └── feed_ioc_cleaner.py ├── feed_modify.py ├── feed_query_validate.py ├── feed_report_info.py ├── feed_report_stats.py ├── feed_report_toggle.py ├── feed_requirements.py ├── feed_synchronize.py ├── filemods_from_list.py ├── generic_binary_search.py ├── generic_process_search.py ├── get_builds.py ├── get_login_caps.py ├── group_datasharing_add.py ├── group_datasharing_del.py ├── group_datasharing_del_all.py ├── group_datasharing_enum.py ├── group_datasharing_info.py ├── group_get_linux.py ├── group_get_osx.py ├── group_get_windowsexe.py ├── group_get_windowsmsi.py ├── kill_all_iexplore.py ├── license_status.py ├── move_policy_from_mbus.conf.example ├── move_policy_from_mbus.py ├── net_exe_usages.py ├── network_subnet_search.py ├── network_traffic_report.py ├── osx_logins.py ├── pci-fim.py ├── platform_agent_report.py ├── powershell_long_running.py ├── powershell_long_running_yesterday.py ├── process_cmdline_regex.py ├── process_composition.py ├── process_report.py ├── process_search.py ├── process_search_hunter.py ├── process_users_on_host.py ├── put_file.py ├── report_search.py ├── reporter.cfg ├── reporter.py ├── restart_sensors.conf ├── restart_sensors.py ├── retrieve_regmod_values.py ├── sensor_backlog_aggregate.py ├── sensor_backlog_individual.py ├── sensor_backlog_report.py ├── sensor_details.py ├── sensor_info.py ├── sensor_isolation_alert.py ├── sensor_list.py ├── sensors_not_checked_in.py ├── server_info.py ├── tf.py ├── watchlist_add.py ├── watchlist_add_edit_del.py ├── watchlist_del.py ├── watchlist_edit.py ├── watchlist_enum.py ├── watchlist_hits_enum.py ├── watchlist_info.py └── watchlist_remove_all_newerThanID.py /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 5 | 6 | # C extensions 7 | *.so 8 | 9 | # Distribution / packaging 10 | .Python 11 | env/ 12 | build/ 13 | develop-eggs/ 14 | dist/ 15 | downloads/ 16 | eggs/ 17 | .eggs/ 18 | lib/ 19 | lib64/ 20 | parts/ 21 | sdist/ 22 | var/ 23 | *.egg-info/ 24 | .installed.cfg 25 | *.egg 26 | 27 | # PyInstaller 28 | # Usually these files are written by a python script from a template 29 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 30 | *.manifest 31 | *.spec 32 | 33 | # Installer logs 34 | pip-log.txt 35 | pip-delete-this-directory.txt 36 | 37 | # Unit test / coverage reports 38 | htmlcov/ 39 | .tox/ 40 | .coverage 41 | .coverage.* 42 | .cache 43 | nosetests.xml 44 | coverage.xml 45 | *,cover 46 | .hypothesis/ 47 | 48 | # Translations 49 | *.mo 50 | *.pot 51 | 52 | # Django stuff: 53 | *.log 54 | 55 | # Sphinx documentation 56 | docs/_build/ 57 | 58 | # PyBuilder 59 | target/ 60 | 61 | #Ipython Notebook 62 | .ipynb_checkpoints 63 | 64 | # PyCharm 65 | .idea/ 66 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 Carbon Black Developer Community 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # cbapi-examples 2 | Repository for all cbapi example scripts 3 | -------------------------------------------------------------------------------- /alert_bulk_resolve.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # 3 | #The MIT License (MIT) 4 | # 5 | # Copyright (c) 2015 Bit9 + Carbon Black 6 | # 7 | # Permission is hereby granted, free of charge, to any person obtaining a copy 8 | # of this software and associated documentation files (the "Software"), to deal 9 | # in the Software without restriction, including without limitation the rights 10 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | # copies of the Software, and to permit persons to whom the Software is 12 | # furnished to do so, subject to the following conditions: 13 | # 14 | # The above copyright notice and this permission notice shall be included in all 15 | # copies or substantial portions of the Software. 16 | # 17 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | # SOFTWARE. 24 | # 25 | # ----------------------------------------------------------------------------- 26 | # 27 | # 28 | # 29 | # 30 | # last updated 2015-06-28 by Ben Johnson bjohnson@bit9.com 31 | # 32 | 33 | import sys 34 | import time 35 | import optparse 36 | import cbapi 37 | 38 | def build_cli_parser(): 39 | parser = optparse.OptionParser(usage="%prog [options]", description="Set status to Resolved for a set of alerts.") 40 | 41 | # for each supported output type, add an option 42 | # 43 | parser.add_option("-c", "--cburl", action="store", default=None, dest="server_url", 44 | help="CB server's URL. e.g., http://127.0.0.1 ") 45 | parser.add_option("-a", "--apitoken", action="store", default=None, dest="token", 46 | help="API Token for Carbon Black server") 47 | parser.add_option("-n", "--no-ssl-verify", action="store_false", default=True, dest="ssl_verify", 48 | help="Do not verify server SSL certificate.") 49 | parser.add_option("-q", "--query", action="store", default=None, dest="query", 50 | help="The query string of alerts to resolve. All matching alerts will be resolved.") 51 | parser.add_option("-y", "--yes", action="store_true", default=False, dest="answered", 52 | help="Automatically answer yes to any question.") 53 | return parser 54 | 55 | def main(argv): 56 | parser = build_cli_parser() 57 | opts, args = parser.parse_args(argv) 58 | if not opts.server_url or not opts.token or not opts.query: 59 | print "Missing required param; run with --help for usage" 60 | sys.exit(-1) 61 | 62 | # build a cbapi object 63 | # 64 | cb = cbapi.CbApi(opts.server_url, token=opts.token, ssl_verify=opts.ssl_verify) 65 | 66 | query = "-status:Resolved " + opts.query 67 | while True: 68 | results = cb.alert_search(query, rows=100) 69 | if results['total_results'] == 0: break 70 | 71 | for result in results['results']: 72 | new = {} 73 | new['unique_id'] = result['unique_id'] 74 | new['status'] = "resolved" 75 | 76 | response = cb.alert_update(new) 77 | if not response or response['result'] != 'success': 78 | raise Exception("error setting status on %s: %s. Aborting." % (result['unique_id'], repr(response))) 79 | break 80 | print "Resolved %s" % (result['unique_id']) 81 | time.sleep(25) 82 | print "Complete." 83 | if __name__ == "__main__": 84 | sys.exit(main(sys.argv[1:])) 85 | -------------------------------------------------------------------------------- /alert_search.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # 3 | #The MIT License (MIT) 4 | # 5 | # Copyright (c) 2015 Bit9 + Carbon Black 6 | # 7 | # Permission is hereby granted, free of charge, to any person obtaining a copy 8 | # of this software and associated documentation files (the "Software"), to deal 9 | # in the Software without restriction, including without limitation the rights 10 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | # copies of the Software, and to permit persons to whom the Software is 12 | # furnished to do so, subject to the following conditions: 13 | # 14 | # The above copyright notice and this permission notice shall be included in all 15 | # copies or substantial portions of the Software. 16 | # 17 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | # SOFTWARE. 24 | # 25 | # ----------------------------------------------------------------------------- 26 | # 27 | # 28 | # 29 | # 30 | # last updated 2015-06-28 by Ben Johnson bjohnson@bit9.com 31 | # 32 | 33 | 34 | import sys 35 | import optparse 36 | import pprint 37 | import cbapi 38 | 39 | def build_cli_parser(): 40 | parser = optparse.OptionParser(usage="%prog [options]", description="Export alerts.") 41 | 42 | # for each supported output type, add an option 43 | # 44 | parser.add_option("-c", "--cburl", action="store", default=None, dest="server_url", 45 | help="CB server's URL. e.g., http://127.0.0.1 ") 46 | parser.add_option("-a", "--apitoken", action="store", default=None, dest="token", 47 | help="API Token for Carbon Black server") 48 | parser.add_option("-n", "--no-ssl-verify", action="store_false", default=True, dest="ssl_verify", 49 | help="Do not verify server SSL certificate.") 50 | parser.add_option("-q", "--query", action="store", default="", dest="query", 51 | help="The query string of alerts to search.") 52 | return parser 53 | 54 | def main(argv): 55 | parser = build_cli_parser() 56 | opts, args = parser.parse_args(argv) 57 | if not opts.server_url or not opts.token: 58 | print "Missing required param; run with --help for usage" 59 | sys.exit(-1) 60 | 61 | # build a cbapi object 62 | # 63 | cb = cbapi.CbApi(opts.server_url, token=opts.token, ssl_verify=opts.ssl_verify) 64 | start = 0 65 | pagesize=100 66 | while True: 67 | results = cb.alert_search(opts.query, rows=int(pagesize), start=start) 68 | if len(results['results']) == 0: break 69 | for result in results['results']: 70 | pprint.pprint(result) 71 | start = start + int(pagesize) 72 | if __name__ == "__main__": 73 | sys.exit(main(sys.argv[1:])) 74 | -------------------------------------------------------------------------------- /auto_blacklist_from_watchlist.conf.example: -------------------------------------------------------------------------------- 1 | [settings] 2 | 3 | # 4 | # Warning: Please check permissions of this file prior to saving usernames/passwords 5 | # 6 | 7 | # 8 | # RabbitMQ Password; see /etc/cb/cb.conf 9 | # 10 | rabbitmqpassword = ooClhMhcH81tuA9h 11 | 12 | # 13 | # RabbitMQ Username; see /etc/cb/cb.conf 14 | # 15 | rabbitmqusername = cb 16 | 17 | # 18 | # Carbon Black Server IP 19 | # 20 | #cbserverip = localhost 21 | cbserverip = 192.168.214.136 22 | 23 | # 24 | # Carbon Black Server API token 25 | # 26 | cbtoken = cb934d264bf31e734ace670e5c83cee45e55f788 27 | 28 | # 29 | # Comma separated list of watchlist names that will trigger auto-blacklisting 30 | # Note: The names must be exactly the same as they are in the Carbon Black Server UI 31 | # 32 | watchlists = VirusTotal, Notepad Spawn -------------------------------------------------------------------------------- /auto_isolate_from_watchlist.conf.example: -------------------------------------------------------------------------------- 1 | [settings] 2 | 3 | # 4 | # Warning: Please check permissions of this file prior to saving usernames/passwords 5 | # 6 | 7 | # 8 | # RabbitMQ Password; see /etc/cb/cb.conf 9 | # 10 | rabbitmqpassword = ad3efBGE45Xza 11 | 12 | # 13 | # RabbitMQ Username; see /etc/cb/cb.conf 14 | # 15 | rabbitmqusername = cb 16 | 17 | # 18 | # Carbon Black Server IP 19 | # 20 | cbserverip = 192.168.23.45 21 | 22 | # 23 | # Carbon Black Server API token 24 | # 25 | cbtoken = 271a314d1d98469468b962f494885fbef9f93ba3 26 | 27 | # 28 | # Comma separated list of watchlist names that will trigger auto-blacklisting 29 | # Note: The names must be exactly the same as they are in the Carbon Black Server UI 30 | # 31 | watchlists = Powershell Execution 32 | -------------------------------------------------------------------------------- /binary_download.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # 3 | #The MIT License (MIT) 4 | # 5 | # Copyright (c) 2015 Bit9 + Carbon Black 6 | # 7 | # Permission is hereby granted, free of charge, to any person obtaining a copy 8 | # of this software and associated documentation files (the "Software"), to deal 9 | # in the Software without restriction, including without limitation the rights 10 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | # copies of the Software, and to permit persons to whom the Software is 12 | # furnished to do so, subject to the following conditions: 13 | # 14 | # The above copyright notice and this permission notice shall be included in all 15 | # copies or substantial portions of the Software. 16 | # 17 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | # SOFTWARE. 24 | # 25 | # ----------------------------------------------------------------------------- 26 | # 27 | # 28 | # 29 | # 30 | # last updated 2015-06-28 by Ben Johnson bjohnson@bit9.com 31 | # 32 | 33 | 34 | import sys 35 | import optparse 36 | 37 | import cbapi 38 | 39 | def build_cli_parser(): 40 | parser = optparse.OptionParser(usage="%prog [options]", description="Download a binary") 41 | 42 | # for each supported output type, add an option 43 | # 44 | parser.add_option("-c", "--cburl", action="store", default=None, dest="url", 45 | help="CB server's URL. e.g., http://127.0.0.1 ") 46 | parser.add_option("-a", "--apitoken", action="store", default=None, dest="token", 47 | help="API Token for Carbon Black server") 48 | parser.add_option("-n", "--no-ssl-verify", action="store_false", default=True, dest="ssl_verify", 49 | help="Do not verify server SSL certificate.") 50 | parser.add_option("-m", "--md5", action="store", default=None, dest="md5", 51 | help="binary query") 52 | parser.add_option("-f", "--filename", action="store", default=None, dest="filename", 53 | help="local filename to save the binary as") 54 | return parser 55 | 56 | def main(argv): 57 | parser = build_cli_parser() 58 | opts, args = parser.parse_args(argv) 59 | if not opts.url or not opts.token or opts.md5 is None: 60 | print "Missing required param; run with --help for usage" 61 | sys.exit(-1) 62 | 63 | if opts.filename is None: 64 | opts.filename = "%s.zip" % (opts.md5,) 65 | 66 | # build a cbapi object 67 | # 68 | cb = cbapi.CbApi(opts.url, token=opts.token, ssl_verify=opts.ssl_verify) 69 | 70 | # perform a single binary search 71 | # 72 | binary = cb.binary(opts.md5) 73 | 74 | # open the file and write out the contents 75 | # 76 | open(opts.filename, "w").write(binary) 77 | 78 | print "-> Downloaded binary %s [%u bytes]" % (opts.md5, len(binary)) 79 | 80 | if __name__ == "__main__": 81 | sys.exit(main(sys.argv[1:])) 82 | -------------------------------------------------------------------------------- /binary_export.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # 3 | #The MIT License (MIT) 4 | # 5 | # Copyright (c) 2015 Bit9 + Carbon Black 6 | # 7 | # Permission is hereby granted, free of charge, to any person obtaining a copy 8 | # of this software and associated documentation files (the "Software"), to deal 9 | # in the Software without restriction, including without limitation the rights 10 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | # copies of the Software, and to permit persons to whom the Software is 12 | # furnished to do so, subject to the following conditions: 13 | # 14 | # The above copyright notice and this permission notice shall be included in all 15 | # copies or substantial portions of the Software. 16 | # 17 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | # SOFTWARE. 24 | # 25 | # ----------------------------------------------------------------------------- 26 | # 27 | # 28 | # 29 | # 30 | # last updated 2015-06-28 by Ben Johnson bjohnson@bit9.com 31 | # 32 | 33 | 34 | import sys 35 | import optparse 36 | import cbapi 37 | 38 | def build_cli_parser(): 39 | parser = optparse.OptionParser(usage="%prog [options]", description="Dump All MD5s from the binary index") 40 | 41 | # for each supported output type, add an option 42 | # 43 | parser.add_option("-c", "--cburl", action="store", default=None, dest="url", 44 | help="CB server's URL. e.g., http://127.0.0.1 ") 45 | parser.add_option("-a", "--apitoken", action="store", default=None, dest="token", 46 | help="API Token for Carbon Black server") 47 | parser.add_option("-n", "--no-ssl-verify", action="store_false", default=True, dest="ssl_verify", 48 | help="Do not verify server SSL certificate.") 49 | parser.add_option("-p", "--pagesize", action="store", default=128, dest="pagesize", 50 | help="Number of MD5s to retrieve during each API invocation") 51 | parser.add_option("-f", "--file", action="store", default=None, dest="filename", 52 | help="filename of file to write all md5s to") 53 | return parser 54 | 55 | def main(argv): 56 | parser = build_cli_parser() 57 | opts, args = parser.parse_args(argv) 58 | if not opts.url or not opts.token or not opts.pagesize or not opts.filename: 59 | print "Missing required param; run with --help for usage" 60 | sys.exit(-1) 61 | 62 | # build a cbapi object 63 | # 64 | cb = cbapi.CbApi(opts.url, token=opts.token, ssl_verify=opts.ssl_verify) 65 | 66 | start = 0 67 | md5s = [] 68 | total = 0 69 | 70 | while True: 71 | 72 | # perform a single binary search 73 | # 74 | binaries = cb.binary_search("", rows=int(opts.pagesize), start=start) 75 | 76 | if 0 == start: 77 | total = int(binaries['total_results']) 78 | print "Total MD5 count is %s" % (binaries['total_results']) 79 | 80 | # api indicates "no more" by returning an empty result set 81 | # 82 | if 0 == len(binaries['results']): 83 | break 84 | 85 | # for each result 86 | for binary in binaries['results']: 87 | md5s.append(binary['md5']) 88 | 89 | print '%s of %s complete (%s%%)' % (len(md5s), total, (100 * len(md5s)) / total) 90 | 91 | start = start + int(opts.pagesize) 92 | 93 | f = open(opts.filename, 'w') 94 | for md5 in md5s: 95 | f.write("%s\n" % (md5,)) 96 | f.close() 97 | 98 | if __name__ == "__main__": 99 | sys.exit(main(sys.argv[1:])) 100 | -------------------------------------------------------------------------------- /binary_search.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # 3 | #The MIT License (MIT) 4 | # 5 | # Copyright (c) 2015 Bit9 + Carbon Black 6 | # 7 | # Permission is hereby granted, free of charge, to any person obtaining a copy 8 | # of this software and associated documentation files (the "Software"), to deal 9 | # in the Software without restriction, including without limitation the rights 10 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | # copies of the Software, and to permit persons to whom the Software is 12 | # furnished to do so, subject to the following conditions: 13 | # 14 | # The above copyright notice and this permission notice shall be included in all 15 | # copies or substantial portions of the Software. 16 | # 17 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | # SOFTWARE. 24 | # 25 | # ----------------------------------------------------------------------------- 26 | # 27 | # 28 | # 29 | # 30 | # last updated 2015-06-28 by Ben Johnson bjohnson@bit9.com 31 | # 32 | 33 | import sys 34 | import optparse 35 | import cbapi 36 | 37 | def build_cli_parser(): 38 | parser = optparse.OptionParser(usage="%prog [options]", description="Perform a binary search") 39 | 40 | # for each supported output type, add an option 41 | # 42 | parser.add_option("-c", "--cburl", action="store", default=None, dest="url", 43 | help="CB server's URL. e.g., http://127.0.0.1 ") 44 | parser.add_option("-a", "--apitoken", action="store", default=None, dest="token", 45 | help="API Token for Carbon Black server") 46 | parser.add_option("-n", "--no-ssl-verify", action="store_false", default=True, dest="ssl_verify", 47 | help="Do not verify server SSL certificate.") 48 | parser.add_option("-q", "--query", action="store", default=None, dest="query", 49 | help="binary query") 50 | return parser 51 | 52 | def main(argv): 53 | parser = build_cli_parser() 54 | opts, args = parser.parse_args(argv) 55 | if not opts.url or not opts.token or opts.query is None: 56 | print "Missing required param; run with --help for usage" 57 | sys.exit(-1) 58 | 59 | # build a cbapi object 60 | # 61 | cb = cbapi.CbApi(opts.url, token=opts.token, ssl_verify=opts.ssl_verify) 62 | 63 | # perform a single binary search 64 | # 65 | binaries = cb.binary_search(opts.query) 66 | 67 | print "%-20s : %s" % ('Displayed Results', len(binaries['results'])) 68 | print "%-20s : %s" % ('Total Results', binaries['total_results']) 69 | print "%-20s : %sms" % ('QTime', int(1000*binaries['elapsed'])) 70 | print '\n' 71 | 72 | # for each result 73 | for binary in binaries['results']: 74 | print binary['md5'] 75 | print "-" * 80 76 | print "%-20s : %s" % ('Size (bytes)', binary.get('orig_mod_len', '')) 77 | print "%-20s : %s" % ('Signature Status', binary.get('digsig_result', '')) 78 | print "%-20s : %s" % ('Publisher', binary.get('digsig_publisher', '')) 79 | print "%-20s : %s" % ('Product Version', binary.get('product_version', '')) 80 | print "%-20s : %s" % ('File Version', binary.get('file_version', '')) 82 | print "%-20s : %s" % ('EXE', binary.get('is_executable_image', '')) 83 | 84 | if len(binary.get('observed_filename', [])) > 0: 85 | print "%-20s : %s" % ('On-Disk Filename(s)', binary['observed_filename'][0].split('\\')[-1]) 86 | for observed_filename in binary['observed_filename'][1:]: 87 | print "%-20s : %s" % ('', observed_filename.split('\\')[-1]) 88 | 89 | print '\n' 90 | if __name__ == "__main__": 91 | sys.exit(main(sys.argv[1:])) 92 | -------------------------------------------------------------------------------- /cb-dns-exfil.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # 3 | #The MIT License (MIT) 4 | # 5 | # Copyright (c) 2015 Bit9 + Carbon Black 6 | # 7 | # Permission is hereby granted, free of charge, to any person obtaining a copy 8 | # of this software and associated documentation files (the "Software"), to deal 9 | # in the Software without restriction, including without limitation the rights 10 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | # copies of the Software, and to permit persons to whom the Software is 12 | # furnished to do so, subject to the following conditions: 13 | # 14 | # The above copyright notice and this permission notice shall be included in all 15 | # copies or substantial portions of the Software. 16 | # 17 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | # SOFTWARE. 24 | # 25 | # ----------------------------------------------------------------------------- 26 | 27 | ######## 28 | # DNS Exfiltration Search 29 | # Usage: python cb-dns-exfil.py 30 | # Author: Jon Ross (jross@bit9.com) 31 | # Date: 17 Nov 2015 32 | # 33 | # This script applies Mark Baggett's freq tool avaialble at 34 | # https://github.com/MarkBaggett/MarkBaggett/tree/master/freq to DNS searches 35 | # found in Carbon Black made on the endpoint's command line. 36 | # 37 | # If the tool finds hostnames that appear to random or computer generated 38 | # it will print a message with the hostname that made the lookup and the 39 | # command line used to generate the query. This is not an exact science 40 | # but instead is meant to offer a means to find exfiltration via DNS 41 | # after the fact or alert quickly if it occurs in your environment. Results 42 | # should be reviewed by an analyst before any actions are taken. 43 | # 44 | ######## 45 | #### Replace these variables with the appropriate values for your environment. 46 | 47 | CBADDR = "192.168.230.40" 48 | API_TOKEN = "11f8e14d1d98469468b962f494885fbef9e16cc5" 49 | 50 | #### The following variable is the query sent to Carbon Black. By default 51 | #### this script inspects all port 53 traffic but you could also filter out 52 | #### your DNS servers by using the following 53 | #### 54 | #### query = "ipport:53 -ipaddr:192.168.230.3 -ipaddr:192.168.230.6" 55 | #### 56 | #### My DNS servers are 192.168.230.3 and 192.168.230.6. Please adjust this 57 | #### to match your server addresses. You may safely remove or add an -ipaddr 58 | #### directive if you have more or fewer servers in your environment. 59 | 60 | query = "ipport:53" 61 | 62 | #### The wordlist variable should point to your wordlist prepared for use 63 | #### with freq. 64 | 65 | wordlist = "englishwords.freq" 66 | 67 | ## Do not edit below this line unless you want to change the logic or output ## 68 | 69 | import re 70 | import cbapi 71 | from freq import * 72 | import requests 73 | 74 | requests.packages.urllib3.disable_warnings() 75 | 76 | myfreq = FreqCounter() 77 | myfreq.load(wordlist) 78 | 79 | cbURL = "https://"+CBADDR 80 | 81 | c = cbapi.CbApi(cbURL, ssl_verify=False, token=API_TOKEN) 82 | 83 | for results in c.process_search_iter(query): 84 | if results['cmdline']: 85 | a = re.search('\s(?=.{1,255}$)[0-9A-Za-z](?:(?:[0-9A-Za-z]|-){0,61}[0-9A-Za-z])?(?:\.[0-9A-Za-z](?:(?:[0-9A-Za-z]|-){0,61}[0-9A-Za-z])?)*\.?\s', results['cmdline']) 86 | if a: 87 | fqdn = a.group(0) 88 | parts=fqdn.split('.') 89 | score = myfreq.probability(parts[0]) 90 | if score<5: 91 | print 'Possible DNS exfil from host %s using %s' % (results['hostname'],results['cmdline']) 92 | -------------------------------------------------------------------------------- /cb-powershell-decode.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # 3 | # The MIT License (MIT) 4 | # 5 | # Copyright (c) 2016 Carbon Black 6 | # 7 | # Permission is hereby granted, free of charge, to any person obtaining a copy 8 | # of this software and associated documentation files (the "Software"), to deal 9 | # in the Software without restriction, including without limitation the rights 10 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | # copies of the Software, and to permit persons to whom the Software is 12 | # furnished to do so, subject to the following conditions: 13 | # 14 | # The above copyright notice and this permission notice shall be included in all 15 | # copies or substantial portions of the Software. 16 | # 17 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | # SOFTWARE. 24 | # 25 | # ----------------------------------------------------------------------------- 26 | # 27 | # last updated 2016-03-13 by Jon Ross jross@carbonblack.com 28 | # -vastly improved base64 decoding and encoded command detection 29 | # updated 2016-02-10 by Jon Ross jross@carbonblack.com 30 | # 31 | 32 | try: 33 | from cbapi.legacy.util.cli_helpers import main_helper 34 | except ImportError: 35 | from cbapi.util.cli_helpers import main_helper 36 | 37 | from cbapi import CbApi 38 | import base64 39 | import re 40 | 41 | 42 | def main(cb, args): 43 | powershells = cb.process_search_iter('process_name:powershell.exe') 44 | for s in powershells: 45 | if s['cmdline']: 46 | encoded = re.search('\-[eE][nN][cC][oOdDeEcCmMaAnN]*\s([A-Za-z0-9\+/=]+)', s['cmdline']) 47 | if encoded != None: 48 | i = encoded.group(1) 49 | if not re.search('[a-zA-Z0-9\+/]+={1,2}$', i): 50 | trailingBytes = len(i) % 4 51 | if trailingBytes == 3: 52 | i = i + '=' 53 | elif trailingBytes == 2: 54 | i = i + '==' 55 | decodedCommand = base64.standard_b64decode(i) 56 | try: 57 | a = decodedCommand.encode('ascii', 'replace') 58 | print "Powershell Decoded Command\n%s/#analyze/%s/1\n%s\n\n" % ( 59 | args['server_url'], s['id'], a.replace('\0', "")) 60 | except UnicodeError: 61 | print "Powershell Decoded Command\n%s/#analyze/%s/1\nNon-ASCII decoding, encoded form printed to assist more research\n%s\n" % ( 62 | args['server_url'], s['id'], s['cmdline']) 63 | pass 64 | 65 | 66 | if __name__ == "__main__": 67 | main_helper("Decode Powershell Encoded Commands", main, custom_required=None) 68 | -------------------------------------------------------------------------------- /cmd_exe_filemods.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # 3 | #The MIT License (MIT) 4 | # 5 | # Copyright (c) 2015 Bit9 + Carbon Black 6 | # 7 | # Permission is hereby granted, free of charge, to any person obtaining a copy 8 | # of this software and associated documentation files (the "Software"), to deal 9 | # in the Software without restriction, including without limitation the rights 10 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | # copies of the Software, and to permit persons to whom the Software is 12 | # furnished to do so, subject to the following conditions: 13 | # 14 | # The above copyright notice and this permission notice shall be included in all 15 | # copies or substantial portions of the Software. 16 | # 17 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | # SOFTWARE. 24 | # 25 | # ----------------------------------------------------------------------------- 26 | # 27 | # 28 | # 29 | # 30 | # last updated 2015-06-28 by Ben Johnson bjohnson@bit9.com 31 | # 32 | 33 | 34 | try: 35 | from cbapi.legacy.util.cli_helpers import main_helper 36 | except ImportError: 37 | from cbapi.util.cli_helpers import main_helper 38 | 39 | def main(cb, args): 40 | for (proc, events) in cb.process_search_and_events_iter(r"process_name:cmd.exe (filemod:*.exe or filemod:*.dll)"): 41 | filemods = events.get('process', {}).get('filemod_complete', []) 42 | for filemod in filemods: 43 | 44 | print filemod 45 | # TODO -- figure out fields 46 | action, timestamp, filepath, md5, junk1, junk2 = filemod.split('|') 47 | 48 | filepath = filepath.lower() 49 | if not filepath.endswith(".exe") or not filepath.endswith(".dll"): 50 | continue 51 | 52 | if action == "1": 53 | action = "CREATE" 54 | elif action == "2": 55 | action = "MODIFY" 56 | elif action == "4": 57 | action = "DELETE" 58 | elif action == "8": 59 | action = "EXECUTABLE_WRITE" 60 | 61 | print "%s,%s,%s,%s,%s,%s" % (timestamp, proc['hostname'], proc['username'], proc['path'], filepath, action) 62 | 63 | if __name__ == "__main__": 64 | main_helper("Search for cmd.exe writing to exe and dll filepaths", main) 65 | -------------------------------------------------------------------------------- /data/autoruns_regexes.txt: -------------------------------------------------------------------------------- 1 | \\registry\\machine\\system\\currentcontrolset\\control\\session manager\\bootexecute(.*) 2 | \\registry\\machine\\system\\currentcontrolset\\services(.*) 3 | \\registry\\machine\\system\\currentcontrolset\\services(.*) 4 | \\registry\\machine\\software\\microsoft\\windows\\currentversion\\runservicesonce(.*) 5 | \\registry\\machine\\software\\microsoft\\windows\\currentversion\\runservices(.*) 6 | \\registry\\machine\\software\\microsoft\\windows nt\\currentversion\\winlogon\\notify(.*) 7 | \\registry\\machine\\software\\microsoft\\windows nt\\currentversion\\winlogon\\userinit(.*) 8 | \\registry\\machine\\software\\microsoft\\windows nt\\currentversion\\winlogon\\shell(.*) 9 | \\registry\\machine\\software\\microsoft\\windows\\currentversion\\shellserviceobjectdelayload(.*) 10 | \\registry\\machine\\software\\microsoft\\windows\\currentversion\\runonce(.*) 11 | \\registry\\machine\\software\\microsoft\\windows\\currentversion\\runonceex(.*) 12 | \\registry\\machine\\software\\microsoft\\windows\\currentversion\\run(.*) 13 | \\registry\\machine\\software\\microsoft\\windows\\currentversion\\policies\\explorer\\run(.*) 14 | \\registry\\machine\\software\\microsoft\\windows nt\\currentversion\\windows(.*) 15 | \\registry\\machine\\software\\microsoft\\windows\\currentversion\\explorer\\sharedtaskscheduler(.*) 16 | \\registry\\machine\\software\\microsoft\\windows nt\\currentversion\\windows\\appinit_dlls(.*) 17 | \\registry\\user\\(.*)\\software\\microsoft\\windows\\currentversion\\runservicesonce(.*) 18 | \\registry\\user\\(.*)\\software\\microsoft\\windows\\currentversion\\runservices(.*) 19 | \\registry\\user\\(.*)\\software\\microsoft\\windows nt\\currentversion\\winlogon\\shell(.*) 20 | \\registry\\user\\(.*)\\software\\microsoft\\windows\\currentversion\\run(.*) 21 | \\registry\\user\\(.*)\\software\\microsoft\\windows\\currentversion\\runonce(.*) 22 | \\registry\\user\\(.*)\\software\\microsoft\\windows\\currentversion\\policies\\explorer\\run(.*) 23 | \\registry\\user\\(.*)\\software\\microsoft\\windows nt\\currentversion\\windows\\load(.*) -------------------------------------------------------------------------------- /del_file.py: -------------------------------------------------------------------------------- 1 | try: 2 | from cbapi.legacy.util.cli_helpers import main_helper 3 | from cbapi.legacy.util.live_response_helpers import LiveResponseHelper 4 | except ImportError: 5 | from cbapi.util.cli_helpers import main_helper 6 | from cbapi.util.live_response_helpers import LiveResponseHelper 7 | 8 | def main(cb, args): 9 | filepath = args.get('filepath') 10 | sensor_id = int(args.get('sensorid')) 11 | lrh = LiveResponseHelper(cb, sensor_id) 12 | lrh.start() 13 | print "[*] Attempting to delete file: %s" % filepath 14 | results = lrh.del_file(filepath) 15 | print "\n[+] Results:\n============" 16 | for i in results: 17 | print i + ' = ' + str(results[i]) 18 | lrh.stop() 19 | 20 | if __name__ == "__main__": 21 | sensor_arg = ("-s", "--sensorid", "store", None, "sensorid", "Sensor id") 22 | file_arg = ("-f", "--filepath", "store", None, "filepath", "File Path") 23 | main_helper("Remove file from remote sensor", main, custom_required=[sensor_arg, file_arg]) 24 | -------------------------------------------------------------------------------- /download_sensor_installer.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # 3 | #The MIT License (MIT) 4 | # 5 | # Copyright (c) 2015 Bit9 + Carbon Black 6 | # 7 | # Permission is hereby granted, free of charge, to any person obtaining a copy 8 | # of this software and associated documentation files (the "Software"), to deal 9 | # in the Software without restriction, including without limitation the rights 10 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | # copies of the Software, and to permit persons to whom the Software is 12 | # furnished to do so, subject to the following conditions: 13 | # 14 | # The above copyright notice and this permission notice shall be included in all 15 | # copies or substantial portions of the Software. 16 | # 17 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | # SOFTWARE. 24 | # 25 | # ----------------------------------------------------------------------------- 26 | # 27 | # 28 | # 29 | # 30 | # last updated 2015-06-28 by Ben Johnson bjohnson@bit9.com 31 | # 32 | 33 | import sys 34 | import optparse 35 | import cbapi 36 | 37 | def build_cli_parser(): 38 | parser = optparse.OptionParser(usage="%prog [options]", description="Dump Binary Info") 39 | 40 | # for each supported output type, add an option 41 | # 42 | parser.add_option("-c", "--cburl", action="store", default=None, dest="url", 43 | help="CB server's URL. e.g., http://127.0.0.1 ") 44 | parser.add_option("-a", "--apitoken", action="store", default=None, dest="token", 45 | help="API Token for Carbon Black server") 46 | parser.add_option("-n", "--no-ssl-verify", action="store_false", default=True, dest="ssl_verify", 47 | help="Do not verify server SSL certificate.") 48 | parser.add_option("-t", "--installer-type", action="store", default=None, dest="type", 49 | help="Installer type; must be one of [WindowsEXE|WindowsMSI]") 50 | parser.add_option("-f", "--filename", action="store", default=None, dest="filename", 51 | help="Filename to save the installer package to") 52 | parser.add_option("-g", "--sensor-group", action="store", default="1", dest="group", 53 | help="Sensor group ID of the group to download an installer for") 54 | return parser 55 | 56 | def truncate(string, length): 57 | if len(string) + 2 > length: 58 | return string[:length] + "..." 59 | return string 60 | 61 | def main(argv): 62 | parser = build_cli_parser() 63 | opts, args = parser.parse_args(argv) 64 | if not opts.url or not opts.token or not opts.type or not opts.group or not opts.filename: 65 | print "Missing required param; run with --help for usage" 66 | sys.exit(-1) 67 | 68 | # build a cbapi object 69 | # 70 | cb = cbapi.CbApi(opts.url, token=opts.token, ssl_verify=opts.ssl_verify) 71 | 72 | # download the installer package 73 | # 74 | print "-> Downloading..." 75 | bytes = cb.sensor_installer(opts.type, opts.group) 76 | print "-> Sensor Installer Package is %s bytes" % (len(bytes)) 77 | print "-> Download complete" 78 | 79 | # save the instaler package to disk 80 | # 81 | print "-> Saving to %s..." % (opts.filename) 82 | open(opts.filename, 'wb').write(bytes) 83 | print "-> Complete" 84 | 85 | if __name__ == "__main__": 86 | sys.exit(main(sys.argv[1:])) 87 | -------------------------------------------------------------------------------- /enumerate_usb_devices.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # 3 | #The MIT License (MIT) 4 | # 5 | # Copyright (c) 2015 Bit9 + Carbon Black 6 | # 7 | # Permission is hereby granted, free of charge, to any person obtaining a copy 8 | # of this software and associated documentation files (the "Software"), to deal 9 | # in the Software without restriction, including without limitation the rights 10 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | # copies of the Software, and to permit persons to whom the Software is 12 | # furnished to do so, subject to the following conditions: 13 | # 14 | # The above copyright notice and this permission notice shall be included in all 15 | # copies or substantial portions of the Software. 16 | # 17 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | # SOFTWARE. 24 | # 25 | # ----------------------------------------------------------------------------- 26 | # 27 | # 28 | # 29 | # 30 | # last updated 2015-06-28 by Ben Johnson bjohnson@bit9.com 31 | # 32 | 33 | try: 34 | from cbapi.legacy.util.cli_helpers import main_helper 35 | except ImportError: 36 | from cbapi.util.cli_helpers import main_helper 37 | 38 | def main(cb, args): 39 | start = args.get('start') 40 | 41 | for (proc, events) in \ 42 | cb.process_search_and_events_iter( 43 | 'start:%s regmod:registry\\machine\\system\\currentcontrolset\\control\\deviceclasses\\{53f56307-b6bf-11d0-94f2-00a0c91efb8b}\\*' % start): 44 | 45 | for event in events.get('regmod_complete', []): 46 | fields = event.split('|') 47 | regpath = fields[2] 48 | if "{53f56307-b6bf-11d0-94f2-00a0c91efb8b}" in regpath: 49 | pieces = regpath.split("usbstor#disk&") 50 | if len(pieces) < 2: 51 | print "WARN::::", pieces 52 | else: 53 | device_info = pieces[1] #.split('{53f56307-b6bf-11d0-94f2-00a0c91efb8b}')[0] 54 | print device_info 55 | 56 | if __name__ == "__main__": 57 | required_arg = ("-s", "--start", "store", None, "start", "Process start time to query for, example, -2h for any processes started in past 2 hours") 58 | main_helper("Search for usb device usages", main, custom_required=[required_arg]) 59 | -------------------------------------------------------------------------------- /event_add.py: -------------------------------------------------------------------------------- 1 | __author__ = 'bwolfson' 2 | 3 | import sys 4 | import optparse 5 | 6 | # in the github repo, cbapi is not in the example directory 7 | sys.path.append('../src/cbapi') 8 | 9 | import cbapi 10 | 11 | def build_cli_parser(): 12 | parser = optparse.OptionParser(usage="%prog [options]", description="Add a tagged_event to the server") 13 | 14 | # for each supported output type, add an option 15 | # 16 | parser.add_option("-c", "--cburl", action="store", default=None, dest="server_url", 17 | help="CB server's URL. e.g., http://127.0.0.1 ") 18 | parser.add_option("-a", "--apitoken", action="store", default=None, dest="token", 19 | help="API Token for Carbon Black server") 20 | parser.add_option("-n", "--no-ssl-verify", action="store_false", default=True, dest="ssl_verify", 21 | help="Do not verify server SSL certificate.") 22 | parser.add_option("-i", "--investigation_id", action = "store", default = None, dest = "investigation_id", 23 | help = "ID of investigation to add this event to") 24 | parser.add_option("-d", "--description", action = "store", default="", dest="description", 25 | help="Description of the event, use quotes") 26 | parser.add_option("-s", "--start_date", action= "store", default = None, dest = "start_date", 27 | help = "start date for the event") 28 | return parser 29 | 30 | def main(argv): 31 | parser = build_cli_parser() 32 | opts, args = parser.parse_args(argv) 33 | if not opts.server_url or not opts.token or not opts.investigation_id or not opts.description or not opts.start_date: 34 | print "Missing required param; run with --help for usage" 35 | sys.exit(-1) 36 | 37 | # build a cbapi object 38 | # 39 | cb = cbapi.CbApi(opts.server_url, token=opts.token, ssl_verify=opts.ssl_verify) 40 | 41 | event = cb.event_add(opts.investigation_id, opts.description, opts.start_date) 42 | print "" 43 | print "-->Event Added:" 44 | for key in event.keys(): 45 | print "%-20s : %s" % (key, event[key]) 46 | 47 | if __name__ == "__main__": 48 | sys.exit(main(sys.argv[1:])) -------------------------------------------------------------------------------- /event_by_process_id.py: -------------------------------------------------------------------------------- 1 | __author__ = 'bwolfson' 2 | 3 | import sys 4 | import optparse 5 | 6 | # in the github repo, cbapi is not in the example directory 7 | sys.path.append('../src/cbapi') 8 | 9 | import cbapi 10 | 11 | def build_cli_parser(): 12 | parser = optparse.OptionParser(usage="%prog [options]", description="Get the info of the tagged_events for a certain investigation by process id") 13 | 14 | # for each supported output type, add an option 15 | # 16 | parser.add_option("-c", "--cburl", action="store", default=None, dest="server_url", 17 | help="CB server's URL. e.g., http://127.0.0.1 ") 18 | parser.add_option("-a", "--apitoken", action="store", default=None, dest="token", 19 | help="API Token for Carbon Black server") 20 | parser.add_option("-n", "--no-ssl-verify", action="store_false", default=True, dest="ssl_verify", 21 | help="Do not verify server SSL certificate.") 22 | parser.add_option("-i", "--id", action = "store", default = None, dest = "id", 23 | help = "process id of the event") 24 | return parser 25 | 26 | def main(argv): 27 | parser = build_cli_parser() 28 | opts, args = parser.parse_args(argv) 29 | if not opts.server_url or not opts.token or not opts.id: 30 | print "Missing required param; run with --help for usage" 31 | sys.exit(-1) 32 | 33 | # build a cbapi object 34 | # 35 | 36 | cb = cbapi.CbApi(opts.server_url, token=opts.token, ssl_verify=opts.ssl_verify) 37 | 38 | event = cb.event_by_process_id(opts.id) 39 | for key in event.keys(): 40 | print "%-20s : %s" % (key, event[key]) 41 | 42 | 43 | if __name__ == "__main__": 44 | sys.exit(main(sys.argv[1:])) 45 | -------------------------------------------------------------------------------- /event_del.py: -------------------------------------------------------------------------------- 1 | __author__ = 'bwolfson' 2 | 3 | import sys 4 | import optparse 5 | 6 | # in the github repo, cbapi is not in the example directory 7 | sys.path.append('../src/cbapi') 8 | 9 | import cbapi 10 | 11 | def build_cli_parser(): 12 | parser = optparse.OptionParser(usage="%prog [options]", description="Delete a tagged event from the server") 13 | 14 | # for each supported output type, add an option 15 | # 16 | parser.add_option("-c", "--cburl", action="store", default=None, dest="server_url", 17 | help="CB server's URL. e.g., http://127.0.0.1 ") 18 | parser.add_option("-a", "--apitoken", action="store", default=None, dest="token", 19 | help="API Token for Carbon Black server") 20 | parser.add_option("-n", "--no-ssl-verify", action="store_false", default=True, dest="ssl_verify", 21 | help="Do not verify server SSL certificate.") 22 | parser.add_option("-i", "--id", action = "store", default = None, dest = "id", 23 | help = "id of the investigation this event is for") 24 | return parser 25 | 26 | def main(argv): 27 | parser = build_cli_parser() 28 | opts, args = parser.parse_args(argv) 29 | if not opts.server_url or not opts.token or not opts.id: 30 | print "Missing required param; run with --help for usage" 31 | sys.exit(-1) 32 | 33 | # build a cbapi object 34 | # 35 | 36 | cb = cbapi.CbApi(opts.server_url, token=opts.token, ssl_verify=opts.ssl_verify) 37 | 38 | event = cb.event_del(opts.id) 39 | print "" 40 | for key in event.keys(): 41 | print "%-20s : %s" % (key, event[key]) 42 | 43 | if __name__ == "__main__": 44 | sys.exit(main(sys.argv[1:])) -------------------------------------------------------------------------------- /event_info.py: -------------------------------------------------------------------------------- 1 | __author__ = 'bwolfson' 2 | 3 | import sys 4 | import optparse 5 | 6 | # in the github repo, cbapi is not in the example directory 7 | sys.path.append('../src/cbapi') 8 | 9 | import cbapi 10 | 11 | def build_cli_parser(): 12 | parser = optparse.OptionParser(usage="%prog [options]", description="Get the info of the tagged_events for a certain investigation") 13 | 14 | # for each supported output type, add an option 15 | # 16 | parser.add_option("-c", "--cburl", action="store", default=None, dest="server_url", 17 | help="CB server's URL. e.g., http://127.0.0.1 ") 18 | parser.add_option("-a", "--apitoken", action="store", default=None, dest="token", 19 | help="API Token for Carbon Black server") 20 | parser.add_option("-n", "--no-ssl-verify", action="store_false", default=True, dest="ssl_verify", 21 | help="Do not verify server SSL certificate.") 22 | parser.add_option("-i", "--id", action = "store", default = None, dest = "id", 23 | help = "id of the investigation this event is for") 24 | return parser 25 | 26 | def main(argv): 27 | parser = build_cli_parser() 28 | opts, args = parser.parse_args(argv) 29 | if not opts.server_url or not opts.token or not opts.id: 30 | print "Missing required param; run with --help for usage" 31 | sys.exit(-1) 32 | 33 | # build a cbapi object 34 | # 35 | 36 | cb = cbapi.CbApi(opts.server_url, token=opts.token, ssl_verify=opts.ssl_verify) 37 | 38 | events = cb.event_info(opts.id) 39 | print events 40 | print "" 41 | count = 1 42 | for event in events: 43 | print "" 44 | print "Event Number: %s" % count 45 | count = count + 1 46 | for field in event: 47 | print "%-20s : %s" % (field, event[field]) 48 | 49 | 50 | if __name__ == "__main__": 51 | sys.exit(main(sys.argv[1:])) -------------------------------------------------------------------------------- /event_update.py: -------------------------------------------------------------------------------- 1 | __author__ = 'bwolfson' 2 | 3 | import sys 4 | import optparse 5 | 6 | # in the github repo, cbapi is not in the example directory 7 | sys.path.append('../src/cbapi') 8 | 9 | import cbapi 10 | 11 | def build_cli_parser(): 12 | parser = optparse.OptionParser(usage="%prog [options]", description="Update a tagged_event's description") 13 | 14 | # for each supported output type, add an option 15 | # 16 | parser.add_option("-c", "--cburl", action="store", default=None, dest="server_url", 17 | help="CB server's URL. e.g., http://127.0.0.1 ") 18 | parser.add_option("-a", "--apitoken", action="store", default=None, dest="token", 19 | help="API Token for Carbon Black server") 20 | parser.add_option("-n", "--no-ssl-verify", action="store_false", default=True, dest="ssl_verify", 21 | help="Do not verify server SSL certificate.") 22 | parser.add_option("-i", "--id", action = "store", default = None, dest = "id", 23 | help = "id of the investigation this event is for") 24 | parser.add_option("-d", "--description", action = "store", default = "", dest = "description", 25 | help = "Updated description for the event") 26 | return parser 27 | 28 | def main(argv): 29 | parser = build_cli_parser() 30 | opts, args = parser.parse_args(argv) 31 | if not opts.server_url or not opts.token or not opts.id or not opts.description: 32 | print "Missing required param; run with --help for usage" 33 | sys.exit(-1) 34 | 35 | # build a cbapi object 36 | # 37 | 38 | cb = cbapi.CbApi(opts.server_url, token=opts.token, ssl_verify=opts.ssl_verify) 39 | 40 | event = cb.event_update(opts.id, opts.description) 41 | print "" 42 | for key in event.keys(): 43 | print "%-20s : %s" % (key, event[key]) 44 | 45 | if __name__ == "__main__": 46 | sys.exit(main(sys.argv[1:])) -------------------------------------------------------------------------------- /feed_action_add.py: -------------------------------------------------------------------------------- 1 | __author__ = 'bwolfson' 2 | 3 | import sys 4 | import optparse 5 | 6 | # in the github repo, cbapi is not in the example directory 7 | sys.path.append('../src/cbapi') 8 | 9 | import cbapi 10 | 11 | def build_cli_parser(): 12 | parser = optparse.OptionParser(usage="%prog [options]", description="Add an action to a feed on the CB server") 13 | 14 | # for each supported output type, add an option 15 | # 16 | parser.add_option("-c", "--cburl", action="store", default=None, dest="server_url", 17 | help="CB server's URL. e.g., http://127.0.0.1 ") 18 | parser.add_option("-a", "--apitoken", action="store", default=None, dest="token", 19 | help="API Token for Carbon Black server") 20 | parser.add_option("-n", "--no-ssl-verify", action="store_false", default=True, dest="ssl_verify", 21 | help="Do not verify server SSL certificate.") 22 | parser.add_option("-i", "--id", action = "store", default = None, dest = "id", 23 | help = "id of the feed") 24 | parser.add_option("-t", "--action_type", action = "store", default = None, dest = "action_type_id", 25 | help = "id for the type of action to enable: Type 0 for email, 1 to write to " 26 | "syslog, and 3 to create alert") 27 | parser.add_option("-e", "--email_recipients", action = "store", default = None, dest = "email_recipients", 28 | help = "list of user ids of email recipients") 29 | return parser 30 | 31 | def main(argv): 32 | parser = build_cli_parser() 33 | opts, args = parser.parse_args(argv) 34 | if not opts.server_url or not opts.token or not opts.id or not opts.action_type_id or not opts.email_recipients: 35 | print "Missing required param; run with --help for usage" 36 | sys.exit(-1) 37 | 38 | # build a cbapi object 39 | # 40 | cb = cbapi.CbApi(opts.server_url, token=opts.token, ssl_verify=opts.ssl_verify) 41 | 42 | #Check to make sure the user supplies a correct action_type_id 43 | type = opts.action_type_id 44 | if not (int(type) == int(0) or int(type) == int(1) or int(type) == int(3)): 45 | print "action_type_id must be either 0,1,or 3" 46 | sys.exit(-1) 47 | 48 | #Check to make sure the action isn't already enabled 49 | curr_actions = cb.feed_action_enum(opts.id) 50 | for action in curr_actions: 51 | if int(action['action_type']) == int(opts.action_type_id): 52 | print "action already enabled" 53 | sys.exit(-1) 54 | else: 55 | continue 56 | 57 | action = cb.feed_action_add(opts.id, opts.action_type_id, opts.email_recipients) 58 | 59 | for key in action.keys(): 60 | print "%-20s : %s" % (key, action[key]) 61 | 62 | if __name__ == "__main__": 63 | sys.exit(main(sys.argv[1:])) -------------------------------------------------------------------------------- /feed_action_del.py: -------------------------------------------------------------------------------- 1 | __author__ = 'bwolfson' 2 | 3 | 4 | import sys 5 | import optparse 6 | 7 | # in the github repo, cbapi is not in the example directory 8 | sys.path.append('../src/cbapi') 9 | 10 | import cbapi 11 | 12 | def build_cli_parser(): 13 | parser = optparse.OptionParser(usage="%prog [options]", description="Delete a certain action of a specified feed from the server") 14 | 15 | # for each supported output type, add an option 16 | # 17 | parser.add_option("-c", "--cburl", action="store", default=None, dest="server_url", 18 | help="CB server's URL. e.g., http://127.0.0.1 ") 19 | parser.add_option("-a", "--apitoken", action="store", default=None, dest="token", 20 | help="API Token for Carbon Black server") 21 | parser.add_option("-n", "--no-ssl-verify", action="store_false", default=True, dest="ssl_verify", 22 | help="Do not verify server SSL certificate.") 23 | parser.add_option("-i", "--id", action = "store", default = None, dest = "id", 24 | help = "id of the feed") 25 | parser.add_option("-d", "--action_id", action = "store", default = None, dest = "action_id", 26 | help = "id of the action to be deleted") 27 | return parser 28 | 29 | def main(argv): 30 | parser = build_cli_parser() 31 | opts, args = parser.parse_args(argv) 32 | if not opts.server_url or not opts.token or not opts.id or not opts.action_id: 33 | print "Missing required param; run with --help for usage" 34 | sys.exit(-1) 35 | 36 | # build a cbapi object 37 | # 38 | 39 | cb = cbapi.CbApi(opts.server_url, token=opts.token, ssl_verify=opts.ssl_verify) 40 | 41 | result = cb.feed_action_del(opts.id, opts.action_id) 42 | print result 43 | 44 | if __name__ == "__main__": 45 | sys.exit(main(sys.argv[1:])) -------------------------------------------------------------------------------- /feed_action_enum.py: -------------------------------------------------------------------------------- 1 | __author__ = 'bwolfson' 2 | 3 | import sys 4 | import optparse 5 | 6 | # in the github repo, cbapi is not in the example directory 7 | sys.path.append('../src/cbapi') 8 | 9 | import cbapi 10 | 11 | def build_cli_parser(): 12 | parser = optparse.OptionParser(usage="%prog [options]", description="Get the actions associated with a certain feed") 13 | 14 | # for each supported output type, add an option 15 | # 16 | parser.add_option("-c", "--cburl", action="store", default=None, dest="server_url", 17 | help="CB server's URL. e.g., http://127.0.0.1 ") 18 | parser.add_option("-a", "--apitoken", action="store", default=None, dest="token", 19 | help="API Token for Carbon Black server") 20 | parser.add_option("-n", "--no-ssl-verify", action="store_false", default=True, dest="ssl_verify", 21 | help="Do not verify server SSL certificate.") 22 | parser.add_option("-i", "--id", action = "store", default = None, dest = "id", 23 | help = "id of the feed") 24 | return parser 25 | 26 | def main(argv): 27 | parser = build_cli_parser() 28 | opts, args = parser.parse_args(argv) 29 | if not opts.server_url or not opts.token or not opts.id: 30 | print "Missing required param; run with --help for usage" 31 | sys.exit(-1) 32 | 33 | # build a cbapi object 34 | # 35 | 36 | cb = cbapi.CbApi(opts.server_url, token=opts.token, ssl_verify=opts.ssl_verify) 37 | 38 | actions = cb.feed_action_enum(opts.id) 39 | count = 1 40 | for action in actions: 41 | print "" 42 | print "Action number: %s" % count 43 | print "-"*50 44 | count += 1 45 | for key in action.keys(): 46 | print "%-20s : %s" % (key, action[key]) 47 | 48 | if __name__ == "__main__": 49 | sys.exit(main(sys.argv[1:])) -------------------------------------------------------------------------------- /feed_action_update.py: -------------------------------------------------------------------------------- 1 | __author__ = 'bwolfson' 2 | 3 | import sys 4 | import optparse 5 | 6 | # in the github repo, cbapi is not in the example directory 7 | sys.path.append('../src/cbapi') 8 | 9 | import cbapi 10 | 11 | def build_cli_parser(): 12 | parser = optparse.OptionParser(usage="%prog [options]", description="Update a certain feed action (Change to a different" 13 | "type of action") 14 | 15 | # for each supported output type, add an option 16 | # 17 | parser.add_option("-c", "--cburl", action="store", default=None, dest="server_url", 18 | help="CB server's URL. e.g., http://127.0.0.1 ") 19 | parser.add_option("-a", "--apitoken", action="store", default=None, dest="token", 20 | help="API Token for Carbon Black server") 21 | parser.add_option("-n", "--no-ssl-verify", action="store_false", default=True, dest="ssl_verify", 22 | help="Do not verify server SSL certificate.") 23 | parser.add_option("-i", "--id", action = "store", default = None, dest = "id", 24 | help = "id of the feed") 25 | parser.add_option("-d", "--action_id", action = "store", default = None, dest = "action_id", 26 | help = "id of the action to be deleted") 27 | parser.add_option("-t", "--action_type", action = "store", type = int, default = None, dest = "action_type_id", 28 | help = "new type of action, type 0 for email, 1 for write to syslog, 3 for create alert") 29 | return parser 30 | 31 | def main(argv): 32 | parser = build_cli_parser() 33 | opts, args = parser.parse_args(argv) 34 | if not opts.server_url or not opts.token or not opts.id or not opts.action_id or not opts.action_type_id: 35 | print "Missing required param; run with --help for usage" 36 | sys.exit(-1) 37 | 38 | # build a cbapi object 39 | # 40 | 41 | cb = cbapi.CbApi(opts.server_url, token=opts.token, ssl_verify=opts.ssl_verify) 42 | 43 | #Check to make sure the user supplies a correct action_type_id 44 | # 45 | 46 | type = opts.action_type_id 47 | if not (int(type) == int(0) or int(type) == int(1) or int(type) == int(3)): 48 | print "action_type_id must be either 0,1,or 3" 49 | sys.exit(-1) 50 | 51 | #Check to make sure the action isn't already enabled 52 | # 53 | 54 | curr_actions = cb.feed_action_enum(opts.id) 55 | for action in curr_actions: 56 | if int(action['action_type']) == int(opts.action_type_id): 57 | print "action already enabled" 58 | sys.exit(-1) 59 | else: 60 | continue 61 | 62 | result = cb.feed_action_update(opts.id, opts.action_id, opts.action_type_id) 63 | print result 64 | 65 | if __name__ == "__main__": 66 | sys.exit(main(sys.argv[1:])) -------------------------------------------------------------------------------- /feed_cert.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # 3 | #The MIT License (MIT) 4 | # 5 | # Copyright (c) 2015 Bit9 + Carbon Black 6 | # 7 | # Permission is hereby granted, free of charge, to any person obtaining a copy 8 | # of this software and associated documentation files (the "Software"), to deal 9 | # in the Software without restriction, including without limitation the rights 10 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | # copies of the Software, and to permit persons to whom the Software is 12 | # furnished to do so, subject to the following conditions: 13 | # 14 | # The above copyright notice and this permission notice shall be included in all 15 | # copies or substantial portions of the Software. 16 | # 17 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | # SOFTWARE. 24 | # 25 | # ----------------------------------------------------------------------------- 26 | # 27 | # 28 | # 29 | # 30 | # last updated 2015-06-28 by Ben Johnson bjohnson@bit9.com 31 | # 32 | 33 | import sys 34 | import optparse 35 | import cbapi 36 | 37 | def build_cli_parser(): 38 | parser = optparse.OptionParser(usage="%prog [options]", description="Configure SSL client certificate authentication for feeds") 39 | 40 | # for each supported output type, add an option 41 | # 42 | parser.add_option("-c", "--cburl", action="store", default=None, dest="server_url", 43 | help="CB server's URL. e.g., http://127.0.0.1 ") 44 | parser.add_option("-a", "--apitoken", action="store", default=None, dest="token", 45 | help="API Token for Carbon Black server") 46 | parser.add_option("-n", "--no-ssl-verify", action="store_false", default=True, dest="ssl_verify", 47 | help="Do not verify server SSL certificate.") 48 | parser.add_option("-i", "--id", action="store", default=None, dest="id", 49 | help="Feed Id") 50 | parser.add_option("-r", "--remove", action="store_true", default=False, dest="remove", 51 | help="Remove SSL client certificate authentication for the feed specified with -i") 52 | parser.add_option("-C", "--certificate", action="store", default=None, dest="certificate", 53 | help="SSL client certificate filename; expected to begin with \"-----BEGIN CERTIFICATE-----\"") 54 | parser.add_option("-K", "--key", action="store", default=None, dest="key", 55 | help="SSL client key filename; expected to begin with \"-----BEGIN RSA PRIVATE KEY-----\"") 56 | return parser 57 | 58 | def main(argv): 59 | parser = build_cli_parser() 60 | opts, args = parser.parse_args(argv) 61 | 62 | if not opts.server_url or not opts.token: 63 | print "Must specify a CB server and API token with -c and -a" 64 | sys.exit(-1) 65 | 66 | if not opts.id: 67 | print "Must specify a feed id" 68 | sys.exit(-1) 69 | 70 | if not opts.remove and not (opts.certificate and opts.key): 71 | print "Missing required param; run with --help for usage" 72 | print "Either -C AND -K must be specified (to add SSL client certificates to a feed) or -r must be specified" 73 | sys.exit(-1) 74 | 75 | # build a cbapi object 76 | # 77 | cb = cbapi.CbApi(opts.server_url, token=opts.token, ssl_verify=opts.ssl_verify) 78 | 79 | feed = {"id": opts.id} 80 | 81 | if opts.remove: 82 | feed["ssl_client_crt"] = "" 83 | feed["ssl_client_key"] = "" 84 | else: 85 | feed["ssl_client_crt"] = open(opts.certificate).read().strip() 86 | feed["ssl_client_key"] = open(opts.key).read().strip() 87 | 88 | cb.feed_modify(opts.id, feed) 89 | 90 | print "-> Success!" 91 | 92 | if __name__ == "__main__": 93 | sys.exit(main(sys.argv[1:])) 94 | -------------------------------------------------------------------------------- /feed_del.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # 3 | #The MIT License (MIT) 4 | # 5 | # Copyright (c) 2015 Bit9 + Carbon Black 6 | # 7 | # Permission is hereby granted, free of charge, to any person obtaining a copy 8 | # of this software and associated documentation files (the "Software"), to deal 9 | # in the Software without restriction, including without limitation the rights 10 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | # copies of the Software, and to permit persons to whom the Software is 12 | # furnished to do so, subject to the following conditions: 13 | # 14 | # The above copyright notice and this permission notice shall be included in all 15 | # copies or substantial portions of the Software. 16 | # 17 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | # SOFTWARE. 24 | # 25 | # ----------------------------------------------------------------------------- 26 | # 27 | # 28 | # 29 | # 30 | # last updated 2015-06-28 by Ben Johnson bjohnson@bit9.com 31 | # 32 | 33 | import sys 34 | import optparse 35 | import cbapi 36 | 37 | def build_cli_parser(): 38 | parser = optparse.OptionParser(usage="%prog [options]", description="Delete an existing feed") 39 | 40 | # for each supported output type, add an option 41 | # 42 | parser.add_option("-c", "--cburl", action="store", default=None, dest="server_url", 43 | help="CB server's URL. e.g., http://127.0.0.1 ") 44 | parser.add_option("-a", "--apitoken", action="store", default=None, dest="token", 45 | help="API Token for Carbon Black server") 46 | parser.add_option("-n", "--no-ssl-verify", action="store_false", default=True, dest="ssl_verify", 47 | help="Do not verify server SSL certificate.") 48 | parser.add_option("-f", "--feedname", action="store", default=None, dest="feedname", 49 | help="Feed Name") 50 | parser.add_option("-i", "--id", action="store", default=None, dest="feedid", 51 | help="Feed Id") 52 | return parser 53 | 54 | def main(argv): 55 | parser = build_cli_parser() 56 | opts, args = parser.parse_args(argv) 57 | if not opts.server_url or not opts.token or (not opts.feedname and not opts.feedid): 58 | print "Missing required param; run with --help for usage" 59 | print "One of -f or -i must be specified" 60 | sys.exit(-1) 61 | 62 | # build a cbapi object 63 | # 64 | cb = cbapi.CbApi(opts.server_url, token=opts.token, ssl_verify=opts.ssl_verify) 65 | 66 | if not opts.feedid: 67 | id = cb.feed_get_id_by_name(opts.feedname) 68 | if id is None: 69 | print "-> No configured feed with name '%s' found!" % (opts.feedname) 70 | return 71 | else: 72 | id = opts.feedid 73 | 74 | # delete the feed 75 | # 76 | cb.feed_del(id) 77 | 78 | print "-> Feed deleted [id=%s]" % (id,) 79 | 80 | if __name__ == "__main__": 81 | sys.exit(main(sys.argv[1:])) 82 | -------------------------------------------------------------------------------- /feed_enum.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # 3 | #The MIT License (MIT) 4 | # 5 | # Copyright (c) 2015 Bit9 + Carbon Black 6 | # 7 | # Permission is hereby granted, free of charge, to any person obtaining a copy 8 | # of this software and associated documentation files (the "Software"), to deal 9 | # in the Software without restriction, including without limitation the rights 10 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | # copies of the Software, and to permit persons to whom the Software is 12 | # furnished to do so, subject to the following conditions: 13 | # 14 | # The above copyright notice and this permission notice shall be included in all 15 | # copies or substantial portions of the Software. 16 | # 17 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | # SOFTWARE. 24 | # 25 | # ----------------------------------------------------------------------------- 26 | # 27 | # 28 | # 29 | # 30 | # last updated 2015-06-28 by Ben Johnson bjohnson@bit9.com 31 | # 32 | 33 | import sys 34 | import optparse 35 | import cbapi 36 | 37 | def build_cli_parser(): 38 | parser = optparse.OptionParser(usage="%prog [options]", description="Enumerate all configured feeds") 39 | 40 | # for each supported output type, add an option 41 | # 42 | parser.add_option("-c", "--cburl", action="store", default=None, dest="server_url", 43 | help="CB server's URL. e.g., http://127.0.0.1 ") 44 | parser.add_option("-a", "--apitoken", action="store", default=None, dest="token", 45 | help="API Token for Carbon Black server") 46 | parser.add_option("-n", "--no-ssl-verify", action="store_false", default=True, dest="ssl_verify", 47 | help="Do not verify server SSL certificate.") 48 | return parser 49 | 50 | def main(argv): 51 | parser = build_cli_parser() 52 | opts, args = parser.parse_args(argv) 53 | if not opts.server_url or not opts.token: 54 | print "Missing required param; run with --help for usage" 55 | sys.exit(-1) 56 | 57 | # build a cbapi object 58 | # 59 | cb = cbapi.CbApi(opts.server_url, token=opts.token, ssl_verify=opts.ssl_verify) 60 | 61 | # enumerate configured feeds 62 | # 63 | feeds = cb.feed_enum() 64 | 65 | # output a banner 66 | # 67 | print "%-3s %-25s %-8s %s" % ("Id", "Name", "Enabled", "Url") 68 | print "%s+%s+%s+%s" % ("-"*3, "-"*27, "-"*10, "-"*31) 69 | 70 | # output a row about each feed 71 | # 72 | for feed in feeds: 73 | print "%-3s| %-25s | %-8s | %s" % (feed['id'], feed['name'], feed['enabled'], feed['feed_url']) 74 | 75 | if __name__ == "__main__": 76 | sys.exit(main(sys.argv[1:])) 77 | -------------------------------------------------------------------------------- /feed_info.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # 3 | #The MIT License (MIT) 4 | # 5 | # Copyright (c) 2015 Bit9 + Carbon Black 6 | # 7 | # Permission is hereby granted, free of charge, to any person obtaining a copy 8 | # of this software and associated documentation files (the "Software"), to deal 9 | # in the Software without restriction, including without limitation the rights 10 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | # copies of the Software, and to permit persons to whom the Software is 12 | # furnished to do so, subject to the following conditions: 13 | # 14 | # The above copyright notice and this permission notice shall be included in all 15 | # copies or substantial portions of the Software. 16 | # 17 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | # SOFTWARE. 24 | # 25 | # ----------------------------------------------------------------------------- 26 | # 27 | # 28 | # 29 | # 30 | # last updated 2015-06-28 by Ben Johnson bjohnson@bit9.com 31 | # 32 | 33 | import sys 34 | import optparse 35 | import cbapi 36 | 37 | def build_cli_parser(): 38 | parser = optparse.OptionParser(usage="%prog [options]", description="Display information about an existing feed") 39 | 40 | # for each supported output type, add an option 41 | # 42 | parser.add_option("-c", "--cburl", action="store", default=None, dest="server_url", 43 | help="CB server's URL. e.g., http://127.0.0.1 ") 44 | parser.add_option("-a", "--apitoken", action="store", default=None, dest="token", 45 | help="API Token for Carbon Black server") 46 | parser.add_option("-n", "--no-ssl-verify", action="store_false", default=True, dest="ssl_verify", 47 | help="Do not verify server SSL certificate.") 48 | parser.add_option("-f", "--feedname", action="store", default=None, dest="feedname", 49 | help="Feed Name") 50 | parser.add_option("-i", "--id", action="store", default=None, dest="feedid", 51 | help="Feed Id") 52 | return parser 53 | 54 | def output_feed_info(feed): 55 | print "%s" % (feed['name']) 56 | print "%s" % ('-' * 80,) 57 | for key in feed.keys(): 58 | if not 'icon' == key: 59 | print "%-20s : %s" % (key, feed[key]) 60 | 61 | def main(argv): 62 | parser = build_cli_parser() 63 | opts, args = parser.parse_args(argv) 64 | if not opts.server_url or not opts.token or (not opts.feedname and not opts.feedid): 65 | print "Missing required param; run with --help for usage" 66 | print "One of -f or -i must be specified" 67 | sys.exit(-1) 68 | 69 | # build a cbapi object 70 | # 71 | cb = cbapi.CbApi(opts.server_url, token=opts.token, ssl_verify=opts.ssl_verify) 72 | 73 | if not opts.feedid: 74 | id = cb.feed_get_id_by_name(opts.feedname) 75 | if id is None: 76 | print "-> No configured feed with name '%s' found!" % (opts.feedname) 77 | return 78 | else: 79 | id = opts.feedid 80 | 81 | output_feed_info(cb.feed_info(id)) 82 | 83 | if __name__ == "__main__": 84 | sys.exit(main(sys.argv[1:])) 85 | -------------------------------------------------------------------------------- /feed_ioc_cleaner/bad_iocs.txt: -------------------------------------------------------------------------------- 1 | d41d8cd98f00b204e9800998ecf8427e 2 | 127.0.0.1 3 | 10.0.0.10 4 | google.com 5 | crl.microsoft.com 6 | -------------------------------------------------------------------------------- /feed_modify.py: -------------------------------------------------------------------------------- 1 | __author__ = 'bwolfson' 2 | 3 | import sys 4 | import optparse 5 | 6 | # in the github repo, cbapi is not in the example directory 7 | sys.path.append('../src/cbapi') 8 | 9 | import cbapi 10 | 11 | def build_cli_parser(): 12 | parser = optparse.OptionParser(usage="%prog [options]", description="Modify an existing feed") 13 | 14 | # for each supported output type, add an option 15 | # 16 | parser.add_option("-c", "--cburl", action="store", default=None, dest="server_url", 17 | help="CB server's URL. e.g., http://127.0.0.1 ") 18 | parser.add_option("-a", "--apitoken", action="store", default=None, dest="token", 19 | help="API Token for Carbon Black server") 20 | parser.add_option("-n", "--no-ssl-verify", action="store_false", default=True, dest="ssl_verify", 21 | help="Do not verify server SSL certificate.") 22 | parser.add_option("-f", "--feedname", action="store", default=None, dest="feedname", 23 | help="Feed Name") 24 | parser.add_option("-i", "--id", action="store", default=None, dest="feedid", 25 | help="Feed Id") 26 | return parser 27 | 28 | def main(argv): 29 | parser = build_cli_parser() 30 | opts, args = parser.parse_args(argv) 31 | if not opts.server_url or not opts.token or (not opts.feedname and not opts.feedid): 32 | print "Missing required param; run with --help for usage" 33 | print "One of -f or -i must be specified" 34 | sys.exit(-1) 35 | 36 | # build a cbapi object 37 | # 38 | cb = cbapi.CbApi(opts.server_url, token=opts.token, ssl_verify=opts.ssl_verify) 39 | 40 | if not opts.feedid: 41 | id = cb.feed_get_id_by_name(opts.feedname) 42 | if id is None: 43 | print "-> No configured feed with name '%s' found!" % (opts.feedname) 44 | return 45 | else: 46 | id = opts.feedid 47 | old_feed = cb.feed_info(id) 48 | 49 | #create a new updated feed based on user input 50 | 51 | # create 52 | if __name__ == "__main__": 53 | sys.exit(main(sys.argv[1:])) -------------------------------------------------------------------------------- /feed_report_info.py: -------------------------------------------------------------------------------- 1 | import sys 2 | import time 3 | import struct 4 | import socket 5 | import pprint 6 | import optparse 7 | 8 | # in the github repo, cbapi is not in the example directory 9 | sys.path.append('../src/cbapi') 10 | 11 | import cbapi 12 | 13 | def build_cli_parser(): 14 | parser = optparse.OptionParser(usage="%prog [options]", description="Display information about a particular feed report") 15 | 16 | # for each supported output type, add an option 17 | # 18 | parser.add_option("-c", "--cburl", action="store", default=None, dest="server_url", 19 | help="CB server's URL. e.g., http://127.0.0.1 ") 20 | parser.add_option("-a", "--apitoken", action="store", default=None, dest="token", 21 | help="API Token for Carbon Black server") 22 | parser.add_option("-n", "--no-ssl-verify", action="store_false", default=True, dest="ssl_verify", 23 | help="Do not verify server SSL certificate.") 24 | parser.add_option("-i", "--id", action="store", default=None, dest="feedid", 25 | help="Id of feed of which the specified report is a part of") 26 | parser.add_option("-r", "--reportid", action="store", default=None, dest="reportid", 27 | help="Id of report to query; this may be alphanumeric") 28 | return parser 29 | 30 | def get_ioc_counts(iocs): 31 | """ 32 | returns counts of md5s, ipv4s, domains, and queries as a tuple given a feed report ioc block 33 | """ 34 | return len(iocs.get('md5', [])), \ 35 | len(iocs.get('ipv4', [])), \ 36 | len(iocs.get('dns', [])), \ 37 | len(iocs.get('query', [])) 38 | 39 | def main(argv): 40 | parser = build_cli_parser() 41 | opts, args = parser.parse_args(argv) 42 | if not opts.server_url or not opts.token or not opts.feedid or not opts.reportid: 43 | print "Missing required param; run with --help for usage" 44 | sys.exit(-1) 45 | 46 | # build a cbapi object 47 | # 48 | cb = cbapi.CbApi(opts.server_url, token=opts.token, ssl_verify=opts.ssl_verify) 49 | 50 | # retrieve threat report 51 | # 52 | report = cb.feed_report_info(opts.feedid, opts.reportid) 53 | 54 | # get ioc counts 55 | # 56 | count_md5s, count_ipv4s, count_domains, count_queries = get_ioc_counts(report.get('iocs', {})) 57 | 58 | # output the threat report details 59 | # 60 | print report["title"] 61 | print "-" * 80 62 | print 63 | 64 | print " Report Summary" 65 | print " %s" % ("-" * 78) 66 | print " %-20s : %s" % ("Score", report["score"]) 67 | print " %-20s : %s" % ("Report Id", report["id"]) 68 | print " %-20s : %s" % ("Link", report["link"]) 69 | print " %-20s : %s" % ("Report Timestamp", time.strftime('%Y-%m-%d %H:%M:%S GMT', time.localtime(report["timestamp"]))) 70 | print " %-20s : %s" % ("Total IOC count", count_md5s + count_ipv4s + count_domains + count_queries) 71 | print 72 | 73 | print " Feed Details" 74 | print " %s" % ("-" * 78) 75 | print " %-20s : %s" % ("Feed Name", report["feed_name"]) 76 | print " %-20s : %s" % ("Feed Id", report["feed_id"]) 77 | print 78 | 79 | print " Report IOCs" 80 | print " %s" % ("-" * 78) 81 | print 82 | 83 | if count_md5s > 0: 84 | print " MD5" 85 | print " %s" % ("-" * 76) 86 | for md5 in report["iocs"]["md5"]: 87 | print " %s" % md5 88 | print 89 | 90 | if count_ipv4s > 0: 91 | print " IPv4" 92 | print " %s" % ("-" * 76) 93 | for ipv4 in report["iocs"]["ipv4"]: 94 | print " %s" % ipv4 95 | print 96 | 97 | if count_domains > 0: 98 | print " Domain" 99 | print " %s" % ("-" * 76) 100 | for domain in report["iocs"]["dns"]: 101 | print " %s" % domain 102 | print 103 | 104 | if count_queries > 0: 105 | print " Query" 106 | print " %s" % ("-" * 76) 107 | print " %-18s : %s" % ("Query", report["iocs"]["query"][0]["search_query"]) 108 | print " %-18s : %s" % ("Index Type", report["iocs"]["query"][0]["index_type"]) 109 | print 110 | 111 | if __name__ == "__main__": 112 | sys.exit(main(sys.argv[1:])) 113 | -------------------------------------------------------------------------------- /feed_report_stats.py: -------------------------------------------------------------------------------- 1 | __author__ = 'bwolfson' 2 | 3 | import sys 4 | import optparse 5 | 6 | # in the github repo, cbapi is not in the example directory 7 | sys.path.append('../src/cbapi') 8 | 9 | import cbapi 10 | 11 | def build_cli_parser(): 12 | parser = optparse.OptionParser(usage="%prog [options]", description="Get the a report's info from a configured feed") 13 | 14 | # for each supported output type, add an option 15 | # 16 | parser.add_option("-c", "--cburl", action="store", default=None, dest="server_url", 17 | help="CB server's URL. e.g., http://127.0.0.1 ") 18 | parser.add_option("-a", "--apitoken", action="store", default=None, dest="token", 19 | help="API Token for Carbon Black server") 20 | parser.add_option("-n", "--no-ssl-verify", action="store_false", default=True, dest="ssl_verify", 21 | help="Do not verify server SSL certificate.") 22 | parser.add_option("-i", "--id", action="store", default=None, dest="id", 23 | help="Feed id") 24 | parser.add_option("-r", "--report_id", action = "store", default = None, dest = "reportid", 25 | help = "Report id") 26 | return parser 27 | 28 | def main(argv): 29 | parser = build_cli_parser() 30 | opts, args = parser.parse_args(argv) 31 | if not opts.server_url or not opts.token or not opts.id or not opts.reportid: 32 | print "Missing required param; run with --help for usage" 33 | sys.exit(-1) 34 | 35 | # build a cbapi object 36 | # 37 | cb = cbapi.CbApi(opts.server_url, token=opts.token, ssl_verify=opts.ssl_verify) 38 | 39 | curr_feeds = cb.feed_enum() 40 | feed_does_exist = False 41 | 42 | for feed in curr_feeds: 43 | if int(feed['id']) == int(opts.id): 44 | feed_does_exist = True 45 | 46 | if not feed_does_exist: 47 | print "No feed with id %s found" % opts.id 48 | sys.exit(-1) 49 | 50 | curr_reports = cb.feed_report_enum(opts.id) 51 | report_does_exist = False 52 | for report in curr_reports: 53 | if opts.reportid == report['id']: 54 | report_does_exist = True 55 | if not report_does_exist: 56 | print "No report with id %s found" % opts.reportid 57 | sys.exit(-1) 58 | 59 | # get the feed's report stats 60 | stats = cb.feed_report_stats(opts.id, opts.reportid) 61 | 62 | for key in stats.keys(): 63 | print "%-22s : %s" % (key, stats[key]) 64 | 65 | if __name__ == "__main__": 66 | sys.exit(main(sys.argv[1:])) -------------------------------------------------------------------------------- /feed_report_toggle.py: -------------------------------------------------------------------------------- 1 | #!/bin/env python 2 | 3 | # usage: 4 | # the -p flag is the URI of the specific threat feed you wish to toggle. 5 | # ./feed_report_toggle.py -p https://cb1.carbonblackse.com/#threat-details/43/e6314816-dcc2-45ec-8fef-d430d4a2c7aa 6 | import sys 7 | import optparse 8 | import cbapi 9 | import pprint 10 | import warnings 11 | 12 | cb_servers = { 13 | 'cb1.carbonblackse.com': 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx', 14 | 'cb2.carbonblackse.com': 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy' 15 | } 16 | 17 | def build_cli_parser(): 18 | parser = optparse.OptionParser(usage="%prog [options]", description="Dump sensor list") 19 | 20 | # for each supported output type, add an option 21 | # 22 | parser.add_option("-c", "--cburl", action="store", default=None, dest="url", 23 | help="CB server's URL. e.g., http://127.0.0.1 ") 24 | parser.add_option("-a", "--apitoken", action="store", default=None, dest="token", 25 | help="API Token for Carbon Black server") 26 | parser.add_option("-n", "--no-ssl-verify", action="store", default=False, dest="ssl_verify", 27 | help="Do not verify server SSL certificate.") 28 | parser.add_option("-p", "--parse_string", action="store", default=None, dest="parse_string", 29 | help="URI of threat report to parse") 30 | return parser 31 | 32 | 33 | def main(): 34 | # builds the args structure, populating with default server and token and creating many flags 35 | # we will only use the -p flag here 36 | args = build_cli_parser() 37 | if not args.parse_string: 38 | print "Missing the url containting the Server, Feed ID and Report ID to parse." 39 | sys.exit(-1) 40 | 41 | su = args.parse_string.strip() 42 | su_list = su.split('/',) 43 | if len(su_list) != 6: 44 | print "Length of list from parsed url is not 6." 45 | print "Printing parsed url and list and exiting script." 46 | print args.parse_string 47 | print su_list 48 | sys.exit(-1) 49 | feed_host = su_list[2] 50 | feed_id = su_list[-2] 51 | report_id = su_list[-1] 52 | 53 | if not feed_host in cb_servers: 54 | print "%s not in list of cb_servers. Exiting" % (feed_host) 55 | sys.exit(1) 56 | args.url = 'https://%s' % (feed_host) 57 | args.token = cb_servers[feed_host] 58 | 59 | cb = cbapi.CbApi(args.url, token=args.token, ssl_verify=args.ssl_verify) 60 | 61 | # retrieve threat report original threat report so we can get the name of the threat feed 62 | # the threat feed name will be used to locate the threat feed id on the servers 63 | with warnings.catch_warnings(): 64 | warnings.simplefilter("ignore") 65 | report = cb.feed_report_info(feed_id, report_id) 66 | 67 | feed_name = report['feed_name'] 68 | 69 | updated_report = {'ids': {}, 'updates': {}} 70 | 71 | if report['is_ignored'] == True: 72 | updated_report['updates']['is_ignored'] = False 73 | elif report['is_ignored'] == False: 74 | updated_report['updates']['is_ignored'] = True 75 | 76 | 77 | for server in cb_servers.keys(): 78 | args.url = 'https://%s' % (server) 79 | args.token = cb_servers[server] 80 | cb = cbapi.CbApi(args.url, token=args.token, ssl_verify=args.ssl_verify) 81 | feed_id = cb.feed_get_id_by_name(feed_name) 82 | updated_report['ids'] = {} 83 | updated_report['ids'][feed_id] = [report_id] 84 | url = "%s/api/v1/threat_report" % (args.url) 85 | r = cb.cbapi_post(url, data=json.dumps(updated_report)) 86 | if r.status_code == 200: 87 | print "%s (report_id: %s) is_enabled was successfully set to %s on %s" % (report['title'], report['id'], updated_report['updates']['is_ignored'], server) 88 | else: 89 | r.raise_for_status() 90 | 91 | if __name__ == "__main__": 92 | sys.exit(main()) 93 | -------------------------------------------------------------------------------- /feed_requirements.py: -------------------------------------------------------------------------------- 1 | __author__ = 'bwolfson' 2 | 3 | import sys 4 | import optparse 5 | 6 | # in the github repo, cbapi is not in the example directory 7 | sys.path.append('../src/cbapi') 8 | 9 | import cbapi 10 | 11 | def build_cli_parser(): 12 | parser = optparse.OptionParser(usage="%prog [options]", description="Get the requirements for a specific feed") 13 | 14 | # for each supported output type, add an option 15 | # 16 | parser.add_option("-c", "--cburl", action="store", default=None, dest="server_url", 17 | help="CB server's URL. e.g., http://127.0.0.1 ") 18 | parser.add_option("-a", "--apitoken", action="store", default=None, dest="token", 19 | help="API Token for Carbon Black server") 20 | parser.add_option("-n", "--no-ssl-verify", action="store_false", default=True, dest="ssl_verify", 21 | help="Do not verify server SSL certificate.") 22 | parser.add_option("-i", "--id", action="store", default=None, dest="id", 23 | help="Feed id") 24 | return parser 25 | 26 | def main(argv): 27 | parser = build_cli_parser() 28 | opts, args = parser.parse_args(argv) 29 | if not opts.server_url or not opts.token or not opts.id: 30 | print "Missing required param; run with --help for usage" 31 | sys.exit(-1) 32 | 33 | # build a cbapi object 34 | # 35 | cb = cbapi.CbApi(opts.server_url, token=opts.token, ssl_verify=opts.ssl_verify) 36 | 37 | requirements = cb.feed_requirements(opts.id) 38 | for requirement in requirements: 39 | print requirement 40 | 41 | sync_result = cb.feed_synchronize(opts.feedname, True) 42 | print sync_result 43 | 44 | if __name__ == "__main__": 45 | sys.exit(main(sys.argv[1:])) -------------------------------------------------------------------------------- /feed_synchronize.py: -------------------------------------------------------------------------------- 1 | __author__ = 'bwolfson' 2 | 3 | import sys 4 | import optparse 5 | 6 | # in the github repo, cbapi is not in the example directory 7 | sys.path.append('../src/cbapi') 8 | 9 | import cbapi 10 | 11 | def build_cli_parser(): 12 | parser = optparse.OptionParser(usage="%prog [options]", description="Display information about an existing feed") 13 | 14 | # for each supported output type, add an option 15 | # 16 | parser.add_option("-c", "--cburl", action="store", default=None, dest="server_url", 17 | help="CB server's URL. e.g., http://127.0.0.1 ") 18 | parser.add_option("-a", "--apitoken", action="store", default=None, dest="token", 19 | help="API Token for Carbon Black server") 20 | parser.add_option("-n", "--no-ssl-verify", action="store_false", default=True, dest="ssl_verify", 21 | help="Do not verify server SSL certificate.") 22 | parser.add_option("-f", "--feedname", action="store", default=None, dest="feedname", 23 | help="Feed Name") 24 | return parser 25 | 26 | def main(argv): 27 | parser = build_cli_parser() 28 | opts, args = parser.parse_args(argv) 29 | if not opts.server_url or not opts.token or not opts.feedname: 30 | print "Missing required param; run with --help for usage" 31 | sys.exit(-1) 32 | 33 | # build a cbapi object 34 | # 35 | cb = cbapi.CbApi(opts.server_url, token=opts.token, ssl_verify=opts.ssl_verify) 36 | 37 | id = cb.feed_get_id_by_name(opts.feedname) 38 | if id is None: 39 | print "-> No configured feed with name '%s' found!" % (opts.feedname) 40 | sys.exit(-1) 41 | 42 | sync_result = cb.feed_synchronize(opts.feedname, True) 43 | print sync_result 44 | 45 | if __name__ == "__main__": 46 | sys.exit(main(sys.argv[1:])) -------------------------------------------------------------------------------- /filemods_from_list.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # 3 | #The MIT License (MIT) 4 | # 5 | # Copyright (c) 2015 Bit9 + Carbon Black 6 | # 7 | # Permission is hereby granted, free of charge, to any person obtaining a copy 8 | # of this software and associated documentation files (the "Software"), to deal 9 | # in the Software without restriction, including without limitation the rights 10 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | # copies of the Software, and to permit persons to whom the Software is 12 | # furnished to do so, subject to the following conditions: 13 | # 14 | # The above copyright notice and this permission notice shall be included in all 15 | # copies or substantial portions of the Software. 16 | # 17 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | # SOFTWARE. 24 | # 25 | # ----------------------------------------------------------------------------- 26 | # 27 | # 28 | # 29 | # 30 | # last updated 2015-06-28 by Ben Johnson bjohnson@bit9.com 31 | # 32 | 33 | # in the github repo, cbapi is not in the example directory 34 | 35 | try: 36 | from cbapi.legacy.util.cli_helpers import main_helper 37 | except ImportError: 38 | from cbapi.util.cli_helpers import main_helper 39 | 40 | def main(cb, args): 41 | 42 | input_file = args.get('inputfile') 43 | 44 | f = file(input_file, "rb") 45 | lines = f.read().split("\r") 46 | 47 | for line in lines: 48 | filepath = line.strip() 49 | if len(filepath) == 0: 50 | continue 51 | 52 | for (proc, events) in cb.process_search_and_events_iter("filemod:%s" % filepath): 53 | hostname = proc.get('hostname') 54 | for filemod in events.get('filemod_complete', []): 55 | print filemod 56 | 57 | print "%s, %s, %s" % (hostname, proc.get('path'), filepath) 58 | 59 | if __name__ == "__main__": 60 | required_arg = ("-i", "--inputfile", "store", None, "inputfile", "List of filemod paths to search for") 61 | main_helper("Search for processes modifying particular filepaths", main, custom_required=[required_arg]) 62 | -------------------------------------------------------------------------------- /generic_binary_search.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # 3 | #The MIT License (MIT) 4 | # 5 | # Copyright (c) 2015 Bit9 + Carbon Black 6 | # 7 | # Permission is hereby granted, free of charge, to any person obtaining a copy 8 | # of this software and associated documentation files (the "Software"), to deal 9 | # in the Software without restriction, including without limitation the rights 10 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | # copies of the Software, and to permit persons to whom the Software is 12 | # furnished to do so, subject to the following conditions: 13 | # 14 | # The above copyright notice and this permission notice shall be included in all 15 | # copies or substantial portions of the Software. 16 | # 17 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | # SOFTWARE. 24 | # 25 | # ----------------------------------------------------------------------------- 26 | # 27 | # 28 | # 29 | # 30 | # last updated 2015-06-28 by Ben Johnson bjohnson@bit9.com 31 | # 32 | 33 | try: 34 | from cbapi.legacy.util.cli_helpers import main_helper 35 | except ImportError: 36 | from cbapi.util.cli_helpers import main_helper 37 | 38 | def main(cb, args): 39 | query = args.get('query') 40 | print "%s,%s,%s,%s,%s,%s" % ("hostname", "username", "start", "parent_path", "path", "cmdline") 41 | for binary in cb.binary_search_iter(query, rows=100): 42 | print "%s,%s,%s,%s,%s" % (binary.get('md5'), 43 | binary.get('server_added_timestamp'), 44 | binary.get('digsig_result'), 45 | binary.get('company_name'), 46 | binary.get('file_version') 47 | ) 48 | 49 | # print "%s,%s,%s,%s,%s,%s" % (proc.get('hostname'), 50 | # proc.get('username'), 51 | # proc.get('start'), 52 | # parent_details.get('path'), 53 | # proc.get('path'), 54 | # proc_details.get('cmdline')) 55 | 56 | if __name__ == "__main__": 57 | required_arg = ("-q", "--query", "store", None, "query", "Binary search query") 58 | main_helper("Generic binary search", main, custom_required=[required_arg]) 59 | -------------------------------------------------------------------------------- /generic_process_search.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # 3 | #The MIT License (MIT) 4 | # 5 | # Copyright (c) 2015 Bit9 + Carbon Black 6 | # 7 | # Permission is hereby granted, free of charge, to any person obtaining a copy 8 | # of this software and associated documentation files (the "Software"), to deal 9 | # in the Software without restriction, including without limitation the rights 10 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | # copies of the Software, and to permit persons to whom the Software is 12 | # furnished to do so, subject to the following conditions: 13 | # 14 | # The above copyright notice and this permission notice shall be included in all 15 | # copies or substantial portions of the Software. 16 | # 17 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | # SOFTWARE. 24 | # 25 | # ----------------------------------------------------------------------------- 26 | # 27 | # 28 | # 29 | # 30 | # last updated 2015-06-28 by Ben Johnson bjohnson@bit9.com 31 | # 32 | 33 | try: 34 | from cbapi.legacy.util.cli_helpers import main_helper 35 | except ImportError: 36 | from cbapi.util.cli_helpers import main_helper 37 | 38 | def main(cb, args): 39 | query = args.get('query') 40 | print "%s,%s,%s,%s,%s,%s" % ("hostname", "username", "start", "parent_path", "path", "cmdline") 41 | for (proc, proc_details, parent_details) in \ 42 | cb.process_search_and_detail_iter(query): 43 | 44 | print "%s,%s,%s,%s,%s,%s" % (proc.get('hostname'), 45 | proc.get('username'), 46 | proc.get('start'), 47 | parent_details.get('path'), 48 | proc.get('path'), 49 | proc_details.get('cmdline')) 50 | 51 | if __name__ == "__main__": 52 | required_arg = ("-q", "--query", "store", None, "query", "Process search query") 53 | main_helper("Generic process search", main, custom_required=[required_arg]) 54 | -------------------------------------------------------------------------------- /get_builds.py: -------------------------------------------------------------------------------- 1 | __author__ = 'bwolfson' 2 | 3 | import sys 4 | import optparse 5 | 6 | # in the github repo, cbapi is not in the example directory 7 | sys.path.append('../src/cbapi') 8 | 9 | import cbapi 10 | 11 | def build_cli_parser(): 12 | parser = optparse.OptionParser(usage="%prog [options]", description="Display build versions from server") 13 | 14 | # for each supported output type, add an option 15 | # 16 | parser.add_option("-c", "--cburl", action="store", default=None, dest="server_url", 17 | help="CB server's URL. e.g., http://127.0.0.1 ") 18 | parser.add_option("-a", "--apitoken", action="store", default=None, dest="token", 19 | help="API Token for Carbon Black server") 20 | parser.add_option("-n", "--no-ssl-verify", action="store_false", default=True, dest="ssl_verify", 21 | help="Do not verify server SSL certificate.") 22 | return parser 23 | 24 | def main(argv): 25 | parser = build_cli_parser() 26 | opts, args = parser.parse_args(argv) 27 | if not opts.server_url or not opts.token: 28 | print "Missing required param; run with --help for usage" 29 | sys.exit(-1) 30 | 31 | # build a cbapi object 32 | # 33 | cb = cbapi.CbApi(opts.server_url, token=opts.token, ssl_verify=opts.ssl_verify) 34 | 35 | builds = cb.get_builds() 36 | for build in builds: 37 | print "" 38 | for key in build.keys(): 39 | print "%-20s : %s" % (key, build[key]) 40 | 41 | if __name__ == "__main__": 42 | sys.exit(main(sys.argv[1:])) -------------------------------------------------------------------------------- /get_login_caps.py: -------------------------------------------------------------------------------- 1 | __author__ = 'bwolfson' 2 | 3 | import sys 4 | import optparse 5 | 6 | # in the github repo, cbapi is not in the example directory 7 | sys.path.append('../src/cbapi') 8 | 9 | import cbapi 10 | 11 | def build_cli_parser(): 12 | parser = optparse.OptionParser(usage="%prog [options]", description="Display login-caps from server") 13 | 14 | # for each supported output type, add an option 15 | # 16 | parser.add_option("-c", "--cburl", action="store", default=None, dest="server_url", 17 | help="CB server's URL. e.g., http://127.0.0.1 ") 18 | parser.add_option("-a", "--apitoken", action="store", default=None, dest="token", 19 | help="API Token for Carbon Black server") 20 | parser.add_option("-n", "--no-ssl-verify", action="store_false", default=True, dest="ssl_verify", 21 | help="Do not verify server SSL certificate.") 22 | return parser 23 | 24 | def main(argv): 25 | parser = build_cli_parser() 26 | opts, args = parser.parse_args(argv) 27 | if not opts.server_url or not opts.token: 28 | print "Missing required param; run with --help for usage" 29 | sys.exit(-1) 30 | 31 | # build a cbapi object 32 | # 33 | cb = cbapi.CbApi(opts.server_url, token=opts.token, ssl_verify=opts.ssl_verify) 34 | 35 | login = cb.get_login_caps() 36 | for key in login.keys(): 37 | print "%-20s : %s" % (key, login[key]) 38 | 39 | if __name__ == "__main__": 40 | sys.exit(main(sys.argv[1:])) -------------------------------------------------------------------------------- /group_datasharing_add.py: -------------------------------------------------------------------------------- 1 | __author__ = 'bwolfson' 2 | 3 | import sys 4 | import optparse 5 | 6 | # in the github repo, cbapi is not in the example directory 7 | sys.path.append('../src/cbapi') 8 | 9 | import cbapi 10 | 11 | def build_cli_parser(): 12 | parser = optparse.OptionParser(usage="%prog [options]", description="Add a new datasharing configuration for a sensor group in the server") 13 | 14 | # for each supported output type, add an option 15 | # 16 | parser.add_option("-c", "--cburl", action="store", default=None, dest="server_url", 17 | help="CB server's URL. e.g., http://127.0.0.1 ") 18 | parser.add_option("-a", "--apitoken", action="store", default=None, dest="token", 19 | help="API Token for Carbon Black server") 20 | parser.add_option("-n", "--no-ssl-verify", action="store_false", default=True, dest="ssl_verify", 21 | help="Do not verify server SSL certificate.") 22 | parser.add_option("-i", "--group_id", action="store", default=True, dest= "group_id", 23 | help = "id of sensor group whose datasharing configs to enumerate") 24 | parser.add_option("-w", "--who", action="store", default=None, dest = "who", 25 | help = "who to datashare with") 26 | parser.add_option("-d", "--what", action="store", default=None, dest = "what", 27 | help = "what type of data to share") 28 | return parser 29 | 30 | def main(argv): 31 | parser = build_cli_parser() 32 | opts, args = parser.parse_args(argv) 33 | if not opts.server_url or not opts.token or not opts.group_id or not opts.who or not opts.what: 34 | print "Missing required param; run with --help for usage" 35 | sys.exit(-1) 36 | 37 | # build a cbapi object 38 | # 39 | cb = cbapi.CbApi(opts.server_url, token=opts.token, ssl_verify=opts.ssl_verify) 40 | 41 | 42 | #check if the given group_id truly corresponds to one of the existing sensor groups 43 | does_exist = False 44 | for group in cb.group_enum(): 45 | if int(opts.group_id) == int(group['id']): 46 | does_exist = True 47 | 48 | if not does_exist: 49 | sys.exit(-1) 50 | 51 | #check if trying to add a configuration that already exists 52 | #also at this point opts.id is valid 53 | no_conflict = True 54 | curr_configs = cb.group_datasharing_enum(opts.group_id) 55 | for config in curr_configs: 56 | if opts.who.lower() == config['who'].lower() and \ 57 | opts.what.lower() == config['what'].lower(): 58 | no_conflict = False 59 | 60 | if no_conflict: 61 | datasharing_config = cb.group_datasharing_add(opts.group_id, opts.who, opts.what) 62 | for key in datasharing_config.keys(): 63 | print "%-20s : %s" % (key, datasharing_config[key]) 64 | else: 65 | print "configuration already exists" 66 | sys.exit(-1) 67 | 68 | 69 | if __name__ == "__main__": 70 | sys.exit(main(sys.argv[1:])) -------------------------------------------------------------------------------- /group_datasharing_del.py: -------------------------------------------------------------------------------- 1 | __author__ = 'bwolfson' 2 | 3 | import sys 4 | import optparse 5 | 6 | # in the github repo, cbapi is not in the example directory 7 | sys.path.append('../src/cbapi') 8 | 9 | import cbapi 10 | 11 | def build_cli_parser(): 12 | parser = optparse.OptionParser(usage="%prog [options]", description="Delete a specific datasharing configuration for a sensor group") 13 | 14 | # for each supported output type, add an option 15 | # 16 | parser.add_option("-c", "--cburl", action="store", default=None, dest="server_url", 17 | help="CB server's URL. e.g., http://127.0.0.1 ") 18 | parser.add_option("-a", "--apitoken", action="store", default=None, dest="token", 19 | help="API Token for Carbon Black server") 20 | parser.add_option("-n", "--no-ssl-verify", action="store_false", default=True, dest="ssl_verify", 21 | help="Do not verify server SSL certificate.") 22 | parser.add_option("-i", "--group_id", action="store", default=True, dest= "group_id", 23 | help = "id of sensor group whose datasharing configs to enumerate") 24 | parser.add_option("-d", "--config_id", action = "store", default=True, dest="config_id", 25 | help = "id of specific configuration to delete") 26 | 27 | return parser 28 | 29 | def main(argv): 30 | parser = build_cli_parser() 31 | opts, args = parser.parse_args(argv) 32 | if not opts.server_url or not opts.token or not opts.group_id or not opts.config_id: 33 | print "Missing required param; run with --help for usage" 34 | sys.exit(-1) 35 | 36 | # build a cbapi object 37 | # 38 | cb = cbapi.CbApi(opts.server_url, token=opts.token, ssl_verify=opts.ssl_verify) 39 | 40 | #check if the given group_id truly corresponds to one of the existing sensor groups 41 | does_exist = False 42 | for group in cb.group_enum(): 43 | if int(opts.group_id) == int(group['id']): 44 | does_exist = True 45 | 46 | if does_exist: 47 | datasharing_config = cb.group_datasharing_del(opts.group_id, opts.config_id) 48 | 49 | for key in datasharing_config.keys(): 50 | print "%-20s : %s" % (key, datasharing_config[key]) 51 | else: 52 | sys.exit(-1) 53 | 54 | if __name__ == "__main__": 55 | sys.exit(main(sys.argv[1:])) -------------------------------------------------------------------------------- /group_datasharing_del_all.py: -------------------------------------------------------------------------------- 1 | __author__ = 'bwolfson' 2 | 3 | import sys 4 | import optparse 5 | 6 | # in the github repo, cbapi is not in the example directory 7 | sys.path.append('../src/cbapi') 8 | 9 | import cbapi 10 | 11 | def build_cli_parser(): 12 | parser = optparse.OptionParser(usage="%prog [options]", description="Delete all datasharing configurations for a sensor group") 13 | 14 | # for each supported output type, add an option 15 | # 16 | parser.add_option("-c", "--cburl", action="store", default=None, dest="server_url", 17 | help="CB server's URL. e.g., http://127.0.0.1 ") 18 | parser.add_option("-a", "--apitoken", action="store", default=None, dest="token", 19 | help="API Token for Carbon Black server") 20 | parser.add_option("-n", "--no-ssl-verify", action="store_false", default=True, dest="ssl_verify", 21 | help="Do not verify server SSL certificate.") 22 | parser.add_option("-i", "--group_id", action="store", default=True, dest= "group_id", 23 | help = "id of sensor group whose datasharing configs to enumerate") 24 | return parser 25 | 26 | def main(argv): 27 | parser = build_cli_parser() 28 | opts, args = parser.parse_args(argv) 29 | if not opts.server_url or not opts.token or not opts.group_id: 30 | print "Missing required param; run with --help for usage" 31 | sys.exit(-1) 32 | 33 | # build a cbapi object 34 | # 35 | cb = cbapi.CbApi(opts.server_url, token=opts.token, ssl_verify=opts.ssl_verify) 36 | 37 | #check if the given group_id truly corresponds to one of the existing sensor groups 38 | does_exist = False 39 | for group in cb.group_enum(): 40 | if int(opts.group_id) == int(group['id']): 41 | does_exist = True 42 | 43 | if does_exist: 44 | config = cb.group_datasharing_del_all(opts.group_id) 45 | 46 | for key in config.keys(): 47 | print "%-20s : %s" % (key, config[key]) 48 | else: 49 | sys.exit(-1) 50 | 51 | if __name__ == "__main__": 52 | sys.exit(main(sys.argv[1:])) -------------------------------------------------------------------------------- /group_datasharing_enum.py: -------------------------------------------------------------------------------- 1 | __author__ = 'bwolfson' 2 | 3 | import sys 4 | import optparse 5 | 6 | # in the github repo, cbapi is not in the example directory 7 | sys.path.append('../src/cbapi') 8 | 9 | import cbapi 10 | 11 | def build_cli_parser(): 12 | parser = optparse.OptionParser(usage="%prog [options]", description="Enumerate datasharing configurations for a certain sensor group") 13 | 14 | # for each supported output type, add an option 15 | # 16 | parser.add_option("-c", "--cburl", action="store", default=None, dest="server_url", 17 | help="CB server's URL. e.g., http://127.0.0.1 ") 18 | parser.add_option("-a", "--apitoken", action="store", default=None, dest="token", 19 | help="API Token for Carbon Black server") 20 | parser.add_option("-n", "--no-ssl-verify", action="store_false", default=True, dest="ssl_verify", 21 | help="Do not verify server SSL certificate.") 22 | parser.add_option("-i", "--group_id", action="store", default=True, dest= "group_id", 23 | help = "id of sensor group whose datasharing configs to enumerate") 24 | return parser 25 | 26 | def main(argv): 27 | parser = build_cli_parser() 28 | opts, args = parser.parse_args(argv) 29 | if not opts.server_url or not opts.token or not opts.group_id: 30 | print "Missing required param; run with --help for usage" 31 | sys.exit(-1) 32 | 33 | # build a cbapi object 34 | # 35 | cb = cbapi.CbApi(opts.server_url, token=opts.token, ssl_verify=opts.ssl_verify) 36 | 37 | #check if the given group_id truly corresponds to one of the existing sensor groups 38 | does_exist = False 39 | for group in cb.group_enum(): 40 | if int(opts.group_id) == int(group['id']): 41 | does_exist = True 42 | 43 | if does_exist: 44 | datasharing_configs = cb.group_datasharing_enum(opts.group_id) 45 | 46 | for config in datasharing_configs: 47 | print "" 48 | for key in config.keys(): 49 | print "%-20s : %s" % (key, config[key]) 50 | else: 51 | sys.exit(-1) 52 | 53 | if __name__ == "__main__": 54 | sys.exit(main(sys.argv[1:])) -------------------------------------------------------------------------------- /group_datasharing_info.py: -------------------------------------------------------------------------------- 1 | __author__ = 'bwolfson' 2 | 3 | import sys 4 | import optparse 5 | 6 | # in the github repo, cbapi is not in the example directory 7 | sys.path.append('../src/cbapi') 8 | 9 | import cbapi 10 | 11 | def build_cli_parser(): 12 | parser = optparse.OptionParser(usage="%prog [options]", description="Retrieve info of a specific datasharing configuration for a sensor group") 13 | 14 | # for each supported output type, add an option 15 | # 16 | parser.add_option("-c", "--cburl", action="store", default=None, dest="server_url", 17 | help="CB server's URL. e.g., http://127.0.0.1 ") 18 | parser.add_option("-a", "--apitoken", action="store", default=None, dest="token", 19 | help="API Token for Carbon Black server") 20 | parser.add_option("-n", "--no-ssl-verify", action="store_false", default=True, dest="ssl_verify", 21 | help="Do not verify server SSL certificate.") 22 | parser.add_option("-i", "--group_id", action="store", default=True, dest= "group_id", 23 | help = "id of sensor group whose datasharing configs to enumerate") 24 | parser.add_option("-d", "--config_id", action = "store", default=True, dest="config_id", 25 | help = "id of specific configuration to delete") 26 | 27 | return parser 28 | 29 | def main(argv): 30 | parser = build_cli_parser() 31 | opts, args = parser.parse_args(argv) 32 | if not opts.server_url or not opts.token or not opts.group_id or not opts.config_id: 33 | print "Missing required param; run with --help for usage" 34 | sys.exit(-1) 35 | 36 | # build a cbapi object 37 | # 38 | cb = cbapi.CbApi(opts.server_url, token=opts.token, ssl_verify=opts.ssl_verify) 39 | 40 | #check if the given group_id truly corresponds to one of the existing sensor groups 41 | does_exist = False 42 | for group in cb.group_enum(): 43 | if int(opts.group_id) == int(group['id']): 44 | does_exist = True 45 | 46 | if does_exist: 47 | datasharing_config = cb.group_datasharing_info(opts.group_id, opts.config_id) 48 | 49 | for key in datasharing_config.keys(): 50 | print "%-20s : %s" % (key, datasharing_config[key]) 51 | else: 52 | sys.exit(-1) 53 | 54 | if __name__ == "__main__": 55 | sys.exit(main(sys.argv[1:])) -------------------------------------------------------------------------------- /group_get_linux.py: -------------------------------------------------------------------------------- 1 | __author__ = 'bwolfson' 2 | 3 | import sys 4 | import optparse 5 | 6 | # in the github repo, cbapi is not in the example directory 7 | sys.path.append('../src/cbapi') 8 | 9 | import cbapi 10 | 11 | def build_cli_parser(): 12 | parser = optparse.OptionParser(usage="%prog [options]", description="Display sensor installer package for Linux") 13 | 14 | # for each supported output type, add an option 15 | # 16 | parser.add_option("-c", "--cburl", action="store", default=None, dest="server_url", 17 | help="CB server's URL. e.g., http://127.0.0.1 ") 18 | parser.add_option("-a", "--apitoken", action="store", default=None, dest="token", 19 | help="API Token for Carbon Black server") 20 | parser.add_option("-n", "--no-ssl-verify", action="store_false", default=True, dest="ssl_verify", 21 | help="Do not verify server SSL certificate.") 22 | return parser 23 | 24 | def main(argv): 25 | parser = build_cli_parser() 26 | opts, args = parser.parse_args(argv) 27 | if not opts.server_url or not opts.token: 28 | print "Missing required param; run with --help for usage" 29 | sys.exit(-1) 30 | 31 | # build a cbapi object 32 | # 33 | cb = cbapi.CbApi(opts.server_url, token=opts.token, ssl_verify=opts.ssl_verify) 34 | 35 | builds = cb.get_builds() 36 | for build in builds: 37 | print "" 38 | for key in build.keys(): 39 | print "%-20s : %s" % (key, build[key]) 40 | 41 | if __name__ == "__main__": 42 | sys.exit(main(sys.argv[1:])) -------------------------------------------------------------------------------- /group_get_osx.py: -------------------------------------------------------------------------------- 1 | __author__ = 'bwolfson' 2 | 3 | import sys 4 | import optparse 5 | 6 | # in the github repo, cbapi is not in the example directory 7 | sys.path.append('../src/cbapi') 8 | 9 | import cbapi 10 | 11 | def build_cli_parser(): 12 | parser = optparse.OptionParser(usage="%prog [options]", description="Display sensor installer package for OSX") 13 | 14 | # for each supported output type, add an option 15 | # 16 | parser.add_option("-c", "--cburl", action="store", default=None, dest="server_url", 17 | help="CB server's URL. e.g., http://127.0.0.1 ") 18 | parser.add_option("-a", "--apitoken", action="store", default=None, dest="token", 19 | help="API Token for Carbon Black server") 20 | parser.add_option("-n", "--no-ssl-verify", action="store_false", default=True, dest="ssl_verify", 21 | help="Do not verify server SSL certificate.") 22 | return parser 23 | 24 | def main(argv): 25 | parser = build_cli_parser() 26 | opts, args = parser.parse_args(argv) 27 | if not opts.server_url or not opts.token: 28 | print "Missing required param; run with --help for usage" 29 | sys.exit(-1) 30 | 31 | # build a cbapi object 32 | # 33 | cb = cbapi.CbApi(opts.server_url, token=opts.token, ssl_verify=opts.ssl_verify) 34 | 35 | builds = cb.get_builds() 36 | for build in builds: 37 | print "" 38 | for key in build.keys(): 39 | print "%-20s : %s" % (key, build[key]) 40 | 41 | if __name__ == "__main__": 42 | sys.exit(main(sys.argv[1:])) -------------------------------------------------------------------------------- /group_get_windowsexe.py: -------------------------------------------------------------------------------- 1 | __author__ = 'bwolfson' 2 | 3 | import sys 4 | import optparse 5 | 6 | # in the github repo, cbapi is not in the example directory 7 | sys.path.append('../src/cbapi') 8 | 9 | import cbapi 10 | 11 | def build_cli_parser(): 12 | parser = optparse.OptionParser(usage="%prog [options]", description="Display sensor installer package for Windows EXE") 13 | 14 | # for each supported output type, add an option 15 | # 16 | parser.add_option("-c", "--cburl", action="store", default=None, dest="server_url", 17 | help="CB server's URL. e.g., http://127.0.0.1 ") 18 | parser.add_option("-a", "--apitoken", action="store", default=None, dest="token", 19 | help="API Token for Carbon Black server") 20 | parser.add_option("-n", "--no-ssl-verify", action="store_false", default=True, dest="ssl_verify", 21 | help="Do not verify server SSL certificate.") 22 | return parser 23 | 24 | def main(argv): 25 | parser = build_cli_parser() 26 | opts, args = parser.parse_args(argv) 27 | if not opts.server_url or not opts.token: 28 | print "Missing required param; run with --help for usage" 29 | sys.exit(-1) 30 | 31 | # build a cbapi object 32 | # 33 | cb = cbapi.CbApi(opts.server_url, token=opts.token, ssl_verify=opts.ssl_verify) 34 | 35 | builds = cb.get_builds() 36 | for build in builds: 37 | print "" 38 | for key in build.keys(): 39 | print "%-20s : %s" % (key, build[key]) 40 | 41 | if __name__ == "__main__": 42 | sys.exit(main(sys.argv[1:])) -------------------------------------------------------------------------------- /group_get_windowsmsi.py: -------------------------------------------------------------------------------- 1 | __author__ = 'bwolfson' 2 | 3 | import sys 4 | import optparse 5 | 6 | # in the github repo, cbapi is not in the example directory 7 | sys.path.append('../src/cbapi') 8 | 9 | import cbapi 10 | 11 | def build_cli_parser(): 12 | parser = optparse.OptionParser(usage="%prog [options]", description="Display sensor installer package for Windows MSI") 13 | 14 | # for each supported output type, add an option 15 | # 16 | parser.add_option("-c", "--cburl", action="store", default=None, dest="server_url", 17 | help="CB server's URL. e.g., http://127.0.0.1 ") 18 | parser.add_option("-a", "--apitoken", action="store", default=None, dest="token", 19 | help="API Token for Carbon Black server") 20 | parser.add_option("-n", "--no-ssl-verify", action="store_false", default=True, dest="ssl_verify", 21 | help="Do not verify server SSL certificate.") 22 | return parser 23 | 24 | def main(argv): 25 | parser = build_cli_parser() 26 | opts, args = parser.parse_args(argv) 27 | if not opts.server_url or not opts.token: 28 | print "Missing required param; run with --help for usage" 29 | sys.exit(-1) 30 | 31 | # build a cbapi object 32 | # 33 | cb = cbapi.CbApi(opts.server_url, token=opts.token, ssl_verify=opts.ssl_verify) 34 | 35 | package = cb.sensor_installer('WindowsMSI', 1) 36 | print package 37 | #for key in package.keys(): 38 | #print "%-20s : %s" % (key, package[key]) 39 | 40 | if __name__ == "__main__": 41 | sys.exit(main(sys.argv[1:])) -------------------------------------------------------------------------------- /kill_all_iexplore.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # 3 | #The MIT License (MIT) 4 | # 5 | # Copyright (c) 2015 Bit9 + Carbon Black 6 | # 7 | # Permission is hereby granted, free of charge, to any person obtaining a copy 8 | # of this software and associated documentation files (the "Software"), to deal 9 | # in the Software without restriction, including without limitation the rights 10 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | # copies of the Software, and to permit persons to whom the Software is 12 | # furnished to do so, subject to the following conditions: 13 | # 14 | # The above copyright notice and this permission notice shall be included in all 15 | # copies or substantial portions of the Software. 16 | # 17 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | # SOFTWARE. 24 | # 25 | # ----------------------------------------------------------------------------- 26 | # 27 | # 28 | # 29 | # 30 | # last updated 2015-06-28 by Ben Johnson bjohnson@bit9.com 31 | # 32 | 33 | try: 34 | from cbapi.legacy.util.cli_helpers import main_helper 35 | from cbapi.legacy.util.live_response_helpers import LiveResponseHelper 36 | except ImportError: 37 | from cbapi.util.cli_helpers import main_helper 38 | from cbapi.util.live_response_helpers import LiveResponseHelper 39 | 40 | def main(cb, args): 41 | sensor_id = int(args.get('sensorid')) 42 | lrh = LiveResponseHelper(cb, sensor_id) 43 | lrh.start() 44 | 45 | # THIS COULD EASILY BE TURNED INTO A LOOP SO THAT YOU CONTINUOUSLY POLL FOR A SPECIFIC PROCESS AND KILL IT 46 | processes = lrh.process_list() 47 | for process in processes: 48 | path = process.get('path') 49 | if path.lower().endswith('iexplore.exe'): 50 | lrh.kill(process.get('pid')) 51 | print "Killed: %s|%s|%s" % (process.get('path'), 52 | process.get('command_line', ''), 53 | process.get('username', '')) 54 | 55 | lrh.stop() 56 | 57 | if __name__ == "__main__": 58 | required_arg = ("-s", "--sensorid", "store", None, "sensorid", "Sensor id") 59 | main_helper("Kill all iexplore.exe processes on particular sensor", main, custom_required=[required_arg]) 60 | -------------------------------------------------------------------------------- /license_status.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # 3 | #The MIT License (MIT) 4 | # 5 | # Copyright (c) 2015 Bit9 + Carbon Black 6 | # 7 | # Permission is hereby granted, free of charge, to any person obtaining a copy 8 | # of this software and associated documentation files (the "Software"), to deal 9 | # in the Software without restriction, including without limitation the rights 10 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | # copies of the Software, and to permit persons to whom the Software is 12 | # furnished to do so, subject to the following conditions: 13 | # 14 | # The above copyright notice and this permission notice shall be included in all 15 | # copies or substantial portions of the Software. 16 | # 17 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | # SOFTWARE. 24 | # 25 | # ----------------------------------------------------------------------------- 26 | # 27 | # 28 | # 29 | # 30 | # last updated 2015-06-28 by Ben Johnson bjohnson@bit9.com 31 | # 32 | 33 | import sys 34 | import optparse 35 | import cbapi 36 | 37 | def build_cli_parser(): 38 | parser = optparse.OptionParser(usage="%prog [options]", description="Display current license status of the Carbon Black Server") 39 | 40 | # for each supported output type, add an option 41 | # 42 | parser.add_option("-c", "--cburl", action="store", default=None, dest="server_url", 43 | help="CB server's URL. e.g., http://127.0.0.1 ") 44 | parser.add_option("-a", "--apitoken", action="store", default=None, dest="token", 45 | help="API Token for Carbon Black server") 46 | parser.add_option("-n", "--no-ssl-verify", action="store_false", default=True, dest="ssl_verify", 47 | help="Do not verify server SSL certificate.") 48 | return parser 49 | 50 | def output_info(server, info): 51 | print server 52 | print "-" * 80 53 | for key in info.keys(): 54 | print "%-30s : %s" % (key, info[key]) 55 | 56 | def main(argv): 57 | parser = build_cli_parser() 58 | opts, args = parser.parse_args(argv) 59 | if not opts.server_url or not opts.token: 60 | print "Missing required param; run with --help for usage" 61 | sys.exit(-1) 62 | 63 | # build a cbapi object 64 | # 65 | cb = cbapi.CbApi(opts.server_url, token=opts.token, ssl_verify=opts.ssl_verify) 66 | 67 | output_info(opts.server_url, cb.license_status()) 68 | 69 | if __name__ == "__main__": 70 | sys.exit(main(sys.argv[1:])) 71 | -------------------------------------------------------------------------------- /move_policy_from_mbus.conf.example: -------------------------------------------------------------------------------- 1 | [settings] 2 | 3 | # 4 | # Warning: Please check permissions of this file prior to saving usernames/passwords 5 | # 6 | 7 | # 8 | # RabbitMQ Password; see /etc/cb/cb.conf 9 | # 10 | rabbitmqpassword = deworjvkdsers 11 | 12 | # 13 | # RabbitMQ Username; see /etc/cb/cb.conf 14 | # 15 | rabbitmqusername = cb 16 | 17 | # 18 | # Carbon Black Server IP 19 | # 20 | #cbserverip = localhost 21 | cbserverip = 192.168.30.40 22 | 23 | # 24 | # Carbon Black Server API token 25 | # 26 | cbtoken = 22d9e14d1a23465f10b962fc94d85f4ef9a16bf1 27 | 28 | # 29 | # Enterprise Protection Server API Token 30 | # 31 | eptoken = 19AB261B-74EB-4C56-9434-BCE2FA55BFF6 32 | 33 | # 34 | # Enterprise Protection Server IP 35 | # 36 | epserverip = 192.168.30.34 37 | 38 | # 39 | # Trigger patterns 40 | # Each section represents a set of regular expression tests that will 41 | # be AND'ed together. If all tests match the host will be moved into 42 | # the policy specified by the target policy directive. 43 | # 44 | # Each regex should be named regex_ where is a valid 45 | # variable found in CbER's message bus data. 46 | # 47 | # Example 1: Matches notepad.exe on the command line and moves the system 48 | # to a policy called end users. 49 | # 50 | # [Notepad test] 51 | # name = 'Notepad test' 52 | # targetpolicy = 'End Users' 53 | # regex_command_line = notepad.exe 54 | # 55 | # Example 2: Matches suspicious Powershell usage and moves system to 56 | # a policy called Penalty Box 57 | # [Powershell IEX] 58 | # name = 'powershell IEX+Download' 59 | # targetPolicy = 'Penalty Box' 60 | # regex_path = powershell.exe$ 61 | # regex_command_line = iex.+?downloadstring\('http 62 | -------------------------------------------------------------------------------- /net_exe_usages.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # 3 | #The MIT License (MIT) 4 | # 5 | # Copyright (c) 2015 Bit9 + Carbon Black 6 | # 7 | # Permission is hereby granted, free of charge, to any person obtaining a copy 8 | # of this software and associated documentation files (the "Software"), to deal 9 | # in the Software without restriction, including without limitation the rights 10 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | # copies of the Software, and to permit persons to whom the Software is 12 | # furnished to do so, subject to the following conditions: 13 | # 14 | # The above copyright notice and this permission notice shall be included in all 15 | # copies or substantial portions of the Software. 16 | # 17 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | # SOFTWARE. 24 | # 25 | # ----------------------------------------------------------------------------- 26 | # 27 | # 28 | # 29 | # 30 | # last updated 2015-06-28 by Ben Johnson bjohnson@bit9.com 31 | # 32 | 33 | try: 34 | from cbapi.legacy.util.cli_helpers import main_helper 35 | except ImportError: 36 | from cbapi.util.cli_helpers import main_helper 37 | 38 | def main(cb, args): 39 | start = args.get('start') 40 | print "%s,%s,%s,%s,%s,%s" % ("hostname", "username", "start", "parent_path", "path", "cmdline") 41 | for (proc, proc_details, parent_details) in \ 42 | cb.process_search_and_detail_iter( 43 | 'start:%s process_name:net.exe -cmdline:"net stop" -cmdline:"net files" -cmdline:"net sessions"' % start): 44 | 45 | print "%s,%s,%s,%s,%s,%s" % (proc.get('hostname'), 46 | proc.get('username'), 47 | proc.get('start'), 48 | parent_details.get('path'), 49 | proc.get('path'), 50 | proc_details.get('cmdline')) 51 | 52 | if __name__ == "__main__": 53 | required_arg = ("-s", "--start", "store", None, "start", "Process start time to query for, example, -2h for any net.exe processes started in past 2 hours") 54 | main_helper("Search for net.exe processes", main, custom_required=[required_arg]) 55 | -------------------------------------------------------------------------------- /osx_logins.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # 3 | #The MIT License (MIT) 4 | # 5 | # Copyright (c) 2015 Bit9 + Carbon Black 6 | # 7 | # Permission is hereby granted, free of charge, to any person obtaining a copy 8 | # of this software and associated documentation files (the "Software"), to deal 9 | # in the Software without restriction, including without limitation the rights 10 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | # copies of the Software, and to permit persons to whom the Software is 12 | # furnished to do so, subject to the following conditions: 13 | # 14 | # The above copyright notice and this permission notice shall be included in all 15 | # copies or substantial portions of the Software. 16 | # 17 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | # SOFTWARE. 24 | # 25 | # ----------------------------------------------------------------------------- 26 | # 27 | # 28 | # 29 | # 30 | # last updated 2015-06-28 by Ben Johnson bjohnson@bit9.com 31 | # 32 | 33 | try: 34 | from cbapi.legacy.util.cli_helpers import main_helper 35 | except ImportError: 36 | from cbapi.util.cli_helpers import main_helper 37 | 38 | def main(cb, args): 39 | 40 | print "UI Logins (CoreServicesUIAgent)" 41 | 42 | for proc in cb.process_search_iter('process_name:CoreServicesUIAgent', start=0, rows=200): 43 | print "%s,%s,%s" % (proc.get('start'), proc.get('hostname'), proc.get('username')) 44 | print 45 | 46 | print "SSH Sessions (sshd -> bash)" 47 | 48 | for proc in cb.process_search_iter('parent_name:sshd process_name:bash', start=0, rows=200): 49 | print "%s,%s,%s" % (proc.get('start'), proc.get('hostname'), proc.get('username')) 50 | print 51 | 52 | if __name__ == "__main__": 53 | main_helper("Search for OSX logins via particular processes.", main) 54 | -------------------------------------------------------------------------------- /platform_agent_report.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # 3 | #The MIT License (MIT) 4 | # 5 | # Copyright (c) 2015 Bit9 + Carbon Black 6 | # 7 | # Permission is hereby granted, free of charge, to any person obtaining a copy 8 | # of this software and associated documentation files (the "Software"), to deal 9 | # in the Software without restriction, including without limitation the rights 10 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | # copies of the Software, and to permit persons to whom the Software is 12 | # furnished to do so, subject to the following conditions: 13 | # 14 | # The above copyright notice and this permission notice shall be included in all 15 | # copies or substantial portions of the Software. 16 | # 17 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | # SOFTWARE. 24 | # 25 | # ----------------------------------------------------------------------------- 26 | # 27 | # 28 | # 29 | # 30 | # last updated 2015-06-28 by Ben Johnson bjohnson@bit9.com 31 | # 32 | 33 | import sys 34 | import time 35 | import optparse 36 | import cbapi 37 | 38 | def build_cli_parser(): 39 | parser = optparse.OptionParser(usage="%prog [options]", description="Dump sensor list") 40 | 41 | # for each supported output type, add an option 42 | # 43 | parser.add_option("-c", "--cburl", action="store", default=None, dest="url", 44 | help="CB server's URL. e.g., http://127.0.0.1 ") 45 | parser.add_option("-a", "--apitoken", action="store", default=None, dest="token", 46 | help="API Token for Carbon Black server") 47 | parser.add_option("-n", "--no-ssl-verify", action="store_false", default=True, dest="ssl_verify", 48 | help="Do not verify server SSL certificate") 49 | parser.add_option("-d", "--details", action="store_true", default=False, dest="detail", 50 | help="Show detailed endpoint-by-endpoint listing") 51 | parser.add_option("-w", "--without-agent", action="store_true", default=False, dest="withoutagent", 52 | help="When ouputting detailed report, only output endpoints without an installed platform agent") 53 | return parser 54 | 55 | def cheesy_is_sensor_more_or_less_active(sensor): 56 | """ 57 | simplistic routine to determine if sensor is active 58 | make this determination by seeing if the scheduled checkin time is this month 59 | 60 | next checkin time is of the form: 2015-03-23 18:09:42.705408-04:00 61 | """ 62 | ds = sensor['next_checkin_time'].split(' ')[0] 63 | 64 | if int(ds.split('-')[0]) < int(time.strftime("%Y")) or \ 65 | int(ds.split('-')[1]) < int(time.strftime("%m")): 66 | return False 67 | 68 | return True 69 | 70 | def main(argv): 71 | parser = build_cli_parser() 72 | opts, args = parser.parse_args(argv) 73 | if not opts.url or not opts.token: 74 | print "Missing required param; run with --help for usage" 75 | sys.exit(-1) 76 | 77 | # build a cbapi object 78 | # 79 | cb = cbapi.CbApi(opts.url, token=opts.token, ssl_verify=opts.ssl_verify) 80 | 81 | # enumerate sensors 82 | # 83 | sensors = cb.sensors() 84 | 85 | num_platform_agents = 0 86 | num_active_endpoints = 0 87 | 88 | # output each sensor in turn 89 | # 90 | if opts.detail: 91 | print "%-20s | %-40s | %-20s | %s" % ("CB Sensor Id", "Computer Name", "Platform Agent Host Id", "Next Checkin Time") 92 | 93 | for sensor in sensors: 94 | if not cheesy_is_sensor_more_or_less_active(sensor): 95 | continue 96 | if opts.detail: 97 | if not opts.withoutagent or (opts.withoutagent and int(sensor['parity_host_id']) == 0): 98 | print "%-20s | %-40s | %-20s | %s" % (sensor['id'], sensor['computer_name'], sensor['parity_host_id'], sensor['next_checkin_time']) 99 | if int(sensor['parity_host_id']) > 0: 100 | num_platform_agents = num_platform_agents + 1 101 | num_active_endpoints = num_active_endpoints + 1 102 | 103 | print 104 | print "Report" 105 | print "------------" 106 | print "%-30s : %s" % ("Total Endpoints", num_active_endpoints) 107 | print "%-30s : %s" % ("Total Platform Agents", num_platform_agents) 108 | print "%-30s : %s" % ("Percentage w/ Platform Agent", num_platform_agents * 100 / num_active_endpoints) 109 | 110 | if not opts.detail: 111 | print 112 | print "Run with the --detail switch for endpoint-by-endpoint reporting" 113 | 114 | if __name__ == "__main__": 115 | sys.exit(main(sys.argv[1:])) 116 | -------------------------------------------------------------------------------- /powershell_long_running.py: -------------------------------------------------------------------------------- 1 | #!/bin/env python 2 | # Author: bj@carbonblack.com 3 | import optparse 4 | import datetime 5 | import sys 6 | import pprint 7 | import requests 8 | import cbapi 9 | 10 | requests.packages.urllib3.disable_warnings() 11 | 12 | def build_cli_parser(): 13 | parser = optparse.OptionParser(usage="%prog [options]", description="Dump sensor list") 14 | 15 | # for each supported output type, add an option 16 | # 17 | parser.add_option("-c", "--cburl", action="store", default=None, dest="url", 18 | help="CB server's URL. e.g., http://127.0.0.1 ") 19 | parser.add_option("-a", "--apitoken", action="store", default=None, dest="token", 20 | help="API Token for Carbon Black server") 21 | parser.add_option("-n", "--no-ssl-verify", action="store", default=False, dest="ssl_verify", 22 | help="Do not verify server SSL certificate.") 23 | return parser 24 | 25 | def parent_search(opts, pdoc): 26 | 27 | opts.query = "hostname: %s process_name: %s process_pid: %d" % (pdoc['hostname'], pdoc['parent_name'], pdoc['parent_pid']) 28 | 29 | # build a cbapi object 30 | cb = cbapi.CbApi(opts.url, token=opts.token, ssl_verify=opts.ssl_verify) 31 | 32 | # use the cbapi object to iterate over all matching process documents 33 | try: 34 | r = cb.process_search(opts.query) 35 | identifier = r['results'][0]['id'] 36 | seg_id = r['results'][0]['segment_id'] 37 | except: 38 | return False 39 | 40 | try: 41 | events = cb.process_events(identifier, seg_id) 42 | for cpe in events['process']['childproc_complete']: 43 | cpe_split = cpe.split('|',) 44 | if int(cpe_split[4]) == pdoc['process_pid'] and cpe_split[5] == 'false': 45 | process_end_time = datetime.datetime.strptime(cpe_split[0], "%Y-%m-%d %H:%M:%S.%f") 46 | return process_end_time 47 | except: 48 | return False 49 | return False 50 | 51 | def main(argv): 52 | parser = build_cli_parser() 53 | opts, args = parser.parse_args(argv) 54 | if not opts.url or not opts.token: 55 | print "Missing required param." 56 | sys.exit(-1) 57 | 58 | opts.query = 'process_name:powershell.exe' 59 | print "Initial Query: %s", opts.query 60 | # build a cbapi object 61 | cb = cbapi.CbApi(opts.url, token=opts.token, ssl_verify=opts.ssl_verify) 62 | source_set = cb.process_search(opts.query) 63 | if source_set['total_results'] > 500: 64 | print "Total Results: %d" % source_set['total_results'] 65 | print "More than 500 results to parse, exiting script to spare your CB server." 66 | sys.exit(0) 67 | 68 | # use the cbapi object to iterate over all matching process documents 69 | answer = cb.process_search_iter(opts.query) 70 | count = 0 71 | lrcount = 0 72 | # iterate over each process document in the results set 73 | for pdoc in answer: 74 | count += 1 75 | # Query the parent process to see if this child process has ended and assign the end date to process_end_time 76 | process_end_time = parent_search(opts, pdoc) 77 | 78 | if process_end_time: 79 | end = process_end_time 80 | else: 81 | end = datetime.datetime.strptime(pdoc['last_update'], "%Y-%m-%dT%H:%M:%S.%fZ") 82 | 83 | # Start time 84 | start = datetime.datetime.strptime(pdoc['start'], "%Y-%m-%dT%H:%M:%S.%fZ") 85 | 86 | # Difference betweeen the process end time and process start time 87 | runtime = int((end - start).seconds) 88 | 89 | # Change the compared value if 60 seconds is not considered a long run of powershell 90 | if runtime > 60: 91 | lrcount += 1 92 | print "#########################" 93 | print "Proc Doc: %s/#/analyze/%s/%d" % (opts.url, pdoc['id'], pdoc['segment_id']) 94 | print "Hostname: ", pdoc['hostname'] 95 | print "Username: ", pdoc['username'] 96 | print "Process Name: ", pdoc['process_name'] 97 | print "Command Line: ", pdoc['cmdline'] 98 | print "Runtime: %d seconds" % runtime 99 | print "Process start : %s" % start 100 | print "Process endtime: %s" % end 101 | print "$$$$$$$$$$$$$$$$$$$$$$$$$" 102 | print "Matching Process Count: ", count 103 | print "Matching Long Running Process Count: ", lrcount 104 | 105 | if __name__ == "__main__": 106 | sys.exit(main(sys.argv[1:])) 107 | 108 | -------------------------------------------------------------------------------- /powershell_long_running_yesterday.py: -------------------------------------------------------------------------------- 1 | #!/bin/env python 2 | # Author: bj@carbonblack.com 3 | import optparse 4 | import datetime 5 | import sys 6 | import pprint 7 | import requests 8 | import cbapi 9 | 10 | requests.packages.urllib3.disable_warnings() 11 | 12 | def build_cli_parser(): 13 | parser = optparse.OptionParser(usage="%prog [options]", description="Dump sensor list") 14 | 15 | # for each supported output type, add an option 16 | # 17 | parser.add_option("-c", "--cburl", action="store", default=None, dest="url", 18 | help="CB server's URL. e.g., http://127.0.0.1 ") 19 | parser.add_option("-a", "--apitoken", action="store", default=None, dest="token", 20 | help="API Token for Carbon Black server") 21 | parser.add_option("-n", "--no-ssl-verify", action="store", default=False, dest="ssl_verify", 22 | help="Do not verify server SSL certificate.") 23 | return parser 24 | 25 | def parent_search(opts, pdoc): 26 | 27 | opts.query = "hostname: %s process_name: %s process_pid: %d" % (pdoc['hostname'], pdoc['parent_name'], pdoc['parent_pid']) 28 | 29 | # build a cbapi object 30 | cb = cbapi.CbApi(opts.url, token=opts.token, ssl_verify=opts.ssl_verify) 31 | 32 | # use the cbapi object to iterate over all matching process documents 33 | try: 34 | r = cb.process_search(opts.query) 35 | identifier = r['results'][0]['id'] 36 | seg_id = r['results'][0]['segment_id'] 37 | except: 38 | return False 39 | 40 | try: 41 | events = cb.process_events(identifier, seg_id) 42 | for cpe in events['process']['childproc_complete']: 43 | cpe_split = cpe.split('|',) 44 | if int(cpe_split[4]) == pdoc['process_pid'] and cpe_split[5] == 'false': 45 | process_end_time = datetime.datetime.strptime(cpe_split[0], "%Y-%m-%d %H:%M:%S.%f") 46 | return process_end_time 47 | except: 48 | return False 49 | return False 50 | 51 | def main(argv): 52 | parser = build_cli_parser() 53 | opts, args = parser.parse_args(argv) 54 | if not opts.url or not opts.token: 55 | print "Missing required param." 56 | sys.exit(-1) 57 | 58 | yesterday = datetime.datetime.now() - datetime.timedelta(days=1) 59 | yesterday = yesterday.strftime('%Y-%m-%d') 60 | opts.query = 'process_name:powershell.exe and start: %s' % yesterday 61 | print "Initial Query: %s", opts.query 62 | # build a cbapi object 63 | cb = cbapi.CbApi(opts.url, token=opts.token, ssl_verify=opts.ssl_verify) 64 | source_set = cb.process_search(opts.query) 65 | if source_set['total_results'] > 500: 66 | print "Total Results: %d" % source_set['total_results'] 67 | print "More than 500 results to parse, exiting script to spare your CB server." 68 | sys.exit(0) 69 | 70 | # use the cbapi object to iterate over all matching process documents 71 | answer = cb.process_search_iter(opts.query) 72 | count = 0 73 | lrcount = 0 74 | # iterate over each process document in the results set 75 | for pdoc in answer: 76 | count += 1 77 | # Query the parent process to see if this child process has ended and assign the end date to process_end_time 78 | process_end_time = parent_search(opts, pdoc) 79 | 80 | if process_end_time: 81 | end = process_end_time 82 | else: 83 | end = datetime.datetime.strptime(pdoc['last_update'], "%Y-%m-%dT%H:%M:%S.%fZ") 84 | 85 | # Start time 86 | start = datetime.datetime.strptime(pdoc['start'], "%Y-%m-%dT%H:%M:%S.%fZ") 87 | 88 | # Difference betweeen the process end time and process start time 89 | runtime = int((end - start).seconds) 90 | 91 | # Change the compared value if 60 seconds is not considered a long run of powershell 92 | if runtime > 60: 93 | lrcount += 1 94 | print "#########################" 95 | print "Proc Doc: %s/#/analyze/%s/%d" % (opts.url, pdoc['id'], pdoc['segment_id']) 96 | print "Hostname: ", pdoc['hostname'] 97 | print "Username: ", pdoc['username'] 98 | print "Process Name: ", pdoc['process_name'] 99 | print "Command Line: ", pdoc['cmdline'] 100 | print "Runtime: %d seconds" % runtime 101 | print "Process start : %s" % start 102 | print "Process endtime: %s" % end 103 | print "$$$$$$$$$$$$$$$$$$$$$$$$$" 104 | print "Matching Process Count: ", count 105 | print "Matching Long Running Process Count: ", lrcount 106 | 107 | if __name__ == "__main__": 108 | sys.exit(main(sys.argv[1:])) 109 | 110 | -------------------------------------------------------------------------------- /process_composition.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # 3 | #The MIT License (MIT) 4 | # 5 | # Copyright (c) 2015 Bit9 + Carbon Black 6 | # 7 | # Permission is hereby granted, free of charge, to any person obtaining a copy 8 | # of this software and associated documentation files (the "Software"), to deal 9 | # in the Software without restriction, including without limitation the rights 10 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | # copies of the Software, and to permit persons to whom the Software is 12 | # furnished to do so, subject to the following conditions: 13 | # 14 | # The above copyright notice and this permission notice shall be included in all 15 | # copies or substantial portions of the Software. 16 | # 17 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | # SOFTWARE. 24 | # 25 | # ----------------------------------------------------------------------------- 26 | # 27 | # 28 | # 29 | # 30 | # last updated 2015-07-03 by Ben Johnson bjohnson@bit9.com 31 | # 32 | 33 | import sys 34 | import optparse 35 | import cbapi 36 | 37 | def build_cli_parser(): 38 | parser = optparse.OptionParser(usage="%prog [options]", description="Perform a process search") 39 | 40 | # for each supported output type, add an option 41 | # 42 | parser.add_option("-c", "--cburl", action="store", default=None, dest="url", 43 | help="CB server's URL. e.g., http://127.0.0.1 ") 44 | parser.add_option("-a", "--apitoken", action="store", default=None, dest="token", 45 | help="API Token for Carbon Black server") 46 | parser.add_option("-n", "--no-ssl-verify", action="store_false", default=True, dest="ssl_verify", 47 | help="Do not verify server SSL certificate.") 48 | return parser 49 | 50 | def output_mostcommon(results, facet_name, legend, max=10): 51 | """ 52 | output the most common terms from process search facet results 53 | """ 54 | 55 | i = 0 56 | print "%-60s | %s" % (legend, '% of Total Processes') 57 | print "%-60s + %s" % ('-' * 60, '-' * 19) 58 | for entry in results['facets'][facet_name]: 59 | print "%-60s | %s%%" % (entry['name'], entry['ratio']) 60 | if i > max: 61 | break 62 | else: 63 | i = i + 1 64 | print 65 | 66 | def main(argv): 67 | parser = build_cli_parser() 68 | opts, args = parser.parse_args(argv) 69 | if not opts.url or not opts.token: 70 | print "Missing required param; run with --help for usage" 71 | sys.exit(-1) 72 | 73 | # build a cbapi object 74 | # 75 | cb = cbapi.CbApi(opts.url, token=opts.token, ssl_verify=opts.ssl_verify) 76 | 77 | # perform a single process search 78 | # 79 | processes = cb.process_search("", rows=0) 80 | 81 | print "%-20s : %s" % ('Total Processes', processes['total_results']) 82 | print "%-20s : %sms" % ('QTime', int(1000*processes['elapsed'])) 83 | print '\n' 84 | 85 | 86 | # top-level statistics - 'noisiest' hostnames, processes, parent 87 | # processes, usernames, and full process paths 88 | # 89 | output_mostcommon(processes, 'hostname', 'Hostname') 90 | output_mostcommon(processes, 'process_name', 'Process Name') 91 | output_mostcommon(processes, 'parent_name', 'Parent Process Name') 92 | output_mostcommon(processes, 'username_full', 'Username') 93 | output_mostcommon(processes, 'path_full', 'Full Process Path') 94 | 95 | # deeper-dive - for the noisiest processes, what are the most common 96 | # parent process names? 97 | # 98 | print 99 | print "-" * 80 100 | print 101 | 102 | i = 0 103 | for entry in processes['facets']['process_name']: 104 | processes2 = cb.process_search("process_name:%s" % (entry['name'],), rows=0) 105 | print 106 | print "Most common parent processes for %s" % (entry['name'],) 107 | print "-" * 80 108 | for entry2 in processes2['facets']['parent_name']: 109 | try: 110 | print " %-40s | %s" % (entry2['name'], entry2['ratio']) 111 | except: 112 | pass 113 | i = i + 1 114 | if i > 10: 115 | break 116 | 117 | if __name__ == "__main__": 118 | sys.exit(main(sys.argv[1:])) 119 | -------------------------------------------------------------------------------- /process_report.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # 3 | #The MIT License (MIT) 4 | # 5 | # Copyright (c) 2015 Bit9 + Carbon Black 6 | # 7 | # Permission is hereby granted, free of charge, to any person obtaining a copy 8 | # of this software and associated documentation files (the "Software"), to deal 9 | # in the Software without restriction, including without limitation the rights 10 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | # copies of the Software, and to permit persons to whom the Software is 12 | # furnished to do so, subject to the following conditions: 13 | # 14 | # The above copyright notice and this permission notice shall be included in all 15 | # copies or substantial portions of the Software. 16 | # 17 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | # SOFTWARE. 24 | # 25 | # ----------------------------------------------------------------------------- 26 | # 27 | # 28 | # 29 | # 30 | # last updated 2015-06-28 by Ben Johnson bjohnson@bit9.com 31 | # 32 | 33 | import sys 34 | import optparse 35 | import cbapi 36 | 37 | def build_cli_parser(): 38 | parser = optparse.OptionParser(usage="%prog [options]", description="Dump a \"report\" package for a given process") 39 | 40 | # for each supported output type, add an option 41 | parser.add_option("-c", "--cburl", action="store", default=None, dest="url", 42 | help="CB server's URL. e.g., http://127.0.0.1 ") 43 | parser.add_option("-a", "--apitoken", action="store", default=None, dest="token", 44 | help="API Token for Carbon Black server") 45 | parser.add_option("-n", "--no-ssl-verify", action="store_false", default=True, dest="ssl_verify", 46 | help="Do not verify server SSL certificate.") 47 | parser.add_option("-f", "--file", action="store", default=None, dest="fname", 48 | help="Filename where the retrieved report is written.") 49 | parser.add_option("-i", "--id", action="store", default=None, dest="id", 50 | help="Carbon Black process identifier") 51 | parser.add_option("-s", "--segment", action="store", default=0, dest="segment", 52 | help="Carbon Black process segment identifier") 53 | return parser 54 | 55 | def main(argv): 56 | parser = build_cli_parser() 57 | opts, args = parser.parse_args(argv) 58 | if not opts.url or not opts.token or not opts.fname or not opts.id: 59 | print "Missing required param." 60 | sys.exit(-1) 61 | 62 | # setup the CbApi object 63 | # 64 | cb = cbapi.CbApi(opts.url, token=opts.token, ssl_verify=opts.ssl_verify) 65 | 66 | print "-> querying for report for id '%s'..." % (opts.id) 67 | report = cb.process_report(opts.id, opts.segment) 68 | 69 | print "-> writing report to file '%s'..." % (opts.fname) 70 | open(opts.fname, "w").write(report) 71 | 72 | print "-> Complete" 73 | 74 | if __name__ == "__main__": 75 | sys.exit(main(sys.argv[1:])) 76 | -------------------------------------------------------------------------------- /process_search.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # 3 | #The MIT License (MIT) 4 | # 5 | # Copyright (c) 2015 Bit9 + Carbon Black 6 | # 7 | # Permission is hereby granted, free of charge, to any person obtaining a copy 8 | # of this software and associated documentation files (the "Software"), to deal 9 | # in the Software without restriction, including without limitation the rights 10 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | # copies of the Software, and to permit persons to whom the Software is 12 | # furnished to do so, subject to the following conditions: 13 | # 14 | # The above copyright notice and this permission notice shall be included in all 15 | # copies or substantial portions of the Software. 16 | # 17 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | # SOFTWARE. 24 | # 25 | # ----------------------------------------------------------------------------- 26 | # 27 | # 28 | # 29 | # 30 | # last updated 2015-06-28 by Ben Johnson bjohnson@bit9.com 31 | # 32 | 33 | import pprint 34 | try: 35 | from cbapi.legacy.util.cli_helpers import main_helper 36 | except ImportError: 37 | from cbapi.util.cli_helpers import main_helper 38 | 39 | def main(cb, args): 40 | 41 | # perform a single process search 42 | # 43 | processes = cb.process_search(args.get('query')) 44 | 45 | print "%-20s : %s" % ('Displayed Results', len(processes['results'])) 46 | print "%-20s : %s" % ('Total Results', processes['total_results']) 47 | print "%-20s : %sms" % ('QTime', int(1000*processes['elapsed'])) 48 | print '\n' 49 | 50 | # for each result 51 | for process in processes['results']: 52 | pprint.pprint(process) 53 | print '\n' 54 | 55 | if __name__ == "__main__": 56 | required_arg = ("-q", "--query", "store", None, "query", "Process search query") 57 | main_helper("Generic process search", main, custom_required=[required_arg]) -------------------------------------------------------------------------------- /process_search_hunter.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # 3 | #The MIT License (MIT) 4 | # 5 | # Copyright (c) 2015 Bit9 + Carbon Black 6 | # 7 | # Permission is hereby granted, free of charge, to any person obtaining a copy 8 | # of this software and associated documentation files (the "Software"), to deal 9 | # in the Software without restriction, including without limitation the rights 10 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | # copies of the Software, and to permit persons to whom the Software is 12 | # furnished to do so, subject to the following conditions: 13 | # 14 | # The above copyright notice and this permission notice shall be included in all 15 | # copies or substantial portions of the Software. 16 | # 17 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | # SOFTWARE. 24 | # 25 | # ----------------------------------------------------------------------------- 26 | # The purpose of this script is to execute a large number of Cb Queries against 27 | # a Cb server and only display back the queries that have a matching process 28 | # ***Facets must be enabled and used in the query*** 29 | # by default Facets are enabled on Process Search Queries in Carbon Black 30 | # 31 | # last updated 2015-11-23 32 | # 33 | 34 | import sys 35 | import struct 36 | import socket 37 | import json 38 | from optparse import OptionParser 39 | 40 | # in the github repo, cbapi is not in the example directory 41 | sys.path.append('../src/cbapi') 42 | from cbapi import CbApi 43 | #this is the size of the data returned 44 | pagesize=20 45 | 46 | def build_cli_parser(): 47 | parser = OptionParser(usage="%prog [options]", description="Hunt a Carbon Black Server based on a list of queries") 48 | 49 | # for each supported output type, add an option 50 | parser.add_option("-c", "--cburl", action="store", default=None, dest="server", 51 | help="CB server's URL. e.g., http://127.0.0.1 ") 52 | parser.add_option("-a", "--apitoken", action="store", default=None, dest="token", 53 | help="API Token for Carbon Black server") 54 | parser.add_option("-f", "--searchfile", action="store", default=None, dest="procsearchfile", 55 | help="File containing a line for each query you would like to run") 56 | parser.add_option("-n", "--no-ssl-verify", action="store_false", default=True, dest="ssl_verify", 57 | help="Do not verify server SSL certificate.") 58 | return parser 59 | 60 | 61 | def processsearchlist(procnamefile): 62 | with open(procnamefile) as tmp: 63 | lines = filter(None, [line.strip() for line in tmp]) 64 | return lines 65 | 66 | parser = build_cli_parser() 67 | opts, args = parser.parse_args(sys.argv[1:]) 68 | if not opts.server or not opts.token or not opts.procsearchfile: 69 | print "Missing required param." 70 | sys.exit(-1) 71 | 72 | cb = CbApi(opts.server, ssl_verify=opts.ssl_verify, token=opts.token) 73 | searchprocess = processsearchlist(opts.procsearchfile) 74 | for search in searchprocess: 75 | data = cb.process_search(search, rows=1) 76 | if 0 != (data['total_results']): 77 | print "------------------------------" 78 | print "Search Query | %s" % (search) 79 | print "Resulting Processes | %s" % (data['total_results']) 80 | facet=data['facets'] 81 | hosts =[] 82 | for term in facet['hostname']: 83 | hosts.append("%s (%s%%)" % (term['name'], term['ratio'])) 84 | print "Resulting Hosts | "+"|".join(hosts) 85 | -------------------------------------------------------------------------------- /process_users_on_host.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # 3 | #The MIT License (MIT) 4 | ## 5 | # Copyright (c) 2015 Bit9 + Carbon Black 6 | # 7 | # Permission is hereby granted, free of charge, to any person obtaining a copy 8 | # of this software and associated documentation files (the "Software"), to deal 9 | # in the Software without restriction, including without limitation the rights 10 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | # copies of the Software, and to permit persons to whom the Software is 12 | # furnished to do so, subject to the following conditions: 13 | # 14 | # The above copyright notice and this permission notice shall be included in all 15 | # copies or substantial portions of the Software. 16 | # 17 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | # SOFTWARE. 24 | # 25 | # ----------------------------------------------------------------------------- 26 | # 27 | # 28 | # USAGE: python process_users_on_host.py -c https://127.0.0.1:443 -a 167b2587fbc3f6c0c488ab3ddd9d370fdb3f3dcb -n -H WIN-N15HDTS50LK 29 | # 30 | # EXAMPLE OUTPUT: 31 | # 32 | # USER REPORT FOR WIN-N15HDTS50LK: 33 | # -------------------------------------------- 34 | # NEW USER found on WIN-N15HDTS50LK : NETWORK SERVICE 35 | # NEW USER found on WIN-N15HDTS50LK : SYSTEM 36 | # NEW USER found on WIN-N15HDTS50LK : LOCAL SERVICE 37 | # NEW USER found on WIN-N15HDTS50LK : WIN-N15HDTS50LK\BTedesco 38 | # NEW USER found on WIN-N15HDTS50LK : (unknown) 39 | # 40 | # Hostname | Process Count : Username 41 | # -------------------------------------------- 42 | # WIN-N15HDTS50LK | 136 = WIN-N15HDTS50LK\BTedesco 43 | # WIN-N15HDTS50LK | 43 = (unknown) 44 | # WIN-N15HDTS50LK | 32 = NETWORK SERVICE 45 | # WIN-N15HDTS50LK | 1487 = SYSTEM 46 | # WIN-N15HDTS50LK | 27 = LOCAL SERVICE 47 | # 48 | # 49 | # 50 | # last updated 2015-12-10 by Ben Tedesco btedesco@bit9.com 51 | # 52 | 53 | import sys 54 | import struct 55 | import socket 56 | from optparse import OptionParser 57 | from cbapi import CbApi 58 | 59 | class CBQuery(object): 60 | def __init__(self, url, token, ssl_verify): 61 | self.cb = CbApi(url, token=token, ssl_verify=ssl_verify) 62 | self.cb_url = url 63 | 64 | def report(self, hostname, user_dictionary): 65 | print "" 66 | print "%s | %s : %s" % ("Hostname", "Process Count", "Username") 67 | print "--------------------------------------------" 68 | 69 | for key,value in user_dictionary.items(): 70 | print "%s | %s = %s" % (hostname, value, key) 71 | 72 | def check(self, hostname): 73 | # print a legend 74 | print "" 75 | print "USER REPORT FOR %s:" % (hostname) 76 | print "--------------------------------------------" 77 | 78 | # build the query string 79 | q = "hostname:%s" % (hostname) 80 | 81 | #define dictionary 82 | user_dictionary = dict() 83 | 84 | # loop over the entire result set 85 | for result in self.cb.process_search_iter(q): 86 | user_name = result.get("username", "") 87 | 88 | if user_name not in user_dictionary.keys(): 89 | print "NEW USER found on %s : %s" % (hostname, user_name) 90 | user_dictionary[user_name] = 1 91 | else: 92 | user_dictionary[user_name] = user_dictionary[user_name] + 1 93 | 94 | self.report(hostname, user_dictionary) 95 | 96 | def build_cli_parser(): 97 | parser = OptionParser(usage="%prog [options]", description="Dump all usernames & associated process counts for given host.") 98 | 99 | # for each supported output type, add an option 100 | parser.add_option("-c", "--cburl", action="store", default=None, dest="url", 101 | help="CB server's URL. e.g., https://127.0.0.1:443") 102 | parser.add_option("-a", "--apitoken", action="store", default=None, dest="token", 103 | help="API Token for Carbon Black server") 104 | parser.add_option("-n", "--no-ssl-verify", action="store_false", default=True, dest="ssl_verify", 105 | help="Do not verify server SSL certificate.") 106 | parser.add_option("-H", "--hostname", action="store", default=None, dest="hostname", 107 | help="Endpoint hostname to query for network traffic") 108 | return parser 109 | 110 | def main(argv): 111 | parser = build_cli_parser() 112 | opts, args = parser.parse_args(argv) 113 | if not opts.url or not opts.token or not opts.hostname: 114 | print "Missing required param." 115 | sys.exit(-1) 116 | 117 | cb = CBQuery(opts.url, opts.token, ssl_verify=opts.ssl_verify) 118 | 119 | cb.check(opts.hostname) 120 | 121 | if __name__ == "__main__": 122 | sys.exit(main(sys.argv[1:])) 123 | -------------------------------------------------------------------------------- /put_file.py: -------------------------------------------------------------------------------- 1 | try: 2 | from cbapi.legacy.util.cli_helpers import main_helper 3 | from cbapi.legacy.util.live_response_helpers import LiveResponseHelper 4 | except ImportError: 5 | from cbapi.util.cli_helpers import main_helper 6 | from cbapi.util.live_response_helpers import LiveResponseHelper 7 | 8 | def main(cb, args): 9 | lfile = args.get('lfile') 10 | rfile = args.get('rfile') 11 | sensor_id = int(args.get('sensorid')) 12 | lrh = LiveResponseHelper(cb, sensor_id) 13 | lrh.start() 14 | 15 | print "[*] Attempting to upload file: %s" % lfile 16 | results = lrh.put_file(rfile, lfile) 17 | print "\n[+] Results:\n============" 18 | for i in results: 19 | print i + ' = ' + str(results[i]) 20 | lrh.stop() 21 | 22 | if __name__ == "__main__": 23 | sensor_arg = ("-s", "--sensorid", "store", None, "sensorid", "Sensor id") 24 | lfile_arg = ("-l", "--localfile", "store", None, "lfile", "Local File Path") 25 | rfile_arg = ("-r", "--remotefile", "store", None, "rfile", "Remote File Path") 26 | main_helper("Place a file on remote sensor", main, custom_required=[sensor_arg, lfile_arg, rfile_arg]) 27 | -------------------------------------------------------------------------------- /report_search.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # 3 | #The MIT License (MIT) 4 | # 5 | # Copyright (c) 2015 Bit9 + Carbon Black 6 | # 7 | # Permission is hereby granted, free of charge, to any person obtaining a copy 8 | # of this software and associated documentation files (the "Software"), to deal 9 | # in the Software without restriction, including without limitation the rights 10 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | # copies of the Software, and to permit persons to whom the Software is 12 | # furnished to do so, subject to the following conditions: 13 | # 14 | # The above copyright notice and this permission notice shall be included in all 15 | # copies or substantial portions of the Software. 16 | # 17 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | # SOFTWARE. 24 | # 25 | # ----------------------------------------------------------------------------- 26 | # 27 | # 28 | # 29 | # 30 | # last updated 2015-06-28 by Ben Johnson bjohnson@bit9.com 31 | # 32 | 33 | import sys 34 | import optparse 35 | import cbapi 36 | 37 | def build_cli_parser(): 38 | parser = optparse.OptionParser(usage="%prog [options]", description="Search threat reports in configured and enabled feeds") 39 | 40 | # for each supported output type, add an option 41 | # 42 | parser.add_option("-c", "--cburl", action="store", default=None, dest="url", 43 | help="CB server's URL. e.g., http://127.0.0.1 ") 44 | parser.add_option("-a", "--apitoken", action="store", default=None, dest="token", 45 | help="API Token for Carbon Black server") 46 | parser.add_option("-n", "--no-ssl-verify", action="store_false", default=True, dest="ssl_verify", 47 | help="Do not verify server SSL certificate.") 48 | parser.add_option("-q", "--query", action="store", default=None, dest="query", 49 | help="threat report query e.g. severity_score:[0 to 100]") 50 | return parser 51 | 52 | def main(argv): 53 | parser = build_cli_parser() 54 | opts, args = parser.parse_args(argv) 55 | if not opts.url or not opts.token or opts.query is None: 56 | print "Missing required param; run with --help for usage" 57 | sys.exit(-1) 58 | 59 | # build a cbapi object 60 | # 61 | cb = cbapi.CbApi(opts.url, token=opts.token, ssl_verify=opts.ssl_verify) 62 | 63 | # perform a single threat report search 64 | # 65 | reports = cb.threat_report_search(opts.query) 66 | 67 | print "%-20s : %s" % ('Displayed Results', len(reports['results'])) 68 | print "%-20s : %s" % ('Total Results', reports['total_results']) 69 | print "%-20s : %sms" % ('QTime', int(1000*reports['elapsed'])) 70 | print '\n' 71 | 72 | # for each result 73 | for report in reports['results']: 74 | pprint.pprint(report) 75 | print '\n' 76 | if __name__ == "__main__": 77 | sys.exit(main(sys.argv[1:])) 78 | -------------------------------------------------------------------------------- /reporter.cfg: -------------------------------------------------------------------------------- 1 | ######################################################################## 2 | # This is the configuration file for the Carbon Black Reporter script 3 | # designed to provide customizable output in the form of a customizable 4 | # Excel Spreadsheet. The script allows you to customize the tab names 5 | # and fields that you wish to display for binary, process and alerts. 6 | ######################################################################## 7 | # Format: 8 | # 9 | # [Tab Name] 10 | # Type = binary|process|alert 11 | # Fields = 12 | # Query = 13 | ######################################################################## 14 | # Available Fields: 15 | # 16 | # Binary Search: 17 | # 18 | # digsig_result,observed_filename,product_version,legal_copyright, 19 | # alliance_link_virustotal,private_build,is_executable_image,orig_mod_len, 20 | # is_64bit,alliance_score_virustotal,group,file_version,comments, 21 | # company_name,internal_name,product_name,alliance_data_virustotal, 22 | # digsig_result_code,timestamp,alliance_updated_virustotal,copied_mod_len, 23 | # server_added_timestamp,md5,endpoint,watchlists,signed,original_filename, 24 | # cb_version,os_type,file_desc,last_seen 25 | # 26 | # Process Search: 27 | # 28 | # process_md5,sensor_id,modload_count,cmdline,last_update,id,parent_name, 29 | # parent_md5,group,hostname,filemod_count,start,comms_ip,netconn_count, 30 | # interface_ip,process_pid,username,process_name,path,regmod_count,parent_pid, 31 | # crossproc_count,segment_id,host_type,os_type,childproc_count,unique_id 32 | # 33 | # Alert Search: 34 | # 35 | # modload_count,alert_type,sensor_criticality,report_score,watchlist_id, 36 | # sensor_id,feed_name,created_time,report_ignored,ioc_type,crossproc_count, 37 | # ioc_confidence,alert_severity,watchlist_name,group,hostname,filemod_count, 38 | # comms_ip,netconn_count,interface_ip,username,process_path,description, 39 | # process_name,process_id,link,ioc_value,regmod_count,md5,segment_id, 40 | # total_hosts,feed_id,status,os_type,childproc_count,unique_id,feed_rating, 41 | # status,username,hostname,feed_name,assigned_to,watchlist_name 42 | ######################################################################## 43 | # For a full description of the fields listed above please visit 44 | # our developer website at https://developer.carbonblack.com/reference/enterprise-response/5.1/rest-api/#process-data:ec3e4958451e5256ed16afd222059e6d 45 | # on the Carbon Black homepage. In the future fields may be added and 46 | # available for use on this site. 47 | ######################################################################## 48 | 49 | [VT Score Greater than 3 All] 50 | Type = binary 51 | Fields = digsig_result,observed_filename,product_version,legal_copyright,alliance_link_virustotal,private_build,is_executable_image,orig_mod_len,is_64bit,alliance_score_virustotal,group,file_version,comments,company_name,internal_name,product_name,alliance_data_virustotal,digsig_result_code,timestamp,alliance_updated_virustotal,copied_mod_len,server_added_timestamp,md5,endpoint,watchlists,signed,original_filename,cb_version,os_type,file_desc,last_seen 52 | Query = alliance_score_virustotal:[3 TO *] 53 | 54 | [VT Process Score Greater than 3] 55 | Type = process 56 | Fields = hostname,process_md5,path 57 | Query = alliance_score_virustotal:[3 TO *] 58 | 59 | [CMD Started by Cscript Process] 60 | Type = process 61 | Fields = modload,filemod,path,regmod,md5,cmdline,hostname,group,process_name,parent_name,process_md5,filewrite_md5,parent_md5,username,host_type 62 | Query = process_name:wscript.exe AND childproc_name:cmd.exe 63 | 64 | [CMD] 65 | Type = process 66 | Fields = path,cmdline,hostname,group,process_name,parent_name,process_md5,username,host_type 67 | Query = childproc_name:cmd.exe 68 | 69 | [Port 22] 70 | Type = process 71 | Fields = modload_count,alert_type,sensor_criticality,report_score,watchlist_id,sensor_id,feed_name,created_time,report_ignored,ioc_type,crossproc_count,ioc_confidence,alert_severity,watchlist_name,group,hostname,filemod_count,comms_ip,netconn_count,interface_ip,username,process_path,description,process_name,process_id,link,ioc_value,regmod_count,md5,segment_id,total_hosts,feed_id,status,os_type,childproc_count,unique_id,feed_rating,status,username,hostname,feed_name,assigned_to,watchlist_name 72 | Query = ipport:22 73 | 74 | -------------------------------------------------------------------------------- /restart_sensors.conf: -------------------------------------------------------------------------------- 1 | Excessive memory usage 2 | Very high memory usage 3 | Excessive event loss 4 | Very high event loss 5 | -------------------------------------------------------------------------------- /restart_sensors.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # 3 | # The MIT License (MIT) 4 | # 5 | # Copyright (c) 2018 Carbon Black 6 | # 7 | # Permission is hereby granted, free of charge, to any person obtaining a copy 8 | # of this software and associated documentation files (the "Software"), to deal 9 | # in the Software without restriction, including without limitation the rights 10 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | # copies of the Software, and to permit persons to whom the Software is 12 | # furnished to do so, subject to the following conditions: 13 | # 14 | # The above copyright notice and this permission notice shall be included in all 15 | # copies or substantial portions of the Software. 16 | # 17 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | # SOFTWARE. 24 | # 25 | # ----------------------------------------------------------------------------- 26 | # 27 | # Created 2018-03-29 by Jason Garman 28 | 29 | # 30 | # Restart Cb Response sensors when certain criteria are met. 31 | # 32 | # This script will restart sensors that match *any* of the status messages contained within the 33 | # accompanying "restart_sensors.conf" file 34 | # 35 | 36 | import sys 37 | from cbapi.example_helpers import build_cli_parser, get_cb_response_object 38 | from cbapi.response import Sensor 39 | 40 | 41 | def main(): 42 | parser = build_cli_parser("Restart Cb Response sensors when certain criteria are met") 43 | parser.add_argument("--config", "-c", help="Configuration file path", default="restart_sensors.conf") 44 | parser.add_argument("--dryrun", "-d", help="Dry run - don't actually restart sensors", action="store_true") 45 | options = parser.parse_args() 46 | 47 | criteria = [c.strip() for c in open(options.config, "r").readlines()] 48 | criteria = [c for c in criteria if c != ""] 49 | 50 | print("Will restart sensors that have any of the following sensor health messages:") 51 | for c in criteria: 52 | print(" - {0}".format(c)) 53 | 54 | cb = get_cb_response_object(options) 55 | 56 | num_sensors_restarted = 0 57 | 58 | for sensor in cb.select(Sensor): 59 | if sensor.sensor_health_message in criteria: 60 | print("Restarting sensor id {0} (hostname {1}) because its health message is {2}" 61 | .format(sensor.id, sensor.hostname, sensor.sensor_health_message)) 62 | num_sensors_restarted += 1 63 | if not options.dryrun: 64 | sensor.restart_sensor() 65 | 66 | print("{0} {1} sensors.".format("Would have restarted" if options.dryrun else "Restarted", num_sensors_restarted)) 67 | 68 | 69 | if __name__ == '__main__': 70 | sys.exit(main()) -------------------------------------------------------------------------------- /sensor_backlog_aggregate.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # 3 | #The MIT License (MIT) 4 | # 5 | # Copyright (c) 2015 Bit9 + Carbon Black 6 | # 7 | # Permission is hereby granted, free of charge, to any person obtaining a copy 8 | # of this software and associated documentation files (the "Software"), to deal 9 | # in the Software without restriction, including without limitation the rights 10 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | # copies of the Software, and to permit persons to whom the Software is 12 | # furnished to do so, subject to the following conditions: 13 | # 14 | # The above copyright notice and this permission notice shall be included in all 15 | # copies or substantial portions of the Software. 16 | # 17 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | # SOFTWARE. 24 | # 25 | # ----------------------------------------------------------------------------- 26 | # 27 | # 28 | # 29 | # 30 | # last updated 2015-06-28 by Ben Johnson bjohnson@bit9.com 31 | # 32 | 33 | import sys 34 | import time 35 | import json 36 | import socket 37 | import optparse 38 | import cbapi 39 | 40 | def build_cli_parser(): 41 | parser = optparse.OptionParser(usage="%prog [options]", description="Display, and optionally log to UDP, global sensor backlog statistics") 42 | 43 | # for each supported output type, add an option 44 | # 45 | parser.add_option("-c", "--cburl", action="store", default=None, dest="url", 46 | help="CB server's URL. e.g., http://127.0.0.1 ") 47 | parser.add_option("-a", "--apitoken", action="store", default=None, dest="token", 48 | help="API Token for Carbon Black server") 49 | parser.add_option("-n", "--no-ssl-verify", action="store_false", default=True, dest="ssl_verify", 50 | help="Do not verify server SSL certificate.") 51 | parser.add_option("-i", "--interval", action="store", default=0, dest="interval", 52 | help="period, in seconds, in whicy to requery to use this script as a monitoring agent") 53 | parser.add_option("-u", "--udp", action="store", default=None, dest="udp", 54 | help="ip:port or name:port to which do deliver output via UDP, e.g. splunk.my.org:514 only applicable with -i") 55 | return parser 56 | 57 | def output(data, udp): 58 | """ 59 | output the sensor backlog data, in JSON format 60 | always output to stdout 61 | output to udp if so specified 62 | """ 63 | print data 64 | 65 | if udp is None: 66 | return 67 | 68 | try: 69 | sockaddr_components = udp.split(':') 70 | ip = socket.gethostbyname(sockaddr_components[0]) 71 | port = int(sockaddr_components[1]) 72 | sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) 73 | sock.sendto(data + '\n', (ip, port)) 74 | except Exception, e: 75 | print e 76 | 77 | return 78 | 79 | def query_forever(cb, interval, udp): 80 | 81 | while True: 82 | 83 | try: 84 | backlog = cb.sensor_backlog() 85 | output(json.dumps(backlog), udp) 86 | except Exception, e: 87 | print e 88 | pass 89 | 90 | time.sleep(float(interval)) 91 | 92 | return 93 | 94 | def main(argv): 95 | parser = build_cli_parser() 96 | opts, args = parser.parse_args(argv) 97 | if not opts.url or not opts.token: 98 | print "Missing required param; run with --help for usage" 99 | sys.exit(-1) 100 | 101 | # build a cbapi object 102 | # 103 | cb = cbapi.CbApi(opts.url, token=opts.token, ssl_verify=opts.ssl_verify) 104 | 105 | # if a period is specified, handle that specially 106 | # 107 | if 0 != opts.interval: 108 | return query_forever(cb, opts.interval, opts.udp) 109 | 110 | # grab the global statistics 111 | # 112 | backlog = cb.sensor_backlog() 113 | 114 | # output 115 | # 116 | for key in backlog.keys(): 117 | print "%-35s : %s" % (key, backlog[key]) 118 | 119 | if __name__ == "__main__": 120 | sys.exit(main(sys.argv[1:])) 121 | -------------------------------------------------------------------------------- /sensor_backlog_report.py: -------------------------------------------------------------------------------- 1 | import sys 2 | import time 3 | import json 4 | import struct 5 | import socket 6 | import pprint 7 | import optparse 8 | import operator 9 | 10 | # in the github repo, cbapi is not in the example directory 11 | sys.path.append('../src/cbapi') 12 | 13 | import cbapi 14 | 15 | thresholds = [1, 2, 4, 8, 32, 64, 128, 512, 1024] 16 | 17 | def build_cli_parser(): 18 | parser = optparse.OptionParser(usage="%prog [options]", description="Output information sensor backlog state on a sensor-by-sensor basis") 19 | 20 | # for each supported output type, add an option 21 | # 22 | parser.add_option("-c", "--cburl", action="store", default=None, dest="url", 23 | help="CB server's URL. e.g., http://127.0.0.1 ") 24 | parser.add_option("-a", "--apitoken", action="store", default=None, dest="token", 25 | help="API Token for Carbon Black server") 26 | parser.add_option("-n", "--no-ssl-verify", action="store_false", default=True, dest="ssl_verify", 27 | help="Do not verify server SSL certificate.") 28 | return parser 29 | 30 | def main(argv): 31 | parser = build_cli_parser() 32 | opts, args = parser.parse_args(argv) 33 | if not opts.url or not opts.token: 34 | print "Missing required param; run with --help for usage" 35 | sys.exit(-1) 36 | 37 | # build a cbapi object 38 | # 39 | cb = cbapi.CbApi(opts.url, token=opts.token, ssl_verify=opts.ssl_verify) 40 | 41 | # grab the global list of sensors 42 | # this includes backlog data for each sensor 43 | # the backlog is measured in terms of bytes of binaries (store files) and event logs 44 | # 45 | sensors = cb.sensors() 46 | 47 | # create empty "buckets" of sensors based on thresholds of event backlog 48 | # 49 | buckets = {} 50 | for threshold in thresholds: 51 | buckets[threshold] = [] 52 | 53 | # update all the event backlog to be a numeric type for sorting 54 | # 55 | for sensor in sensors: 56 | sensor['num_eventlog_bytes'] = int(sensor.get('num_eventlog_bytes', 0)) 57 | 58 | # sort by total event backlog (desc) 59 | # 60 | sensors.sort(key=operator.itemgetter('num_eventlog_bytes')) 61 | sensors.reverse() 62 | 63 | # output 64 | # 65 | print "%-30s | %-5s | %-50s | %-10s | %10s | %s" % ("Hostname", "Id", "SID", "BinBytes", "EventBytes", "EventMB") 66 | print "%-30s | %-5s | %-50s | %-10s | %10s | %10s" % ('-' * 30, '-' * 5, '-' * 50, '-' * 10, '-' * 10, '-' * 10) 67 | for sensor in sensors: 68 | sid = sensor.get('computer_sid', '') 69 | if None is sid: 70 | sid = "" 71 | 72 | 73 | if True: 74 | print "%-30s | %-5s | %-50s | %-10s | %10s | %s" % (sensor.get('computer_name', ''), 75 | sensor.get('id', ''), 76 | sid, 77 | sensor.get('num_storefiles_bytes', 0), 78 | sensor.get('num_eventlog_bytes', 0), 79 | sensor.get('num_eventlog_bytes', 0) / (1024 * 1024) 80 | ) 81 | 82 | for threshold in thresholds: 83 | if int(sensor.get('num_eventlog_bytes', 0)) < threshold * 1024 * 1024: 84 | buckets[threshold].append(sensor) 85 | break 86 | 87 | 88 | print 89 | print 90 | 91 | # output an overall summary of backlogs by 'buckets' of backlog 92 | # 93 | bucketlist = buckets.keys() 94 | bucketlist.sort() 95 | print "%-20s %s" % ("EventBacklogMB", "NumSensors") 96 | print "%-20s %s" % ("-" * 20, "-" * 20) 97 | for bucket in bucketlist: 98 | print "%-20s %s" % (bucket, len(buckets[bucket])) 99 | 100 | if __name__ == "__main__": 101 | sys.exit(main(sys.argv[1:])) 102 | -------------------------------------------------------------------------------- /sensor_details.py: -------------------------------------------------------------------------------- 1 | #!/bin/env python 2 | # A script to print all the details about a single sensor 3 | 4 | __author__ = 'BJSwope' 5 | import sys 6 | import optparse 7 | import cbapi 8 | import pprint 9 | import warnings 10 | 11 | def build_cli_parser(): 12 | parser = optparse.OptionParser(usage="%prog [options]", description="Dump sensor list") 13 | 14 | # for each supported output type, add an option 15 | # 16 | parser.add_option("-c", "--cburl", action="store", default=None, dest="url", 17 | help="CB server's URL. e.g., http://127.0.0.1 ") 18 | parser.add_option("-a", "--apitoken", action="store", default=None, dest="token", 19 | help="API Token for Carbon Black server") 20 | parser.add_option("-n", "--no-ssl-verify", action="store", default=False, dest="ssl_verify", 21 | help="Do not verify server SSL certificate.") 22 | parser.add_option("-e", "--sensor", action="store", default=None, dest="sensor", 23 | help="sensor id to retrieve") 24 | return parser 25 | 26 | 27 | def main(argv): 28 | parser = build_cli_parser() 29 | opts, args = parser.parse_args(argv) 30 | if not opts.url or not opts.token or not opts.sensor: 31 | print "Missing required param; run with --help for usage" 32 | sys.exit(-1) 33 | 34 | cb = cbapi.CbApi(opts.url, token=opts.token, ssl_verify=opts.ssl_verify, ignore_system_proxy=True) 35 | with warnings.catch_warnings(): 36 | warnings.simplefilter("ignore") 37 | sensor = cb.sensor(opts.sensor) 38 | 39 | pprint.pprint(sensor) 40 | 41 | if __name__ == "__main__": 42 | sys.exit(main(sys.argv[1:])) 43 | 44 | 45 | -------------------------------------------------------------------------------- /sensor_info.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # 3 | #The MIT License (MIT) 4 | # 5 | # Copyright (c) 2015 Bit9 + Carbon Black 6 | # 7 | # Permission is hereby granted, free of charge, to any person obtaining a copy 8 | # of this software and associated documentation files (the "Software"), to deal 9 | # in the Software without restriction, including without limitation the rights 10 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | # copies of the Software, and to permit persons to whom the Software is 12 | # furnished to do so, subject to the following conditions: 13 | # 14 | # The above copyright notice and this permission notice shall be included in all 15 | # copies or substantial portions of the Software. 16 | # 17 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | # SOFTWARE. 24 | # 25 | # ----------------------------------------------------------------------------- 26 | # 27 | # 28 | # 29 | # 30 | # last updated 2015-06-28 by Ben Johnson bjohnson@bit9.com 31 | # 32 | 33 | import sys 34 | import optparse 35 | import cbapi 36 | 37 | def build_cli_parser(): 38 | parser = optparse.OptionParser(usage="%prog [options]", description="Output information about a single sensor") 39 | 40 | # for each supported output type, add an option 41 | # 42 | parser.add_option("-c", "--cburl", action="store", default=None, dest="url", 43 | help="CB server's URL. e.g., http://127.0.0.1 ") 44 | parser.add_option("-a", "--apitoken", action="store", default=None, dest="token", 45 | help="API Token for Carbon Black server") 46 | parser.add_option("-n", "--no-ssl-verify", action="store_false", default=True, dest="ssl_verify", 47 | help="Do not verify server SSL certificate.") 48 | parser.add_option("-s", "--sensor-id", action="store", default=None, dest="sensorid", 49 | help="Sensor Id of the endpoint to query") 50 | return parser 51 | 52 | def main(argv): 53 | parser = build_cli_parser() 54 | opts, args = parser.parse_args(argv) 55 | if not opts.url or not opts.token or not opts.sensorid: 56 | print "Missing required param; run with --help for usage" 57 | sys.exit(-1) 58 | 59 | # build a cbapi object 60 | # 61 | cb = cbapi.CbApi(opts.url, token=opts.token, ssl_verify=opts.ssl_verify) 62 | 63 | # enumerate sensors 64 | # 65 | sensor = cb.sensor(opts.sensorid) 66 | 67 | # output 68 | # 69 | for key in sensor.keys(): 70 | print "%-35s : %s" % (key, sensor[key]) 71 | 72 | if __name__ == "__main__": 73 | sys.exit(main(sys.argv[1:])) 74 | -------------------------------------------------------------------------------- /sensor_list.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # 3 | #The MIT License (MIT) 4 | # 5 | # Copyright (c) 2015 Bit9 + Carbon Black 6 | # 7 | # Permission is hereby granted, free of charge, to any person obtaining a copy 8 | # of this software and associated documentation files (the "Software"), to deal 9 | # in the Software without restriction, including without limitation the rights 10 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | # copies of the Software, and to permit persons to whom the Software is 12 | # furnished to do so, subject to the following conditions: 13 | # 14 | # The above copyright notice and this permission notice shall be included in all 15 | # copies or substantial portions of the Software. 16 | # 17 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | # SOFTWARE. 24 | # 25 | # ----------------------------------------------------------------------------- 26 | # 27 | # 28 | # 29 | # 30 | # last updated 2015-06-28 by Ben Johnson bjohnson@bit9.com 31 | # 32 | 33 | import sys 34 | import optparse 35 | import cbapi 36 | 37 | def build_cli_parser(): 38 | parser = optparse.OptionParser(usage="%prog [options]", description="Dump sensor list") 39 | 40 | # for each supported output type, add an option 41 | # 42 | parser.add_option("-c", "--cburl", action="store", default=None, dest="url", 43 | help="CB server's URL. e.g., http://127.0.0.1 ") 44 | parser.add_option("-a", "--apitoken", action="store", default=None, dest="token", 45 | help="API Token for Carbon Black server") 46 | parser.add_option("-n", "--no-ssl-verify", action="store_false", default=True, dest="ssl_verify", 47 | help="Do not verify server SSL certificate.") 48 | parser.add_option("-f", "--format", action="store", default='plain', dest="format", 49 | help="Output in pipe-delimited ('pipe'), plaintext ('plain') format or csv ('csv'); plain by default") 50 | parser.add_option("-g", "--group", action="store", default=None, dest="groupid", 51 | help="Limit sensor listing to just those specified by the sensor group id provided") 52 | return parser 53 | 54 | def main(argv): 55 | parser = build_cli_parser() 56 | opts, args = parser.parse_args(argv) 57 | if not opts.url or not opts.token: 58 | print "Missing required param; run with --help for usage" 59 | sys.exit(-1) 60 | 61 | if not opts.format == 'plain' and not opts.format == 'pipe' and not opts.format == 'csv': 62 | print "Format must be one of [plain|pipe|csv]" 63 | sys.exit(-1) 64 | 65 | # build a cbapi object 66 | # 67 | cb = cbapi.CbApi(opts.url, token=opts.token, ssl_verify=opts.ssl_verify) 68 | 69 | # set up filters 70 | # 71 | filters = {} 72 | if opts.groupid is not None: 73 | filters['groupid'] = opts.groupid 74 | 75 | # enumerate sensors 76 | # 77 | sensors = cb.sensors(filters) 78 | 79 | # output column headings as appropriate 80 | # 81 | if opts.format == 'pipe': 82 | print "%s|%s|%s|%s|%s" % ("sensor id", "group id", "computer name", "OS", "last checkin time") 83 | if opts.format == 'csv': 84 | print "%s,%s,%s,%s,%s" % ("sensor id", "group id", "computer name", "OS", "last checkin time") 85 | 86 | # output each sensor in turn 87 | # 88 | for sensor in sensors: 89 | if opts.format == 'plain': 90 | print "%-20s : %s" % ("computer name", sensor['computer_name']) 91 | print "----------------------------------------------" 92 | print "%-20s : %s" % ("sensor_group_id", sensor['group_id']) 93 | print "%-20s : %s" % ("sensor id", sensor['id']) 94 | print "%-20s : %s" % ("os", sensor['os_environment_display_string']) 95 | print "%-20s : %s" % ("last checkin time", sensor['last_checkin_time']) 96 | print 97 | elif opts.format == 'pipe': 98 | print "%s|%s|%s|%s|%s" % (sensor['id'], sensor['group_id'], sensor['computer_name'], sensor['os_environment_display_string'], sensor['last_checkin_time']) 99 | elif opts.format == 'csv': 100 | print '"%s","%s","%s","%s","%s"' % (sensor['id'], sensor['group_id'], sensor['computer_name'], sensor['os_environment_display_string'], sensor['last_checkin_time']) 101 | 102 | if __name__ == "__main__": 103 | sys.exit(main(sys.argv[1:])) 104 | -------------------------------------------------------------------------------- /server_info.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # 3 | #The MIT License (MIT) 4 | # 5 | # Copyright (c) 2015 Bit9 + Carbon Black 6 | # 7 | # Permission is hereby granted, free of charge, to any person obtaining a copy 8 | # of this software and associated documentation files (the "Software"), to deal 9 | # in the Software without restriction, including without limitation the rights 10 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | # copies of the Software, and to permit persons to whom the Software is 12 | # furnished to do so, subject to the following conditions: 13 | # 14 | # The above copyright notice and this permission notice shall be included in all 15 | # copies or substantial portions of the Software. 16 | # 17 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | # SOFTWARE. 24 | # 25 | # ----------------------------------------------------------------------------- 26 | # 27 | # 28 | # 29 | # 30 | # last updated 2015-06-28 by Ben Johnson bjohnson@bit9.com 31 | # 32 | 33 | import sys 34 | import optparse 35 | import cbapi 36 | 37 | def build_cli_parser(): 38 | parser = optparse.OptionParser(usage="%prog [options]", description="Display global information about the Carbon Black Server") 39 | 40 | # for each supported output type, add an option 41 | # 42 | parser.add_option("-c", "--cburl", action="store", default=None, dest="server_url", 43 | help="CB server's URL. e.g., http://127.0.0.1 ") 44 | parser.add_option("-a", "--apitoken", action="store", default=None, dest="token", 45 | help="API Token for Carbon Black server") 46 | parser.add_option("-v", "--verifyservercert", action="store_true", default=False, dest="ssl_verify", 47 | help="Perform SSL certificate verificaton of the server cert (applies when using https CB server urls)") 48 | return parser 49 | 50 | def output_info(server, info): 51 | print server 52 | print "-" * 80 53 | for key in info.keys(): 54 | print "%-30s : %s" % (key, info[key]) 55 | 56 | def main(argv): 57 | parser = build_cli_parser() 58 | opts, args = parser.parse_args(argv) 59 | if not opts.server_url or not opts.token: 60 | print "Missing required param; run with --help for usage" 61 | sys.exit(-1) 62 | 63 | # build a cbapi object 64 | # 65 | cb = cbapi.CbApi(opts.server_url, token=opts.token, ssl_verify=opts.ssl_verify) 66 | 67 | output_info(opts.server_url, cb.info()) 68 | 69 | if __name__ == "__main__": 70 | sys.exit(main(sys.argv[1:])) 71 | -------------------------------------------------------------------------------- /watchlist_add_edit_del.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # 3 | #The MIT License (MIT) 4 | # 5 | # Copyright (c) 2015 Bit9 + Carbon Black 6 | # 7 | # Permission is hereby granted, free of charge, to any person obtaining a copy 8 | # of this software and associated documentation files (the "Software"), to deal 9 | # in the Software without restriction, including without limitation the rights 10 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | # copies of the Software, and to permit persons to whom the Software is 12 | # furnished to do so, subject to the following conditions: 13 | # 14 | # The above copyright notice and this permission notice shall be included in all 15 | # copies or substantial portions of the Software. 16 | # 17 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | # SOFTWARE. 24 | # 25 | # ----------------------------------------------------------------------------- 26 | # 27 | # 28 | # 29 | # 30 | # last updated 2015-06-28 by Ben Johnson bjohnson@bit9.com 31 | # 32 | 33 | import sys 34 | import optparse 35 | import cbapi 36 | 37 | def build_cli_parser(): 38 | parser = optparse.OptionParser(usage="%prog [options]", description="Add, Edit, and Delete a Watchlist") 39 | 40 | # for each supported output type, add an option 41 | # 42 | parser.add_option("-c", "--cburl", action="store", default=None, dest="url", 43 | help="CB server's URL. e.g., http://127.0.0.1 ") 44 | parser.add_option("-a", "--apitoken", action="store", default=None, dest="token", 45 | help="API Token for Carbon Black server") 46 | parser.add_option("-n", "--no-ssl-verify", action="store_false", default=True, dest="ssl_verify", 47 | help="Do not verify server SSL certificate.") 48 | return parser 49 | 50 | def watchlist_output(watchlist): 51 | ''' 52 | output information about a watchlist 53 | ''' 54 | 55 | # output the details about the watchlist 56 | # 57 | print '\n' 58 | print ' %-20s | %s' % ('field', 'value') 59 | print ' %-20s + %s' % ('-' * 20, '-' * 60) 60 | print ' %-20s | %s' % ('id', watchlist['id']) 61 | print ' %-20s | %s' % ('name', watchlist['name']) 62 | print ' %-20s | %s' % ('date_added', watchlist['date_added']) 63 | print ' %-20s | %s' % ('last_hit', watchlist['last_hit']) 64 | print ' %-20s | %s' % ('last_hit_count', watchlist['last_hit_count']) 65 | print ' %-20s | %s' % ('search_query', watchlist['search_query']) 66 | print '\n' 67 | 68 | def main(argv): 69 | parser = build_cli_parser() 70 | opts, args = parser.parse_args(argv) 71 | if not opts.url or not opts.token: 72 | print "Missing required param; run with --help for usage" 73 | sys.exit(-1) 74 | 75 | # build a cbapi object 76 | # 77 | cb = cbapi.CbApi(opts.url, token=opts.token, ssl_verify=opts.ssl_verify) 78 | 79 | # add a watchlist 80 | # for the purposes of this test script, hardcode the watchlist type, name, and query string 81 | # 82 | print "-> Adding watchlist..." 83 | watchlist = cb.watchlist_add( 84 | 'events', 85 | 'test watchlist', 86 | 'process_name:notepad.exe') 87 | print "-> Watchlist added [id=%s]" % (watchlist['id']) 88 | 89 | # get record describing this watchlist 90 | # 91 | print "-> Querying for watchlist information..." 92 | watchlist = cb.watchlist(watchlist['id']) 93 | print "-> Watchlist queried; details:" 94 | watchlist_output(watchlist) 95 | 96 | # edit the search query of the just-added watchlist 97 | # 98 | print "-> Modifying the watchlist query..." 99 | watchlist['search_query'] = 'process_name:calc.exe' 100 | cb.watchlist_modify(watchlist['id'], watchlist) 101 | print "-> Watchlist modified" 102 | 103 | # get record describing this watchlist 104 | # 105 | print "-> Querying for watchlist information..." 106 | watchlist = cb.watchlist(watchlist['id']) 107 | print "-> Watchlist queried; details:" 108 | watchlist_output(watchlist) 109 | 110 | # delete the just-added watchlist 111 | # 112 | print "-> Deleting Watchlist..." 113 | cb.watchlist_del(watchlist['id']) 114 | print "-> Watchlist deleted" 115 | 116 | if __name__ == "__main__": 117 | sys.exit(main(sys.argv[1:])) 118 | -------------------------------------------------------------------------------- /watchlist_del.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # 3 | #The MIT License (MIT) 4 | # 5 | # Copyright (c) 2015 Bit9 + Carbon Black 6 | # 7 | # Permission is hereby granted, free of charge, to any person obtaining a copy 8 | # of this software and associated documentation files (the "Software"), to deal 9 | # in the Software without restriction, including without limitation the rights 10 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | # copies of the Software, and to permit persons to whom the Software is 12 | # furnished to do so, subject to the following conditions: 13 | # 14 | # The above copyright notice and this permission notice shall be included in all 15 | # copies or substantial portions of the Software. 16 | # 17 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | # SOFTWARE. 24 | # 25 | # ----------------------------------------------------------------------------- 26 | # 27 | # 28 | # 29 | # 30 | # last updated 2015-06-28 by Ben Johnson bjohnson@bit9.com 31 | # 32 | 33 | import sys 34 | import optparse 35 | import cbapi 36 | 37 | def build_cli_parser(): 38 | parser = optparse.OptionParser(usage="%prog [options]", description="Add a watchlist") 39 | 40 | # for each supported output type, add an option 41 | # 42 | parser.add_option("-c", "--cburl", action="store", default=None, dest="url", 43 | help="CB server's URL. e.g., http://127.0.0.1 ") 44 | parser.add_option("-a", "--apitoken", action="store", default=None, dest="token", 45 | help="API Token for Carbon Black server") 46 | parser.add_option("-n", "--no-ssl-verify", action="store_false", default=True, dest="ssl_verify", 47 | help="Do not verify server SSL certificate.") 48 | parser.add_option("-i", "--id", action="store", default=None, dest="id", 49 | help="Watchlist ID to delete") 50 | return parser 51 | 52 | def main(argv): 53 | parser = build_cli_parser() 54 | opts, args = parser.parse_args(argv) 55 | if not opts.url or not opts.token or not opts.id: 56 | print "Missing required param; run with --help for usage" 57 | sys.exit(-1) 58 | 59 | # build a cbapi object 60 | # 61 | cb = cbapi.CbApi(opts.url, token=opts.token, ssl_verify=opts.ssl_verify) 62 | 63 | # delete the watchlist 64 | # for the purposes of this test script, hardcode the watchlist type, name, and query string 65 | # 66 | print "-> Deleting watchlist [id=%s]..." % (opts.id,) 67 | watchlist = cb.watchlist_del(opts.id) 68 | print "-> Watchlist deleted" 69 | 70 | if __name__ == "__main__": 71 | sys.exit(main(sys.argv[1:])) 72 | -------------------------------------------------------------------------------- /watchlist_edit.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # 3 | #The MIT License (MIT) 4 | # 5 | # Copyright (c) 2015 Bit9 + Carbon Black 6 | # 7 | # Permission is hereby granted, free of charge, to any person obtaining a copy 8 | # of this software and associated documentation files (the "Software"), to deal 9 | # in the Software without restriction, including without limitation the rights 10 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | # copies of the Software, and to permit persons to whom the Software is 12 | # furnished to do so, subject to the following conditions: 13 | # 14 | # The above copyright notice and this permission notice shall be included in all 15 | # copies or substantial portions of the Software. 16 | # 17 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | # SOFTWARE. 24 | # 25 | # ----------------------------------------------------------------------------- 26 | # 27 | # 28 | # 29 | # 30 | # last updated 2015-06-28 by Ben Johnson bjohnson@bit9.com 31 | # 32 | 33 | import sys 34 | import optparse 35 | import cbapi 36 | 37 | def build_cli_parser(): 38 | parser = optparse.OptionParser(usage="%prog [options]", description="Edit the Query of an Existing Watchlist") 39 | 40 | # for each supported output type, add an option 41 | # 42 | parser.add_option("-c", "--cburl", action="store", default=None, dest="url", 43 | help="CB server's URL. e.g., http://127.0.0.1 ") 44 | parser.add_option("-a", "--apitoken", action="store", default=None, dest="token", 45 | help="API Token for Carbon Black server") 46 | parser.add_option("-n", "--no-ssl-verify", action="store_false", default=True, dest="ssl_verify", 47 | help="Do not verify server SSL certificate.") 48 | parser.add_option("-i", "--id", action="store", default=None, dest="id", 49 | help="Watchlist ID to modify") 50 | parser.add_option("-q", "--query", action="store", default=None, dest="query", 51 | help="New search query, e.g. process_name:notepad.exe") 52 | return parser 53 | 54 | def watchlist_output(watchlist): 55 | ''' 56 | output information about a watchlist 57 | ''' 58 | 59 | # output the details about the watchlist 60 | # 61 | print '\n' 62 | print ' %-20s | %s' % ('field', 'value') 63 | print ' %-20s + %s' % ('-' * 20, '-' * 60) 64 | print ' %-20s | %s' % ('id', watchlist['id']) 65 | print ' %-20s | %s' % ('name', watchlist['name']) 66 | print ' %-20s | %s' % ('search_query', watchlist['search_query']) 67 | print '\n' 68 | 69 | def main(argv): 70 | parser = build_cli_parser() 71 | opts, args = parser.parse_args(argv) 72 | if not opts.url or not opts.token or not opts.id or not opts.query: 73 | print "Missing required param; run with --help for usage" 74 | sys.exit(-1) 75 | 76 | # build a cbapi object 77 | # 78 | cb = cbapi.CbApi(opts.url, token=opts.token, ssl_verify=opts.ssl_verify) 79 | 80 | # edit the search query of the just-added watchlist 81 | # 82 | watchlist = { 'search_query': opts.query } 83 | print "-> Modifying the watchlist query..." 84 | cb.watchlist_modify(opts.id, watchlist) 85 | print "-> Watchlist modified" 86 | 87 | # get record describing this watchlist 88 | # 89 | print "-> Querying for watchlist information..." 90 | watchlist = cb.watchlist(opts.id) 91 | print "-> Watchlist queried; details:" 92 | watchlist_output(watchlist) 93 | 94 | if __name__ == "__main__": 95 | sys.exit(main(sys.argv[1:])) 96 | -------------------------------------------------------------------------------- /watchlist_enum.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # 3 | #The MIT License (MIT) 4 | # 5 | # Copyright (c) 2015 Bit9 + Carbon Black 6 | # 7 | # Permission is hereby granted, free of charge, to any person obtaining a copy 8 | # of this software and associated documentation files (the "Software"), to deal 9 | # in the Software without restriction, including without limitation the rights 10 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | # copies of the Software, and to permit persons to whom the Software is 12 | # furnished to do so, subject to the following conditions: 13 | # 14 | # The above copyright notice and this permission notice shall be included in all 15 | # copies or substantial portions of the Software. 16 | # 17 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | # SOFTWARE. 24 | # 25 | # ----------------------------------------------------------------------------- 26 | # 27 | # 28 | # 29 | # 30 | # last updated 2015-06-28 by Ben Johnson bjohnson@bit9.com 31 | # 32 | 33 | import sys 34 | import optparse 35 | import cbapi 36 | 37 | def build_cli_parser(): 38 | parser = optparse.OptionParser(usage="%prog [options]", description="Dump Binary Info") 39 | 40 | # for each supported output type, add an option 41 | # 42 | parser.add_option("-c", "--cburl", action="store", default=None, dest="url", 43 | help="CB server's URL. e.g., http://127.0.0.1 ") 44 | parser.add_option("-a", "--apitoken", action="store", default=None, dest="token", 45 | help="API Token for Carbon Black server") 46 | parser.add_option("-n", "--no-ssl-verify", action="store_false", default=True, dest="ssl_verify", 47 | help="Do not verify server SSL certificate.") 48 | parser.add_option("-f", "--full", action="store_true", default=False, dest="fulloutput", 49 | help="Do not truncate watchlist queries in the output") 50 | return parser 51 | 52 | def truncate(fulloutput, string, length): 53 | if fulloutput: 54 | return string 55 | if len(string) + 2 > length: 56 | return string[:length] + "..." 57 | return string 58 | 59 | def main(argv): 60 | parser = build_cli_parser() 61 | opts, args = parser.parse_args(argv) 62 | if not opts.url or not opts.token: 63 | print "Missing required param; run with --help for usage" 64 | sys.exit(-1) 65 | 66 | # build a cbapi object 67 | # 68 | cb = cbapi.CbApi(opts.url, token=opts.token, ssl_verify=opts.ssl_verify) 69 | 70 | # enumerate all watchlists 71 | # 72 | watchlists = cb.watchlist() 73 | 74 | print "%-4s | %-32s | %s" % ('id', 'name', 'query') 75 | print "%-4s + %-32s + %s" % ('-' * 4, '-' * 32, '-' * 60) 76 | 77 | # for each result 78 | for watchlist in watchlists: 79 | print "%-4s | %-32s | %s" % (watchlist['id'], watchlist['name'], truncate(opts.fulloutput, watchlist['search_query'], 57)) 80 | 81 | if __name__ == "__main__": 82 | sys.exit(main(sys.argv[1:])) 83 | -------------------------------------------------------------------------------- /watchlist_info.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # 3 | #The MIT License (MIT) 4 | # 5 | # Copyright (c) 2015 Bit9 + Carbon Black 6 | # 7 | # Permission is hereby granted, free of charge, to any person obtaining a copy 8 | # of this software and associated documentation files (the "Software"), to deal 9 | # in the Software without restriction, including without limitation the rights 10 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | # copies of the Software, and to permit persons to whom the Software is 12 | # furnished to do so, subject to the following conditions: 13 | # 14 | # The above copyright notice and this permission notice shall be included in all 15 | # copies or substantial portions of the Software. 16 | # 17 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | # SOFTWARE. 24 | # 25 | # ----------------------------------------------------------------------------- 26 | # 27 | # 28 | # 29 | # 30 | # last updated 2015-06-28 by Ben Johnson bjohnson@bit9.com 31 | # 32 | 33 | import sys 34 | import optparse 35 | import cbapi 36 | 37 | def build_cli_parser(): 38 | parser = optparse.OptionParser(usage="%prog [options]", description="Dump Binary Info") 39 | 40 | # for each supported output type, add an option 41 | # 42 | parser.add_option("-c", "--cburl", action="store", default=None, dest="url", 43 | help="CB server's URL. e.g., http://127.0.0.1 ") 44 | parser.add_option("-a", "--apitoken", action="store", default=None, dest="token", 45 | help="API Token for Carbon Black server") 46 | parser.add_option("-n", "--no-ssl-verify", action="store_false", default=True, dest="ssl_verify", 47 | help="Do not verify server SSL certificate.") 48 | parser.add_option("-i", "--id", action="store", default=None, dest="id") 49 | return parser 50 | 51 | def truncate(string, length): 52 | if len(string) + 2 > length: 53 | return string[:length] + "..." 54 | return string 55 | 56 | def main(argv): 57 | parser = build_cli_parser() 58 | opts, args = parser.parse_args(argv) 59 | if not opts.url or not opts.token or not opts.id: 60 | print "Missing required param; run with --help for usage" 61 | sys.exit(-1) 62 | 63 | # build a cbapi object 64 | # 65 | cb = cbapi.CbApi(opts.url, token=opts.token, ssl_verify=opts.ssl_verify) 66 | 67 | # get record describing this watchlist 68 | # 69 | watchlist = cb.watchlist(opts.id) 70 | 71 | # output the details about the watchlist 72 | # 73 | print '%-20s | %s' % ('field', 'value') 74 | print '%-20s + %s' % ('-' * 20, '-' * 60) 75 | print '%-20s | %s' % ('id', watchlist['id']) 76 | print '%-20s | %s' % ('name', watchlist['name']) 77 | print '%-20s | %s' % ('date_added', watchlist['date_added']) 78 | print '%-20s | %s' % ('last_hit', watchlist['last_hit']) 79 | print '%-20s | %s' % ('last_hit_count', watchlist['last_hit_count']) 80 | print '%-20s | %s' % ('search_query', watchlist['search_query']) 81 | print '%-20s | %s' % ('readonly', watchlist['readonly']) 82 | 83 | if __name__ == "__main__": 84 | sys.exit(main(sys.argv[1:])) 85 | -------------------------------------------------------------------------------- /watchlist_remove_all_newerThanID.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # 3 | #The MIT License (MIT) 4 | # 5 | # Copyright (c) 2015 Bit9 + Carbon Black 6 | # 7 | # Permission is hereby granted, free of charge, to any person obtaining a copy 8 | # of this software and associated documentation files (the "Software"), to deal 9 | # in the Software without restriction, including without limitation the rights 10 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | # copies of the Software, and to permit persons to whom the Software is 12 | # furnished to do so, subject to the following conditions: 13 | # 14 | # The above copyright notice and this permission notice shall be included in all 15 | # copies or substantial portions of the Software. 16 | # 17 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | # SOFTWARE. 24 | # 25 | # ----------------------------------------------------------------------------- 26 | # 27 | # 28 | # Delete all watchlists >= Watchlist ID 29 | # 30 | # EXAMPLE USAGE: python watchlist_remove_all_newerThanID.py -c http://127.0.0.1 -a 6b5aee99c133c003b9c11e584c9958da8f8943fa -n -i 25 31 | # 32 | # 33 | # Used to automate maintenance of watchlists, can be added to a cron file to remove new superfluous watchlists 34 | # 35 | # last updated 2016-04-15 by Ben Tedesco btedesco@carbonblack.com 36 | # 37 | 38 | import sys 39 | import optparse 40 | import cbapi 41 | 42 | def build_cli_parser(): 43 | parser = optparse.OptionParser(usage="%prog [options]", description="Add a watchlist") 44 | 45 | # for each supported output type, add an option 46 | # 47 | parser.add_option("-c", "--cburl", action="store", default=None, dest="url", 48 | help="CB server's URL. e.g., http://127.0.0.1 ") 49 | parser.add_option("-a", "--apitoken", action="store", default=None, dest="token", 50 | help="API Token for Carbon Black server") 51 | parser.add_option("-n", "--no-ssl-verify", action="store_false", default=True, dest="ssl_verify", 52 | help="Do not verify server SSL certificate.") 53 | parser.add_option("-i", "--id", action="store", default=None, dest="id", 54 | help="Watchlist ID's >= to delete") 55 | return parser 56 | 57 | def main(argv): 58 | parser = build_cli_parser() 59 | opts, args = parser.parse_args(argv) 60 | if not opts.url or not opts.token or not opts.id: 61 | print "Missing required param; run with --help for usage" 62 | sys.exit(-1) 63 | 64 | # build a cbapi object 65 | # 66 | cb = cbapi.CbApi(opts.url, token=opts.token, ssl_verify=opts.ssl_verify) 67 | 68 | watchlists = cb.watchlist() 69 | 70 | watchlist_int_param = int(opts.id) 71 | 72 | # for each result 73 | for watchlist in watchlists: 74 | watchlist_int_id = int(watchlist['id']) 75 | #print "watchlist['id']: %s, opts.id: %s" % (watchlist_int_id,watchlist_int_param,) 76 | if watchlist_int_id >= watchlist_int_param: 77 | #print "MATCH: watchlist['id']: %s > opts.id: %s" % (watchlist_int_id,watchlist_int_param,) 78 | print "-> Deleting watchlist [id=%s]: %s" % (watchlist_int_id,watchlist['name'],) 79 | watchlist = cb.watchlist_del(watchlist_int_id) 80 | print "-> Watchlist deleted" 81 | 82 | if __name__ == "__main__": 83 | sys.exit(main(sys.argv[1:])) 84 | --------------------------------------------------------------------------------