def handle_zoomeye(query, limit, type, offset): z = ZoomEye() z.auto_login() info = z.resources_info().get('resources') if info: msg = '[+] Available ZoomEye search: (search:%s)' % (info.get('search', 'NO FOUND')) colorprint.green(msg) else: msg = '[-] ZoomEye API authorization failed, Please re-run it and enter a new token.' colorprint.red(msg) sys.exit() # 开始爬取 result_count = 0 is_continue = True page = 0 while is_continue: data = z.dork_search(query, page=page, resource=type) if data: for i in data: ip_str = i.get('ip') if 'portinfo' in i: ip_str = ip_str + ':' + str(i.get('portinfo').get('port')) result_count += 1 if result_count >= offset: conf.target.add(ip_str) if len(conf.target) >= limit: is_continue = False break page += 1 else: break
def handle_censys(query, limit, offset): global UID global SECRET UID = ConfigFileParser().censys_UID() SECRET = ConfigFileParser().censys_SECRET() msg = '[+] Trying to login with credentials in config file: {}.'.format( paths.CONFIG_PATH) colorprint.green(msg) if not can_auto_login(): err_msg = '[-] Automatic authorization failed.\n[*] Please input your censys API Key (https://censys.io/account/api).' colorprint.cyan(err_msg) UID = input('[*] UID > ').strip() SECRET = input('[*] SECRET > ').strip() if not can_auto_login(): err_msg = "[-] authorization failed" colorprint.red(err_msg) sys.exit() page_start = int(offset / 100) + 1 page_stop = page_start + int(limit / 100) + 1 for page in range(page_start, page_stop): get_ip(query, page) # the last loop dont need sleep if page < page_stop - 1: time.sleep(3)
def proxy_regester(args): # if define proxy if args.proxy: proxy = args.proxy else: proxy = ConfigFileParser().proxy() if proxy: # check proxy format try: # check protocol protocol = proxy.split("://")[0].lower() if protocol not in ("socks4",'socks5','http'): raise Exception("proxy protocol format error, please check your proxy (socks4|socks5|http)") # check ip addr ip = proxy.split("://")[1].split(":")[0] compile_ip=re.compile('^(1\d{2}|2[0-4]\d|25[0-5]|[1-9]\d|[1-9])\.(1\d{2}|2[0-4]\d|25[0-5]|[1-9]\d|\d)\.(1\d{2}|2[0-4]\d|25[0-5]|[1-9]\d|\d)\.(1\d{2}|2[0-4]\d|25[0-5]|[1-9]\d|\d)$') if not compile_ip.match(ip): raise Exception("proxy ip format error, please check your proxy") # check port port = int(proxy.split("://")[1].split(":")[1]) if not 0 <= port <= 65535: raise Exception("proxy port format error, please check your proxy") except Exception as e: colorprint.red(e) sys.exit() msg = "[+] setting proxy: {}://{}:{}".format(protocol, ip, port) colorprint.green(msg) conf.proxy = (protocol, ip, port) else: conf.proxy = None
def handle_fofa(query, limit, offset=0): try: msg = '[+] Trying to login with credentials in config file: {}.'.format( paths.CONFIG_PATH) colorprint.green(msg) email = ConfigFileParser().fofa_email() key = ConfigFileParser().fofa_key() #print(key) if check(email, key): pass else: raise Exception( "Automatic authorization failed") # will go to except block except Exception as e: logger.debug(e) msg = '[*] Automatic authorization failed.' colorprint.cyan(msg) msg = '[*] Please input your FoFa Email and API Key below.' colorprint.cyan(msg) email = input("[*] Fofa Email: ").strip() key = input('[*] Fofa API Key: ').strip() if not check(email, key): msg = '[-] Fofa API authorization failed, Please re-run it and enter a valid key.' colorprint.red(msg) sys.exit() query = base64.b64encode(query.encode('utf-8')).decode('utf-8') # count how many result to search size = limit + offset url = f"https://fofa.so/api/v1/search/all?email={email}&key={key}&qbase64={query}&size={size}" try: response = request.get(url).text resp = json.loads(response) if not resp["error"]: for item in resp.get('results')[offset:]: #print(type(item[0])) if 'https:' not in item[0]: try: requests.get("http://" + item[0], timeout=5, verify=False) conf.target.add("http://" + item[0]) print("http://" + item[0]) except: pass else: try: requests.get(item[0], timeout=5, verify=False) conf.target.add(item[0]) print(item[0]) except: pass except Exception as e: colorprint.red(e) sys.exit()
def output_register(args): # if not define output, named it by time if not args.output_path: filename = time.strftime("%Y-%m-%d-%H-%M-%S", time.localtime()) + '.txt' conf.output_path = os.path.join(paths.OUTPUT_PATH, filename) msg = '[+] Output: %s' % conf.output_path colorprint.green(msg)
def login(self): msg = '[+] Trying to login with credentials in config file: %s.' % paths.CONFIG_PATH colorprint.green(msg) self.api_key = ConfigFileParser().shodan_apikey() if not self.api_key: msg = '[*] Automatic authorization failed.' colorprint.cyan(msg) msg = '[*] Please input your Shodan API Key (https://account.shodan.io/).' colorprint.cyan(msg) self.api_key = input('[*] API KEY > ').strip()
def run(): init_engine() free_conf_memory() if th.thread_mode: # set lock for multi_threaded mode set_threadLock() colorprint.green('[+] Set working way Multi-Threaded mode') colorprint.green('[+] Set the number of thread: %d' % th.concurrent_num) for i in range(th.concurrent_num): t = threading.Thread(target=scan, name=str(i)) t.setDaemon(True) t.start() # It can quit with Ctrl-C while th.concurrent_count > 0 and th.is_continue: time.sleep(0.01) # Coroutine mode else: colorprint.green('[+] Set working way Coroutine mode') colorprint.green('[+] Set the number of Coroutine: %d' % th.concurrent_num) gevent.joinall( [gevent.spawn(scan) for i in range(0, th.concurrent_num)]) # save result to output file output2file(th.result) print_progress() if 'err_msg' in th: colorprint.red(th.err_msg)
def account_info(self): try: if not self.api_key: colorprint.red("[-] Shodan api cant not be Null") sys.exit() api = Shodan(self.api_key) account_info = api.info() msg = "[+] Available Shodan query credits: %d" % account_info.get( 'query_credits') colorprint.green(msg) except APIError as e: colorprint.red(e) sys.exit() return True
def can_auto_login(): if UID and SECRET: msg = '[+] Trying to login with credentials in config file: %s.' % paths.CONFIG_PATH colorprint.green(msg) try: res = requests.get(API_URL + "/data", auth=(UID, SECRET), timeout=10) if res.status_code != 200: raise SystemExit else: return True except: return False else: return False
def auto_login(self): msg = '[+] Trying to login with credentials in config file: %s.' % paths.CONFIG_PATH colorprint.green(msg) try: self.username = ConfigFileParser().ZoomEyeEmail() self.password = ConfigFileParser().ZoomEyePassword() except: pass if bool(self.username and self.password): if self.get_token(): return msg = '[*] Automatic authorization failed.' colorprint.cyan(msg) self.manual_login()
def handle_fofa(query, limit, offset=0): try: msg = '[+] Trying to login with credentials in config file: {}.'.format( paths.CONFIG_PATH) colorprint.green(msg) email = ConfigFileParser().fofa_email() key = ConfigFileParser().fofa_key() if check(email, key): pass else: raise Exception( "Automatic authorization failed") # will go to except block except Exception as e: logger.debug(e) msg = '[*] Automatic authorization failed.' colorprint.cyan(msg) msg = '[*] Please input your FoFa Email and API Key below.' colorprint.cyan(msg) email = input("[*] Fofa Email: ").strip() key = input('[*] Fofa API Key: ').strip() if not check(email, key): msg = '[-] Fofa API authorization failed, Please re-run it and enter a valid key.' colorprint.red(msg) sys.exit() query = base64.b64encode(query.encode('utf-8')).decode('utf-8') # count how many result to search size = limit + offset url = f"https://fofa.info/api/v1/search/all?email={email}&key={key}&qbase64={query}&size={size}&fields=host,ip,protocol,port" try: response = request.get(url).text resp = json.loads(response) if not resp["error"]: for item in resp.get('results')[offset:]: host = item[0] protocol = item[2] # 下面根据host,ip, protocal, port来组装,一般用host就够了,但是对于http/https还需要处理一下 if protocol == "https" or protocol == "http": if not host.startswith("http"): host = protocol + "://" + host conf.target.add(host) except Exception as e: colorprint.red(e) sys.exit()
def load_poc(): conf.poc_module = [] for module_path in conf.module_path: try: module_name = os.path.basename(module_path).split(".")[0] module_spec = importlib.util.spec_from_file_location(module_name, module_path) module = importlib.util.module_from_spec(module_spec) module_spec.loader.exec_module(module) # module.__name__ == module_name msg = '[+] Load custom script: {}'.format(os.path.basename(module_path)) colorprint.green(msg) conf.poc_module.append(module) except: msg = "[-] Your current script [{}] caused this exception\n[-] Error Msg:\n{}".format(os.path.basename(module_path),traceback.format_exc()) colorprint.red(msg) sys.exit(0)
def load_module(): global scan_module try: module_spec = importlib.util.spec_from_file_location( ESSENTIAL_MODULE_METHODS, conf.module_path) module = importlib.util.module_from_spec(module_spec) module_spec.loader.exec_module(module) # bug here how to change poc-->ESSENTIAL_MODULE_METHODS scan_module = module.poc msg = '[+] Load custom script: %s' % os.path.basename(conf.module_path) colorprint.green(msg) except Exception as e: msg = "[-] Your current script [%s.py] caused this exception\n%s\n%s" \ % (os.path.basename(conf.module_path), '[Error Msg]: ' + str(e),\ 'Maybe you can download this module from pip or easy_install') colorprint.red(msg) sys.exit(0)
def handle_fofa(query, limit, offset=0): try: msg = '[+] Trying to login with credentials in config file: %s.' % paths.CONFIG_PATH colorprint.green(msg) email = ConfigFileParser().fofa_email() key = ConfigFileParser().fofa_key() if check(email, key): pass else: raise SystemExit # will go to except block except Exception as e: logger.debug(e) msg = '[*] Automatic authorization failed.' colorprint.cyan(msg) msg = '[*] Please input your FoFa Email and API Key below.' colorprint.cyan(msg) email = input("[*] Fofa Email: ").strip() key = input('[*] Fofa API Key: ').strip() if not check(email, key): msg = '[-] Fofa API authorization failed, Please re-run it and enter a valid key.' colorprint.red(msg) sys.exit() query = base64.b64encode(query) request = "https://fofa.so/api/v1/search/all?email={0}&key={1}&qbase64={2}".format( email, key, query) try: response = requests.get(request) resp = response.readlines()[0] resp = json.loads(resp) if resp["error"] is None: for item in resp.get('results'): conf.target.append(item[0]) if resp.get('size') >= 100: colorprint.cyan( "{0} items found! just 100 returned....".format( resp.get('size'))) except Exception as e: colorprint.red(e) sys.exit()
def load_poc(): conf.poc_module = [] for module_path in conf.module_path: try: module_name = os.path.basename(module_path).split(".")[0] module_spec = importlib.util.spec_from_file_location( module_name, module_path) module = importlib.util.module_from_spec(module_spec) module_spec.loader.exec_module(module) # module.__name__ == module_name msg = '[+] Load custom script: {}'.format( os.path.basename(module_path)) colorprint.green(msg) conf.poc_module.append(module) except Exception as e: msg = "[-] Your current script [{}.py] caused this exception\n{}\n{}" \ .format((os.path.basename(conf.module_path), '[Error Msg]: ' + str(e), \ 'Maybe you can download this module from pip or easy_install')) colorprint.red(msg) sys.exit(0)
def handle_google(query, limit, offset=0): key = ConfigFileParser().google_developer_key() engine = ConfigFileParser().google_engine() if not key or not engine: msg = "[-] Please config your 'developer_key' and 'search_enging' at saucerfram.conf" colorprint.red(msg) sys.exit() try: service = build("customsearch", "v1", http=_initHttpClient(), developerKey=key) result_info = service.cse().list(q=query, cx=engine).execute() msg = '[+] Max query results: %s' % str( result_info.get('searchInformation', {}).get('totalResults')) colorprint.green(msg) ans = set() limit += offset for i in range(int(offset / 10), int((limit + 10 - 1) / 10)): result = service.cse().list(q=query, cx=engine, num=10, start=i * 10 + 1).execute() if 'items' in result: for url in result.get('items'): ans.add(url.get('link')) for t in ans: conf.target.put(t) except SocketError: colorprint.red( '[-] Unable to connect Google, maybe agent/proxy error.') sys.exit() except ServerHttpDenied as e: colorprint.cyan('[-] It seems like Google-Server denied this request.') colorprint.red(e) sys.exit()
def handle_zoomeye(query, limit=50, type='host', offset=0): z = ZoomEye() z.auto_login() info = z.resources_info().get('resources') if info: msg = '[+] Available ZoomEye search: (search:%s)' % (info.get( 'search', 'NO FOUND')) colorprint.green(msg) else: msg = '[-] ZoomEye API authorization failed, Please re-run it and enter a new token.' colorprint.red(msg) sys.exit() # 开始爬取 limit += offset for page_n in range(int(offset / 10), int((limit + 9) / 10)): data = z.dork_search(query, page=page_n, resource=type) if data: for i in data: ip_str = i.get('ip') if 'portinfo' in i: ip_str = ip_str + ':' + str(i.get('portinfo').get('port')) conf.target.put(ip_str) else: break
def check_show(args): # if show scripts if args.show_scripts: module_name_list = os.listdir(paths.SCRIPT_PATH) colorprint.green('[+] Script Name ') order = 1 for module in module_name_list: # only show useful scripts if module not in ['__init__.py','test.py'] and os.path.splitext(module)[1] == '.py': colorprint.green(str(order)+ '. ' +module) order += 1 msg = '\n' + ' ' * 25 + 'Total: %d' % (order-1) colorprint.green(msg) sys.exit()
def target_register(args): # init target queue conf.target = set() # single target to queue if args.target_single: msg = '[+] Load target : {}'.format(args.target_single) colorprint.green(msg) conf.target.add(args.target_single) # file target to queue if args.target_file: if not os.path.isfile(args.target_file): msg = '[-] TargetFile not found: {}'.format(args.target_file) colorprint.red(msg) sys.exit() msg = '[+] Load targets from : {}'.format(args.target_file) colorprint.green(msg) with open(args.target_file, 'r', encoding='utf8') as f: targets = f.readlines() for target in targets: conf.target.add(target.strip('\n')) # range of ip target to queue .e.g. 192.168.1.1-192.168.1.100 if args.target_range: try: lists = gen_ip(args.target_range) if (len(lists)) > 100000: warn_msg = "[*] Loading {} targets, Maybe it's too much, continue? [y/N]".format( (len(lists))) colorprint.cyan(warn_msg, end='') flag = input() if flag in ('Y', 'y', 'yes', 'YES', 'Yes'): pass else: msg = '[-] User quit!' colorprint.cyan(msg) sys.exit() msg = '[+] Load targets from : {}'.format(args.target_range) colorprint.green(msg) # save to conf for target in lists: conf.target.add(target) except: # Exception as e: # colorprint.red(e) err_msg = "Invalid input in [-iR], Example: -iR 192.168.1.1-192.168.1.100" colorprint.red(err_msg) sys.exit() # ip/mask e.g. 192.168.1.2/24 if args.target_network: try: ip_range = ipaddress.ip_network(args.target_network, strict=False) for ip in ip_range.hosts(): conf.target.add(ip) except: # Exception as e: # colorprint.red(e) msg = "[-] Invalid input in [-iN], Example: -iN 192.168.1.0/24" colorprint.red(msg) sys.exit() msg = '[+] Load targets from : {}'.format(args.target_network) colorprint.green(msg) # set search limit of api if args.api_limit <= 0: err_msg = 'Invalid input in [-limit] (can not be negative number)' colorprint.red(err_msg) sys.exit() if args.api_limit > 10000: warn_msg = "Loading {} targets, Maybe it's too much, continue? [y/N]".format( args.api_limit) colorprint.cyan(warn_msg) flag = input() if flag in ('Y', 'y', 'yes', 'YES', 'Yes'): pass else: msg = 'User quit!' colorprint.cyan(msg) sys.exit() conf.limit = args.api_limit # set search offset of api if args.api_offset < 0: warn_msg = "Wrong offset setting, would you like to set it to 0? [y/N]".format( args.api_limit) colorprint.cyan(warn_msg) flag = input() if flag in ('Y', 'y', 'yes', 'YES', 'Yes'): args.api_offset = 0 else: msg = 'User quit!' colorprint.cyan(msg) sys.exit() conf.offset = args.api_offset if args.zoomeye_dork: from lib.api.zoomeye.zoomeye import handle_zoomeye # verify search_type for zoomeye if args.search_type not in ['web', 'host']: msg = '[-] Invalid value in [--search-type], show usage with [-h]' colorprint.red(msg) sys.exit() conf.search_type = args.search_type handle_zoomeye(query=args.zoomeye_dork, limit=conf.limit, type=conf.search_type, offset=conf.offset) if args.fofa_dork: from lib.api.fofa.fofa import handle_fofa handle_fofa(query=args.fofa_dork, limit=conf.limit, offset=conf.offset) if args.shodan_dork: from lib.api.shodan.shodan import handle_shodan handle_shodan(query=args.shodan_dork, limit=conf.limit, offset=conf.offset) if args.censys_dork: from lib.api.censys.censys import handle_censys handle_censys(query=args.censys_dork, limit=conf.limit, offset=conf.offset) # verify targets number if len(conf.target) == 0: err_msg = 'No targets found\nPlease load targets with [-iU|-iF|-iR|-iN] or use API with [-aZ|-aS|-aG|-aF]' colorprint.red(err_msg) sys.exit()