def proxyCheck(ipaddr): text.printGreen("IP2Proxy: https://github.com/ip2location/ip2proxy-python") try: db = IP2Proxy.IP2Proxy() db.open("IP2PROXY-LITE-PX8.BIN") record = db.get_all(ipaddr) if str(record['is_proxy']) == "1": print( " * Determined this is a proxy based on the IP2Proxy database." ) print('Proxy Type: ' + record['proxy_type']) print('Country Code: ' + record['country_short']) print('Country Name: ' + record['country_long']) print('Region Name: ' + record['region']) print('City Name: ' + record['city']) print('ISP: ' + record['isp']) print('Domain: ' + record['domain']) print('Usage Type: ' + record['usage_type']) print('ASN: ' + record['asn']) print('AS Name: ' + record['as_name']) print('Last Seen: ' + record['last_seen']) elif str(record['is_proxy']) != "1": text.printRed( " * Determined this is not a proxy based on the reputation .BIN file referenced." ) else: text.printRed( " * Encountered an error while checking if the IP was a proxy." ) except Exception as e: print(e) return
def virusTotalHash(hash, apikey): text.printGreen("VIRUSTOTAL: https://www.virustotal.com/gui/") headers = {'x-apikey': apikey} url = 'https://www.virustotal.com/api/v3/files/%s' % hash response = requests.get(url=url, headers=headers) if response.status_code == 200: returned = response.json() print("Hash: " + str(returned['data']['id'])) print("Analysis URL: " + str(returned['data']['links']['self'])) print("Last Analyzed: " + time.strftime( '%Y-%m-%d %H:%M:%S', time.localtime(returned['data']['attributes'] ['last_analysis_date']))) print("Last Analysis Stats: ") print(" - Engines Failed to Analyze: " + str( returned['data']['attributes']['last_analysis_stats']['failure'])) print(" - Engines Deemed Malicious: " + str(returned['data']['attributes']['last_analysis_stats'] ['malicious'])) print(" - Engines Deemed Suspicious: " + str(returned['data']['attributes']['last_analysis_stats'] ['suspicious'])) print(" - Engines Did Not Determine Malicious: " + str(returned['data']['attributes']['last_analysis_stats'] ['undetected'])) print("Community Reputation: " + str(returned['data']['attributes']['reputation'])) print("Community Harmless Votes: " + str(returned['data']['attributes']['total_votes']['harmless'])) print("Community Malicious Votes: " + str(returned['data']['attributes']['total_votes']['malicious']))
def shodanIP(ipaddr, apikey): api = shodan.Shodan(apikey) text.printGreen("SHODAN: https://www.shodan.io/") text.printGreen(" * Maximum associated IPs returned is 100.") try: print(api.host(ipaddr)) except: text.printRed("No information is available for the IP address.")
def threatMinerHash(filehash): text.printGreen("THREATMINER: https://www.threatminer.org/") # API Documentation: https://www.threatminer.org/api.php # Request types ("RT") are different between domains, IPs, and hashes! # RT 1: Metadata # RT 2: HTTP Traffic # RT 3: Hosts (domains and IPs) # RT 5: Registry Keys # RT 6: AV Detections # RT 7: Report Tagging url = "https://api.threatminer.org/v2/sample.php" # Get metadata. params = {'q': filehash, 'rt': '1'} response = requests.get(url=url, params=params) if response.status_code == 200: returned = response.json() if returned['status_code'] == 200: for value in returned['results']: print("File Type: " + str(value['file_type'])) print("File Name: " + str(value['file_name'])) print("Last Analyzed: " + str(value['date_analyzed'])) else: text.printRed(" * No metadata was found.") # Get HTTP Traffic. params = {'q': filehash, 'rt': '2'} response = requests.get(url=url, params=params) if response.status_code == 200: returned = response.json() if returned['status_code'] == 200: contactedDomainCount = 1 for value in returned['results']['http_traffic']: contactedDomain = value['domain'] print("Contacted Domain #" + str(contactedDomainCount) + ": " + contactedDomain) contactedDomainCount += 1 else: text.printRed(" * No HTTP traffic records were found.") # Get Associated Hosts params = {'q': filehash, 'rt': '3'} response = requests.get(url=url, params=params) if response.status_code == 200: returned = response.json() if returned['status_code'] == 200: contactedDomainCount = 1 for value in returned['results']['domains']: contactedDomain = value['domain'] resolvedDomain = value['ip'] print("Contacted Domain #" + str(contactedDomainCount) + ": " + contactedDomain + "at IP " + str(resolvedDomain)) contactedDomainCount += 1 contactedIPsCount = 1 for value in returned['results']['hosts']: print("Contacted IP #" + str(contactedIPsCount) + ": " + value) else: text.printRed(" * No Associated Domains or IPs Found.")
def abuseIPDB(ipaddr, apikey): text.printGreen("ABUSE IP DATABASE: https://www.abuseipdb.com/") params = {'ipAddress': ipaddr, 'maxAgeInDays': 90} headers = {'Accept': 'application/json', 'Key': apikey} url = 'https://api.abuseipdb.com/api/v2/check' response = requests.get(url=url, headers=headers, params=params) if response.status_code == 200: returned = response.json() #print("IP: " + str(returned['data']['ipAddress'])) print("Reports in 90d: " + str(returned['data']['totalReports'])) print("Last Report: " + str(returned['data']['lastReportedAt'])) print("Confidence of Abuse: " + str(returned['data']['abuseConfidenceScore']) + "%")
def virusTotalIP(ipaddr, apikey): text.printGreen("VIRUSTOTAL: https://www.virustotal.com/gui/") headers = {'x-apikey': apikey} url = 'https://virustotal.com/api/v3/ip_addresses/%s' % ipaddr response = requests.get(url=url, headers=headers) if response.status_code == 200: returned = response.json() print("IP: " + str(returned['data']['id'])) print("Reputation: " + str(returned['data']['attributes']['reputation'])) print("Harmless Votes: " + str(returned['data']['attributes']['total_votes']['harmless'])) print("Malicious Votes: " + str(returned['data']['attributes']['total_votes']['malicious']))
def virusTotalDomain(domain, apikey): text.printGreen("VIRUSTOTAL: https://www.virustotal.com/gui/") headers = {'x-apikey': apikey} url = 'https://www.virustotal.com/api/v3/domains/%s' %domain response = requests.get(url=url, headers=headers) if response.status_code == 200: returned = response.json() print("Domain: " + str(returned['data']['id'])) print("Reputation: " + str(returned['data']['attributes']['reputation'])) print("Harmless Votes: " + str(returned['data']['attributes']['total_votes']['harmless'])) print("Malicious Votes: " + str(returned['data']['attributes']['total_votes']['malicious'])) epochRegistrationDate = int(str(returned['data']['attributes']['creation_date'])) humanRegDate = time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(epochRegistrationDate)) print("Registered at: " + humanRegDate + " UTC.")
def shodanDomain(domain, apikey): api = shodan.Shodan(apikey) text.printGreen("SHODAN: https://www.shodan.io/") text.printGreen(" * Maximum associated IPs returned is 100.") try: # Search Shodan results = api.search(domain) # Show the results print('Results found: {}'.format(results['total'])) totalAssocIP = 1 for result in results['matches']: print('IP #{}: {}'.format(totalAssocIP, result['ip_str'])) totalAssocIP += 1 except shodan.APIError as e: print('Error: {}'.format(e))
def threatMinerIP(ipaddr): text.printGreen("THREATMINER: https://www.threatminer.org/") # API Documentation: https://www.threatminer.org/api.php # Request types ("RT") are different between domains, IPs, and hashes! # RT 1: WHOIS # RT 2: Passive DNS # RT 4: Related Samples (Hash Only) url = "https://api.threatminer.org/v2/host.php" # Get WHOIS. params = {'q': ipaddr, 'rt': '1'} response = requests.get(url=url, params=params) if response.status_code == 200: returned = response.json() if returned['status_code'] == 200: for value in returned['results']: print("ORG Name: " + str(value['org_name'])) print("Registrar: " + str(value['register'])) else: text.printRed(" * No WHOIS information was found.") # Get Passive DNS. params = {'q': ipaddr, 'rt': '2'} response = requests.get(url=url, params=params) if response.status_code == 200: returned = response.json() if returned['status_code'] == 200: totalAssoc = 1 for value in returned['results']: assocDomain = value['domain'] print("Associated Domain #" + str(totalAssoc) + ": " + assocDomain) totalAssoc += 1 else: text.printRed(" * No passive DNS records were found.") # Get related samples (hash only) params = {'q': ipaddr, 'rt': '4'} response = requests.get(url=url, params=params) if response.status_code == 200: returned = response.json() if returned['status_code'] == 200: totalAssoc = 1 for assocHash in returned['results']: print("Associated Hash #" + str(totalAssoc) + ": " + assocHash) totalAssoc += 1 else: text.printRed(" * No related samples were found.")
def urlhausIP(ipaddr): text.printGreen( "URLHAUS: https://urlhaus.abuse.ch/ \n" + " * Getting the URLHAUS list. This is large and can take a moment to download based on your connection." ) response = requests.get("https://urlhaus.abuse.ch/downloads/text/") if response.status_code == 200: returned = response.text tryFind = returned.find(ipaddr) if tryFind == -1: text.printRed("Did not find any results in URLHaus.") if tryFind > -1: text.printGreen( "Found the IP beginning at character #" + str(tryFind) + ". Search the full site for the IP here: https://urlhaus.abuse.ch/browse/ \n" + "No further searching against URLHaus is done to respect the team's wishes." )
def hybridAnalysisIP(ipaddr, apikey): text.printGreen("HYBRID ANALYSIS: https://www.hybrid-analysis.com/") text.printGreen(" * Utilizes the CrowdStrike Falcon Sandbox.") url = "https://www.hybrid-analysis.com/api/v2/search/terms" payload = 'host=%s' % ipaddr headers = { 'api-key': apikey, 'User-Agent': 'CrowdStrike Falcon', 'Content-Type': 'application/x-www-form-urlencoded' } response = requests.request("POST", url=url, headers=headers, data=payload) if response.status_code == 200: returned = response.json() if returned['count'] > 0: text.printGreen("Showing results whose threat score is above 10.") threatDict = {} for eachresult in returned['result']: if eachresult['threat_score'] > 10: jobID = eachresult['job_id'] threatScore = eachresult['threat_score'] threatDict[jobID] = threatScore sortedThreatDict = sorted(threatDict.items(), key=lambda item: item[1]) for key, value in sortedThreatDict: print("Job ID: " + str(key) + " with threat score of " + str(value) + " and SHA256 hash of " + str(eachresult['sha256'])) if returned['count'] == 0: text.printRed( " * No results for that IP address on Hybrid-Analysis.")
def threatMinerDomain(domain): text.printGreen("THREATMINER: https://www.threatminer.org/") # API Documentation: https://www.threatminer.org/api.php # Request types ("RT") are different between domains, IPs, and hashes! # RT 2: Passive DNS # RT 4: Related Samples (Hash Only) # RT 5: Subdomains # RT 6: APTNotes url = "https://api.threatminer.org/v2/domain.php" # Get Passive DNS. params = {'q': domain, 'rt': '2'} response = requests.get(url=url, params=params) if response.status_code == 200: returned = response.json() if returned['status_code'] == "200": totalAssocIP = 1 for value in returned['results']: print ("Associated IP #" + str(totalAssocIP) + ": " + str(value['ip'])) totalAssocIP += 1 else: text.printRed(" * No passive DNS records found.") # Get associated hash values. params = {'q': domain, 'rt': '4'} response = requests.get(url=url, params=params) if response.status_code == 200: returned = response.json() if returned['status_code'] == 200: totalAssocHash = 1 for value in returned['results']: print("Associated Hash #" + str(totalAssocHash) + ": " + str(value)) totalAssocHash += 1 else: text.printRed(" * No associated hash values found.") # Get associated subdomains. params = {'q': domain, 'rt': '5'} response = requests.get(url=url, params=params) if response.status_code == 200: returned = response.json() if returned['status_code'] == 200: totalAssocSubdomains = 1 for value in returned['results']: print("Associated subdomain #" + str(totalAssocSubdomains) + ": " + str(value)) totalAssocSubdomains += 1 else: text.printRed(" * No associated subdomains found.") # Get associated APTNotes. params = {'q': domain, 'rt': '6'} response = requests.get(url=url, params=params) if response.status_code == 200: returned = response.json() if returned['status_code'] == 200: text.printGreen(" * We found some APTNotes, a collection of public reports on APTs! ThreatMiner provides this through an API.") text.printGreen(" * APTNotes is available on GitHub: https://github.com/aptnotes - Full credit to the original authors.") totalAssocReports = 1 for value in returned['results']: print("Associated APTNote #" + str(totalAssocReports) + ": " + str(value['filename'] + " was published in " + str(value['year']))) print("[PDF WARNING] Download available at: " + str(value['URL'])) totalAssocReports += 1 else: text.printRed(" * No associated APTNotes found.")
ASSOCIATEDIPCHECK = args.associatedips """ # Will be used for association checking logic. Not currently in use. if ASSOCIATEDIPCHECK == True: text.printGreen("Associated IPs will be checked.") elif ASSOCIATEDIPCHECK == False: text.printRed("Associated IPs will NOT be checked.") else: text.printRed("Could not determine the boolean value of ASSOCIATEDIPCHECK.") """ API_KEYS_LIST = readAPIKeys() if args.ip: for addr in args.ip: ipHandler.checkPrivate(addr) text.printGreen("Looking up IP " + str(addr)) ipHandler.abuseIPDB(addr, API_KEYS_LIST['ABUSEIPDB']) ipHandler.virusTotalIP(addr, API_KEYS_LIST['VT']) ipHandler.threatMinerIP(addr) ipHandler.hybridAnalysisIP(addr, API_KEYS_LIST['HYBRID']) ipHandler.urlhausIP(addr) # TO DO: # Somehow handle cases where Shodan spits out enormous amounts of data. ipHandler.shodanIP(addr, API_KEYS_LIST['SHODAN']) ipHandler.proxyCheck(addr) if args.domain: for domain in args.domain: text.printGreen("Looking up domain " + str(domain))