├── README.md ├── config.json ├── cymon └── cymon.py └── sipi.py /README.md: -------------------------------------------------------------------------------- 1 | #Simple IP Information Tools (sIPI) 2 | ##for IP Reputation Data Analysis 3 | 4 | [[@st2labs]] Simple IP Information Tool [[@st2labs]] 5 | 6 | __Author__: Julian J. Gonzalez Caracuel - Twitter: @rhodius | @seguriadxato2 | @st2labs 7 | 8 | __Vesion__: 0.1 9 | 10 | # Abstracts 11 | 12 | This tool is aimed for Incident Response Team and anyone what's want to know the behaviour of the "suspicious" IP Address. 13 | The tools do search looking for reputation info from a set of open threat intelligence sources. Information about this IP like malware activity, malicious activity, blacklist, spam and botnet activity. 14 | 15 | __Depedencies__: 16 | - request 17 | - shodan 18 | 19 | __Installation__: 20 | 21 | pip install requests & easy_install shodan 22 | git clone "repositori" 23 | config API token into config.json 24 | 25 | try: 26 | $> python sipi.py any_ip -A 27 | 28 | # Descripcion 29 | 30 | [[@st2labs]] Simple IP Information Tool [[@st2labs]] 31 | 32 | sIPi - is a free reconnaissance tool for obtain IP Address Information from 33 | many Open Sources: cymon.io | shoda.io | ipinfo.io 34 | 35 | Julian J. Gonzalez Caracuel - @rhodius 36 | Version: 0.1 37 | 38 | Es una herramienta que analiza una IP o lista de IP, obteniendo como resultado información sobre: 39 | 40 | - reputación / actividad 41 | - nivel de exposición 42 | - geolocalización 43 | 44 | Reputación / detección de la IP en lista negras según las siguientes categorias: 45 | 46 | Source: cymon.io - Cymon is the largest open tracker of malware, phishing, botnets, spam, and more 47 | 48 | ['malware', 49 | 'botnet', 50 | 'spam', 51 | 'phishing', 52 | 'malicious activity', 53 | 'blacklist', 54 | 'dnsbl'] 55 | 56 | Nivel de exposición: 57 | 58 | Source: shodan.io - Shodan is the world's first search engine for Internet-connected devices. 59 | 60 | Obtiene información toda la dirección IP que tiene SHODAN sobre la dirección IP, dependiendo del nivel de acceso al motor SHODAN 61 | se podra obtener información con mayor cantidad de datos (número de puertos, banner, geolocalización) 62 | 63 | Geolocalización: 64 | 65 | Source: ipinfo.io 66 | 67 | Obtiene información simple de la dirección IP, geolocalización e información sobre el ASN, permite un ratio de 1000/day 68 | 69 | # Instalacion Requisitos 70 | 71 | cymon.io - Necesita token de autenticación - usuario registrado ratio: 1000/days 72 | shodan.io - Necesita token de autenticación - usuario registrado limite 100 resultados, puertos limitados 73 | 74 | La configuración de los token, se introduce en Fichero: config.json, que debe estar en el directorio donde se ejecuta sipi.py 75 | << API token from all service is setting up into a "config.json" filename place in the root directory >> 76 | 77 | Dependencias 78 | 79 | requests 80 | 81 | pip install requests 82 | 83 | shodan 84 | 85 | easy_install shodan 86 | 87 | Linux & Windows 88 | 89 | 90 | 91 | # Examples | Ejemplos 92 | 93 | Buscar información en todas las categorias de reputación, nivel de exposición & ip información 94 | Get Info to IP's list filename in All categoty from cymon, and adds info from Shodan & IPInfo 95 | $> python sipi.py list_ip -A -s -i 96 | 97 | Obtener información sobre la IP en lista de SPAM, nivel de exposición & ip información 98 | Get Info to IP's list filename only in SPAM categoty from cymon, and adds info from Shodan & IPInfo 99 | $> python sipi.py list_ip -t spam -s -i 100 | 101 | Obtener información sobre la lista de IP en reputación a nivel de Malware 102 | Get Info to IP's list filename only in MALWARE categoty from cymon with 1 day ago and 1000 entry limits 103 | $> python sipi.py list_ip -t malware -d 1 -l 1000 104 | 105 | -d Solamente se puede analizar el nivel de reputación de la IP hace 3 días 106 | If you don't find anythings, maybe events was more than 3 day ago, please try to use -d 4 options 107 | Para más de 3 días utilizar -d 4 108 | 109 | -l Controlar el número de resultados donde analizar la IP - Default: 100 110 | 111 | # Output Example: 112 | 113 | $> python sipi.py lista.txt -d 4 -A 114 | 115 | [[@st2labs]] Simple IP Information Tool [[@st2labs]] 116 | 117 | sIPi - is a free recorn tool for obtain IP Address Information from 118 | many Open Sources: cymon.io | shoda.io | ipinfo.io 119 | 120 | Julian J. Gonzalez Caracuel - @rhodius 121 | Version: 0.1 122 | 123 | [!] This IP ['83.55.23.240s'] is not valid & have been removed from searching 124 | 125 | 126 | If days more than 3, auto change mode is active 127 | [ip_blacklist > ip_events] to obtain Ip Info 128 | 129 | 130 | ++++++++++++++++++++++++++++++++++++++ 131 | + Info obtain from: http://cymon.io + 132 | + Checking for ip_events 133 | ++++++++++++++++++++++++++++++++++++++ 134 | 135 | 136 | +---------------------------------+ 137 | +-Events for IP:93.76.61.78 138 | +---------------------------------+ 139 | 140 | +-- 141 | 142 | [!] IP 93.76.61.78 found in malicious activity BlackList 143 | Detected by: [u'esentire threat labs'] 144 | 145 | --+ 146 | 147 | [NOT_FOUND] IP 93.76.61.78 in this CATEGORIES:['malware', 'botnet', 'spam', 'phishing', 'blacklist', 'dnsbl'] 148 | 149 | 150 | +---------------------------------+ 151 | +-Events for IP:93.183.250.196 152 | +---------------------------------+ 153 | 154 | +-- 155 | 156 | [!] IP 93.183.250.196 found in malicious activity BlackList 157 | Detected by: [u'esentire threat labs'] 158 | 159 | --+ 160 | 161 | [NOT_FOUND] IP 93.183.250.196 in this CATEGORIES:['malware', 'botnet', 'spam', 'phishing', 'blacklist', 'dnsbl'] 162 | 163 | 164 | +---------------------------------+ 165 | +-Events for IP:176.101.204.172 166 | +---------------------------------+ 167 | 168 | +-- 169 | 170 | [!] IP 176.101.204.172 found in malicious activity BlackList 171 | Detected by: [u'esentire threat labs'] 172 | 173 | --+ 174 | 175 | [NOT_FOUND] IP 176.101.204.172 in this CATEGORIES:['malware', 'botnet', 'spam', 'phishing', 'blacklist', 'dnsbl'] 176 | 177 | # License Info 178 | 179 | This is free software; you can redistribute it and/or modify 180 | it under the terms of the GNU General Public License as published by 181 | the Free Software Foundation version 2 of the License. 182 | 183 | This is distributed in the hope that it will be useful, 184 | but WITHOUT ANY WARRANTY; without even the implied warranty of 185 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 186 | GNU General Public License for more details. 187 | 188 | You should have received a copy of the GNU General Public License 189 | along it; if not, write to the Free Software 190 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 191 | -------------------------------------------------------------------------------- /config.json: -------------------------------------------------------------------------------- 1 | { 2 | "cymon": { 3 | "token": "your_token_code_here" 4 | }, 5 | "shodan": { 6 | "token": "your_token_code_here" 7 | } 8 | } -------------------------------------------------------------------------------- /cymon/cymon.py: -------------------------------------------------------------------------------- 1 | # 2 | # --- 3 | # Cymon.io 4 | # Code from_: https://github.com/eSentire/cymon-python 5 | # Modify by @Julian J Gonzalez / ST2Labs 6 | 7 | import json 8 | import requests 9 | from urllib import quote_plus 10 | 11 | 12 | class Cymon(object): 13 | 14 | def __init__(self, auth_token=None, 15 | endpoint='https://cymon.io:443/api/nexus/v1'): 16 | self.endpoint = endpoint 17 | self.session = requests.Session() 18 | self.session.headers = { 19 | 'content-type': 'application/json', 20 | 'accept': 'application/json', 21 | } 22 | if auth_token: 23 | self.session.headers.update( 24 | {'Authorization': 'Token {0}'.format(auth_token)}) 25 | 26 | def get(self, method, params=None): 27 | r = self.session.get(self.endpoint + method, params=params) 28 | r.raise_for_status() 29 | return r 30 | 31 | def post(self, method, params, headers=None): 32 | r = self.session.post(self.endpoint + method, data=json.dumps(params), 33 | headers=headers) 34 | r.raise_for_status() 35 | return r 36 | 37 | def ip_lookup(self, ip_addr): 38 | r = self.get('/ip/' + ip_addr) 39 | return r.json() 40 | 41 | def ip_events(self, ip_addr): 42 | r = self.get('/ip/' + ip_addr + '/events') 43 | return r.json() 44 | 45 | def ip_domains(self, ip_addr): 46 | r = self.get('/ip/' + ip_addr + '/domains') 47 | return r.json() 48 | 49 | def ip_urls(self, ip_addr): 50 | r = self.get('/ip/' + ip_addr + '/urls') 51 | return r.json() 52 | 53 | def domain_lookup(self, name): 54 | r = self.get('/domain/' + name) 55 | return r.json() 56 | 57 | def url_lookup(self, location): 58 | r = self.get('/url/' + quote_plus(location)) 59 | return r.json() 60 | 61 | def ip_blacklist(self, tag, days=1, limit=10, offset=10): 62 | # supported tags: malware, botnet, spam, phishing, dnsbl, blacklist 63 | r = self.get('/blacklist/ip/' + tag + '/?days=%d' % (days) + 64 | '&limit=%d' % (limit) + 65 | '&offset=%d' % (offset)) 66 | return r.json() 67 | 68 | def domain_blacklist(self, tag, days=1, limit=15, offset=10): 69 | # supported tags: malware, botnet, spam, phishing, dnsbl, blacklist 70 | r = self.get('/blacklist/domain/' + tag + '/?days=%d' % (days) + 71 | '&limit=%d' % (limit) + 72 | '&offset=%d' % (offset)) 73 | return r.json() 74 | -------------------------------------------------------------------------------- /sipi.py: -------------------------------------------------------------------------------- 1 | """ 2 | Copyright 2015 Julian J. Gonzalez 3 | www.st2labs.com | @ST2Labs | @rhodius | @seguridadxato2 4 | 5 | __Author__: Julian J. GOnzalez 6 | __Version__: 0.1 7 | 8 | 9 | This is free software; you can redistribute it and/or modify 10 | it under the terms of the GNU General Public License as published by 11 | the Free Software Foundation version 2 of the License. 12 | 13 | This is distributed in the hope that it will be useful, 14 | but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | GNU General Public License for more details. 17 | 18 | You should have received a copy of the GNU General Public License 19 | along it; if not, write to the Free Software 20 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 21 | """ 22 | import sys 23 | import os 24 | import argparse 25 | import shodan 26 | sys.path.insert(0, str(os.path.dirname( 27 | os.path.abspath(__file__)) + 28 | os.path.sep + 'cymon' + os.path.sep)) 29 | from cymon import Cymon 30 | 31 | __author__ = "\n Julian J. Gonzalez Caracuel - @rhodius\n" 32 | __version__ = " Version: 0.1\n" 33 | __team__ = " ST2Labs TEAM: 0.1\n" 34 | __title__ = '\n Simple IP Information Tool [[@st2labs]]\n' 35 | __description__ = ''' 36 | sIPi - is a free reconnaissance tool for obtain IP Address Information from 37 | many Open Sources: cymon.io | shoda.io | ipinfo.io 38 | ''' 39 | __banner__ = ''' 40 | _______ _____ _____ _____ 41 | |______ | |_____] | 42 | ______| __|__ | __|__ 43 | --------------------------- 44 | ''' 45 | 46 | __credit__ = ((__banner__ + __title__ + __description__ + 47 | __author__ + __version__)) 48 | 49 | 50 | def usage(): 51 | print (''' 52 | 53 | Use: 54 | sipi 55 | Info: 56 | sipi -h 57 | ''') 58 | 59 | 60 | def validIPv4(ip): 61 | import re 62 | v = False 63 | if re.match(r'^((\d{1,2}|1\d{2}|2[0-4]\d|25[0-5])\.){3}(\d{1,2}|1\d{2}|2[0-4]\d|25[0-5])$', ip): 64 | v = True 65 | return v 66 | 67 | 68 | def decode_data(data): 69 | 70 | import json 71 | 72 | n_dict = {} 73 | a_dict = json.loads(data) 74 | for key, value in list(a_dict.items()): 75 | nkey = key.encode('utf-8') 76 | if isinstance(value, int): 77 | nvalue = value 78 | else: 79 | if value is not None: 80 | nvalue = value.encode('utf-8') 81 | else: 82 | nvalue = value 83 | n_dict[nkey] = nvalue 84 | return n_dict 85 | 86 | 87 | def error(index): 88 | 89 | if index == 1: 90 | msg = '\n' 91 | msg += ' Error IP format. Must be like 192.168.0.1 \n' 92 | msg += ' Try again\n' 93 | print ((__credit__ + msg)) 94 | elif index == 2: 95 | msg = '\n' 96 | msg += ' Format Fileconfig it''s not support it.' 97 | msg += ' Need valid JSON encoded\n' 98 | msg += ' Try again\n' 99 | print ((__credit__ + msg)) 100 | elif index == 3: 101 | msg = '\n' 102 | msg += ' Error config.json not exits it.\n' 103 | msg += ' Try again\n' 104 | print ((__credit__ + msg)) 105 | 106 | 107 | def show_result(data_): 108 | print ((__credit__)) 109 | sys.stdout.write(' \n') 110 | sys.stdout.write(' \n') 111 | for item in data_: 112 | print ((' - ' + str(item))) 113 | sys.stdout.write(' \n') 114 | 115 | 116 | def show_info(data_): 117 | 118 | try: 119 | res_ = [] 120 | res_.append('') 121 | res_.append('++++++++++++++++++++++++++++++++++++++') 122 | res_.append('+ Info obtain from: http://ipinfo.io +') 123 | res_.append('++++++++++++++++++++++++++++++++++++++') 124 | res_.append('') 125 | if not data_: 126 | res_.append(' No results') 127 | res_.append(' Only a private range IP detected ') 128 | return 129 | for i in data_: 130 | # i is dict 131 | if 'ip' in i: 132 | res_.append('ip: ' + str(i['ip'])) 133 | if 'hostname' in i: 134 | res_.append('hostname: ' + str(i['hostname'])) 135 | if 'city' in i: 136 | res_.append('city: ' + str(i['city'])) 137 | if 'region' in i: 138 | res_.append('region: ' + str(i['region'])) 139 | if 'country' in i: 140 | res_.append('country: ' + str(i['country'])) 141 | if 'org' in i: 142 | res_.append('org: ' + str(i['org'])) 143 | if 'gps' in i: 144 | res_.append('gps: ' + str(i['loc'])) 145 | res_.append('++++++++++++++++++++++++++++++++++++++ ') 146 | res_.append('') 147 | return res_ 148 | except Exception as e: 149 | print ((' Error Searching IPInfo Data {}'.format(e))) 150 | 151 | 152 | def ipinfo(iplist): 153 | import requests 154 | 155 | try: 156 | hostlist = [] 157 | ipinfolist = [] 158 | if type(iplist) is not list: 159 | hostlist.append(iplist) 160 | else: 161 | hostlist = iplist 162 | 163 | for ip in hostlist: 164 | req_ = 'http://ipinfo.io/' + ip 165 | r = requests.get(req_) 166 | info_ = r.json() 167 | ipinfolist.append(info_) 168 | 169 | return ipinfolist 170 | except Exception as e: 171 | print ((' Error looking for IP Info: {}'.format(e))) 172 | 173 | 174 | def getModeCode(modo): 175 | 176 | # Default ip_blacklist 177 | v = 1 178 | if modo == 'ip_events': 179 | v = 2 180 | return v 181 | 182 | 183 | def search(api, iplist, cat, day, limit, modo='ip_blacklist'): 184 | 185 | try: 186 | res_ = [] 187 | res_.append('') 188 | res_.append('++++++++++++++++++++++++++++++++++++++') 189 | res_.append('+ Info obtain from: http://cymon.io +') 190 | res_.append('+ Checking for {} '.format(modo)) 191 | res_.append('++++++++++++++++++++++++++++++++++++++') 192 | res_.append('') 193 | hostlist = [] 194 | catlist = [] 195 | if type(iplist) is not list: 196 | hostlist.append(iplist) 197 | else: 198 | hostlist = iplist 199 | # 200 | # Preparada para utilizar la misma funcion search 201 | # para IP event / IP Blacklist 202 | # cmodo = 1 ip_blacklist 203 | # cmodo = 2 ip_events 204 | 205 | cmodo = getModeCode(modo) 206 | 207 | if type(cat) is not list: 208 | catlist.append(cat) 209 | else: 210 | catlist = cat 211 | f = getattr(api, modo) 212 | 213 | if cmodo == 1: 214 | 215 | for item in catlist: 216 | res_.append('') 217 | res_.append('+--------------------------+') 218 | res_.append('+-Category:{}'.format(item)) 219 | res_.append('+--------------------------+') 220 | res_.append('') 221 | iplistnotfound = [] 222 | r = f(item, day, limit) 223 | for ip in hostlist: 224 | ip_found = False 225 | for elem in r['results']: 226 | if ip in elem['addr']: 227 | ip_found = True 228 | if ip_found: 229 | res_.append(str(' [FOUND] IP {0} found in {1}' + 230 | 'BlackList').format(ip, item)) 231 | r = api.ip_lookup(ip)['sources'] 232 | res_.append(' From: {} ->'.format(r)) 233 | res_.append('') 234 | else: 235 | iplistnotfound.append(ip) 236 | res_.append(str(' IPs {0} [NOT_FOUND] ' + 237 | ' in CATEGORY:{1}').format(iplistnotfound, item)) 238 | res_.append(str(' [!] Try search with -d 4' + 239 | ' options')) 240 | res_.append('') 241 | elif cmodo == 2: 242 | 243 | for ip in hostlist: 244 | taglistnotfound = [] 245 | r = f(ip) 246 | res_.append('') 247 | res_.append('+---------------------------------+') 248 | res_.append('+-Events for IP:{}'.format(ip)) 249 | res_.append('+---------------------------------+') 250 | res_.append('') 251 | for item in catlist: 252 | tag_found = False 253 | for elem in r['results']: 254 | if item in elem['tag']: 255 | tag_found = True 256 | if tag_found: 257 | res_.append(' +--') 258 | res_.append('') 259 | res_.append(str(' [!] IP {0} found in {1}' + 260 | ' BlackList').format(ip, item)) 261 | s = api.ip_lookup(ip)['sources'] 262 | res_.append(' Detected by: {}'.format(s)) 263 | res_.append('') 264 | res_.append(' --+') 265 | res_.append('') 266 | else: 267 | taglistnotfound.append(item) 268 | res_.append(str(' [NOT_FOUND] IP {0} ' + 269 | ' in this CATEGORIES:{1}' + 270 | ' ').format(ip, taglistnotfound)) 271 | res_.append('') 272 | return res_ 273 | except Exception as e: 274 | import traceback 275 | print (" CYMON API Error_: ") 276 | print ((' msg_ {}'.format(e))) 277 | print ((" {}".format(traceback.print_tb(sys.exc_info()[2])))) 278 | print ('') 279 | sys.exit(2) 280 | 281 | 282 | def saveOnFile(data_, filepath): 283 | 284 | if os.path.isfile(filepath): 285 | print ((str(' [!] File {} exists, please choose' + 286 | 'other filename').format(filepath))) 287 | print ('') 288 | print (' >> Results not save on filename!') 289 | sys.exit(2) 290 | 291 | with open(filepath, 'ab+') as f: 292 | for element in data_: 293 | f.write(str(element) + '\r\n') 294 | f.close() 295 | 296 | 297 | def loadSetting(filepath): 298 | import json 299 | try: 300 | with open(filepath, 'rb') as f: 301 | d = json.loads(f.read()) 302 | return d 303 | except TypeError: 304 | error(2) 305 | sys.exit(2) 306 | except ValueError: 307 | error(2) 308 | sys.exit(2) 309 | 310 | 311 | def search_shodan(api, iplist): 312 | try: 313 | hostlist = [] 314 | ipnotdatalist = [] 315 | res_ = [] 316 | res_.append('') 317 | res_.append('++++++++++++++++++++++++++++++++++++++') 318 | res_.append('+ Info obtain from: http://shodan.io +') 319 | res_.append('++++++++++++++++++++++++++++++++++++++') 320 | res_.append('') 321 | 322 | if type(iplist) is not list: 323 | hostlist.append(iplist) 324 | else: 325 | hostlist = iplist 326 | for ip in hostlist: 327 | try: 328 | host = api.host(ip) 329 | except shodan.APIError as e: 330 | ipnotdatalist.append(ip) 331 | continue 332 | 333 | if host: 334 | # Print general info 335 | res_.append('') 336 | res_.append('+-------------------------------------+') 337 | res_.append('+- SHODAN Info for IP:{}'.format(ip)) 338 | res_.append('+-------------------------------------+') 339 | res_.append('') 340 | 341 | for item in sorted(host): 342 | if ((item != 'data' and 343 | item != 'region_code' and 344 | item != 'area_code' and 345 | item != 'country_code3' and 346 | item != 'dma_code' and 347 | item != 'ports' and 348 | item != 'postal_code')): 349 | 350 | res_.append('{}: {}'.format(item, host[item])) 351 | 352 | # Print all banners 353 | res_.append('') 354 | res_.append('+- Service Info') 355 | res_.append('+') 356 | res_.append(' Ports detected: {}'.format(host['ports'])) 357 | res_.append('') 358 | 359 | for item in host['data']: 360 | 361 | res_.append('Port: {}'.format(item['port'])) 362 | res_.append('Protocol: {}/{}'.format( 363 | item['transport'], 364 | item['_shodan']['module'])) 365 | banner = item['data'].splitlines() 366 | msg = '' 367 | for line in banner: 368 | msg += line + ' ' 369 | res_.append('Banner: {}'.format(msg)) 370 | res_.append('') 371 | res_.append(str(' [!] IPs with not Information found ' + 372 | ' in SHODAN:{}').format(ipnotdatalist)) 373 | return res_ 374 | except Exception as e: 375 | print (('Search_shodan_ Error: %s' % e)) 376 | 377 | 378 | def main(argv): 379 | 380 | try: 381 | info_ = [] 382 | parser = argparse.ArgumentParser( 383 | formatter_class=argparse.RawDescriptionHelpFormatter, 384 | description='') 385 | 386 | ogroup = parser.add_argument_group(title='Output') 387 | maingroup = parser.add_argument_group(title='Main Functions') 388 | shodangroup = parser.add_argument_group(title='SHODAN Functions') 389 | cygroup = parser.add_argument_group(title='CYMON.io Funtions') 390 | maingroup.add_argument('host', 391 | help='Input IP or IP list file') 392 | shodangroup.add_argument('-s', 393 | '--shodan', 394 | help=''' Search IP in SHODAN engine''', 395 | action='store_true' 396 | ) 397 | g1 = cygroup.add_mutually_exclusive_group(required=True) 398 | 399 | g1.add_argument('-A', 400 | '--all', 401 | help=''' Search Blacklist IP in 3 days ago 402 | with 100 max result, use -d & -l to increment it 403 | in ALL Categories ''', 404 | action='store_true' 405 | ) 406 | g1.add_argument('-t', 407 | '--cat', 408 | default=None, 409 | help=''' Default: spam | Add one of this Category: 410 | malware botnet spam phishing malicious activity blacklist dnsbl 411 | ''', 412 | metavar='SPAM' 413 | ) 414 | ogroup.add_argument('-o', 415 | '--output', 416 | default=None, 417 | help='''Output filename or Directory''', 418 | metavar='FILE' 419 | ) 420 | maingroup.add_argument('-i', 421 | '--info', 422 | default=None, 423 | help='''IP Information data from ipinfo.io''', 424 | action='store_true' 425 | ) 426 | cygroup.add_argument('-d', 427 | '--days', 428 | type=int, 429 | default=3, 430 | help='''Looking for days <1-3> ago in Blacklist 431 | IP Mode, use 4 to active mode security events 432 | list | Default mode is 3 days ago''' 433 | ) 434 | cygroup.add_argument('-l', 435 | '--limit', 436 | type=int, 437 | default=100, 438 | help='''Result limit in Security 439 | Event list IP | Default limit is 100''' 440 | ) 441 | 442 | args = parser.parse_args() 443 | _shodan = args.shodan 444 | _host = args.host 445 | _outname = args.output 446 | _category = args.cat 447 | _all = args.all 448 | _info = args.info 449 | _isfile = False 450 | _days = args.days 451 | _limit = args.limit 452 | _out = False 453 | 454 | cymon_cat = ['malware', 455 | 'botnet', 456 | 'spam', 457 | 'phishing', 458 | 'malicious activity', 459 | 'blacklist', 460 | 'dnsbl'] 461 | 462 | if not validIPv4(_host): 463 | if os.path.isfile(_host): 464 | _isfile = True 465 | else: 466 | error(1) 467 | sys.exit(2) 468 | 469 | if _outname is not None: 470 | _out = True 471 | if os.path.isabs(_outname): 472 | _fpathOut = _outname 473 | else: 474 | _fpathOut = str(os.path.dirname( 475 | os.path.abspath(sys.argv[0])) + 476 | os.sep + 477 | _outname) 478 | 479 | hostlist = [] 480 | if _isfile: 481 | with open(_host, 'rb') as f: 482 | iplist = [] 483 | ipnotvalidlist = [] 484 | hostlist = f.read().splitlines() 485 | for ip in hostlist: 486 | if validIPv4(ip): 487 | iplist.append(ip) 488 | else: 489 | ipnotvalidlist.append(ip) 490 | info_.append((str('[!] This IP {} is not valid' + 491 | ' & have been removed from ' + 492 | 'searching').format(ipnotvalidlist))) 493 | info_.append('') 494 | hostlist = iplist 495 | else: 496 | hostlist = _host 497 | 498 | default_file = 'config.json' 499 | if os.path.isfile(default_file): 500 | conf = loadSetting(default_file) 501 | c_token = conf['cymon']['token'] 502 | s_token = conf['shodan']['token'] 503 | else: 504 | error(3) 505 | sys.exit(2) 506 | 507 | api = Cymon(c_token) 508 | 509 | cat = 'spam' 510 | if _category: 511 | cat = _category 512 | 513 | mode = 'ip_blacklist' 514 | if (_days >= 4): 515 | info_.append('') 516 | info_.append('[!] If days more than 3, auto change mode is active') 517 | info_.append(' [ip_blacklist > ip_events] to obtain Ip Info') 518 | info_.append('') 519 | mode = 'ip_events' 520 | 521 | if _all: 522 | cat = cymon_cat 523 | 524 | r = search(api, hostlist, cat, _days, _limit, mode) 525 | 526 | if _shodan: 527 | sapi = shodan.Shodan(s_token) 528 | rs = search_shodan(sapi, hostlist) 529 | if rs is None: 530 | rs = [] 531 | rs.append(' Main_: Shodan Error') 532 | 533 | if _info: 534 | ipl = ipinfo(hostlist) 535 | ri = show_info(ipl) 536 | if ri is None: 537 | ri = [] 538 | ri.append(' IPInfo Error') 539 | 540 | all_result = info_ 541 | 542 | if _shodan and _info: 543 | all_result += list(r + rs + ri) 544 | elif _shodan: 545 | all_result += list(r + rs) 546 | elif _info: 547 | all_result += list(r + ri) 548 | else: 549 | all_result += r 550 | 551 | if _out: 552 | saveOnFile(all_result, _fpathOut) 553 | 554 | show_result(all_result) 555 | 556 | except Exception: 557 | import traceback 558 | print ((" Main Error_: ")) 559 | print ((" {}".format(traceback.print_tb(sys.exc_info()[2])))) 560 | print ('') 561 | sys.exit(2) 562 | 563 | 564 | if __name__ == "__main__": 565 | 566 | try: 567 | if len(sys.argv) > 1: 568 | main(sys.argv[1:]) 569 | else: 570 | print ((__credit__)) 571 | usage() 572 | except KeyboardInterrupt: 573 | sys.exit(2) 574 | except Exception as e: 575 | import traceback 576 | print ('Somethin was wrong ...') 577 | print ((("Error> {}").format(e))) 578 | print ((" {}".format(traceback.print_tb(sys.exc_info()[2])))) 579 | --------------------------------------------------------------------------------