POC-T框架学习————6、相关脚本深入学习二

前言

在前面一节中,我们主要根据程序的入口走了一遍POC-T的大致流程,了解了POC-T的一个基本的工作机制,下面我们将从各个方面进行对源代码深入分析(主要安装目录来进行解析)

相关代码学习

文件根目录

1、toolkit.conf文件(用于配置ZoomEye、Shodan、Google、fofa、bing、cloudeye的账户、代理、api_key等信息)

如上图所示,如果你想要使用POC-T进行网络爬虫以及对一些信息进行搜集等,期间如果使用到ZoomEye、shodan、bing等,那么建议您增加上面的配置类信息。

2、requirement.txt(指明该框架的使用需要哪些python功能模块的支持)

3、POC-T.py(框架的入口)

data目录————资源库(用户可控)

1、pass100.txt\pass1000.txt(弱口令)

排名前100、1000的弱口令字典,主要用于爆破处理。

2、User-agents.txt(UA字典库)

上面的字典中包含了多种UA信息,用户也可以根据自己的需求增加特殊的UA。

3、wooyun_domain(域名信息)

以上的字典当中包含了域名信息,用户也可以根据需要进行增加。

doc目录————文件及版权声明

1、banner.png

2、usage.png

lib目录————项目代码

1、__init__.py(初始化)

2、cli.py(框架整个逻辑的处理流程)

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# project = https://github.com/Xyntax/POC-T
# author = i@cdxy.me
#import各种功能模块              
import os.path                                                            #系统path
import traceback                                                          #异常处理
from lib.parse.cmdline import cmdLineParser                               #命令行信息匹配
from lib.core.option import initOptions                                   #初始化功能选项
from lib.controller.loader import loadModule, loadPayloads                #导入功能模块、payload模块
from lib.core.common import setPaths, banner, systemQuit, openBrowser     #设置Path、打印banner信息、退出系统、使用浏览器打开等
from lib.core.data import paths, conf, logger, cmdLineOptions             #path、配置、日志、命令行选项
from lib.core.enums import EXIT_STATUS                                    #退出状态
from lib.core.settings import IS_WIN                                      #是否是Windows系统
from lib.core.exception import ToolkitUserQuitException                   #用户退出异常
from lib.core.exception import ToolkitMissingPrivileges                   #权限错误
from lib.core.exception import ToolkitSystemException                     #系统异常
from lib.controller.engine import running                                 #运行
from thirdparty.colorama.initialise import init as winowsColorInit        #Windows界面颜色

#main函数(整个框架的入口)
def main():
    """
    Main function of POC-T when running from command line.
    """
    try:
        paths.ROOT_PATH = os.path.dirname(os.path.dirname(os.path.realpath(__file__)))
        try:
            os.path.isdir(paths.ROOT_PATH)
        except UnicodeEncodeError:
            errMsg = "your system does not properly handle non-ASCII paths. "
            errMsg += "Please move the project root directory to another location"
            logger.error(errMsg)
            raise SystemExit
        setPaths()                                                        #设置path路径等选项

        cmdLineOptions.update(cmdLineParser().__dict__)                   #命令参数选项匹配规则
        initOptions(cmdLineOptions)                                       #初始化功能选项

        if IS_WIN:
            winowsColorInit()
        banner()                                                          #框架banner信息

        loadModule()                                                      #导入功能模块
        loadPayloads()                                                    #导入payload

        run()                                                             #处理

        if conf.OPEN_BROWSER:
            openBrowser()

        systemQuit(EXIT_STATUS.SYSETM_EXIT)                               #结束(退出)

    except ToolkitMissingPrivileges, e:                                   #各种异常
        logger.error(e)
        systemQuit(EXIT_STATUS.ERROR_EXIT)

    except ToolkitSystemException, e:
        logger.error(e)
        systemQuit(EXIT_STATUS.ERROR_EXIT)

    except ToolkitUserQuitException:
        systemQuit(EXIT_STATUS.USER_QUIT)
    except KeyboardInterrupt:
        systemQuit(EXIT_STATUS.USER_QUIT)

    except Exception:
        print traceback.format_exc()
        logger.warning('It seems like you reached a unhandled exception, please report it to author\'s mail:<i@cdxy.me> or raise a issue via:<https://github.com/Xyntax/POC-T/issues/new>.')

if __name__ == "__main__":
    main()

3、debug.py(调试\测试信息)

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# project = https://github.com/Xyntax/POC-T
# author = i@cdxy.me

"""
POC-T functional testing script
"""

auto = """

# help
-h;powered by cdxy <mail:i@cdxy.me>
--help;powered by cdxy <mail:i@cdxy.me>

# version
-v;2.
--version;2.

# show
--show;Script Name

# --browser --single -iA -iN -iS -iF
-s test;[-] Please load targets
-s test -iA 1-10 --single;[*] [single-mode] found!
-s test -iN 10.10.0/30 --browser -oF;[-] [--browser] is based on file output
-s test -iS "http://test.com" --browser;[*] System exit.
-s test -iF data/pass100.txt -t 50 -oF;concurrent: 50;[*] System exit.

# -s
-iA 1-10;Use -s to load script
-s 1234567890 -iS aaa;Script [1234567890.py] not exist
-s test -iS aaa;[*] System exit.
-s test.py -iS aaa;[*] System exit.
-s script/test.py -iS aaa;[*] System exit.
-s ./ -iS aaa;[-] [./] not a file.

# -eT -eC -t
-eT -s test -iA 1-10 -t 5 -oF;concurrent: 5;[*] System exit.
-eT -s test -iF data/pass100.txt -t 50 -oF;concurrent: 50;[*] System exit.
-eT -s test -iA 1-10 -t 500 -oF;range: 1 to 100
-eG -s test -iS http://sss.com -oF;[*] System exit

# -oS
-s test -iS aaa;by cdxy mail:i@cdxy.me };[*] System exit.
-s test -iS aaa -oS;[*] System exit.$mail:i@cdxy.me }

# --limit -aS -aZ -aG
-s test -aS 1 --limit=0;[-] Invalid value in [--limit]
-s test -aS 1 --limit=2;[+] Total: 2;[*] System exit.
-s test -aZ 1 --limit=2;[+] Total: 10;[*] System exit.
-s test -aZ 1 --limit=10;[+] Total: 10;[*] System exit.
-s test -aZ 1 --limit=11;[+] Total: 20;[*] System exit.
-s test -aG 1 --limit=2;[+] Total: 10;[*] System exit.
-s test -aG 1 --limit=10;[+] Total: 10;[*] System exit.
-s test -aG 1 --limit=11;[+] Total: 20;[*] System exit.
-s test -aG faefafw32qtfafw3;[+] Total: 0;[*] System exit.

# --offset
-s test -aS 1 --offset=0;[*] System exit.
-s test -aS 1 --offset=10;[*] System exit.

# --search-type
-s test -aZ 1 --search-type "hello";[-] Invalid value in [--search-type]
-s test -aZ 1 --search-type 111;[-] Invalid value in [--search-type]
-s test -aZ 1 --search-type web;[*] System exit.
-s test -aZ 1 --search-type host;[*] System exit.
-s test -aZ 1 --search-type web,host;[-] Invalid value in [--search-type]

# --gproxy
-s test -aG 1 --gproxy="http 127.0.0.1 1111";[-] Unable to connect Google
-s test -aG 1 --gproxy="http 127.0.0.1";[-] SyntaxError in GoogleProxy string
-s test -aG 1 --gproxy="1 127.0.0.1 1";[-] Invalid proxy-type
-s test -aG 1 --gproxy="http 127.0.0.1 fa";[-] Invalid port in GoogleProxy string
-s test -aG 1 --gproxy="http 127.0.0.1 1894";[*] System exit.
-s test -aG 1 --gproxy="sock5 127.0.0.1 7070";[*] System exit.
-s test -aG 1 --gproxy "http 127.0.0.1 23124";[-] Unable to connect Google

# output
-s test -iA 1-10 -o _checko.txt;[*] System exit.
-s test -iA 1-10 -o _checko1.txt -oF;[-] Cannot use [-oF] and [-o] together
-s test -iA 1-10 -o _checko2.txt -oS;[*] System exit.


# scripts

"""

header = """#!/usr/bin/env python
# -*- coding: utf-8 -*-
# project = https://github.com/Xyntax/POC-T
# author"""

import os
import subprocess


def headerCheck(path):
    parents = os.listdir(path)
    for parent in parents:
        if parent == 'thirdparty':
            continue
        child = os.path.join(path, parent)
        if os.path.isdir(child):
            headerCheck(child)
        elif os.path.isfile(child):
            if child.endswith('.py'):
                if open(child).read().startswith(header):
                    pass
                else:
                    print 'Invalid header in %s' % child


def autoCheckResult(output, error, expect, unexpect):
    for each in expect:
        if each in output or each in error:
            pass
        else:
            return False
    for each in unexpect:
        if each in output or each in error:
            return False
        else:
            pass
    return True


def autoCheck():
    base = 'python POC-T.py '
    for each in auto.split('\n'):
        if not each or each.startswith('#'):
            continue
        u = each.split('$')[1:]
        each = each.split('$')[0]
        c = each.split(';')[0]
        r = each.split(';')[1:]

        command = base + c
        process = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE,shell=True)
        o = process.stdout.read()
        e = process.stderr.read()
        if autoCheckResult(o, e, r, u):
            pass
        else:
            print command


def checkInvalidVersion():
    command = 'python3 POC-T.py -h'
    process = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True)
    o = process.stdout.read()
    e = process.stderr.read()
    if autoCheckResult(o, e, ['[CRITICAL] incompatible Python version'], []):
        pass
    else:
        print command


def checkOutput(base_path):
    target1 = os.path.join(base_path, '_checko.txt')
    target2 = os.path.join(base_path, '_checko1.txt')
    target3 = os.path.join(base_path, '_checko2.txt')
    try:
        if len(open(target1).read()) and not os.path.isfile(target2) and len(open(target3).read()):
            os.remove(target1)
            os.remove(target3)
        else:
            print '!!!failed!!!'
    except IOError:
        print '!!!failed!!!'


def debugMain():
    try:
        root_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
        os.chdir(root_dir)
        print '>>> base-dir [%s]' % root_dir

        print '>>> start header check'
        headerCheck(root_dir)

        print '>>> start invalid-version check'
        checkInvalidVersion()

        print '>>> start command check'
        autoCheck()

        print '>>> start output check'
        checkOutput(root_dir)

    except KeyboardInterrupt:
        exit('User quit!')
    return


if __name__ == '__main__':
    debugMain()

API子目录————用于调用fofa\google\shodan\zoomeye

fofa

1..__init__.py(初始化)

2、pack.py(核心——完成fofa认证之后使用fofa去根据用户输入的信息去查询数据)

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# project = https://github.com/Xyntax/POC-T
# author = bit4

import sys                                                   #sys库
from lib.core.data import paths, logger                      #路径、日志
from lib.utils.config import ConfigFileParser                #匹配文件匹配
from lib.core.common import getSafeExString                  
import getpass                                               #各种第三方库
import urllib
import base64
import json


def check(email, key):                                        #fofa身份认证
    if email and key:
        auth_url = "https://fofa.so/api/v1/info/my?email={0}&key={1}".format(email, key)
        try:
            response = urllib.urlopen(auth_url)
            if response.code == 200:
                return True
        except Exception, e:
            # logger.error(e)
            return False
    return False


def FofaSearch(query, limit=100, offset=0):  # TODO 付费获取结果的功能实现
    try:
        msg = 'Trying to login with credentials in config file: %s.' % paths.CONFIG_PATH
        logger.info(msg)
        email = ConfigFileParser().FofaEmail()
        key = ConfigFileParser().FofaKey()
        if check(email, key):
            pass
        else:
            raise  # will go to except block
    except:
        msg = 'Automatic authorization failed.'
        logger.warning(msg)
        msg = 'Please input your FoFa Email and API Key below.'
        logger.info(msg)
        email = raw_input("Fofa Email: ").strip()
        key = getpass.getpass(prompt='Fofa API Key: ').strip()
        if not check(email, key):
            msg = 'Fofa API authorization failed, Please re-run it and enter a valid key.'
            sys.exit(logger.error(msg))

    query = base64.b64encode(query)

    request = "https://fofa.so/api/v1/search/all?email={0}&key={1}&qbase64={2}".format(email, key, query)
    result = []
    try:
        response = urllib.urlopen(request)
        resp = response.readlines()[0]
        resp = json.loads(resp)
        if resp["error"] is None:
            for item in resp.get('results'):
                result.append(item[0])
            if resp.get('size') >= 100:
                logger.info("{0} items found! just 100 returned....".format(resp.get('size')))
    except Exception, e:
        sys.exit(logger.error(getSafeExString(e)))
    finally:
        return result

其余的三个都差不多,都是实现的API的认证之后进行的查询。

controller子目录

1、__init__.py(初始化)

2、api.py(根据API名称匹配API,之后调用API进行操作)

3、engine.py(处理机制)

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# project = https://github.com/Xyntax/POC-T
# author = i@cdxy.me


import threading
import time
import traceback
from lib.core.data import th, conf, logger
from lib.core.common import dataToStdout
from lib.utils.console import getTerminalSize
from lib.utils.versioncheck import PYVERSION
from lib.core.enums import POC_RESULT_STATUS, ENGINE_MODE_STATUS


def initEngine():
    th.thread_mode = True if conf.ENGINE is ENGINE_MODE_STATUS.THREAD else False
    th.module_name = conf.MODULE_NAME
    th.f_flag = conf.FILE_OUTPUT
    th.s_flag = conf.SCREEN_OUTPUT
    th.output = conf.OUTPUT_FILE_PATH
    th.thread_count = th.threads_num = th.THREADS_NUM
    th.single_mode = conf.SINGLE_MODE
    th.scan_count = th.found_count = 0
    th.console_width = getTerminalSize()[0] - 2
    th.is_continue = True
    th.found_single = False
    th.start_time = time.time()
    setThreadLock()
    msg = 'Set the number of concurrent: %d' % th.threads_num
    logger.success(msg)


def singleMode():
    th.is_continue = False
    th.found_single = True


def scan():
    while 1:
        if th.thread_mode: th.load_lock.acquire()
        if th.queue.qsize() > 0 and th.is_continue:
            payload = str(th.queue.get(timeout=1.0))
            if th.thread_mode: th.load_lock.release()
        else:
            if th.thread_mode: th.load_lock.release()
            break
        try:
            # POC在执行时报错如果不被处理,线程框架会停止并退出
            status = th.module_obj.poc(payload)
            resultHandler(status, payload)
        except Exception:
            th.errmsg = traceback.format_exc()
            th.is_continue = False
        changeScanCount(1)
        if th.s_flag:
            printProgress()
    if th.s_flag:
        printProgress()

    changeThreadCount(-1)


def run():
    initEngine()
    if conf.ENGINE is ENGINE_MODE_STATUS.THREAD:
        for i in range(th.threads_num):
            t = threading.Thread(target=scan, name=str(i))
            setThreadDaemon(t)
            t.start()
        # It can quit with Ctrl-C
        while 1:
            if th.thread_count > 0 and th.is_continue:
                time.sleep(0.01)
            else:
                break

    elif conf.ENGINE is ENGINE_MODE_STATUS.GEVENT:
        from gevent import monkey
        monkey.patch_all()
        import gevent
        while th.queue.qsize() > 0 and th.is_continue:
            gevent.joinall([gevent.spawn(scan) for i in xrange(0, th.threads_num) if
                            th.queue.qsize() > 0])

    dataToStdout('\n')

    if 'errmsg' in th:
        logger.error(th.errmsg)

    if th.found_single:
        msg = "[single-mode] found!"
        logger.info(msg)


def resultHandler(status, payload):
    if not status or status is POC_RESULT_STATUS.FAIL:
        return
    elif status is POC_RESULT_STATUS.RETRAY:
        changeScanCount(-1)
        th.queue.put(payload)
        return
    elif status is True or status is POC_RESULT_STATUS.SUCCESS:
        msg = payload
    else:
        msg = str(status)
    changeFoundCount(1)
    if th.s_flag:
        printMessage(msg)
    if th.f_flag:
        output2file(msg)
    if th.single_mode:
        singleMode()


def setThreadLock():
    if th.thread_mode:
        th.found_count_lock = threading.Lock()
        th.scan_count_lock = threading.Lock()
        th.thread_count_lock = threading.Lock()
        th.file_lock = threading.Lock()
        th.load_lock = threading.Lock()


def setThreadDaemon(thread):
    # Reference: http://stackoverflow.com/questions/190010/daemon-threads-explanation
    if PYVERSION >= "2.6":
        thread.daemon = True
    else:
        thread.setDaemon(True)


def changeFoundCount(num):
    if th.thread_mode: th.found_count_lock.acquire()
    th.found_count += num
    if th.thread_mode: th.found_count_lock.release()


def changeScanCount(num):
    if th.thread_mode: th.scan_count_lock.acquire()
    th.scan_count += num
    if th.thread_mode: th.scan_count_lock.release()


def changeThreadCount(num):
    if th.thread_mode: th.thread_count_lock.acquire()
    th.thread_count += num
    if th.thread_mode: th.thread_count_lock.release()


def printMessage(msg):
    dataToStdout('\r' + msg + ' ' * (th.console_width - len(msg)) + '\n\r')


def printProgress():
    msg = '%s found | %s remaining | %s scanned in %.2f seconds' % (
        th.found_count, th.queue.qsize(), th.scan_count, time.time() - th.start_time)
    out = '\r' + ' ' * (th.console_width - len(msg)) + msg
    dataToStdout(out)


def output2file(msg):
    if th.thread_mode: th.file_lock.acquire()
    f = open(th.output, 'a')
    f.write(msg + '\n')
    f.close()
    if th.thread_mode: th.file_lock.release()

4、loader.py(导入各种功能模块)

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# project = https://github.com/Xyntax/POC-T
# author = i@cdxy.me

import Queue
import sys
import imp
import os
from lib.core.data import th, conf, logger, paths
from lib.core.enums import API_MODE_NAME, TARGET_MODE_STATUS
from lib.core.settings import ESSENTIAL_MODULE_METHODS
from lib.core.exception import ToolkitValueException
from lib.controller.api import runApi
from thirdparty.IPy import IPy

#导入功能模块
def loadModule():
    _name = conf.MODULE_NAME
    msg = 'Load custom script: %s' % _name
    logger.success(msg)

    fp, pathname, description = imp.find_module(os.path.splitext(_name)[0], [paths.SCRIPT_PATH])
    try:
        th.module_obj = imp.load_module("_", fp, pathname, description)
        for each in ESSENTIAL_MODULE_METHODS:
            if not hasattr(th.module_obj, each):
                errorMsg = "Can't find essential method:'%s()' in current script,Please modify your script/PoC."
                sys.exit(logger.error(errorMsg))
    except ImportError, e:
        errorMsg = "Your current scipt [%s.py] caused this exception\n%s\n%s" \
                   % (_name, '[Error Msg]: ' + str(e), 'Maybe you can download this module from pip or easy_install')
        sys.exit(logger.error(errorMsg))

#导入payload
def loadPayloads():
    infoMsg = 'Initialize targets...'
    logger.success(infoMsg)
    th.queue = Queue.Queue()
    if conf.TARGET_MODE is TARGET_MODE_STATUS.RANGE:
        int_mode()
    elif conf.TARGET_MODE is TARGET_MODE_STATUS.FILE:
        file_mode()
    elif conf.TARGET_MODE is TARGET_MODE_STATUS.IPMASK:
        net_mode()
    elif conf.TARGET_MODE is TARGET_MODE_STATUS.SINGLE:
        single_target_mode()
    elif conf.TARGET_MODE is TARGET_MODE_STATUS.API:
        api_mode()

    else:
        raise ToolkitValueException('conf.TARGET_MODE value ERROR.')
    logger.success('Total: %s' % str(th.queue.qsize()))

#文件
def file_mode():
    for line in open(conf.INPUT_FILE_PATH):
        sub = line.strip()
        if sub:
            th.queue.put(sub)

#数列
def int_mode():
    _int = conf.I_NUM2.strip().split('-')
    for each in range(int(_int[0].strip()), int(_int[1].strip())):
        th.queue.put(str(each))

#网段
def net_mode():
    ori_str = conf.NETWORK_STR
    try:
        _list = IPy.IP(ori_str)
    except Exception, e:
        sys.exit(logger.error('Invalid IP/MASK,%s' % e))
    for each in _list:
        th.queue.put(str(each))

#单一目标
def single_target_mode():
    th.queue.put(str(conf.SINGLE_TARGET_STR))

#api
def api_mode():
    conf.API_OUTPUT = os.path.join(paths.DATA_PATH, conf.API_MODE)
    if not os.path.exists(conf.API_OUTPUT):
        os.mkdir(conf.API_OUTPUT)

    file = runApi()
    for line in open(file):
        sub = line.strip()
        if sub:
            th.queue.put(sub)

未完,待续,后期继续更新!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

FLy_鹏程万里

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值