├── .gitignore ├── MaltegoTransform.py ├── README.md ├── __init__.py ├── config.py ├── credentials.cfg-sample ├── credentials.py ├── iSight ├── LICENSE ├── README.md ├── __init__.py ├── iSightTransforms.py └── isighttransforms.mtz ├── packetmail ├── LICENSE ├── PacketmailTransforms.py ├── README.md ├── __init__.py └── packetmail.mtz ├── proxies.cfg └── torlookup ├── LICENSE ├── README.md ├── TorExitNodeTransforms.py ├── __init__.py └── torlookuptransforms.mtz /.gitignore: -------------------------------------------------------------------------------- 1 | credentials.cfg 2 | *.pyc 3 | */*.pyc 4 | torlookup/exit-addresses 5 | -------------------------------------------------------------------------------- /MaltegoTransform.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | ####################################################### 3 | # Maltego Python Local Transform Helper # 4 | # Version 0.2 # 5 | # # 6 | # Local transform specification can be found at: # 7 | # http://ctas.paterva.com/view/Specification # 8 | # # 9 | # For more help and other local transforms # 10 | # try the forum or mail me: # 11 | # # 12 | # http://www.paterva.com/forum # 13 | # # 14 | # Andrew MacPherson [ andrew <> Paterva.com ] # 15 | # # 16 | ####################################################### 17 | import sys 18 | 19 | class MaltegoEntity(object): 20 | value = ""; 21 | weight = 100; 22 | displayInformation = None; 23 | additionalFields = []; 24 | iconURL = ""; 25 | entityType = "Phrase" 26 | 27 | def __init__(self,eT=None,v=None): 28 | if (eT is not None): 29 | self.entityType = eT; 30 | if (v is not None): 31 | self.value = sanitise(v); 32 | self.additionalFields = []; 33 | self.displayInformation = None; 34 | 35 | def setType(self,eT=None): 36 | if (eT is not None): 37 | self.entityType = eT; 38 | 39 | def setValue(self,eV=None): 40 | if (eV is not None): 41 | self.value = sanitise(eV); 42 | 43 | def setWeight(self,w=None): 44 | if (w is not None): 45 | self.weight = w; 46 | 47 | def setDisplayInformation(self,di=None): 48 | if (di is not None): 49 | self.displayInformation = di; 50 | 51 | def addAdditionalFields(self,fieldName=None,displayName=None,matchingRule=False,value=None): 52 | self.additionalFields.append([sanitise(fieldName),sanitise(displayName),matchingRule,sanitise(value)]); 53 | 54 | def setIconURL(self,iU=None): 55 | if (iU is not None): 56 | self.iconURL = iU; 57 | 58 | def returnEntity(self): 59 | print ""; 60 | print "" + str(self.value) + ""; 61 | print "" + str(self.weight) + ""; 62 | if (self.displayInformation is not None): 63 | print ""; 64 | if (len(self.additionalFields) > 0): 65 | print ""; 66 | for i in range(len(self.additionalFields)): 67 | if (str(self.additionalFields[i][2]) <> "strict"): 68 | print "" + str(self.additionalFields[i][3]) + ""; 69 | else: 70 | print "" + str(self.additionalFields[i][3]) + ""; 71 | print ""; 72 | if (len(self.iconURL) > 0): 73 | print "" + self.iconURL + ""; 74 | print ""; 75 | 76 | class MaltegoTransform(object): 77 | entities = [] 78 | exceptions = [] 79 | UIMessages = [] 80 | values = {}; 81 | 82 | def __init__(self): 83 | values = {}; 84 | value = None; 85 | 86 | def parseArguments(self,argv): 87 | if (argv[1] is not None): 88 | self.value = argv[1]; 89 | 90 | if (len(argv) > 2): 91 | if (argv[2] is not None): 92 | vars = argv[2].split('#'); 93 | for x in range(0,len(vars)): 94 | vars_values = vars[x].split('=') 95 | if (len(vars_values) == 2): 96 | self.values[vars_values[0]] = vars_values[1]; 97 | 98 | def getValue(self): 99 | if (self.value is not None): 100 | return self.value; 101 | 102 | def getVar(self,varName): 103 | if (varName in self.values.keys()): 104 | if (self.values[varName] is not None): 105 | return self.values[varName]; 106 | 107 | def addEntity(self,enType,enValue): 108 | me = MaltegoEntity(enType,enValue); 109 | self.addEntityToMessage(me); 110 | return self.entities[len(self.entities)-1]; 111 | 112 | def addEntityToMessage(self,maltegoEntity): 113 | self.entities.append(maltegoEntity); 114 | 115 | def addUIMessage(self,message,messageType="Inform"): 116 | self.UIMessages.append([messageType,message]); 117 | 118 | def addException(self,exceptionString): 119 | self.exceptions.append(exceptionString); 120 | 121 | def throwExceptions(self): 122 | print ""; 123 | print ""; 124 | print "" 125 | 126 | for i in range(len(self.exceptions)): 127 | print "" + self.exceptions[i] + ""; 128 | print "" 129 | print ""; 130 | print ""; 131 | exit(); 132 | 133 | def returnOutput(self): 134 | print ""; 135 | print ""; 136 | 137 | print "" 138 | for i in range(len(self.entities)): 139 | self.entities[i].returnEntity(); 140 | print "" 141 | 142 | print "" 143 | for i in range(len(self.UIMessages)): 144 | print "" + self.UIMessages[i][1] + ""; 145 | print "" 146 | 147 | print ""; 148 | print ""; 149 | 150 | def writeSTDERR(self,msg): 151 | sys.stderr.write(str(msg)); 152 | 153 | def heartbeat(self): 154 | self.writeSTDERR("+"); 155 | 156 | def progress(self,percent): 157 | self.writeSTDERR("%" + str(percent)); 158 | 159 | def debug(self,msg): 160 | self.writeSTDERR("D:" + str(msg)); 161 | 162 | 163 | 164 | def sanitise(value): 165 | replace_these = ["&",">","<"]; 166 | replace_with = ["&",">","<"]; 167 | tempvalue = value; 168 | for i in range(0,len(replace_these)): 169 | tempvalue = tempvalue.replace(replace_these[i],replace_with[i]); 170 | return tempvalue; -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # maltego-transforms 2 | 3 | Repository for some Python Maltego transforms. 4 | 5 | * Packetmail 6 | * iSight 7 | * Tor Exit Node Lookup 8 | 9 | Note that none of this is supported by the parties providing these services and please refer to the provided LICENSE files for a full description. 10 | 11 | ## Requirements 12 | * Python with the following packages installed 13 | * Requests 14 | * configparser 15 | 16 | ## Installation 17 | Provided you have met the requirements listed above, you need to: 18 | * Import each .mtz and modify the path accordingly for your installation. 19 | * Copy the credentials.cvg-sample to credentials.cfg and add your keys 20 | * Proxy config (untested) can be added to proxy.cfg. Use the format specified in here: http://docs.python-requests.org/en/v1.0.4/user/advanced/ 21 | -------------------------------------------------------------------------------- /__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0xd34db33f/maltego-transforms/833d1b16ddb4ec15236ffa591aa7151ee15950aa/__init__.py -------------------------------------------------------------------------------- /config.py: -------------------------------------------------------------------------------- 1 | import configparser 2 | 3 | class Proxies: 4 | 5 | http_proxy = None 6 | https_proxy = None 7 | config = None 8 | def __init__(self): 9 | self.config = configparser.ConfigParser() 10 | self.config.read('proxies.cfg') 11 | self.http_proxy = str(self.config['PROXYLIST'][u'http']) 12 | self.https_proxy = str(self.config['PROXYLIST'][u'https']) 13 | 14 | def getProxies(self): 15 | proxyDict = { 16 | "http" : self.http_proxy, 17 | "https" : self.https_proxy, 18 | } 19 | return proxyDict 20 | 21 | -------------------------------------------------------------------------------- /credentials.cfg-sample: -------------------------------------------------------------------------------- 1 | [ISIGHT] 2 | pubKey = INSERTPUBKEYHERE 3 | privKey = INSERTPRIVKEYHERE 4 | 5 | [PACKETMAIL] 6 | packetmailApiKey = INSERTKEYHERE 7 | -------------------------------------------------------------------------------- /credentials.py: -------------------------------------------------------------------------------- 1 | import configparser 2 | 3 | class Credentials: 4 | 5 | config = None 6 | def __init__(self): 7 | self.config = configparser.ConfigParser() 8 | self.config.read('credentials.cfg') 9 | 10 | def getCredentials(self,parentModuleName,credentialName): 11 | return self.config[parentModuleName][credentialName] 12 | 13 | -------------------------------------------------------------------------------- /iSight/LICENSE: -------------------------------------------------------------------------------- 1 | ''' 2 | Copyright (c) 2015, Ryan Keyes 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | * Redistributions of source code must retain the above copyright 8 | notice, this list of conditions and the following disclaimer. 9 | * Redistributions in binary form must reproduce the above copyright 10 | notice, this list of conditions and the following disclaimer in the 11 | documentation and/or other materials provided with the distribution. 12 | 13 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 14 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 15 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 16 | DISCLAIMED. IN NO EVENT SHALL RYAN KEYES, HIS EMPLOYER, OR ISIGHT PARTNERS BE LIABLE FOR ANY 17 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 18 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 19 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 20 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 21 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 22 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 23 | ''' 24 | -------------------------------------------------------------------------------- /iSight/README.md: -------------------------------------------------------------------------------- 1 | # maltego-transforms-isight 2 | 3 | Maltego transform for iSight Partner's API. See code license for details (it's BSD, basically have fun). Please note that this is 4 | not in any way associated with or supported by iSight Partners. Use at your own risk. 5 | -------------------------------------------------------------------------------- /iSight/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0xd34db33f/maltego-transforms/833d1b16ddb4ec15236ffa591aa7151ee15950aa/iSight/__init__.py -------------------------------------------------------------------------------- /iSight/iSightTransforms.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | 3 | ''' 4 | Copyright (c) 2015, Ryan Keyes 5 | All rights reserved. 6 | 7 | Redistribution and use in source and binary forms, with or without 8 | modification, are permitted provided that the following conditions are met: 9 | * Redistributions of source code must retain the above copyright 10 | notice, this list of conditions and the following disclaimer. 11 | * Redistributions in binary form must reproduce the above copyright 12 | notice, this list of conditions and the following disclaimer in the 13 | documentation and/or other materials provided with the distribution. 14 | 15 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 16 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 17 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 18 | DISCLAIMED. IN NO EVENT SHALL RYAN KEYES, HIS EMPLOYER, OR ISIGHT PARTNERS BE LIABLE FOR ANY 19 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 20 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 21 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 22 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 24 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 | ''' 26 | 27 | import requests 28 | import hmac 29 | import traceback 30 | import string 31 | import hashlib 32 | import json 33 | import time 34 | import email 35 | import sys 36 | 37 | from MaltegoTransform import MaltegoTransform 38 | 39 | from credentials import Credentials 40 | from config import Proxies 41 | 42 | proxyList = Proxies() 43 | url = 'https://api.isightpartners.com' 44 | 45 | creds = Credentials() 46 | pubKey = str(creds.getCredentials('ISIGHT',u'pubKey')) 47 | privKey = str(creds.getCredentials('ISIGHT',u'privKey')) 48 | apiVer = '2.0' 49 | 50 | 51 | # Get the HTTP authentication headers. 52 | def getAuthHeaders(authKey, respFormat, timestamp): 53 | authHeaders = { 54 | 'X-Auth' : pubKey, 55 | 'X-Auth-Hash' : hmac.new(privKey, authKey, hashlib.sha256).hexdigest(), 56 | 'Accept' : respFormat, 57 | 'Accept-Version' : apiVer, 58 | 'Date' : timestamp 59 | } 60 | return authHeaders 61 | 62 | # Get past 24 hours of IOCs from iSIGHT. 63 | def getJSON(endpoint,query,queryVars): 64 | 65 | # Submit request to iSIGHT's API and get the resulting IOCs. 66 | respFormat = 'application/json' 67 | timestamp = email.Utils.formatdate(localtime=True) 68 | authKey = endpoint + query + apiVer + respFormat + timestamp 69 | 70 | # Get the HTTP authentication headers. 71 | authHeaders = getAuthHeaders(authKey, respFormat, timestamp) 72 | req = requests.get(url+endpoint,params=queryVars, headers=authHeaders, verify=True, proxies=proxyList.getProxies()) 73 | try: 74 | jsonData = json.loads(req.text) 75 | except Exception,e: 76 | #Moving on 77 | jsonData = {} 78 | return jsonData 79 | 80 | def formatURLs(x,y): 81 | return x+'\n'+y 82 | 83 | # Modify this function for development/troubleshooting. 84 | def ipToReport(malEntityData, ip): 85 | urlLookup = {} 86 | query = '?ip='+ip 87 | queryVars = { 88 | 'ip':ip 89 | } 90 | 91 | try: 92 | jsonData = getJSON('/search/basic',query,queryVars) 93 | if 'message' in jsonData.keys(): 94 | jsonMessage = jsonData[u'message'] 95 | for jsonReport in jsonMessage: 96 | if 'title' in jsonReport.keys(): 97 | title = jsonReport[u'title'] 98 | if not title in urlLookup: 99 | urlLookup[title] = [] 100 | urlLookup[title].append(jsonReport[u'webLink']+u' '+ title) 101 | 102 | for k,v in urlLookup.iteritems(): 103 | currEntity = malEntityData.addEntity("maltego.Website", '%s' % k) 104 | urlField = reduce(formatURLs,v) 105 | currEntity.addAdditionalFields(fieldName="URLS",displayName="URLs",value=urlField) 106 | except Exception,e: 107 | #Meh I'm just going to catch everything and let the user deal with it 108 | malEntityData.addEntity("maltego.Phrase", 'ipToAbuseList Error: - %s' % str(e)) 109 | 110 | return malEntityData 111 | 112 | def ipToPivot(malEntityData, ip): 113 | urlLookup = {} 114 | try: 115 | jsonData = getJSON('/pivot/indicator/ip/'+ip,'','') 116 | 117 | if 'message' in jsonData.keys(): 118 | jsonMessage = jsonData[u'message'] 119 | indicators = jsonMessage[u'publishedIndicators'] 120 | for jsonReport in indicators: 121 | if jsonReport[u'domain'] is not None: 122 | currEntity = malEntityData.addEntity("maltego.Domain", '%s' % jsonReport[u'domain']) 123 | if jsonReport[u'ip'] is not None: 124 | currEntity = malEntityData.addEntity("maltego.IPv4Address", '%s' % jsonReport[u'ip']) 125 | if jsonReport[u'md5'] is not None: 126 | currEntity = malEntityData.addEntity("maltego.Phrase",'%s' %jsonReport[u'md5']) 127 | except Exception,e: 128 | #Meh I'm just going to catch everything and let the user deal with it 129 | malEntityData.addEntity("maltego.Phrase", 'ipToAbuseList Error: - %s' % str(e)) 130 | 131 | return malEntityData 132 | 133 | def domainToReport(malEntityData, domain): 134 | urlLookup = {} 135 | query = '?domain='+domain 136 | queryVars = { 137 | 'domain':domain 138 | } 139 | 140 | try: 141 | jsonData = getJSON('/search/basic',query,queryVars) 142 | if 'message' in jsonData.keys(): 143 | jsonMessage = jsonData[u'message'] 144 | for jsonReport in jsonMessage: 145 | if 'title' in jsonReport.keys(): 146 | title = jsonReport[u'title'] 147 | if not title in urlLookup: 148 | urlLookup[title] = [] 149 | urlLookup[title].append(jsonReport[u'webLink']+u' '+ title) 150 | 151 | for k,v in urlLookup.iteritems(): 152 | currEntity = malEntityData.addEntity("maltego.Website", '%s' % k) 153 | urlField = reduce(formatURLs,v) 154 | currEntity.addAdditionalFields(fieldName="URLS",displayName="URLs",value=urlField) 155 | except Exception,e: 156 | #Meh I'm just going to catch everything and let the user deal with it 157 | malEntityData.addEntity("maltego.Phrase", 'ipToAbuseList Error: - %s' % str(e)) 158 | 159 | return malEntityData 160 | 161 | def domainToPivot(malEntityData, domain): 162 | urlLookup = {} 163 | try: 164 | jsonData = getJSON('/pivot/indicator/domain/'+domain,'','') 165 | 166 | if 'message' in jsonData.keys(): 167 | jsonMessage = jsonData[u'message'] 168 | indicators = jsonMessage[u'publishedIndicators'] 169 | for jsonReport in indicators: 170 | if jsonReport[u'domain'] is not None: 171 | currEntity = malEntityData.addEntity("maltego.Domain", '%s' % jsonReport[u'domain']) 172 | if jsonReport[u'ip'] is not None: 173 | currEntity = malEntityData.addEntity("maltego.IPv4Address", '%s' % jsonReport[u'ip']) 174 | if jsonReport[u'md5'] is not None: 175 | currEntity = malEntityData.addEntity("maltego.Phrase",'%s' %jsonReport[u'md5']) 176 | except Exception,e: 177 | #Meh I'm just going to catch everything and let the user deal with it 178 | malEntityData.addEntity("maltego.Phrase", 'ipToAbuseList Error: - %s' % str(e)) 179 | 180 | return malEntityData 181 | 182 | transformFunctions = { 183 | 'ipToReport': ipToReport, 184 | 'ipToPivot': ipToPivot, 185 | 'domainToReport': domainToReport, 186 | 'domainToPivot': domainToPivot, 187 | } 188 | 189 | # Main 190 | if __name__ == '__main__': 191 | transformName = sys.argv[1] 192 | dataToTransform = sys.argv[2] 193 | 194 | malEntity = MaltegoTransform() 195 | results = transformFunctions[transformName](malEntity,dataToTransform) 196 | results.returnOutput() 197 | -------------------------------------------------------------------------------- /iSight/isighttransforms.mtz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0xd34db33f/maltego-transforms/833d1b16ddb4ec15236ffa591aa7151ee15950aa/iSight/isighttransforms.mtz -------------------------------------------------------------------------------- /packetmail/LICENSE: -------------------------------------------------------------------------------- 1 | ''' 2 | Copyright (c) 2015, Ryan Keyes 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | * Redistributions of source code must retain the above copyright 8 | notice, this list of conditions and the following disclaimer. 9 | * Redistributions in binary form must reproduce the above copyright 10 | notice, this list of conditions and the following disclaimer in the 11 | documentation and/or other materials provided with the distribution. 12 | 13 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 14 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 15 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 16 | DISCLAIMED. IN NO EVENT SHALL RYAN KEYES OR HIS EMPLOYER BE LIABLE FOR ANY 17 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 18 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 19 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 20 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 21 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 22 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 23 | ''' 24 | -------------------------------------------------------------------------------- /packetmail/PacketmailTransforms.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Copyright (c) 2015, Ryan Keyes 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | * Redistributions of source code must retain the above copyright 8 | notice, this list of conditions and the following disclaimer. 9 | * Redistributions in binary form must reproduce the above copyright 10 | notice, this list of conditions and the following disclaimer in the 11 | documentation and/or other materials provided with the distribution. 12 | 13 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 14 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 15 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 16 | DISCLAIMED. IN NO EVENT SHALL RYAN KEYES OR HIS EMPLOYER BE LIABLE FOR ANY 17 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 18 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 19 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 20 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 21 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 22 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 23 | ''' 24 | 25 | import os, sys 26 | import requests 27 | import json 28 | import re 29 | 30 | from MaltegoTransform import MaltegoTransform 31 | from credentials import Credentials 32 | from config import Proxies 33 | 34 | creds = Credentials() 35 | packetmailApiKey = str(creds.getCredentials('PACKETMAIL',u'packetmailApiKey')) 36 | proxyList = Proxies() 37 | baseUrl = "https://www.packetmail.net/iprep.php/" 38 | 39 | 40 | def ipToAbuseList(malEntityData, ipAddr): 41 | try: 42 | httpResponse = requests.get(baseUrl + ipAddr+ '?apikey=' + packetmailApiKey, proxies = proxyList.getProxies()) 43 | #httpResponse = requests.get(baseUrl + ipAddr+ '?apikey=' + packetmailApiKey) 44 | jsonResponse = httpResponse.json() 45 | #Sanity check to make sure it appears we got some valid JSON data 46 | checkForOrigin = 'origin' in jsonResponse 47 | if checkForOrigin == False: 48 | raise Exception('Invalid JSON data detected from packetmail.net') 49 | if checkForOrigin == True: 50 | for entities in jsonResponse.keys(): 51 | if entities == 'MaxMind_Free_GeoIP': 52 | currEntity = malEntityData.addEntity("maltego.Location", '%s' % entities) 53 | if jsonResponse[entities][0].get('country_name'): 54 | currEntity.addAdditionalFields(fieldName="country",displayName="Country",value=str(jsonResponse[entities][0]['country_name'])) 55 | if jsonResponse[entities][0].get('city'): 56 | currEntity.addAdditionalFields(fieldName="city",displayName="City",value=str(jsonResponse[entities][0]['city'])) 57 | if jsonResponse[entities][0].get('country_code'): 58 | currEntity.addAdditionalFields(fieldName="countrycode",displayName="Country Code",value=jsonResponse[entities][0]['country_code']+'\n') 59 | if jsonResponse[entities][0].get('longitude'): 60 | currEntity.addAdditionalFields(fieldName="longitude",displayName="Longitude",value=str(jsonResponse[entities][0]['longitude'])+'\n') 61 | if jsonResponse[entities][0].get('latitude'): 62 | currEntity.addAdditionalFields(fieldName="latitude",displayName="Latitude",value=str(jsonResponse[entities][0]['latitude'])+'\n') 63 | currEntity.addAdditionalFields(fieldName="source",displayName="Source",value='%s' % entities) 64 | if 'source' in jsonResponse[entities] and not entities == "disclaimer": 65 | currEntity = malEntityData.addEntity("maltego.Website", '%s' % entities) 66 | currEntity.addAdditionalFields(fieldName="Feed",displayName="Feed Name",value=entities+'\n') 67 | currEntity.addAdditionalFields(fieldName="URLS",displayName="URLs",value=jsonResponse[entities]['source']+'\n') 68 | if jsonResponse[entities].get('last_seen'): 69 | currEntity.addAdditionalFields('link#maltego.link.label','Label','Last Seen',value=jsonResponse[entities]['last_seen']+'\n') 70 | context = '' 71 | if isinstance((jsonResponse[entities]['context']), basestring) is True: 72 | hash_value = '' 73 | hash_type = '' 74 | MD5 = '' 75 | SHA1 = '' 76 | SHA256 = '' 77 | MD5_search = re.search(r'([a-f0-9]{32}|[A-F0-9]{32})', (jsonResponse[entities]['context'])) 78 | SHA1_search = re.search(r'([a-f0-9]{40}|[A-F0-9]{40})', (jsonResponse[entities]['context'])) 79 | SHA256_search = re.search(r'([a-f0-9]{64}|[A-F0-9]{64})', 80 | (jsonResponse[entities]['context'])) 81 | if SHA256_search: 82 | currEntity.addAdditionalFields(fieldName="SHA256",displayName="SHA256",value=SHA256_search.group(1)+'\n') 83 | hash_value = SHA256_search.group(1) 84 | hash_type = 'SHA256' 85 | if MD5_search and hash_value is '': 86 | currEntity.addAdditionalFields(fieldName="MD5",displayName="MD5",value=MD5_search.group(1)+'\n') 87 | hash_value = MD5_search.group(1) 88 | hash_type = 'MD5' 89 | if SHA1_search and hash_value is '': 90 | currEntity.addAdditionalFields(fieldName="SHA1",displayName="SHA1",value=SHA1_search.group(1)+'\n') 91 | hash_value = SHA1_search.group(1) 92 | hash_type = 'SHA1' 93 | if hash_value is '': 94 | context = (jsonResponse[entities]['context']) 95 | else: 96 | context = "Malware" 97 | currEntity = malEntityData.addEntity("maltego.Hash", '%s' % hash_value) 98 | currEntity.addAdditionalFields(fieldName="type",displayName="Hash Type",value='%s' % hash_type+'\n') 99 | 100 | currEntity.addAdditionalFields(fieldName="Feed",displayName="Feed Name",value=entities+'\n') 101 | currEntity.addAdditionalFields(fieldName="URL",displayName="Source URL",value=jsonResponse[entities]['source']+'\n') 102 | if jsonResponse[entities].get('last_seen'): 103 | currEntity.addAdditionalFields('link#maltego.link.label','Label','Last Seen',value=jsonResponse[entities]['last_seen']+'\n') 104 | else: 105 | if jsonResponse[entities]['context'][0].get('category'): 106 | cat_context = str(jsonResponse[entities]['context'][0]['category']) 107 | context = "Category - " + (jsonResponse[entities]['context'][0]['category']) + " " 108 | if jsonResponse[entities]['context'][0].get('signature'): 109 | context = context + "Signature - " + (jsonResponse[entities]['context'][0]['signature']) + " " 110 | if entities == "seclytics_daily": 111 | context = ' - '.join(jsonResponse[entities]['context'][0]['categories']) 112 | currEntity.addAdditionalFields(fieldName="Context",displayName="Context",value=context+'\n') 113 | 114 | except Exception,e: 115 | #Meh I'm just going to catch everything and let the user deal with it 116 | malEntityData.addEntity("maltego.Phrase", 'ipToAbuseList Error: - %s' % str(e)) 117 | return malEntityData 118 | 119 | ### Main 120 | if __name__ == '__main__': 121 | 122 | malEntityData = MaltegoTransform() 123 | results = ipToAbuseList(malEntityData, sys.argv[1]) 124 | results.returnOutput() 125 | -------------------------------------------------------------------------------- /packetmail/README.md: -------------------------------------------------------------------------------- 1 | # maltego-transforms-packetmail 2 | 3 | Maltego transform for Packetmail.net. See code license for details (it's BSD, basically have fun) 4 | 5 | Thanks to Nathan Fowler for the Packetmail service. 6 | 7 | ## Configuration Steps: 8 | 1. Ask Nathan Fowler (nathan@packetmail.net) for an API key. 9 | 2. Place said API key in top level credentials.cfg 10 | 3. Make sure you have Python 2.7 and Requests module installed. For Requests information, please see http://docs.python-requests.org/en/latest/ 11 | 4. Import packetmail.mtz into Maltego. This will give you a transform named "To Packetmail Abuse List" under "Other Transforms" for IP addresses. 12 | 5. Correct the fields of the "To Packetmail Abuse List" transform to conform to your local configuration. 13 | 6. Profi....ermm start looking up information. 14 | -------------------------------------------------------------------------------- /packetmail/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0xd34db33f/maltego-transforms/833d1b16ddb4ec15236ffa591aa7151ee15950aa/packetmail/__init__.py -------------------------------------------------------------------------------- /packetmail/packetmail.mtz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0xd34db33f/maltego-transforms/833d1b16ddb4ec15236ffa591aa7151ee15950aa/packetmail/packetmail.mtz -------------------------------------------------------------------------------- /proxies.cfg: -------------------------------------------------------------------------------- 1 | [PROXYLIST] 2 | http = 3 | https = 4 | -------------------------------------------------------------------------------- /torlookup/LICENSE: -------------------------------------------------------------------------------- 1 | ''' 2 | Copyright (c) 2015, Ryan Keyes 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | * Redistributions of source code must retain the above copyright 8 | notice, this list of conditions and the following disclaimer. 9 | * Redistributions in binary form must reproduce the above copyright 10 | notice, this list of conditions and the following disclaimer in the 11 | documentation and/or other materials provided with the distribution. 12 | 13 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 14 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 15 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 16 | DISCLAIMED. IN NO EVENT SHALL RYAN KEYES OR HIS EMPLOYER BE LIABLE FOR ANY 17 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 18 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 19 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 20 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 21 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 22 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 23 | ''' 24 | -------------------------------------------------------------------------------- /torlookup/README.md: -------------------------------------------------------------------------------- 1 | # maltego-transforms-torlookup 2 | 3 | Maltego transform for Tor. See code license for details (it's BSD, basically have fun) 4 | -------------------------------------------------------------------------------- /torlookup/TorExitNodeTransforms.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Copyright (c) 2015, Ryan Keyes 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | * Redistributions of source code must retain the above copyright 8 | notice, this list of conditions and the following disclaimer. 9 | * Redistributions in binary form must reproduce the above copyright 10 | notice, this list of conditions and the following disclaimer in the 11 | documentation and/or other materials provided with the distribution. 12 | 13 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 14 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 15 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 16 | DISCLAIMED. IN NO EVENT SHALL RYAN KEYES OR HIS EMPLOYER BE LIABLE FOR ANY 17 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 18 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 19 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 20 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 21 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 22 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 23 | ''' 24 | 25 | import os, sys 26 | import requests 27 | 28 | import os.path as path 29 | import time 30 | 31 | from MaltegoTransform import MaltegoTransform 32 | from config import Proxies 33 | 34 | proxyList = Proxies() 35 | 36 | def downloadUpdatedList(): 37 | try: 38 | httpResponse = requests.get("https://check.torproject.org/exit-addresses", proxies = proxyList.getProxies()) 39 | outputFile = open("exit-addresses",'w') 40 | outputFile.write(httpResponse.text) 41 | outputFile.close() 42 | httpResponse.close() 43 | except Exception,e: 44 | print e 45 | 46 | def ipToTorList(malEntityData, ipAddr): 47 | try: 48 | if not path.isfile('exit-addresses') or (time.time()-path.getmtime('exit-addresses'))/60 > 120: 49 | downloadUpdatedList() 50 | with open('exit-addresses','r') as dataFile: 51 | for line in dataFile: 52 | if line.startswith('ExitAddress %s' % ipAddr): 53 | currEntity = malEntityData.addEntity("maltego.Phrase", 'Tor Exit Node') 54 | except Exception,e: 55 | #Meh I'm just going to catch everything and let the user deal with it 56 | malEntityData.addEntity("maltego.Phrase", 'ipToAbuseList Error: - %s' % str(e)) 57 | return malEntityData 58 | 59 | ### Main 60 | if __name__ == '__main__': 61 | 62 | malEntityData = MaltegoTransform() 63 | results = ipToTorList(malEntityData, sys.argv[1]) 64 | results.returnOutput() 65 | -------------------------------------------------------------------------------- /torlookup/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0xd34db33f/maltego-transforms/833d1b16ddb4ec15236ffa591aa7151ee15950aa/torlookup/__init__.py -------------------------------------------------------------------------------- /torlookup/torlookuptransforms.mtz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0xd34db33f/maltego-transforms/833d1b16ddb4ec15236ffa591aa7151ee15950aa/torlookup/torlookuptransforms.mtz --------------------------------------------------------------------------------