def main() -> None: """main function""" # Look for default ini file in "/etc/actworkers.ini" and ~/config/actworkers/actworkers.ini # (or replace .config with $XDG_CONFIG_DIR if set) args = cli.handle_args(parseargs()) actapi = worker.init_act(args) if not args.apikey: cli.fatal("You must specify --apikey on command line or in config file") in_data = sys.stdin.read().strip() proxies = ( {"http": args.proxy_string, "https": args.proxy_string} if args.proxy_string else None ) vtapi = VirusTotalApi(args.apikey, proxies=proxies) if args.hexdigest: handle_hexdigest(actapi, vtapi, in_data, output_format=args.output_format) elif args.ip: handle_ip(actapi, vtapi, in_data, output_format=args.output_format) elif args.domain: handle_domain(actapi, vtapi, in_data, output_format=args.output_format) else: # Type not specified, autodetect handle_ioc(actapi, vtapi, in_data, output_format=args.output_format)
def main() -> None: """main function""" # Look for default ini file in "/etc/actworkers.ini" and ~/config/actworkers/actworkers.ini # (or replace .config with $XDG_CONFIG_DIR if set) args = cli.handle_args(parseargs()) actapi = worker.init_act(args) if not args.country_codes: cli.fatal("You must specify --country-codes on command line or in config file") if not os.path.isfile(args.country_codes): cli.fatal( "Country/region file not found at specified location: {}".format( args.country_codes ), 2, ) # Get map of CC -> Country Name cn_map = get_cn_map(args.country_codes) db_cache = get_db_cache(CACHE_DIR) # Read IPs from stdin if args.stdin: in_data = sys.stdin.read().split("\n") handle_ip( actapi, cn_map, in_data, db_cache, args.proxy_string, args.output_format ) # Bulk lookup elif args.bulk: all_ips = open(args.bulk, "r").readlines() batch_size = 50 i = 0 while i < len(all_ips): handle_ip( actapi, cn_map, (all_ips[i : i + batch_size]), db_cache, args.proxy_string, args.output_format, ) i += batch_size time.sleep(1) db_cache.close()
def main() -> None: "main function" # Look for default ini file in "/etc/actworkers.ini" and # ~/config/actworkers/actworkers.ini # (or replace .config with $XDG_CONFIG_DIR if set) args = cli.handle_args(parseargs()) if not args.argus_apikey: cli.fatal("You must specify --argus-apikey on command line or in config file") actapi = worker.init_act(args) process(actapi, args)
def main() -> None: """main function""" # Look for default ini file in "/etc/actworkers.ini" and ~/config/actworkers/actworkers.ini # (or replace .config with $XDG_CONFIG_DIR if set) args = cli.handle_args(parseargs()) actapi = worker.init_act(args) if not args.country_codes: cli.fatal("You must specify --country-codes on command line or in config file") if not args.veris_prefix: cli.fatal("You must specify --veris-prefix") if not (args.veris_url or args.veris_file or args.stdin): cli.fatal("You must specify --veris-url, --veris-file or --stdin") args.veris_prefix = args.veris_prefix.upper() if not os.path.isfile(args.country_codes): cli.fatal( "Country/region file not found at specified location: {}".format( args.country_codes ), 2, ) args.threat_actor_variety = [ variety.strip() for variety in args.threat_actor_variety.split(",") ] # Configuration object that will be passed around to functions config = { # act API "actapi": actapi, # Map of CC -> Country Name "cn_map": get_cn_map(args.country_codes), # Map of CC -> Country Name "campaign_map": get_campaigns(args.veris_prefix, args.veris_campaign) if args.veris_campaign else {}, # Cache of url > sha256 "db_cache": urlcache.URLCache( requests_common_kwargs={ "proxies": {"http": args.proxy_string, "https": args.proxy_string}, "timeout": args.http_timeout, } ), "proxies": {"http": args.proxy_string, "https": args.proxy_string} if args.proxy_string else None, } # Add all arguments from args to config config.update(vars(args)) process(config)
def main() -> None: """Main function""" # Look for default ini file in "/etc/actworkers.ini" and # ~/config/actworkers/actworkers.ini (or replace .config with # $XDG_CONFIG_DIR if set) args = parseargs() try: shorteners = [x.strip() for x in args.url_shorteners.split(",")] except AttributeError: cli.fatal("Empty list of shorteners?") actapi = worker.init_act(args) proxies = ({ "http": args.proxy_string, "https": args.proxy_string } if args.proxy_string else None) process(actapi, shorteners, args.user_agent, proxies, args.output_format)
def main() -> None: """program entry point""" # Look for default ini file in "/etc/actworkers.ini" and # ~/config/actworkers/actworkers.ini # (or replace .config with $XDG_CONFIG_DIR if set) args = cli.handle_args(parseargs()) if not args.feed_uri: cli.fatal("--feed-uri not specified") if args.dump_dir and not args.dump_dir.is_dir(): os.makedirs(args.dump_dir) proxies = ({ "http": args.proxy_string, "https": args.proxy_string } if args.proxy_string else None) actapi = worker.init_act(args) try: # Get "updated" from last successful run last_run_filename = get_last_run_filename(args.feed_cache, args.feed_uri) with pid.PidFile(force_tmpdir=True, pidname="act_feed.pid"): handle_feed( last_run_filename, args.feed_uri, actapi, args.dump_dir, proxies, args.cert_file, args.no_exit_on_error, ) except pid.base.PidFileAlreadyLockedError: error("pid file found - feed is already running")
def run() -> None: args = cli.handle_args(parseargs()) actapi = worker.init_act(args) if not args.apikey or not args.secret: cli.fatal( "You must specify --apikey and --secret on command line or in config file" ) proxies = ({ "http": args.proxy_string, "https": args.proxy_string } if args.proxy_string else None) for in_data in sys.stdin: in_data = in_data.strip() if args.hexdigest or HASH_RE.search(in_data): handle_hexdigest( actapi, in_data, args.apikey, args.secret, proxies, output_format=args.output_format, ) elif args.domain: handle_domain( actapi, in_data, args.apikey, args.secret, proxies, output_format=args.output_format, )
def main() -> None: """main function""" # Look for default ini file in "/etc/actworkers.ini" and ~/config/actworkers/actworkers.ini # (or replace .config with $XDG_CONFIG_DIR if set) args = cli.handle_args(parseargs()) actapi = worker.init_act(args) if not (args.privatekey and args.publickey): cli.fatal( "You must specify --privatekey and --publickey on command line or in config file" ) proxies = ( {"http": args.proxy_string, "https": args.proxy_string} if args.proxy_string else None ) iSightHandler = ISightAPIRequestHandler(args.root, args.privatekey, args.publickey) data = iSightHandler.indicators(days=args.days, proxies=proxies) if "success" not in data or not data["success"]: logging.error( "Unable to download from isight API [%s]", data["message"] if "message" in data else "NA", ) return timestamp = int(time.time()) ### DEBUG -- dump json to disc for each run if args.debugdir: with open( os.path.join(args.debugdir, "error-{0}.json".format(timestamp)), "w" ) as f: json.dump(data, f) for i, dp in enumerate(data["message"]): ### --- Handle mentions facts # Create report ID from the url (same approach as for feeds) and title to this ID. reportID = hashlib.sha256(dp["webLink"].encode("utf8")).hexdigest() handle_fact(actapi.fact("name", dp["title"]).source("report", reportID)) for obj in OBJECT_MAP: # run through all fields that we want to mention if obj in dp and dp[obj]: # if the report contains data in the field factType = OBJECT_MAP[obj](dp[obj]) # translate to ACT fact type handle_fact( actapi.fact("mentions") # and create fact from field .source("report", reportID) .destination(factType, dp[obj].lower()) ) if dp["url"]: handle_fact( actapi.fact("mentions") .source("report", reportID) .destination("uri", dp["url"]) ) handle_uri(actapi, dp["url"]) ### --- IP -> malwareFamily if dp["malwareFamily"] and dp["ip"]: handle_facts( act.api.fact.fact_chain( actapi.fact("connectsTo") .source("content", "*") .destination("uri", "*"), actapi.fact("componentOf") .source("ipv4", dp["ip"]) .destination("uri", "*"), actapi.fact("classifiedAs") .source("content", "*") .destination("tool", dp["malwareFamily"]), ) ) ### --- URL -> malwareFamily elif dp["networkType"] == "url" and dp["malwareFamily"]: handle_uri(actapi, dp["url"]) handle_facts( act.api.fact.fact_chain( actapi.fact("connectsTo") .source("content", "*") .destination("uri", dp["url"]), actapi.fact("classifiedAs") .source("content", "*") .destination("tool", dp["malwareFamily"]), ) ) ### --- FQDN -> malwareFamily elif dp["networkType"] == "network" and dp["domain"] and dp["malwareFamily"]: handle_facts( act.api.fact.fact_chain( actapi.fact("connectsTo") .source("content", "*") .destination("uri", "*"), actapi.fact("componentOf") .source("fqdn", dp["domain"]) .destination("uri", "*"), actapi.fact("classifiedAs") .source("content", "*") .destination("tool", dp["malwareFamily"]), ) ) ### --- hash -> malwareFamily elif ( dp["fileType"] and dp["malwareFamily"] and (dp["sha1"] or dp["sha256"] or dp["md5"]) ): for digest_type in ["md5", "sha1", "sha256"]: ### In some cases the iSight api does not return a sha256 hashdigest ### so we need to make a chain through a placeholder content if not dp["sha256"]: if dp[digest_type]: handle_facts( act.api.fact.fact_chain( actapi.fact("represents") .source("hash", dp[digest_type]) .destination("content", "*"), actapi.fact("classifiedAs") .source("content", "*") .destination("tool", dp["malwareFamily"]), ) ) else: ## There is a sha256, so we do _not_ need a chain if dp[digest_type]: handle_fact( actapi.fact("classifiedAs") .source("content", dp["sha256"]) .destination("tool", dp["malwareFamily"]) ) handle_fact( actapi.fact("represents") .source("hash", dp[digest_type]) .destination("content", dp["sha256"]) ) ### -- Hash --> actor elif ( dp["fileType"] and dp["actor"] and (dp["sha1"] or dp["sha256"] or dp["md5"]) ): for digest_type in ["md5", "sha1", "sha256"]: ### In some cases the iSight api does not return a sha256 hashdigest ### so we need to make a chain through a placeholder content if not dp["sha256"]: if dp[digest_type]: handle_facts( act.api.fact.fact_chain( actapi.fact("represents") .source("hash", dp[digest_type]) .destination("content", "*"), actapi.fact("observedIn") .source("content", "*") .destination("incident", "*"), actapi.fact("attributedTo") .source("incident", "*") .destination("threatActor", dp["actor"]), ) ) else: ## There is a sha256, so we do _not_ need a chain between all the way from hexdigest if dp[digest_type]: handle_fact( actapi.fact("represents") .source("hash", dp[digest_type]) .destination("content", dp["sha256"]) ) handle_facts( act.api.fact.fact_chain( actapi.fact("observedIn") .source("content", dp["sha256"]) .destination("incident", "*"), actapi.fact("attributedTo") .source("incident", "*") .destination("threatActor", dp["actor"]), ) ) ### We do have a sha256 of a file (but possibly nothing else). Add the content to hexdigest facts elif dp["fileType"] and dp["sha256"]: for digest in ["sha1", "md5", "sha256"]: if dp[digest]: handle_fact( actapi.fact("represents") .source("hash", dp[digest]) .destination("content", dp["sha256"]) ) if args.debugdir: fields = [ k for k, v in dp.items() if v and k not in [ "reportId", "title", "ThreatScape", "audience", "intelligenceType", "publishDate", "reportLink", "webLink", ] ] logging.error( "[%s] Extra fields while handeling index[%s] '%s'", timestamp, i, ", ".join(fields), ) ### -- DEBUG! else: if args.debugdir: fields = [ k for k, v in dp.items() if v and k not in [ "reportId", "title", "ThreatScape", "audience", "intelligenceType", "publishDate", "reportLink", "webLink", ] ] logging.error( "[%s] Unable to handle index[%s] with fields '%s'", timestamp, i, ", ".join(fields), )