def cybox_mutex(observable, observable_type, objects): nsname, nsurl = observable.namespace.last().namespace.split(':', 1) NS = cybox.utils.Namespace(nsurl, nsname) cybox.utils.set_id_namespace(NS) observables = Observables() for obj in objects: m = Mutex() m.name = obj.mutex_name o = Observable(m) o.title = observable.name o.description = observable.description observables.add(o) return observables
def dict_from_object(cls, win_mutex_obj): """Parse and return a dictionary for a Win Mutex Object object""" win_mutex_dict = Mutex.dict_from_object(defined_object) if win_mutex_obj.get_Handle() is not None: win_mutex_dict['handle'] = Win_Handle.dict_from_object(win_mutex_obj.get_Handle()) if win_mutex_obj.get_Security_Attributes() is not None: win_mutex_dict['security_attributes'] = Base_Object_Attribute.dict_from_object(win_mutex_obj.get_Security_Attributes()) return win_mutex_dict
def from_obj(win_mutex_obj): if not win_mutex_obj: return None win_mutex_ = Mutex.from_obj(win_mutex_obj, WinMutex()) win_mutex_.handle = WinHandle.from_obj(win_mutex_obj.get_Handle()) win_mutex_.security_attributes = String.from_dict(win_mutex_obj.get_Security_Attributes()) return win_mutex_
def from_dict(win_mutex_dict): if not win_mutex_dict: return None win_mutex_ = Mutex.from_dict(win_mutex_dict, WinMutex()) win_mutex_.handle = WinHandle.from_dict(win_mutex_dict.get('handle')) win_mutex_.security_attributes = String.from_dict(win_mutex_dict.get('security_attributes')) return win_mutex_
def object_from_dict(cls, win_mutex_dict): """Create the Win Mutex Object object representation from an input dictionary""" win_mutex_obj = Mutex.object_from_dict(win_mutex_attributes,win_mutex_binding.WindowsMutexObjectType()) win_mutex_obj.set_anyAttributes_({'xsi:type' : 'WinMutexObj:WindowsMutexObjectType'}) for key, value in win_mutex_dict.items(): if key == 'handle' : win_mutex_obj.set_Handle(Win_Handle.object_from_dict(value)) elif key == 'security_attributes' and utils.test_value(value): win_mutex_obj.set_Security_Attributes(Base_Object_Attribute.object_from_dict(common_types_binding.StringObjectAttributeType(datatype='String'), value)) return win_mutex_obj
def build(self): self.stix_header.title = self.pulse["name"] self.stix_header.description = self.pulse["description"] self.stix_header.short_description = "%spulse/%s" % ( PULSE_SERVER_BASE, str(self.pulse["id"])) self.stix_header.package_intents.append(PackageIntent.TERM_INDICATORS) self.stix_header.information_source = InformationSource() self.stix_header.information_source.time = Time() self.stix_header.information_source.description = "Alienvault OTX - https://otx.alienvault.com/" self.stix_header.information_source.time.produced_time = self.pulse[ "modified"] self.stix_header.information_source.identity = Identity() self.stix_header.information_source.identity.name = "Alienvault OTX" self.stix_package.stix_header = self.stix_header hashes = [] addresses = [] domains = [] urls = [] mails = [] for p_indicator in self.pulse["indicators"]: if p_indicator["type"] in self.hash_translation: new_ind = Indicator() new_ind.description = p_indicator["description"] new_ind.title = "%s from %spulse/%s" % ( p_indicator["indicator"], PULSE_SERVER_BASE, str(self.pulse["id"])) file_ = File() hash_ = Hash(p_indicator["indicator"], self.hash_translation[p_indicator["type"]]) file_.add_hash(hash_) observable_ = Observable(file_) elif p_indicator["type"] in self.address_translation: new_ind = Indicator() new_ind.description = p_indicator["description"] new_ind.title = "%s from %spulse/%s" % ( p_indicator["indicator"], PULSE_SERVER_BASE, str(self.pulse["id"])) ipv4_ = Address.from_dict({ 'address_value': p_indicator["indicator"], 'category': self.address_translation[p_indicator["type"]] }) observable_ = Observable(ipv4_) elif p_indicator["type"] in self.name_translation: new_ind = Indicator() new_ind.description = p_indicator["description"] new_ind.title = "%s from %spulse/%s" % ( p_indicator["indicator"], PULSE_SERVER_BASE, str(self.pulse["id"])) domain_ = DomainName.from_dict({ 'value': p_indicator["indicator"], 'type': 'FQDN' }) observable_ = Observable(domain_) elif p_indicator["type"] == "URL": new_ind = Indicator() new_ind.description = p_indicator["description"] new_ind.title = "%s from %spulse/%s" % ( p_indicator["indicator"], PULSE_SERVER_BASE, str(self.pulse["id"])) url_ = URI.from_dict({ 'value': p_indicator["indicator"], 'type': URI.TYPE_URL }) observable_ = Observable(url_) elif p_indicator["type"] == "email": email_ = Address.from_dict({ 'address_value': p_indicator["indicator"], 'category': Address.CAT_EMAIL }) observable_ = Observable(email_) #elif p_indicator["type"] == "CVE": # vuln_ = Vulnerability() # vuln_.cveid = p_indicator["indicator"].upper() # observable_ = Observable(vuln_) elif p_indicator["type"] == "Mutex": mutex_ = Mutex.from_dict({ 'named': True, 'name': p_indicator["indicator"] }) observable_ = Observable(mutex_) elif p_indicator["type"] == "CIDR": nrange = IP(p_indicator["indicator"]) nrange_values = nrange.strNormal(3).replace("-", ",") ipv4_ = Address.from_dict({ 'address_value': nrange_values, 'category': Address.CAT_IPV4 }) ipv4_.address_value.condition = "InclusiveBetween" observable_ = Observable(ipv4_) else: continue mind = Indicator() mind.description = p_indicator["description"] mind.title = "%s from %spulse/%s" % (p_indicator["indicator"], PULSE_SERVER_BASE, str(self.pulse["id"])) observable_.title = "%s - %s" % (p_indicator["type"], p_indicator["indicator"]) mind.add_observable(observable_) self.stix_package.add_indicator(mind)
def setUp(self): self.test_dict = {'named': True, 'name': 'test_name'} self.mutex_obj = Mutex.object_from_dict(self.test_dict) self.mutex_dict = Mutex.dict_from_object(self.mutex_obj)
def make_cybox_object(type_, name=None, value=None): """ Converts type_, name, and value to a CybOX object instance. :param type_: The object type. :type type_: str :param name: The object name. :type name: str :param value: The object value. :type value: str :returns: CybOX object """ if type_ == "Account": acct = Account() acct.description = value return acct elif type_ == "Address": return Address(category=name, address_value=value) elif type_ == "Email Message": e = EmailMessage() e.raw_body = value return e elif type_ == "API": api = API() api.description = value return api elif type_ == "Artifact": if name == "Data Region": atype = Artifact.TYPE_GENERIC elif name == 'FileSystem Fragment': atype = Artifact.TYPE_FILE_SYSTEM elif name == 'Memory Region': atype = Artifact.TYPE_MEMORY else: raise UnsupportedCybOXObjectTypeError(type_, name) return Artifact(value, atype) elif type_ == "Code": obj = Code() obj.code_segment = value obj.type = name return obj elif type_ == "Disk": disk = Disk() disk.disk_name = type_ disk.type = name return disk elif type_ == "Disk Partition": disk = DiskPartition() disk.device_name = type_ disk.type = name return disk elif type_ == "DNS Query": r = URI() r.value = value dq = DNSQuestion() dq.qname = r d = DNSQuery() d.question = dq return d elif type_ == "DNS Record": # DNS Record indicators in CRITs are just a free form text box, there # is no good way to map them into the attributes of a DNSRecord cybox # object. So just stuff it in the description until someone tells me # otherwise. d = StructuredText(value=value) dr = DNSRecord() dr.description = d return dr elif type_ == "GUI Dialogbox": obj = GUIDialogbox() obj.box_text = value return obj elif type_ == "GUI Window": obj = GUIWindow() obj.window_display_name = value return obj elif type_ == "HTTP Request Header Fields" and name and name == "User-Agent": # TODO/NOTE: HTTPRequestHeaderFields has a ton of fields for info. # we should revisit this as UI is reworked or CybOX is improved. obj = HTTPRequestHeaderFields() obj.user_agent = value return obj elif type_ == "Library": obj = Library() obj.name = value obj.type = name return obj elif type_ == "Memory": obj = Memory() obj.memory_source = value return obj elif type_ == "Mutex": m = Mutex() m.named = True m.name = String(value) return m elif type_ == "Network Connection": obj = NetworkConnection() obj.layer7_protocol = value return obj elif type_ == "Pipe": p = Pipe() p.named = True p.name = String(value) return p elif type_ == "Port": p = Port() try: p.port_value = PositiveInteger(value) except ValueError: # XXX: Raise a better exception... raise UnsupportedCybOXObjectTypeError(type_, name) return p elif type_ == "Process": p = Process() p.name = String(value) return p elif type_ == "String": c = Custom() c.custom_name = "crits:String" c.description = ("This is a generic string used as the value of an " "Indicator or Object within CRITs.") c.custom_properties = CustomProperties() p1 = Property() p1.name = "value" p1.description = "Generic String" p1.value = value c.custom_properties.append(p1) return c elif type_ == "System": s = System() s.hostname = String(value) return s elif type_ == "URI": r = URI() r.type_ = name r.value = value return r elif type_ == "User Account": obj = UserAccount() obj.username = value return obj elif type_ == "Volume": obj = Volume() obj.name = value return obj elif type_ == "Win Driver": w = WinDriver() w.driver_name = String(value) return w elif type_ == "Win Event Log": obj = WinEventLog() obj.log = value return obj elif type_ == "Win Event": w = WinEvent() w.name = String(value) return w elif type_ == "Win Handle": obj = WinHandle() obj.type_ = name obj.object_address = value return obj elif type_ == "Win Kernel Hook": obj = WinKernelHook() obj.description = value return obj elif type_ == "Win Mailslot": obj = WinMailslot() obj.name = value return obj elif type_ == "Win Network Share": obj = WinNetworkShare() obj.local_path = value return obj elif type_ == "Win Process": obj = WinProcess() obj.window_title = value return obj elif type_ == "Win Registry Key": obj = WinRegistryKey() obj.key = value return obj elif type_ == "Win Service": obj = WinService() obj.service_name = value return obj elif type_ == "Win System": obj = WinSystem() obj.product_name = value return obj elif type_ == "Win Task": obj = WinTask() obj.name = value return obj elif type_ == "Win User Account": obj = WinUser() obj.security_id = value return obj elif type_ == "Win Volume": obj = WinVolume() obj.drive_letter = value return obj elif type_ == "X509 Certificate": obj = X509Certificate() obj.raw_certificate = value return obj """ The following are types that are listed in the 'Indicator Type' box of the 'New Indicator' dialog in CRITs. These types, unlike those handled above, cannot be written to or read from CybOX at this point. The reason for the type being omitted is written as a comment inline. This can (and should) be revisited as new versions of CybOX are released. NOTE: You will have to update the corresponding make_crits_object function with handling for the reverse direction. In the mean time, these types will raise unsupported errors. """ #elif type_ == "Device": # No CybOX API #elif type_ == "DNS Cache": # No CybOX API #elif type_ == "GUI": # revisit when CRITs supports width & height specification #elif type_ == "HTTP Session": # No good mapping between CybOX/CRITs #elif type_ == "Linux Package": # No CybOX API #elif type_ == "Network Packet": # No good mapping between CybOX/CRITs #elif type_ == "Network Route Entry": # No CybOX API #elif type_ == "Network Route": # No CybOX API #elif type_ == "Network Subnet": # No CybOX API #elif type_ == "Semaphore": # No CybOX API #elif type_ == "Socket": # No good mapping between CybOX/CRITs #elif type_ == "UNIX File": # No CybOX API #elif type_ == "UNIX Network Route Entry": # No CybOX API #elif type_ == "UNIX Pipe": # No CybOX API #elif type_ == "UNIX Process": # No CybOX API #elif type_ == "UNIX User Account": # No CybOX API #elif type_ == "UNIX Volume": # No CybOX API #elif type_ == "User Session": # No CybOX API #elif type_ == "Whois": # No good mapping between CybOX/CRITs #elif type_ == "Win Computer Account": # No CybOX API #elif type_ == "Win Critical Section": # No CybOX API #elif type_ == "Win Executable File": # No good mapping between CybOX/CRITs #elif type_ == "Win File": # No good mapping between CybOX/CRITs #elif type_ == "Win Kernel": # No CybOX API #elif type_ == "Win Mutex": # No good mapping between CybOX/CRITs #elif type_ == "Win Network Route Entry": # No CybOX API #elif type_ == "Win Pipe": # No good mapping between CybOX/CRITs #elif type_ == "Win Prefetch": # No CybOX API #elif type_ == "Win Semaphore": # No CybOX API #elif type_ == "Win System Restore": # No CybOX API #elif type_ == "Win Thread": # No good mapping between CybOX/CRITs #elif type_ == "Win Waitable Timer": # No CybOX API raise UnsupportedCybOXObjectTypeError(type_, name)
def main(): # NOTE: ID values will differ due to being regenerated on each script execution pkg = STIXPackage() pkg.title = "Examples of Observable Composition" # USE CASE: single obj with single condition obs = File() obs.file_name = "foo.exe" obs.file_name.condition = "Contains" pkg.add_observable(obs) # USE CASE: single obj with multiple conditions obs = File() obs.file_name = "foo" obs.file_name.condition = "Contains" obs.size_in_bytes = '1896000' obs.size_in_bytes.condition = "Equals" pkg.add_observable(obs) # USE CASE: multiple obj with individual conditions obs = EmailMessage() obs.subject = "Syria strategic plans leaked" obs.subject.condition = "Equals" file_obj = File() file_obj.file_name = "bombISIS.pdf" file_obj.file_name.condition = "Equals" obs.add_related(file_obj, "Contains") pkg.add_observable(obs) # USE CASE: multiple objects with complex condition like (A OR B) AND C # orcomp = either of a mutex or file are present orcomp = ObservableComposition() orcomp.operator = "OR" obs = Mutex() obs.name = 'foo' obs.name.condition = "Contains" orcomp.add(obs) obs = File() obs.file_name = "barfoobar" obs.file_name.condition = "Equals" orcomp.add(obs) # andcomp = the above is true AND a network connection is present andcomp = ObservableComposition() andcomp.operator = "AND" andcomp.add(orcomp) obs = NetworkConnection() sock = SocketAddress() sock.ip_address = "46.123.99.25" sock.ip_address.category = "ipv4-addr" sock.ip_address.condition = "Equals" obs.destination_socket_address = sock andcomp.add(obs) pkg.add_observable(andcomp) # USE CASE: single object, one property with multiple values obs = SocketAddress() obs.ip_address = ['10.0.0.0', '10.0.0.1', '10.0.0.2'] # comma delimiter automagically added obs.ip_address.condition = "Equals" obs.ip_address.apply_condition = "ANY" pkg.add_observable(obs) print pkg.to_xml()
def make_cybox_object(type_, value=None): """ Converts type_, name, and value to a CybOX object instance. :param type_: The object type. :type type_: str :param value: The object value. :type value: str :returns: CybOX object """ if type_ == IndicatorTypes.USER_ID: acct = Account() acct.description = value return acct elif type_ in IPTypes.values(): if type_ == IPTypes.IPV4_ADDRESS: name = 'ipv4-addr' elif type_ == IPTypes.IPV6_ADDRESS: name = 'ipv6-addr' elif type_ == IPTypes.IPV4_SUBNET: name = 'ipv4-net' elif type_ == IPTypes.IPV6_SUBNET: name = 'ipv6-net' return Address(category=name, address_value=value) elif type_ == IndicatorTypes.API_KEY: api = API() api.description = value return api elif type_ == IndicatorTypes.DOMAIN: obj = DomainName() obj.value = value return obj elif type_ == IndicatorTypes.USER_AGENT: obj = HTTPRequestHeaderFields() obj.user_agent = value return obj elif type_ == IndicatorTypes.MUTEX: m = Mutex() m.named = True m.name = String(value) return m elif type_ in (IndicatorTypes.SOURCE_PORT, IndicatorTypes.DEST_PORT): p = Port() try: p.port_value = PositiveInteger(value) except ValueError: # XXX: Raise a better exception... raise UnsupportedCybOXObjectTypeError(type_, name) return p elif type_ == IndicatorTypes.PROCESS_NAME: p = Process() p.name = String(value) return p elif type_ == IndicatorTypes.URI: r = URI() r.type_ = 'URL' r.value = value return r elif type_ in (IndicatorTypes.REGISTRY_KEY, IndicatorTypes.REG_KEY_CREATED, IndicatorTypes.REG_KEY_DELETED, IndicatorTypes.REG_KEY_ENUMERATED, IndicatorTypes.REG_KEY_MONITORED, IndicatorTypes.REG_KEY_OPENED): obj = WinRegistryKey() obj.key = value return obj """ The following are types that are listed in the 'Indicator Type' box of the 'New Indicator' dialog in CRITs. These types, unlike those handled above, cannot be written to or read from CybOX at this point. The reason for the type being omitted is written as a comment inline. This can (and should) be revisited as new versions of CybOX are released. NOTE: You will have to update the corresponding make_crits_object function with handling for the reverse direction. In the mean time, these types will raise unsupported errors. """ #elif type_ == "Device": # No CybOX API #elif type_ == "DNS Cache": # No CybOX API #elif type_ == "GUI": # revisit when CRITs supports width & height specification #elif type_ == "HTTP Session": # No good mapping between CybOX/CRITs #elif type_ == "Linux Package": # No CybOX API #elif type_ == "Network Packet": # No good mapping between CybOX/CRITs #elif type_ == "Network Route Entry": # No CybOX API #elif type_ == "Network Route": # No CybOX API #elif type_ == "Network Subnet": # No CybOX API #elif type_ == "Semaphore": # No CybOX API #elif type_ == "Socket": # No good mapping between CybOX/CRITs #elif type_ == "UNIX File": # No CybOX API #elif type_ == "UNIX Network Route Entry": # No CybOX API #elif type_ == "UNIX Pipe": # No CybOX API #elif type_ == "UNIX Process": # No CybOX API #elif type_ == "UNIX User Account": # No CybOX API #elif type_ == "UNIX Volume": # No CybOX API #elif type_ == "User Session": # No CybOX API #elif type_ == "Whois": # No good mapping between CybOX/CRITs #elif type_ == "Win Computer Account": # No CybOX API #elif type_ == "Win Critical Section": # No CybOX API #elif type_ == "Win Executable File": # No good mapping between CybOX/CRITs #elif type_ == "Win File": # No good mapping between CybOX/CRITs #elif type_ == "Win Kernel": # No CybOX API #elif type_ == "Win Mutex": # No good mapping between CybOX/CRITs #elif type_ == "Win Network Route Entry": # No CybOX API #elif type_ == "Win Pipe": # No good mapping between CybOX/CRITs #elif type_ == "Win Prefetch": # No CybOX API #elif type_ == "Win Semaphore": # No CybOX API #elif type_ == "Win System Restore": # No CybOX API #elif type_ == "Win Thread": # No good mapping between CybOX/CRITs #elif type_ == "Win Waitable Timer": # No CybOX API raise UnsupportedCybOXObjectTypeError(type_)
def make_cybox_object(type_, value=None): """ Converts type_, name, and value to a CybOX object instance. :param type_: The object type. :type type_: str :param value: The object value. :type value: str :returns: CybOX object """ if type_ == IndicatorTypes.USER_ID: acct = Account() acct.description = value return acct elif type_ in IPTypes.values(): if type_ == IPTypes.IPV4_ADDRESS: name = 'ipv4-addr' elif type_ == IPTypes.IPV6_ADDRESS: name = 'ipv6-addr' elif type_ == IPTypes.IPV4_SUBNET: name = 'ipv4-net' elif type_ == IPTypes.IPV6_SUBNET: name = 'ipv6-net' return Address(category=name, address_value=value) elif type_ == IndicatorTypes.API_KEY: api = API() api.description = value return api elif type_ == IndicatorTypes.DOMAIN: obj = DomainName() obj.value = value elif type_ == IndicatorTypes.USER_AGENT: obj = HTTPRequestHeaderFields() obj.user_agent = value return obj elif type_ == IndicatorTypes.MUTEX: m = Mutex() m.named = True m.name = String(value) return m elif type_ in (IndicatorTypes.SOURCE_PORT, IndicatorTypes.DEST_PORT): p = Port() try: p.port_value = PositiveInteger(value) except ValueError: # XXX: Raise a better exception... raise UnsupportedCybOXObjectTypeError(type_, name) return p elif type_ == IndicatorTypes.PROCESS_NAME: p = Process() p.name = String(value) return p elif type_ == IndicatorTypes.URI: r = URI() r.type_ = 'URL' r.value = value return r elif type_ in (IndicatorTypes.REGISTRY_KEY, IndicatorTypes.REG_KEY_CREATED, IndicatorTypes.REG_KEY_DELETED, IndicatorTypes.REG_KEY_ENUMERATED, IndicatorTypes.REG_KEY_MONITORED, IndicatorTypes.REG_KEY_OPENED): obj = WinRegistryKey() obj.key = value return obj """ The following are types that are listed in the 'Indicator Type' box of the 'New Indicator' dialog in CRITs. These types, unlike those handled above, cannot be written to or read from CybOX at this point. The reason for the type being omitted is written as a comment inline. This can (and should) be revisited as new versions of CybOX are released. NOTE: You will have to update the corresponding make_crits_object function with handling for the reverse direction. In the mean time, these types will raise unsupported errors. """ #elif type_ == "Device": # No CybOX API #elif type_ == "DNS Cache": # No CybOX API #elif type_ == "GUI": # revisit when CRITs supports width & height specification #elif type_ == "HTTP Session": # No good mapping between CybOX/CRITs #elif type_ == "Linux Package": # No CybOX API #elif type_ == "Network Packet": # No good mapping between CybOX/CRITs #elif type_ == "Network Route Entry": # No CybOX API #elif type_ == "Network Route": # No CybOX API #elif type_ == "Network Subnet": # No CybOX API #elif type_ == "Semaphore": # No CybOX API #elif type_ == "Socket": # No good mapping between CybOX/CRITs #elif type_ == "UNIX File": # No CybOX API #elif type_ == "UNIX Network Route Entry": # No CybOX API #elif type_ == "UNIX Pipe": # No CybOX API #elif type_ == "UNIX Process": # No CybOX API #elif type_ == "UNIX User Account": # No CybOX API #elif type_ == "UNIX Volume": # No CybOX API #elif type_ == "User Session": # No CybOX API #elif type_ == "Whois": # No good mapping between CybOX/CRITs #elif type_ == "Win Computer Account": # No CybOX API #elif type_ == "Win Critical Section": # No CybOX API #elif type_ == "Win Executable File": # No good mapping between CybOX/CRITs #elif type_ == "Win File": # No good mapping between CybOX/CRITs #elif type_ == "Win Kernel": # No CybOX API #elif type_ == "Win Mutex": # No good mapping between CybOX/CRITs #elif type_ == "Win Network Route Entry": # No CybOX API #elif type_ == "Win Pipe": # No good mapping between CybOX/CRITs #elif type_ == "Win Prefetch": # No CybOX API #elif type_ == "Win Semaphore": # No CybOX API #elif type_ == "Win System Restore": # No CybOX API #elif type_ == "Win Thread": # No good mapping between CybOX/CRITs #elif type_ == "Win Waitable Timer": # No CybOX API raise UnsupportedCybOXObjectTypeError(type_, name)
def build(self): self.stix_header.title = self.pulse["name"] self.stix_header.description = self.pulse["description"] self.stix_header.short_description = "%spulse/%s" % (PULSE_SERVER_BASE, str(self.pulse["id"])) self.stix_header.package_intents.append(PackageIntent.TERM_INDICATORS) self.stix_header.information_source = InformationSource() self.stix_header.information_source.time = Time() self.stix_header.information_source.description = "Alienvault OTX - https://otx.alienvault.com/" self.stix_header.information_source.time.produced_time = self.pulse["modified"] self.stix_header.information_source.identity = Identity() self.stix_header.information_source.identity.name = "Alienvault OTX" self.stix_package.stix_header = self.stix_header hashes = [] addresses = [] domains = [] urls = [] mails = [] for p_indicator in self.pulse["indicators"]: if p_indicator["type"] in self.hash_translation: new_ind = Indicator() new_ind.description = p_indicator["description"] new_ind.title = "%s from %spulse/%s" % (p_indicator["indicator"], PULSE_SERVER_BASE, str(self.pulse["id"])) file_ = File() hash_ = Hash(p_indicator["indicator"], self.hash_translation[p_indicator["type"]]) file_.add_hash(hash_) observable_ = Observable(file_) elif p_indicator["type"] in self.address_translation: new_ind = Indicator() new_ind.description = p_indicator["description"] new_ind.title = "%s from %spulse/%s" % (p_indicator["indicator"], PULSE_SERVER_BASE, str(self.pulse["id"])) ipv4_ = Address.from_dict({'address_value': p_indicator["indicator"], 'category': self.address_translation[p_indicator["type"]]}) observable_ = Observable(ipv4_) elif p_indicator["type"] in self.name_translation: new_ind = Indicator() new_ind.description = p_indicator["description"] new_ind.title = "%s from %spulse/%s" % (p_indicator["indicator"], PULSE_SERVER_BASE, str(self.pulse["id"])) domain_ = DomainName.from_dict({'value': p_indicator["indicator"], 'type':'FQDN'}) observable_ = Observable(domain_) elif p_indicator["type"] == "URL": new_ind = Indicator() new_ind.description = p_indicator["description"] new_ind.title = "%s from %spulse/%s" % (p_indicator["indicator"], PULSE_SERVER_BASE, str(self.pulse["id"])) url_ = URI.from_dict({'value': p_indicator["indicator"], 'type': URI.TYPE_URL}) observable_ = Observable(url_) elif p_indicator["type"] == "email": email_ = Address.from_dict({'address_value': p_indicator["indicator"], 'category': Address.CAT_EMAIL}) observable_ = Observable(email_) #elif p_indicator["type"] == "CVE": # vuln_ = Vulnerability() # vuln_.cveid = p_indicator["indicator"].upper() # observable_ = Observable(vuln_) elif p_indicator["type"] == "Mutex": mutex_ = Mutex.from_dict({'named': True, 'name': p_indicator["indicator"]}) observable_ = Observable(mutex_) elif p_indicator["type"] == "CIDR": nrange = IP(p_indicator["indicator"]) nrange_values = nrange.strNormal(3).replace("-", ",") ipv4_ = Address.from_dict({'address_value': nrange_values, 'category': Address.CAT_IPV4}) ipv4_.address_value.condition = "InclusiveBetween" observable_ = Observable(ipv4_) else: continue mind = Indicator() mind.description = p_indicator["description"] mind.title = "%s from %spulse/%s" % (p_indicator["indicator"], PULSE_SERVER_BASE, str(self.pulse["id"])) observable_.title = "%s - %s" % (p_indicator["type"], p_indicator["indicator"]) mind.add_observable(observable_) self.stix_package.add_indicator(mind)
def build(self): """Define the STIX report.""" self.stix_header.title = self.pulse["name"] self.stix_header.description = self.pulse["description"] self.stix_header.package_intents = "Indicators" self.stix_header.information_source = InformationSource() self.stix_header.information_source.time = Time() self.stix_header.information_source.time.received_time = self.pulse[ "modified"] self.stix_header.information_source.time.produced_time = self.stix_package.timestamp self.stix_header.information_source.identity = Identity() self.stix_header.information_source.identity.name = IDENTITY_NAME # self.stix_package.stix_header = self.stix_header # self.stix_package.stix_header.handling = self._marking() # self.report = Report() # self.report.header = Header() # self.report.header.title = self.pulse["name"] # self.report.header.descriptions = self.pulse["description"] # self.report.header.intents = "Indicators" # self.report.header.short_description = "%spulse/%s" % ( # PULSE_SERVER_BASE, str(self.pulse["id"])) # self.report.header.information_source = InformationSource() # self.report.header.information_source.time = Time() # self.report.header.information_source.time.received_time = self.pulse[ # "modified"] # self.report.header.information_source.time.produced_time = self.report.timestamp # self.report.header.information_source.identity = Identity() # self.report.header.information_source.identity.name = IDENTITY_NAME hashes = False addresses = False emails = False domains = False urls = False mutex = False hash_indicator = Indicator() hash_indicator.set_producer_identity(IDENTITY_NAME) hash_indicator.set_produced_time(hash_indicator.timestamp) hash_indicator.set_received_time(self.pulse["modified"]) hash_indicator.title = "[OTX] [Files] " + self.pulse["name"] hash_indicator.add_indicator_type("File Hash Watchlist") hash_indicator.confidence = "Low" address_indicator = Indicator() address_indicator.set_producer_identity(IDENTITY_NAME) address_indicator.set_produced_time(address_indicator.timestamp) address_indicator.set_received_time(self.pulse["modified"]) address_indicator.title = "[OTX] [IP] " + self.pulse["name"] address_indicator.add_indicator_type("IP Watchlist") address_indicator.confidence = "Low" domain_indicator = Indicator() domain_indicator.set_producer_identity(IDENTITY_NAME) domain_indicator.set_produced_time(domain_indicator.timestamp) domain_indicator.set_received_time(self.pulse["modified"]) domain_indicator.title = "[OTX] [Domain] " + self.pulse["name"] domain_indicator.add_indicator_type("Domain Watchlist") domain_indicator.confidence = "Low" url_indicator = Indicator() url_indicator.set_producer_identity(IDENTITY_NAME) url_indicator.set_produced_time(url_indicator.timestamp) url_indicator.set_received_time(self.pulse["modified"]) url_indicator.title = "[OTX] [URL] " + self.pulse["name"] url_indicator.add_indicator_type("URL Watchlist") url_indicator.confidence = "Low" email_indicator = Indicator() email_indicator.set_producer_identity(IDENTITY_NAME) email_indicator.set_produced_time(email_indicator.timestamp) email_indicator.set_received_time(self.pulse["modified"]) email_indicator.title = "[OTX] [Email] " + self.pulse["name"] email_indicator.add_indicator_type("Malicious E-mail") email_indicator.confidence = "Low" mutex_indicator = Indicator() mutex_indicator.set_producer_identity(IDENTITY_NAME) mutex_indicator.set_produced_time(mutex_indicator.timestamp) mutex_indicator.set_received_time(self.pulse["modified"]) mutex_indicator.title = "[OTX] [Mutex] " + self.pulse["name"] mutex_indicator.add_indicator_type("Malware Artifacts") mutex_indicator.confidence = "Low" for p_indicator in self.pulse["indicators"]: if p_indicator["type"] in self.hash_translation: file_object = File() file_object.add_hash(Hash(p_indicator["indicator"])) file_object.hashes[0].simple_hash_value.condition = "Equals" file_object.hashes[0].type_.condition = "Equals" file_obs = Observable(file_object) file_obs.title = "File: " + \ str(file_object.hashes[0].type_) + \ " - " + p_indicator["indicator"] hash_indicator.add_observable(file_obs) try: hash_indicator.description = p_indicator["description"] except KeyError: hash_indicator.description = "" hashes = True elif p_indicator["type"] in self.address_translation: ip = Address() ip.address_value = p_indicator["indicator"] ip.category = self.address_translation[p_indicator["type"]] ip.address_value.condition = "Equals" ip_obs = Observable(ip) ip_obs.title = "Address: " + str(ip.address_value) address_indicator.add_observable(ip_obs) try: address_indicator.description = p_indicator["description"] except KeyError: address_indicator.description = "" addresses = True elif p_indicator["type"] in self.name_translation: domain = DomainName() domain.value = p_indicator["indicator"] domain.type_ = "FQDN" domain.value.condition = "Equals" domain_obs = Observable(domain) domain_obs.title = "Domain: " + str(domain.value) domain_indicator.add_observable(domain_obs) try: domain_indicator.description = p_indicator["description"] except KeyError: domain_indicator.description = "" domains = True elif p_indicator["type"] == "URL": url = URI() url.value = p_indicator["indicator"] url.type_ = URI.TYPE_URL url.value.condition = "Equals" url_obs = Observable(url) url_obs.title = "URI: " + str(url.value) url_indicator.add_observable(url_obs) try: url_indicator.description = p_indicator["description"] except KeyError: url_indicator.description = "" urls = True elif p_indicator["type"] == "email": email = Address() email.address_value = p_indicator["indicator"] email.category = "e-mail" email.address_value.condition = "Equals" email_obs = Observable(email) email_obs.title = "Address: " + str(email.address_value) email_indicator.add_observable(email_obs) try: email_indicator.description = p_indicator["indicator"] except KeyError: email_indicator.description = "" emails = True elif p_indicator["type"] == "Mutex": mutex = Mutex() mutex.name = p_indicator["indicator"] mutex.named = True mutex_obs = Observable(mutex) mutex_obs.title = "Mutex: " + str(mutex.name) mutex_indicator.add_observable(mutex_obs) try: mutex_indicator.description = p_indicator["indicator"] except KeyError: mutex_indicator.description = "" mutex = True else: continue if hashes: self.stix_package.add_indicator(hash_indicator) if addresses: self.stix_package.add_indicator(address_indicator) if domains: self.stix_package.add_indicator(domain_indicator) if urls: self.stix_package.add_indicator(url_indicator) if emails: self.stix_package.add_indicator(email_indicator) if mutex: self.stix_package.add_indicator(mutex_indicator)
observables_doc.add(WinRegistryKey.from_dict({"hive": "SYSTEM", "key": "some\\registry\\key", "number_values": 2, "values": [{"name": "Something", "datatype": "REG_DWORD", #or whatever it is... "data": "Something else"}, {"name": "Another", "datatype": "REG_BINARY", #or whatever it is... "data": base64.b64encode("\x90\x90\x90")}], #binary stuff must be normalized, base64 is the usual "number_subkeys": 1, # subkeys have the same members as keys: "subkeys": [{"key": "SubkeyName", "number_values": 1, "values": [{"name": "SubkeyVal", "datatype": "REG_DWORD", "data": "Subkey val data"}]}] })) observables_doc.add(Mutex.from_dict({"name": "Some_MUTEX!!!"})) # we can also specify conditions: proc = Process.from_dict({"name": "anotherProcess.exe", "pid": 102, "parent_pid": 10, "image_info": {"command_line": "anotherProcess.exe /c blahblah.bat"}}) proc.name.condition = "Equals" proc.image_info.command_line.condition = "Contains" # we need the same object so we can use the id for the compositions below obs1 = Observable(proc) observables_doc.add(obs1) file = File.from_dict({"file_name": "blah", "file_extension": "bat"}) file.file_name.condition = "Contains" file.file_extension.condition = "Equals"