├── Pipfile ├── Pipfile.lock ├── README.md ├── app ├── __init__.py ├── blueprint │ ├── __init__.py │ ├── home │ │ ├── __init__.py │ │ ├── index.py │ │ ├── items.py │ │ └── logs.py │ └── views │ │ ├── __init__.py │ │ ├── dirs.py │ │ ├── domains.py │ │ ├── finger.py │ │ ├── initiative.py │ │ ├── pocs.py │ │ └── ports.py ├── config.py ├── extensions.py ├── lib │ ├── __init__.py │ ├── core │ │ ├── __init__.py │ │ ├── agent.py │ │ ├── agent_dir.py │ │ ├── agent_poc.py │ │ ├── awvs_core.py │ │ └── datatype.py │ ├── handler │ │ ├── __init__.py │ │ └── decorator.py │ ├── thirdparty │ │ ├── __init__.py │ │ ├── cmsfinger │ │ │ ├── __init__.py │ │ │ ├── cms_analyse.py │ │ │ ├── cms_finger.json │ │ │ ├── cms_finger_bak.json │ │ │ ├── fofa_finger.json │ │ │ └── fofa_finger_bak.json │ │ └── wafcheck │ │ │ ├── __init__.py │ │ │ ├── actions.py │ │ │ └── config.py │ └── utils │ │ ├── __init__.py │ │ ├── data.py │ │ ├── deps.py │ │ └── tools.py ├── static │ ├── css │ │ ├── 404.css │ │ ├── font.css │ │ ├── login.css │ │ ├── public.css │ │ ├── theme1.css │ │ ├── theme2.css │ │ ├── theme3.css │ │ ├── theme4.css │ │ ├── theme5.css │ │ └── xadmin.css │ ├── downloads │ │ └── 6bf9bc68-5162-463d-a3b2-3b1300a9389b.xlsx │ ├── fonts │ │ ├── iconfont.eot │ │ ├── iconfont.svg │ │ ├── iconfont.ttf │ │ └── iconfont.woff │ ├── images │ │ ├── aiwrap.png │ │ ├── bg.png │ │ └── spaceman.svg │ ├── js │ │ ├── 404.js │ │ ├── jquery.min.js │ │ ├── xadmin.js │ │ └── xcity.js │ └── lib │ │ └── layui │ │ ├── css │ │ ├── layui.css │ │ ├── layui.mobile.css │ │ └── modules │ │ │ ├── code.css │ │ │ ├── laydate │ │ │ └── default │ │ │ │ └── laydate.css │ │ │ └── layer │ │ │ └── default │ │ │ ├── icon-ext.png │ │ │ ├── icon.png │ │ │ ├── layer.css │ │ │ ├── loading-0.gif │ │ │ ├── loading-1.gif │ │ │ └── loading-2.gif │ │ ├── font │ │ ├── iconfont.eot │ │ ├── iconfont.svg │ │ ├── iconfont.ttf │ │ └── iconfont.woff │ │ ├── images │ │ └── face │ │ │ ├── 0.gif │ │ │ ├── 1.gif │ │ │ ├── 10.gif │ │ │ ├── 11.gif │ │ │ ├── 12.gif │ │ │ ├── 13.gif │ │ │ ├── 14.gif │ │ │ ├── 15.gif │ │ │ ├── 16.gif │ │ │ ├── 17.gif │ │ │ ├── 18.gif │ │ │ ├── 19.gif │ │ │ ├── 2.gif │ │ │ ├── 20.gif │ │ │ ├── 21.gif │ │ │ ├── 22.gif │ │ │ ├── 23.gif │ │ │ ├── 24.gif │ │ │ ├── 25.gif │ │ │ ├── 26.gif │ │ │ ├── 27.gif │ │ │ ├── 28.gif │ │ │ ├── 29.gif │ │ │ ├── 3.gif │ │ │ ├── 30.gif │ │ │ ├── 31.gif │ │ │ ├── 32.gif │ │ │ ├── 33.gif │ │ │ ├── 34.gif │ │ │ ├── 35.gif │ │ │ ├── 36.gif │ │ │ ├── 37.gif │ │ │ ├── 38.gif │ │ │ ├── 39.gif │ │ │ ├── 4.gif │ │ │ ├── 40.gif │ │ │ ├── 41.gif │ │ │ ├── 42.gif │ │ │ ├── 43.gif │ │ │ ├── 44.gif │ │ │ ├── 45.gif │ │ │ ├── 46.gif │ │ │ ├── 47.gif │ │ │ ├── 48.gif │ │ │ ├── 49.gif │ │ │ ├── 5.gif │ │ │ ├── 50.gif │ │ │ ├── 51.gif │ │ │ ├── 52.gif │ │ │ ├── 53.gif │ │ │ ├── 54.gif │ │ │ ├── 55.gif │ │ │ ├── 56.gif │ │ │ ├── 57.gif │ │ │ ├── 58.gif │ │ │ ├── 59.gif │ │ │ ├── 6.gif │ │ │ ├── 60.gif │ │ │ ├── 61.gif │ │ │ ├── 62.gif │ │ │ ├── 63.gif │ │ │ ├── 64.gif │ │ │ ├── 65.gif │ │ │ ├── 66.gif │ │ │ ├── 67.gif │ │ │ ├── 68.gif │ │ │ ├── 69.gif │ │ │ ├── 7.gif │ │ │ ├── 70.gif │ │ │ ├── 71.gif │ │ │ ├── 8.gif │ │ │ └── 9.gif │ │ ├── lay │ │ └── modules │ │ │ ├── carousel.js │ │ │ ├── code.js │ │ │ ├── colorpicker.js │ │ │ ├── element.js │ │ │ ├── flow.js │ │ │ ├── form.js │ │ │ ├── jquery.js │ │ │ ├── laydate.js │ │ │ ├── layedit.js │ │ │ ├── layer.js │ │ │ ├── laypage.js │ │ │ ├── laytpl.js │ │ │ ├── mobile.js │ │ │ ├── rate.js │ │ │ ├── slider.js │ │ │ ├── table.js │ │ │ ├── tree.js │ │ │ ├── upload.js │ │ │ └── util.js │ │ ├── layui.all.js │ │ └── layui.js └── templates │ ├── 404.html │ ├── change_pwd.html │ ├── dirs │ ├── dirs_add.html │ └── dirs_list.html │ ├── domain │ ├── domains_add.html │ └── domians_list.html │ ├── finger │ ├── finger_add.html │ └── finger_list.html │ ├── index.html │ ├── initiative │ ├── initiative_add.html │ └── initiative_list.html │ ├── items │ ├── items_add.html │ └── items_list.html │ ├── login.html │ ├── logs.html │ ├── pocs │ ├── pocs_add.html │ └── pocs_list.html │ ├── ports │ ├── ports_add.html │ └── ports_list.html │ └── welcome.html ├── img ├── Voyager.jpg ├── img0.png ├── img1.png ├── img2.png ├── img3.png ├── img4.png └── img5.png ├── manager.py └── run.sh /Pipfile: -------------------------------------------------------------------------------- 1 | [[source]] 2 | name = "pypi" 3 | url = "https://pypi.org/simple" 4 | verify_ssl = true 5 | 6 | [dev-packages] 7 | 8 | [packages] 9 | flask = "*" 10 | flask-pymongo = "*" 11 | docker = "*" 12 | flask-wtf = "*" 13 | xlsxwriter = "*" 14 | 15 | [requires] 16 | python_version = "3.8.1" 17 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # 旅行者探测器系统 2 |  3 | 4 | ## 0x01 功能介绍 5 | 作为一个渗透人员,在每次渗透网站的时候都要拿出一堆黑客工具,比如nmap, awvs, 御剑等工具进行测试,由于实在厌烦了一些低级重复性的工作,趁着2020年新年创建了一个工具集合平台,将渗透测试常见的域名扫描,端口扫描,目录扫描,漏洞扫描的工具集合在一起 6 | 7 | 目前平台还在持续开发中,肯定有不少问题和需要改进的地方,欢迎大佬们提交建议和Bug,也非常欢迎各位大佬Star或者是Fork 8 | 9 |  10 | 11 | **系统数据是伪造的** 12 | 13 | ## 0x02 系统结构 14 | 15 | ### 开发框架 16 | 17 | 基础语言: **Python(3.8.1)** 18 | 19 | Web框架: **Flask(1.1.1)** 20 | 21 | 数据库: **Mongodb** 22 | 23 | 逻辑处理: **Docker** 24 | 25 | 前端: **Layui** 26 | 27 | ### 数据载入 28 | 29 | 数据流入有两种方式,一种是从WEB界面引入,还有一种是从上级任务引入,比如说端口扫描任务的IP既可以从WEB页面引入,也可以从域名扫描处获得。漏洞扫描的任务只能从端口扫描和域名扫描的任务中引入 30 | 31 | 32 | ## 0x02 功能介绍 33 | 34 | ### 0x001 域名扫描 35 | 采用的是[oneforall](https://github.com/shmilylty/OneForAll),当前使用的版本是0.0.9,我修改了部分代码,使得工具和平台能够结合 36 | 37 |  38 | 39 | ### 0x002 端口扫描 40 | 程序采用的是[masscan](https://github.com/robertdavidgraham/masscan)和[nmap](https://github.com/nmap/nmap)结合的方式,先用masscan扫描开放的端口,然后再用nmap对开放的端口进行详细的信息探测, 41 | 这步是最重要的一步,通过nmap给端口打上标签,为以后的POC扫描提供数据,由于nmap只能识别广义的操作系统,中间件,数据库三层结构,再往上的web应用nmap无法识别,只能通过接下来的cms识别给web应用程序打标签 42 | 43 | ### 0x003 目录扫描 44 | 目录扫描采用的工具是[dirsearch](https://github.com/maurosoria/dirsearch),排除了部分bug并且扩充了字典然后进行封装 45 | 46 | ### 0x004 指纹识别 47 | 指纹识别采用的是新潮团队的[TideFinger](https://github.com/TideSec/TideFinger), 我提取出了TideFinger的指纹进行比对,原先TideFinger是单任务运行多线程请求的方式,为了配合框架我改成了多任务并发单线程请求的方式,由于Python3和Python2在字符编码上存在差异,导致相同的字符串可能会计算出不同的MD5值,这个指纹识别的库以后需要大量修改 48 | 49 | 导出的扫描结果 50 |  51 | 52 | ### 0x005 漏洞扫描 53 | 漏洞扫描功能现在引入了xunfeng和kunpeng的poc,一共144个,标签以nmap的标签为主,比如445端口的标签是microsoft-ds, 3389的标签是ms-wbt-server。这两个框架合并存在一定问题,比如说:xunfeng和kunpeng的poc主要针对非WEB应用,两个框架的POC存在重复的问题.我做了一定的去重工作,后期随着POC的增多,去重会是一个问题 54 | 55 | ### 0x006 WAF探测 56 | 分析了一下sqlmap的源代码,从中提取出了sqlmap用于WAF探测的代码并进行了封装, 用来探测类http端口是否有WAF保护,此功能并未在前台展示,一些模块比如目录扫描会自动进行调用 57 | 58 | ### 0x007 主动扫描 59 | 主动扫描用的是AWVS12,已经封装在Docker里了,通过AWVS12的restful进行API调用 60 | 61 | ## 0x03 安装教程 62 | 63 | 这里以Kali linux 2019.4作为基础操作系统 64 | 65 | ### 0x001 安装docker 66 | 由于Kali默认没有安装Docker,需要手动安装 67 | 68 | ```bash 69 | # curl -fsSL https://download.docker.com/linux/debian/gpg | apt-key add - 70 | # echo 'deb [arch=amd64] https://download.docker.com/linux/debian buster stable' > /etc/apt/sources.list.d/docker.list 71 | # apt-get update && apt-get install docker-ce 72 | # systemctl enable docker 73 | # systemctl start docker 74 | ``` 75 | 76 |  77 | 78 | 79 | ### 0x002 下载源码安装 80 | 81 | ```bash 82 | git clone https://github.com/ody5sey/Voyager.git 83 | cd Voyager 84 | bash run.sh 85 | ``` 86 | 87 | 88 | ### 0x003 运行 89 | 90 | ```bash 91 | python manager.py 92 | ``` 93 | 94 | 添加新用户 95 | curl http://127.0.0.1:5000/add 96 | 然后访问 http://127.0.0.1:5000/ 97 | 98 | 默认的用户名和密码是luffy:s1riu5 99 | 100 |  101 | 102 | 正式开始前需要先创建一个项目 103 | 104 | ## 0x04 时间参数 105 | 106 | **域名扫描**: 开启了爆破模式,一个域名大约需要6分钟 107 | 108 | **端口扫描**: 服务器环境中百兆宽带内网测试将全C端,全端口的扫描压缩到10分钟之内,但是家用路由器根本无法承受如此巨大的负载,只好限制速度。现在单IP全端口扫描时间不到一分钟 109 | 110 | **目录扫描**: 四个字典单个目标6分钟 111 | 112 | ## 0x05 TODO 113 | 114 | 权当是立FLAG吧 115 | 116 | ### 功能更新 117 | 118 | - [ ] POC框架中引入bugscan和beebeeto,以改善针对WEB应用扫描不全的问题,这样四个主流POC框架的POC数量总计有1500+ 119 | - [ ] 引入AWVS12,首先对类http标签进行WAF测试,没有WAF保护的WEB应用将推送给AWVS检测 120 | - [ ] 引入被动扫描器XRAY,和之前AWVS的一样,没有WAF保护的WEB应用将用AWVS的爬虫和xray进行检测 121 | - [ ] 引入IP代理功能,为部分模块添加代理参数 122 | - [ ] 引入Metasploit, 可以调用metasploit接口 123 | - [ ] 引入爆破功能,本来想用hydra实现的,但是发现效果并不是很好,现在比较倾向于写爆破组件然后以插件的形式载入 124 | - [ ] 引入一键日站功能,在输入IP地址或者是域名之后自动依次载入攻击组件 125 | - [ ] 引入微信接口,从微信载入攻击目标然后后台自动攻击 126 | 127 | ### 长期更新 128 | 129 | - [ ] 各组件的协调优化以及BUG修复, 漏报,误报的修复 130 | - [ ] 指纹库的更新和poc库的更新 131 | 132 | -------------------------------------------------------------------------------- /app/__init__.py: -------------------------------------------------------------------------------- 1 | from flask import Flask 2 | from flask import render_template 3 | 4 | from app.extensions import mongo 5 | from app.extensions import csrf 6 | from app.config import DevConfig 7 | 8 | 9 | def create_app(config_class=DevConfig): 10 | app = Flask(__name__) 11 | 12 | app.config.from_object(config_class) 13 | 14 | mongo.init_app(app) 15 | csrf.init_app(app) 16 | 17 | # 注册 blueprint 18 | from app.blueprint import admin as admin_blueprint 19 | 20 | app.register_blueprint(admin_blueprint, url_prefix="/") 21 | 22 | @app.errorhandler(404) 23 | def page_not_found(error): 24 | return render_template("404.html"), 404 25 | 26 | return app 27 | -------------------------------------------------------------------------------- /app/blueprint/__init__.py: -------------------------------------------------------------------------------- 1 | from flask import Blueprint 2 | from flask import session 3 | from flask import redirect 4 | from flask import url_for 5 | from functools import wraps 6 | 7 | admin = Blueprint("admin", __name__) 8 | 9 | 10 | # 管理员登陆装饰器 11 | def admin_required(func): 12 | @wraps(func) 13 | def decorated_function(*args, **kwargs): 14 | if session.get('admin', None) is None: 15 | # 如果session中未找到该键,则用户需要登录 16 | return redirect(url_for('admin.login')) 17 | return func(*args, **kwargs) 18 | 19 | return decorated_function 20 | 21 | 22 | from app.blueprint.views import pocs 23 | from app.blueprint.views import ports 24 | from app.blueprint.views import domains 25 | from app.blueprint.views import dirs 26 | from app.blueprint.views import finger 27 | from app.blueprint.views import initiative 28 | from app.blueprint.home import logs 29 | from app.blueprint.home import items 30 | from app.blueprint.home import index 31 | -------------------------------------------------------------------------------- /app/blueprint/home/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ddosi/Voyager/a9c63235967b64c79b04af09f976ec35945b4f57/app/blueprint/home/__init__.py -------------------------------------------------------------------------------- /app/blueprint/home/index.py: -------------------------------------------------------------------------------- 1 | import datetime 2 | 3 | from flask import render_template 4 | from flask import request 5 | from flask import redirect 6 | from flask import jsonify 7 | from flask import url_for 8 | from flask import session 9 | 10 | from werkzeug.security import generate_password_hash 11 | from werkzeug.security import check_password_hash 12 | 13 | from app.blueprint import admin 14 | from app.blueprint import admin_required 15 | from app import mongo 16 | 17 | 18 | @admin.route("/add") 19 | def add(): 20 | name = "luffy" 21 | password = "s1riu5" 22 | 23 | if mongo.db.users.find_one({'name': name}) == None: 24 | user = {'name': name, 'age': 18, 'password_hash': generate_password_hash(password=password)} 25 | mongo.db.users.insert_one(user) 26 | 27 | return "OK" 28 | 29 | 30 | @admin.route("/login", methods=["GET", "POST"]) 31 | def login(): 32 | if request.method == "POST": 33 | 34 | username = request.form.get('username', None) 35 | password = request.form.get('password', None) 36 | 37 | user = mongo.db.users.find_one({'name': username}) 38 | 39 | if user is None: 40 | result = {"status": 403, "msg": "用户名或者是密码错误"} 41 | return jsonify(result) 42 | 43 | if check_password_hash(pwhash=user["password_hash"], password=password): 44 | session["admin"] = username 45 | 46 | data = {"status": 200, "url_jump": "/"} 47 | return jsonify(data) 48 | 49 | 50 | else: 51 | 52 | result = {"status": 403, "msg": "用户名或者是密码错误"} 53 | return jsonify(result) 54 | 55 | return render_template('login.html') 56 | 57 | 58 | @admin.route("/") 59 | @admin_required 60 | def index(): 61 | if request.method == "GET": 62 | return render_template('index.html') 63 | 64 | 65 | @admin.route("/welcome") 66 | @admin_required 67 | def welcome(): 68 | if request.method == "GET": 69 | current_time = datetime.datetime.now() 70 | items_count = mongo.db.items.count_documents({}) 71 | tasks_count = mongo.db.tasks.count_documents({}) 72 | domains_count = mongo.db.subdomains.count_documents({}) 73 | ports_count = mongo.db.ports.count_documents({}) 74 | vuls_count = mongo.db.vuls.count_documents({}) 75 | 76 | return render_template('welcome.html', **locals()) 77 | 78 | 79 | @admin.route("/logout") 80 | @admin_required 81 | def logout(): 82 | session.pop('admin') 83 | return redirect(url_for('admin.login')) 84 | 85 | 86 | @admin.route("/change_pwd", methods=["GET", "POST"]) 87 | @admin_required 88 | def change_passwd(): 89 | # 修改密码的视图函数 90 | 91 | if request.method == "GET": 92 | return render_template('change_pwd.html') 93 | 94 | if request.method == "POST": 95 | 96 | old_pass = request.form.get('old_passwd', None) 97 | new_pass = request.form.get('new_password', None) 98 | new_confirm = request.form.get('new_confirm', None) 99 | 100 | username = session.get("admin") 101 | 102 | user = mongo.db.users.find_one({'name': username}) 103 | 104 | if not check_password_hash(pwhash=user["password_hash"], password=old_pass): 105 | data = {"status": 403, "msg": "旧密码错误"} 106 | return jsonify(data) 107 | 108 | if new_pass != new_confirm: 109 | data = {"status": 403, "msg": "新密码不匹配"} 110 | return jsonify(data) 111 | 112 | mongo.db.users.update_one( 113 | {'name': username}, 114 | {'$set': { 115 | 'password_hash': generate_password_hash(password=new_pass) 116 | 117 | } 118 | } 119 | ) 120 | 121 | data = {"status": 200, "msg": "密码修改成功"} 122 | return jsonify(data) 123 | -------------------------------------------------------------------------------- /app/blueprint/home/items.py: -------------------------------------------------------------------------------- 1 | import math 2 | import datetime 3 | 4 | from flask import render_template 5 | from flask import request 6 | from flask import jsonify 7 | from flask import session 8 | 9 | from app.blueprint import admin 10 | from app.blueprint import admin_required 11 | from app.lib.utils.tools import get_page 12 | from app.lib.utils.tools import get_uuid 13 | from app import mongo 14 | 15 | 16 | @admin.route("/items") 17 | @admin_required 18 | def items(): 19 | if request.method == "GET": 20 | 21 | p = request.args.get('p') 22 | show_status = 0 23 | if not p: 24 | p = 1 25 | else: 26 | p = int(p) 27 | if p > 1: 28 | show_status = 1 29 | 30 | limit_start = (p - 1) * 20 31 | coll = mongo.db.items 32 | result = coll.find({}).sort([("timestamp", -1)]).limit(20).skip(limit_start) 33 | '''总页数''' 34 | total = coll.find({}).count() 35 | page_total = int(math.ceil(total / 20)) 36 | page_list = get_page(page_total, p) 37 | 38 | datas = { 39 | 'data_list': result, 40 | 'p': p, 41 | 'page_total': page_total, 42 | 'show_status': show_status, 43 | 'page_list': page_list 44 | } 45 | 46 | return render_template('items/items_list.html', datas=datas) 47 | 48 | 49 | @admin.route("/items_add", methods=["GET"]) 50 | @admin_required 51 | def items_add(): 52 | if request.method == "GET": 53 | return render_template('items/items_add.html') 54 | 55 | 56 | @admin.route("/items_controllers", methods=["POST"]) 57 | @admin_required 58 | def items_controllers(): 59 | if request.method == "POST": 60 | item_name = request.form.get('project', None) 61 | action = request.form.get('action', None) 62 | 63 | if action == "add": 64 | item = mongo.db.items.find_one({'project': item_name}) 65 | 66 | if item != None: 67 | data = {"status": 403, "msg": "项目已存在"} 68 | return jsonify(data) 69 | 70 | item_id = get_uuid() 71 | item = {'project': item_name, 'create_date': datetime.datetime.now(), "id": item_id, 72 | "user": session.get("admin")} 73 | mongo.db.items.insert_one(item) 74 | 75 | data = {"status": 200, "msg": "项目添加成功"} 76 | return jsonify(data) 77 | 78 | if action == "delete": 79 | mongo.db.items.delete_one({'project': item_name}) 80 | mongo.db.tasks.delete_many({"parent_name": item_name}) 81 | mongo.db.ports.delete_many({"parent_name": item_name}) 82 | mongo.db.subdomains.delete_many({"parent_name": item_name}) 83 | mongo.db.vuls.delete_many({"parent_name": item_name}) 84 | mongo.db.dir_vuls.delete_many({"parent_name": item_name}) 85 | 86 | data = {"status": 200, "msg": "项目删除成功"} 87 | return jsonify(data) 88 | 89 | data = {"status": 403, "url_jump": "任务添加失败"} 90 | return jsonify(data) 91 | -------------------------------------------------------------------------------- /app/blueprint/home/logs.py: -------------------------------------------------------------------------------- 1 | import math 2 | import os 3 | 4 | from flask import render_template 5 | from flask import request 6 | from flask import jsonify 7 | 8 | from app.blueprint import admin 9 | from app.blueprint import admin_required 10 | from app.lib.utils.tools import get_page 11 | from app import mongo 12 | 13 | 14 | @admin.route("/logs") 15 | @admin_required 16 | def logs(): 17 | if request.method == "GET": 18 | 19 | p = request.args.get('p') 20 | show_status = 0 21 | if not p: 22 | p = 1 23 | else: 24 | p = int(p) 25 | if p > 1: 26 | show_status = 1 27 | 28 | limit_start = (p - 1) * 20 29 | coll = mongo.db.exports 30 | result = coll.find({}).sort([("timestamp", -1)]).limit(20).skip(limit_start) 31 | 32 | '''总页数''' 33 | total = coll.find({}).count() 34 | page_total = int(math.ceil(total / 20)) 35 | page_list = get_page(page_total, p) 36 | 37 | datas = { 38 | 'data_list': result, 39 | 'p': p, 40 | 'page_total': page_total, 41 | 'show_status': show_status, 42 | 'page_list': page_list 43 | } 44 | 45 | return render_template('logs.html', datas=datas) 46 | 47 | 48 | @admin.route("/logs_controllers", methods=["POST"]) 49 | @admin_required 50 | def logs_controllers(): 51 | if request.method == "POST": 52 | 53 | task_id = request.form.get('task_id', None) 54 | action = request.form.get('action', None) 55 | 56 | if action == "delete": 57 | file_object = mongo.db.exports.find_one({'id': task_id}) 58 | file_path = file_object["full_path"] 59 | 60 | if os.path.exists(file_path): 61 | os.unlink(file_path) 62 | mongo.db.exports.delete_one({'id': task_id}) 63 | 64 | data = {"status": 200, "msg": "日志删除成功"} 65 | return jsonify(data) 66 | 67 | if action == "export": 68 | 69 | if mongo.db.exports.find_one({'id': task_id})["status"] != "Finished": 70 | data = {"status": 403, "msg": "任务尚未完成"} 71 | return jsonify(data) 72 | 73 | file_object = mongo.db.exports.find_one({'id': task_id}) 74 | file_path = file_object["file_path"] 75 | 76 | data = {"status": 200, "file_url": file_path} 77 | return jsonify(data) 78 | -------------------------------------------------------------------------------- /app/blueprint/views/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ddosi/Voyager/a9c63235967b64c79b04af09f976ec35945b4f57/app/blueprint/views/__init__.py -------------------------------------------------------------------------------- /app/blueprint/views/dirs.py: -------------------------------------------------------------------------------- 1 | import math 2 | import datetime 3 | import ast 4 | import json 5 | 6 | from flask import render_template 7 | from flask import request 8 | from flask import jsonify 9 | from flask import session 10 | 11 | from app.blueprint import admin 12 | from app.blueprint import admin_required 13 | from app.lib.utils.tools import get_page 14 | from app.lib.utils.tools import get_uuid 15 | from app.lib.utils.tools import json_to_excel 16 | from app.lib.core.agent import Controller 17 | from app.lib.core.agent_dir import ControllerDirs 18 | from app.extensions import mongo 19 | 20 | 21 | @admin.route("/dir_lists", methods=["GET"]) 22 | @admin_required 23 | def dirs(): 24 | if request.method == "GET": 25 | 26 | p = request.args.get('p') 27 | show_status = 0 28 | if not p: 29 | p = 1 30 | else: 31 | p = int(p) 32 | if p > 1: 33 | show_status = 1 34 | 35 | limit_start = (p - 1) * 20 36 | coll = mongo.db.tasks 37 | result = coll.find({"hack_type": "目录扫描"}).sort([("create_date", -1)]).limit(20).skip(limit_start) 38 | '''总页数''' 39 | total = coll.find({}).count() 40 | page_total = int(math.ceil(total / 20)) 41 | page_list = get_page(page_total, p) 42 | 43 | datas = { 44 | 'data_list': result, 45 | 'p': p, 46 | 'page_total': page_total, 47 | 'show_status': show_status, 48 | 'page_list': page_list 49 | } 50 | 51 | return render_template("dirs/dirs_list.html", datas=datas) 52 | 53 | 54 | @admin.route("/dirs_add", methods=["GET", "POST"]) 55 | @admin_required 56 | def dirs_add(): 57 | if request.method == "GET": 58 | items = mongo.db.items.find({}) 59 | new_list = list() 60 | for i in items: 61 | new_list.append(i["project"]) 62 | return render_template('dirs/dirs_add.html', items=new_list) 63 | 64 | if request.method == "POST": 65 | 66 | project_all = list() 67 | tasks = mongo.db.tasks.find({'status': "Finished", "$or": [{"hack_type": "端口扫描"}, {"hack_type": "域名扫描"}]}) 68 | for i in tasks: 69 | 70 | if i['parent_name'] not in project_all: 71 | project_all.append(i['parent_name']) 72 | 73 | # 如果没有子域名扫描项目 74 | if len(project_all) == 0: 75 | result = {"status": 200, "list_info": project_all} 76 | return jsonify(result) 77 | 78 | result = {"status": 200, "list_info": project_all} 79 | return jsonify(result) 80 | 81 | 82 | @admin.route("/dirs_controllers", methods=["POST"]) 83 | @admin_required 84 | def dirs_controller(): 85 | if request.method == "POST": 86 | project = request.form.get('project', None) 87 | child_task_name = request.form.get('target_id', None) 88 | ip_address = request.form.get("ip_address", None) 89 | ext = request.form.get("ext", None) 90 | task_id = request.form.get('task_id', None) 91 | action = request.form.get('action', None) 92 | 93 | if action == "add": 94 | 95 | if len(ip_address) != 0: 96 | # 输入文本的方案 97 | 98 | # [{'http_address': 'http://192.168.3.2:8123', 'keydict': 'common.txt', 'parent_name': '测试项目', 'pid': '141aa854-a78c-42fe-bbf4-99b7d0be37aa'},] 99 | pid = get_uuid() 100 | target_list = list() 101 | 102 | for i in ip_address.split('\n'): 103 | 104 | if len(i) > 0: 105 | new_dict = dict() 106 | new_dict["http_address"] = i 107 | new_dict["keydict"] = ",".join(ast.literal_eval(ext)) 108 | new_dict["parent_name"] = project 109 | new_dict["pid"] = pid 110 | 111 | target_list.append(new_dict) 112 | 113 | task = {"id": pid, "create_date": datetime.datetime.now(), "parent_name": project, 114 | "target": json.dumps(target_list, ensure_ascii=False), "task_type": "即时任务", "hack_type": "目录扫描", 115 | "status": "Running", 116 | "progress": "0.00%", "contain_id": "Null", "end_time": "Null", 117 | "live_host": 0, "hidden_host": len(target_list), "total_host": "{}", 118 | "user": session.get("admin")} 119 | 120 | mongo.db.tasks.insert_one(task) 121 | 122 | ControllerDirs.thread_start(method="lilith", project=project, task_name="s1riu5", pid=pid) 123 | 124 | data = {"status": 200, "msg": "项目添加成功"} 125 | return jsonify(data) 126 | 127 | if child_task_name != None: 128 | task_id_new = get_uuid() 129 | task = {"id": task_id_new, "create_date": datetime.datetime.now(), "parent_name": project, 130 | "target": "Null", "task_type": "即时任务", "hack_type": "目录扫描", "status": "Running", 131 | "progress": "0.00%", "contain_id": "Null", "end_time": "Null", 132 | "live_host": 0, "hidden_host": 0, "total_host": "{}", "user": session.get("admin")} 133 | 134 | mongo.db.tasks.insert_one(task) 135 | 136 | ControllerDirs.thread_start(method="adam", project=project, task_name=child_task_name, pid=task_id_new) 137 | 138 | data = {"status": 200, "msg": "项目添加成功"} 139 | return jsonify(data) 140 | 141 | if action == "delete": 142 | task = mongo.db.tasks.find_one({'id': task_id}) 143 | if task["contain_id"] != "Null": 144 | Controller.stop_contain(task["contain_id"]) 145 | mongo.db.tasks.delete_one({'id': task_id}) 146 | mongo.db.vul_dirs.delete_many({'pid': task_id}) 147 | mongo.db.exports.delete_many({'pid': task_id}) 148 | 149 | data = {"status": 200, "msg": "项目删除成功"} 150 | return jsonify(data) 151 | 152 | if action == "export": 153 | if mongo.db.tasks.find_one({'id': task_id})["status"] != "Finished": 154 | result = {"status": 403, "msg": "任务还没有完成"} 155 | return jsonify(result) 156 | 157 | new_target = [] 158 | 159 | subdomains = mongo.db.dir_vuls.find( 160 | {'pid': task_id}) 161 | 162 | for i in subdomains: 163 | new_dict = dict() 164 | new_dict["父级项目"] = i["parent_name"] 165 | new_dict["地址"] = i["vul_path"] 166 | new_dict["状态"] = i["status_code"] 167 | new_dict["创建时间"] = i["create_date"] 168 | 169 | new_target.append(new_dict) 170 | 171 | if len(new_target) == 0: 172 | result = {"status": 403, "msg": "没有结果"} 173 | return jsonify(result) 174 | 175 | if mongo.db.exports.find_one({"pid": task_id}) != None: 176 | result = {"status": 403, "msg": "任务已存在,请前往导出页面查看"} 177 | return jsonify(result) 178 | 179 | else: 180 | 181 | # 得到即将下载文件的路径和名称 182 | path, full_path = json_to_excel(new_target) 183 | 184 | log = {"id": get_uuid(), "hack_type": "目录扫描", 185 | "parent_name": mongo.db.tasks.find_one({'id': task_id})["parent_name"], "file_path": path, 186 | "status": "Finished", "user": session.get("admin"), "create_date": datetime.datetime.now(), 187 | "full_path": full_path} 188 | 189 | mongo.db.exports.insert(log) 190 | 191 | result = {"status": 200, "file_url": path} 192 | return jsonify(result) 193 | 194 | data = {"status": 403, "msg": "操作失败"} 195 | return jsonify(data) 196 | -------------------------------------------------------------------------------- /app/blueprint/views/domains.py: -------------------------------------------------------------------------------- 1 | import math 2 | import datetime 3 | 4 | from flask import render_template 5 | from flask import request 6 | from flask import jsonify 7 | from flask import session 8 | 9 | from app.blueprint import admin 10 | from app.blueprint import admin_required 11 | from app.lib.utils.tools import get_page 12 | from app.lib.utils.tools import get_uuid 13 | from app.lib.utils.tools import json_to_excel 14 | from app.lib.core.agent import Controller 15 | from app.extensions import mongo 16 | 17 | 18 | @admin.route("/domian_lists", methods=["GET"]) 19 | @admin_required 20 | def domains(): 21 | if request.method == "GET": 22 | 23 | p = request.args.get('p') 24 | show_status = 0 25 | if not p: 26 | p = 1 27 | else: 28 | p = int(p) 29 | if p > 1: 30 | show_status = 1 31 | 32 | limit_start = (p - 1) * 20 33 | coll = mongo.db.tasks 34 | result = coll.find({"hack_type": "域名扫描"}).sort([("create_date", -1)]).limit(20).skip(limit_start) 35 | '''总页数''' 36 | total = coll.find({}).count() 37 | page_total = int(math.ceil(total / 20)) 38 | page_list = get_page(page_total, p) 39 | 40 | datas = { 41 | 'data_list': result, 42 | 'p': p, 43 | 'page_total': page_total, 44 | 'show_status': show_status, 45 | 'page_list': page_list 46 | } 47 | 48 | return render_template('domain/domians_list.html', datas=datas) 49 | 50 | 51 | @admin.route("/domian_add", methods=["GET"]) 52 | @admin_required 53 | def domains_add(): 54 | if request.method == "GET": 55 | items = mongo.db.items.find({}) 56 | new_list = list() 57 | for i in items: 58 | new_list.append(i["project"]) 59 | return render_template('domain/domains_add.html', items=new_list) 60 | 61 | 62 | @admin.route("/domains_controllers", methods=["POST"]) 63 | @admin_required 64 | def domains_controllers(): 65 | if request.method == "POST": 66 | domain_name = request.form.get('domain', None) 67 | project = request.form.get('project', None) 68 | task_id = request.form.get('task_id', None) 69 | action = request.form.get('action', None) 70 | 71 | if action == "add": 72 | if project == None or domain_name == None or len(project) == 0: 73 | result = {"status": 403, "msg": "值不能为空"} 74 | return jsonify(result) 75 | 76 | if mongo.db.tasks.find({'parent_name': project, "hack_type": "域名扫描"}).count() > 0: 77 | result = {"status": 403, "msg": "域名扫描项目已存在"} 78 | return jsonify(result) 79 | 80 | new_list = [ii for ii in domain_name.split("\n") if len(ii) > 0] 81 | 82 | target_name = ",".join(new_list) 83 | 84 | task_id = get_uuid() 85 | 86 | task = {"id": task_id, "create_date": datetime.datetime.now(), "parent_name": project, 87 | "target": target_name, "task_type": "即时任务", "hack_type": "域名扫描", "status": "Running", 88 | "progress": "0.00%", "contain_id": "Null", "end_time": "Null", 89 | "live_host": len(new_list), "hidden_host": "{}", "total_host": 0, 90 | "user": session.get("admin")} 91 | 92 | mongo.db.tasks.insert_one(task) 93 | 94 | Controller.subdomain_scan(task_id) 95 | 96 | data = {"status": 200, "msg": "项目添加成功"} 97 | return jsonify(data) 98 | 99 | if action == "delete": 100 | task = mongo.db.tasks.find_one({'id': task_id}) 101 | if task["contain_id"] != "Null": 102 | Controller.stop_contain(task["contain_id"]) 103 | 104 | mongo.db.tasks.delete_one({'id': task_id}) 105 | mongo.db.subdomains.delete_many({'pid': task_id}) 106 | mongo.db.exports.delete_many({'pid': task_id}) 107 | 108 | data = {"status": 200, "msg": "项目删除成功"} 109 | return jsonify(data) 110 | 111 | if action == "export": 112 | if mongo.db.tasks.find_one({'id': task_id})["status"] != "Finished": 113 | result = {"status": 403, "msg": "任务还没有完成"} 114 | return jsonify(result) 115 | 116 | new_target = [] 117 | 118 | subdomains = mongo.db.subdomains.find( 119 | {'parent_name': mongo.db.tasks.find_one({'id': task_id})["parent_name"]}) 120 | 121 | for i in subdomains: 122 | new_dict = dict() 123 | new_dict["父级项目"] = i["parent_name"] 124 | new_dict["域名"] = i["subdomain_name"] 125 | new_dict["时间"] = i["create_date"].strftime("%Y-%m-%d %H:%M:%S") 126 | new_dict["端口"] = i["port"] 127 | new_dict["IP地址"] = i["ips"] 128 | new_dict["标题"] = i["title"] 129 | new_dict["指纹"] = i["banner"] 130 | 131 | new_target.append(new_dict) 132 | 133 | if len(new_target) == 0: 134 | result = {"status": 403, "msg": "没有域名结果"} 135 | return jsonify(result) 136 | 137 | if mongo.db.exports.find_one({"pid": task_id}) != None: 138 | result = {"status": 403, "msg": "任务已存在,请前往导出页面查看"} 139 | return jsonify(result) 140 | 141 | else: 142 | 143 | # 得到即将下载文件的路径和名称 144 | path, full_path = json_to_excel(new_target) 145 | 146 | log = {"id": get_uuid(), "hack_type": "域名扫描", 147 | "parent_name": mongo.db.tasks.find_one({'id': task_id})["parent_name"], "file_path": path, 148 | "status": "Finished", "user": session.get("admin"), "create_date": datetime.datetime.now(), 149 | "full_path": full_path} 150 | 151 | mongo.db.exports.insert(log) 152 | 153 | result = {"status": 200, "file_url": path} 154 | return jsonify(result) 155 | 156 | data = {"status": 403, "msg": "操作失败"} 157 | return jsonify(data) 158 | -------------------------------------------------------------------------------- /app/blueprint/views/pocs.py: -------------------------------------------------------------------------------- 1 | import datetime 2 | import math 3 | 4 | from flask import request 5 | from flask import jsonify 6 | from flask import render_template 7 | from flask import session 8 | 9 | from app.extensions import mongo 10 | from app.blueprint import admin 11 | from app.blueprint import admin_required 12 | from app.lib.utils.tools import get_page 13 | 14 | from app.lib.core.agent import Controller 15 | from app.lib.core.agent_poc import ControllerPocs 16 | from app.lib.utils.tools import get_uuid 17 | from app.lib.utils.tools import json_to_excel 18 | 19 | 20 | # POC漏洞扫描的逻辑 21 | @admin.route("/poc_lists", methods=["GET"]) 22 | @admin_required 23 | def pocs(): 24 | if request.method == "GET": 25 | 26 | p = request.args.get('p') 27 | show_status = 0 28 | if not p: 29 | p = 1 30 | else: 31 | p = int(p) 32 | if p > 1: 33 | show_status = 1 34 | 35 | limit_start = (p - 1) * 20 36 | coll = mongo.db.tasks 37 | result = coll.find({"hack_type": "POC扫描"}).sort([("create_date", -1)]).limit(20).skip(limit_start) 38 | 39 | '''总页数''' 40 | total = coll.find({}).count() 41 | page_total = int(math.ceil(total / 20)) 42 | page_list = get_page(page_total, p) 43 | 44 | datas = { 45 | 'data_list': result, 46 | 'p': p, 47 | 'page_total': page_total, 48 | 'show_status': show_status, 49 | 'page_list': page_list 50 | } 51 | 52 | return render_template('pocs/pocs_list.html', datas=datas) 53 | 54 | 55 | @admin.route("/pocs_add", methods=["GET", "POST"]) 56 | @admin_required 57 | def pocs_add(): 58 | if request.method == "GET": 59 | items = mongo.db.items.find({}) 60 | new_list = list() 61 | for i in items: 62 | new_list.append(i["project"]) 63 | 64 | return render_template('pocs/pocs_add.html', items=new_list) 65 | 66 | if request.method == "POST": 67 | 68 | project_all = list() 69 | new_list = list() 70 | tasks = mongo.db.tasks.find( 71 | {'status': "Finished", "$or": [{"hack_type": "端口扫描"}, {"hack_type": "域名扫描"}, {"hack_type": "指纹识别"}]}) 72 | for i in tasks: 73 | if i['total_host'] > 0 and i['parent_name'] not in project_all: 74 | project_all.append(i['parent_name']) 75 | 76 | # 如果没有子域名扫描项目 77 | if len(project_all) == 0: 78 | result = {"status": 200, "list_info": new_list} 79 | return jsonify(result) 80 | 81 | for i in project_all: 82 | new_dict = dict() 83 | new_dict["project_name"] = i 84 | # new_dict["task_id"] = mongo.db.tasks.find_one({'parent_name': i, "hack_type": "端口扫描"})["id"] 85 | new_list.append(new_dict) 86 | 87 | result = {"status": 200, "list_info": new_list} 88 | return jsonify(result) 89 | 90 | 91 | @admin.route("/pocs_controllers", methods=["POST"]) 92 | @admin_required 93 | def pocs_controllers(): 94 | if request.method == "POST": 95 | 96 | action = request.form.get("action", None) 97 | project = request.form.get("project", None) 98 | target_name = request.form.get("target_name", None) 99 | task_id = request.form.get("task_id", None) 100 | 101 | if action == "add": 102 | if project == None or action == None or target_name == None: 103 | result = {"status": 403, "msg": "值不能为空"} 104 | return jsonify(result) 105 | 106 | uid = get_uuid() 107 | task = {"id": uid, "create_date": datetime.datetime.now(), "parent_name": project, 108 | "target": "Null", "task_type": "即时任务", "hack_type": "POC扫描", "status": "Running", 109 | "progress": "0.00%", "contain_id": "Null", "end_time": "Null", 110 | "live_host": 0, "hidden_host": 0, "total_host": 0, "user": session.get("admin")} 111 | 112 | mongo.db.tasks.insert_one(task) 113 | 114 | ControllerPocs.thread_start(target_name, project, uid) 115 | 116 | data = {"status": 200, "msg": "项目添加成功"} 117 | return jsonify(data) 118 | 119 | if action == "delete": 120 | 121 | task = mongo.db.tasks.find_one({'id': task_id}) 122 | 123 | if task == None: 124 | result = {"status": 403, "msg": "任务不存在"} 125 | return jsonify(result) 126 | 127 | if task["contain_id"] != "Null": 128 | Controller.stop_contain(task["contain_id"]) 129 | mongo.db.tasks.delete_one({'id': task_id}) 130 | mongo.db.pocs.delete_many({'pid': task_id}) 131 | mongo.db.vuldocker.delete_many({'pid': task_id}) 132 | mongo.db.vuls.delete_many({'pid': task_id}) 133 | 134 | result = {"status": 200, "msg": "任务删除成功"} 135 | return jsonify(result) 136 | 137 | if action == "export": 138 | if mongo.db.tasks.find_one({'id': task_id})["status"] != "Finished": 139 | result = {"status": 403, "msg": "任务还没有完成"} 140 | return jsonify(result) 141 | 142 | new_target = [] 143 | 144 | vuls = mongo.db.vuls.find({"pid": task_id}) 145 | 146 | for i in vuls: 147 | new_dict = dict() 148 | new_dict["父级项目"] = i["parent_name"] 149 | new_dict["时间"] = i["create_date"].strftime("%Y-%m-%d %H:%M:%S") 150 | new_dict["IP地址"] = i["ip_address"] 151 | new_dict["端口"] = i["port"] 152 | new_dict["漏洞信息"] = i["vul_info"] 153 | new_dict["漏洞名称"] = i["vul_name"] 154 | 155 | new_target.append(new_dict) 156 | 157 | if len(new_target) == 0: 158 | result = {"status": 403, "msg": "没有漏洞"} 159 | return jsonify(result) 160 | 161 | if mongo.db.exports.find_one({"pid": task_id}) != None: 162 | result = {"status": 403, "msg": "任务已存在,请前往导出页面查看"} 163 | return jsonify(result) 164 | 165 | else: 166 | 167 | # 得到即将下载文件的路径和名称 168 | path, full_path = json_to_excel(new_target) 169 | 170 | log = {"id": get_uuid(), "hack_type": "漏洞扫描", 171 | "parent_name": mongo.db.tasks.find_one({'id': task_id})["parent_name"], "file_path": path, 172 | "status": "Finished", "user": session.get("admin"), "create_date": datetime.datetime.now(), 173 | "full_path": full_path} 174 | 175 | mongo.db.exports.insert(log) 176 | 177 | result = {"status": 200, "file_url": path} 178 | return jsonify(result) 179 | 180 | data = {"status": 403, "msg": "操作失败"} 181 | return jsonify(data) 182 | -------------------------------------------------------------------------------- /app/config.py: -------------------------------------------------------------------------------- 1 | import docker 2 | import os 3 | 4 | BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) 5 | 6 | DOCKER_CLIENT = docker.from_env() 7 | 8 | # AWVS配置相关 9 | AWVS_API_KEY = "1986ad8c0a5b3df4d7028d5f3c06e936cb2bb5b2fe8454374af5bc8e350ec2da6" 10 | AWVS_HOST_ADDRESS = "https://127.0.0.1:13443/" 11 | 12 | 13 | # Flask配置文件 14 | class BaseConfig(object): 15 | MONGO_URI = "mongodb://root:shad0wBrok3r@127.0.0.1:27017/pioneer1?authSource=admin" 16 | SECRET_KEY = "NEVEW" 17 | 18 | 19 | class DevConfig(BaseConfig): 20 | DEBUG = True 21 | -------------------------------------------------------------------------------- /app/extensions.py: -------------------------------------------------------------------------------- 1 | from flask_pymongo import PyMongo 2 | from flask_wtf.csrf import CSRFProtect 3 | 4 | mongo = PyMongo() 5 | csrf = CSRFProtect() 6 | 7 | -------------------------------------------------------------------------------- /app/lib/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ddosi/Voyager/a9c63235967b64c79b04af09f976ec35945b4f57/app/lib/__init__.py -------------------------------------------------------------------------------- /app/lib/core/__init__.py: -------------------------------------------------------------------------------- 1 | from app.lib.thirdparty.wafcheck import waf_check 2 | from app import mongo 3 | 4 | import queue 5 | from multiprocessing.pool import Pool 6 | 7 | 8 | def formatnum(str): 9 | try: 10 | if str == "" or str == None: 11 | return 0 12 | str = str.replace("%", "") 13 | str = float(str) 14 | return str 15 | except: 16 | return 0 17 | 18 | 19 | 20 | 21 | def run_check(check_list, pid): 22 | queues = queue.Queue() 23 | 24 | pool = Pool(10) # 创建一个线程池,10个线程数 25 | 26 | for fn in check_list: 27 | 28 | if mongo.db.tasks.find_one({"id": pid}) == None: 29 | pool.terminate() 30 | pool.close() 31 | return False 32 | 33 | print(fn) 34 | 35 | pool.apply_async(waf_check, (fn, queues)) 36 | 37 | pool.close() # 关闭进程池,不再接受新的进程 38 | pool.join() # 主进程阻塞等待子进程的退出 39 | 40 | checkd_list = list(queues.queue) 41 | 42 | return checkd_list 43 | -------------------------------------------------------------------------------- /app/lib/core/agent.py: -------------------------------------------------------------------------------- 1 | from app.config import DOCKER_CLIENT 2 | from app.lib.handler.decorator import threaded 3 | from app.lib.core import formatnum 4 | from app import mongo 5 | 6 | import time 7 | import datetime 8 | import ast 9 | 10 | 11 | class Controller(object): 12 | """ 13 | 用来控制docker任务的核心函数 14 | """ 15 | 16 | @staticmethod 17 | @threaded 18 | def stop_contain(contain_id): 19 | """ 20 | 用来终止启动的容器 21 | :param contain_id:8462ccf520899aff47b7bdb6b8f0fa65cc43f24c214a26dd94f2d58425bd6799 22 | :return: 23 | """ 24 | 25 | try: 26 | 27 | if DOCKER_CLIENT.containers.get(contain_id).status == "running": 28 | docker_object = DOCKER_CLIENT.containers.get(contain_id) 29 | docker_object.stop() 30 | 31 | return True 32 | else: 33 | 34 | return True 35 | except: 36 | return False 37 | 38 | @staticmethod 39 | @threaded 40 | def subdomain_scan(uid): 41 | """ 42 | 添加域名扫描任务 43 | :param domain: example.com 44 | :param uid: c2385a01-bb0a-40a3-8694-05a31a440ba6 45 | :return: 46 | """ 47 | # 有任务在执行的时候先暂停 48 | while True: 49 | 50 | task = mongo.db.tasks.find_one({'id': uid}) 51 | 52 | if task is None: 53 | return True 54 | 55 | if mongo.db.tasks.find({'status': "Running"}).count() > 1: 56 | time.sleep(5) 57 | 58 | else: 59 | break 60 | 61 | contain = DOCKER_CLIENT.containers.run("ap0llo/oneforall:0.0.9", [uid], remove=True, detach=True, 62 | auto_remove=True, 63 | network="host") 64 | 65 | mongo.db.tasks.update_one({"id": uid}, {"$set": {"contain_id": contain.id}}) 66 | 67 | # 心跳线程用来更新任务状态 68 | while True: 69 | 70 | task_dir = mongo.db.tasks.find_one({"id": uid}) 71 | if task_dir is None: 72 | return True 73 | 74 | process_json = ast.literal_eval(task_dir["hidden_host"]) 75 | 76 | if len(process_json) == 0: 77 | time.sleep(10) 78 | 79 | tasks_num = task_dir["live_host"] 80 | 81 | now_progress = 0 82 | # 统计总任务进度 83 | for k, v in process_json.items(): 84 | progress_ = formatnum(v) 85 | now_progress = now_progress + progress_ 86 | 87 | progress = '{0:.2f}%'.format(now_progress / tasks_num) 88 | 89 | if progress == "100.00%": 90 | mongo.db.tasks.update_one( 91 | {"id": uid}, 92 | {'$set': { 93 | 'progress': "100.00%", 94 | 'status': 'Finished', 95 | 'end_time': datetime.datetime.now(), 96 | 'total_host': mongo.db.subdomains.find({'pid': uid}).count(), 97 | 98 | } 99 | } 100 | ) 101 | return True 102 | 103 | else: 104 | mongo.db.tasks.update_one( 105 | {"id": uid}, 106 | {'$set': { 107 | 'progress': progress 108 | 109 | } 110 | } 111 | ) 112 | 113 | time.sleep(3) 114 | 115 | @staticmethod 116 | @threaded 117 | def ports_scan(uid): 118 | """ 119 | 添加域名扫描任务 120 | :param domain: example.com 121 | :param uid: c2385a01-bb0a-40a3-8694-05a31a440ba6 122 | :return: 123 | """ 124 | 125 | # 有任务在执行的时候先暂停 126 | while True: 127 | 128 | task = mongo.db.tasks.find_one({'id': uid}) 129 | 130 | if task is None: 131 | return True 132 | 133 | if mongo.db.tasks.find({'status': "Running"}).count() > 1: 134 | time.sleep(5) 135 | 136 | else: 137 | break 138 | 139 | contain = DOCKER_CLIENT.containers.run("ap0llo/nmap:7.80", [uid], remove=True, detach=True, 140 | auto_remove=True, 141 | network="host") 142 | 143 | mongo.db.tasks.update_one({"id": uid}, {"$set": {"contain_id": contain.id}}) 144 | 145 | return True 146 | -------------------------------------------------------------------------------- /app/lib/core/datatype.py: -------------------------------------------------------------------------------- 1 | import copy 2 | import types 3 | 4 | 5 | class AttribDict(dict): 6 | """ 7 | This class defines the dictionary with added capability to access members as attributes 8 | 9 | >>> foo = AttribDict() 10 | >>> foo.bar = 1 11 | >>> foo.bar 12 | 1 13 | """ 14 | 15 | def __init__(self, indict=None, attribute=None): 16 | if indict is None: 17 | indict = {} 18 | 19 | # Set any attributes here - before initialisation 20 | # these remain as normal attributes 21 | self.attribute = attribute 22 | dict.__init__(self, indict) 23 | self.__initialised = True 24 | 25 | # After initialisation, setting attributes 26 | # is the same as setting an item 27 | 28 | def __len__(self): 29 | return len(self.items()) 30 | 31 | def __getattr__(self, item): 32 | """ 33 | Maps values to attributes 34 | Only called if there *is NOT* an attribute with this name 35 | """ 36 | 37 | try: 38 | return self.__getitem__(item) 39 | except KeyError: 40 | return None 41 | 42 | def __setattr__(self, item, value): 43 | """ 44 | Maps attributes to values 45 | Only if we are initialised 46 | """ 47 | 48 | # This test allows attributes to be set in the __init__ method 49 | if "_AttribDict__initialised" not in self.__dict__: 50 | return dict.__setattr__(self, item, value) 51 | 52 | # Any normal attributes are handled normally 53 | elif item in self.__dict__: 54 | dict.__setattr__(self, item, value) 55 | 56 | else: 57 | self.__setitem__(item, value) 58 | 59 | def __getstate__(self): 60 | return self.__dict__ 61 | 62 | def __setstate__(self, dict): 63 | self.__dict__ = dict 64 | 65 | def __deepcopy__(self, memo): 66 | retVal = self.__class__() 67 | memo[id(self)] = retVal 68 | 69 | for attr in dir(self): 70 | if not attr.startswith('_'): 71 | value = getattr(self, attr) 72 | if not isinstance(value, (types.BuiltinFunctionType, types.FunctionType, types.MethodType)): 73 | setattr(retVal, attr, copy.deepcopy(value, memo)) 74 | 75 | for key, value in self.items(): 76 | retVal.__setitem__(key, copy.deepcopy(value, memo)) 77 | 78 | return retVal 79 | -------------------------------------------------------------------------------- /app/lib/handler/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ddosi/Voyager/a9c63235967b64c79b04af09f976ec35945b4f57/app/lib/handler/__init__.py -------------------------------------------------------------------------------- /app/lib/handler/decorator.py: -------------------------------------------------------------------------------- 1 | import threading 2 | import datetime 3 | 4 | 5 | # 用来在线程中启动函数的装饰器 6 | def threaded(func): 7 | def wrapper(*args, **kwargs): 8 | thread = threading.Thread(target=func, args=args, kwargs=kwargs) 9 | thread.start() 10 | return thread 11 | 12 | return wrapper 13 | 14 | 15 | # 用来计算运行时间的装饰器 16 | def time_count(func): 17 | def wrapper(*args, **kwargs): 18 | start_time = datetime.datetime.now() 19 | result = func(*args, **kwargs) 20 | end_time = datetime.datetime.now() 21 | print(f"消耗时间{end_time - start_time}") 22 | 23 | return result 24 | 25 | return wrapper 26 | -------------------------------------------------------------------------------- /app/lib/thirdparty/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ddosi/Voyager/a9c63235967b64c79b04af09f976ec35945b4f57/app/lib/thirdparty/__init__.py -------------------------------------------------------------------------------- /app/lib/thirdparty/cmsfinger/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ddosi/Voyager/a9c63235967b64c79b04af09f976ec35945b4f57/app/lib/thirdparty/cmsfinger/__init__.py -------------------------------------------------------------------------------- /app/lib/thirdparty/wafcheck/__init__.py: -------------------------------------------------------------------------------- 1 | from app.lib.thirdparty.wafcheck.actions import Connect 2 | 3 | 4 | def waf_check(target, que): 5 | try: 6 | if "http_address" in target: 7 | 8 | info = Connect.queryPage(target["http_address"]) 9 | 10 | if info == "No": 11 | que.put(target) 12 | 13 | 14 | else: 15 | que.put(target) 16 | 17 | return True 18 | except: 19 | return False 20 | -------------------------------------------------------------------------------- /app/lib/thirdparty/wafcheck/actions.py: -------------------------------------------------------------------------------- 1 | from app.lib.utils.deps import findDynamicContent 2 | from app.lib.utils.deps import removeDynamicContent 3 | from app.lib.utils.deps import randomInt 4 | from app.lib.utils.deps import randomStr 5 | from app.lib.utils.deps import _comparison 6 | from app.lib.utils.deps import removeReflectiveValues 7 | from app.lib.thirdparty.wafcheck.config import IPS_WAF_CHECK_PAYLOAD 8 | from app.lib.thirdparty.wafcheck.config import HACKER_AGENT 9 | from app.lib.thirdparty.wafcheck.config import USER_AGENT 10 | 11 | import requests 12 | 13 | 14 | class Connect(): 15 | """ 16 | 该类是用来检测网站是否是WAF保护的 17 | """ 18 | 19 | @staticmethod 20 | def getPage(http_address, second=False): 21 | 22 | try: 23 | 24 | if second: 25 | UA = HACKER_AGENT 26 | else: 27 | UA = USER_AGENT 28 | 29 | burp0_url = http_address 30 | burp0_headers = { 31 | "User-Agent": UA, 32 | "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8", 33 | "Accept-Language": "zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2", 34 | "Accept-Encoding": "gzip, deflate", "Connection": "close", "Upgrade-Insecure-Requests": "1"} 35 | response = requests.get(burp0_url, headers=burp0_headers, timeout=(3, 5)) 36 | 37 | html = response.content.decode("utf-8") 38 | 39 | return html 40 | 41 | except: 42 | return False 43 | 44 | @staticmethod 45 | def queryPage(http_address): 46 | 47 | raw_url = f"{http_address}/?id={randomInt(2)}" 48 | first_page = Connect.getPage(raw_url) 49 | 50 | if first_page: 51 | 52 | payload = f"{randomInt(4)} {IPS_WAF_CHECK_PAYLOAD}" 53 | 54 | value = f"{raw_url}&{randomStr()}={payload}" 55 | 56 | second_page = Connect.getPage(value, second=True) 57 | 58 | if second_page: 59 | # 删除反射值 60 | value = removeReflectiveValues(second_page, payload) 61 | 62 | # 在正式对比前先排除一下动态数据的内容 63 | marks = findDynamicContent(first_page, second_page) 64 | response1 = removeDynamicContent(first_page, marks) 65 | response2 = removeDynamicContent(value, marks) 66 | 67 | _ratio = _comparison(response1, response2) 68 | if _ratio: 69 | return "No" 70 | else: 71 | return "Yes" 72 | 73 | 74 | else: 75 | return "Yes" 76 | 77 | else: 78 | return "Null" 79 | -------------------------------------------------------------------------------- /app/lib/thirdparty/wafcheck/config.py: -------------------------------------------------------------------------------- 1 | 2 | # 测试是否存在WAF的PAYLOAD 3 | IPS_WAF_CHECK_PAYLOAD = "AND 1=1 UNION ALL SELECT 1,NULL,'',table_name FROM information_schema.tables WHERE 2>1--/**/; EXEC xp_cmdshell('cat ../../../etc/passwd')#" 4 | 5 | IPS_WAF_CHECK_TIMEOUT = 3 6 | 7 | DYNAMICITY_BOUNDARY_LENGTH = 20 8 | 9 | # 网页对比度 高于0.95就任务两个页面正常 10 | UPPER_RATIO_BOUND = 0.95 11 | 12 | # 正常HTTP请求的user-agent 13 | USER_AGENT = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:71.0) Gecko/20100101 Firefox/71.0" 14 | 15 | # 黑客请求的user-agent 16 | HACKER_AGENT = "sqlmap/1.3.12.28#dev (http://sqlmap.org)" 17 | -------------------------------------------------------------------------------- /app/lib/utils/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ddosi/Voyager/a9c63235967b64c79b04af09f976ec35945b4f57/app/lib/utils/__init__.py -------------------------------------------------------------------------------- /app/lib/utils/data.py: -------------------------------------------------------------------------------- 1 | from app.lib.core.datatype import AttribDict 2 | 3 | conf = AttribDict({"THREADS": 10}) 4 | 5 | if __name__ == '__main__': 6 | task = {"id": "shadow", "pid": "pifd"} 7 | 8 | conf.finger = AttribDict(task) 9 | 10 | print(conf.finger.id) 11 | -------------------------------------------------------------------------------- /app/lib/utils/deps.py: -------------------------------------------------------------------------------- 1 | import random 2 | import string 3 | import re 4 | import difflib 5 | 6 | from difflib import SequenceMatcher 7 | 8 | from app.lib.thirdparty.wafcheck.config import DYNAMICITY_BOUNDARY_LENGTH 9 | from app.lib.thirdparty.wafcheck.config import UPPER_RATIO_BOUND 10 | 11 | 12 | def randomInt(length=4): 13 | """ 14 | Returns random integer value with provided number of digits 15 | 16 | >>> randomInt(6) 17 | 963638 18 | """ 19 | 20 | choice = random.choice 21 | 22 | return int("".join(choice(string.digits if _ != 0 else string.digits.replace('0', '')) for _ in range(0, length))) 23 | 24 | 25 | def randomStr(length=4, lowercase=False, alphabet=None): 26 | """ 27 | Returns random string value with provided number of characters 28 | 29 | >>> randomStr(6) 30 | 'FUPGpY' 31 | """ 32 | 33 | choice = random.choice 34 | 35 | if alphabet: 36 | retVal = "".join(choice(alphabet) for _ in range(0, length)) 37 | elif lowercase: 38 | retVal = "".join(choice(string.ascii_lowercase) for _ in range(0, length)) 39 | else: 40 | retVal = "".join(choice(string.ascii_letters) for _ in range(0, length)) 41 | 42 | return retVal 43 | 44 | 45 | def removeReflectiveValues(content, payload): 46 | """ 47 | 简单粗暴的消除返回文本中有请求参数的函数 48 | """ 49 | 50 | if payload in content: 51 | new_content = content.replace(payload) 52 | 53 | return new_content 54 | else: 55 | return content 56 | 57 | 58 | def trimAlphaNum(value): 59 | """ 60 | Trims alpha numeric characters from start and ending of a given value 61 | 62 | >>> trimAlphaNum('AND 1>(2+3)-- foobar') 63 | ' 1>(2+3)-- ' 64 | """ 65 | 66 | while value and value[-1].isalnum(): 67 | value = value[:-1] 68 | 69 | while value and value[0].isalnum(): 70 | value = value[1:] 71 | 72 | return value 73 | 74 | 75 | def findDynamicContent(firstPage, secondPage): 76 | """ 77 | This function checks if the provided pages have dynamic content. If they 78 | are dynamic, proper markings will be made 79 | 80 | >>> findDynamicContent("Lorem ipsum dolor sit amet, congue tation referrentur ei sed. Ne nec legimus habemus recusabo, natum reque et per. Facer tritani reprehendunt eos id, modus constituam est te. Usu sumo indoctum ad, pri paulo molestiae complectitur no.", "Lorem ipsum dolor sit amet, congue tation referrentur ei sed. Ne nec legimus habemus recusabo, natum reque et per. Facer tritani reprehendunt eos id, modus constituam est te. Usu sumo indoctum ad, pri paulo molestiae complectitur no.") 81 | >>> dynamicMarkings 82 | [('natum reque et per. ', 'Facer tritani repreh')] 83 | """ 84 | 85 | if not firstPage or not secondPage: 86 | return 87 | 88 | # infoMsg = "searching for dynamic content" 89 | # singleTimeLogMessage(infoMsg) 90 | 91 | blocks = list(SequenceMatcher(None, firstPage, secondPage).get_matching_blocks()) 92 | dynamicMarkings = [] 93 | 94 | # Removing too small matching blocks 95 | for block in blocks[:]: 96 | (_, _, length) = block 97 | 98 | if length <= 2 * DYNAMICITY_BOUNDARY_LENGTH: 99 | blocks.remove(block) 100 | 101 | # Making of dynamic markings based on prefix/suffix principle 102 | if len(blocks) > 0: 103 | blocks.insert(0, None) 104 | blocks.append(None) 105 | 106 | for i in range(len(blocks) - 1): 107 | prefix = firstPage[blocks[i][0]:blocks[i][0] + blocks[i][2]] if blocks[i] else None 108 | suffix = firstPage[blocks[i + 1][0]:blocks[i + 1][0] + blocks[i + 1][2]] if blocks[i + 1] else None 109 | 110 | if prefix is None and blocks[i + 1][0] == 0: 111 | continue 112 | 113 | if suffix is None and (blocks[i][0] + blocks[i][2] >= len(firstPage)): 114 | continue 115 | 116 | if prefix and suffix: 117 | prefix = prefix[-DYNAMICITY_BOUNDARY_LENGTH:] 118 | suffix = suffix[:DYNAMICITY_BOUNDARY_LENGTH] 119 | 120 | for _ in (firstPage, secondPage): 121 | match = re.search(r"(?s)%s(.+)%s" % (re.escape(prefix), re.escape(suffix)), _) 122 | if match: 123 | infix = match.group(1) 124 | if infix[0].isalnum(): 125 | prefix = trimAlphaNum(prefix) 126 | if infix[-1].isalnum(): 127 | suffix = trimAlphaNum(suffix) 128 | break 129 | 130 | dynamicMarkings.append((prefix if prefix else None, suffix if suffix else None)) 131 | 132 | return dynamicMarkings 133 | 134 | 135 | def removeDynamicContent(page, dynamicMarkings): 136 | """ 137 | Removing dynamic content from supplied page basing removal on 138 | precalculated dynamic markings 139 | """ 140 | 141 | if page: 142 | for item in dynamicMarkings: 143 | 144 | prefix, suffix = item 145 | 146 | if prefix is None and suffix is None: 147 | continue 148 | elif prefix is None: 149 | page = re.sub(r"(?s)^.+%s" % re.escape(suffix), suffix.replace('\\', r'\\'), page) 150 | elif suffix is None: 151 | page = re.sub(r"(?s)%s.+$" % re.escape(prefix), prefix.replace('\\', r'\\'), page) 152 | else: 153 | page = re.sub(r"(?s)%s.+%s" % (re.escape(prefix), re.escape(suffix)), 154 | "%s%s" % (prefix.replace('\\', r'\\'), suffix.replace('\\', r'\\')), page) 155 | 156 | return page 157 | 158 | 159 | def _comparison(first_page, second_page): 160 | seqMatcher = difflib.SequenceMatcher(None) 161 | 162 | seqMatcher.set_seq1(first_page) 163 | seqMatcher.set_seq2(second_page) 164 | 165 | ratio = round(seqMatcher.quick_ratio(), 3) 166 | 167 | if ratio < UPPER_RATIO_BOUND: 168 | return False 169 | 170 | else: 171 | return True 172 | -------------------------------------------------------------------------------- /app/static/css/404.css: -------------------------------------------------------------------------------- 1 | html, body { 2 | overflow: hidden; 3 | background: #000; 4 | padding: 0px; margin: 0px; 5 | width: 100%; height: 100%; 6 | } 7 | img { 8 | max-width: 100%; 9 | vertical-align: middle; 10 | border: 0; 11 | -ms-interpolation-mode: bicubic; 12 | } 13 | a { color: white; text-decoration: none; border-bottom: none; } 14 | a:hover { color: white; text-decoration: none; } 15 | h1 { 16 | background: -webkit-linear-gradient(#5f5287, #8b7cb9); 17 | font-family: "proxima nova","Roboto","helvetica",Arial,sans-serif; 18 | -webkit-background-clip: text; 19 | -webkit-text-fill-color: transparent; 20 | font-size: 34px; 21 | font-weight: bold; 22 | letter-spacing: -2px; 23 | line-height: 50px; 24 | } 25 | h2 { 26 | color: white; 27 | font-family: "proxima nova","Roboto","helvetica",Arial,sans-serif; 28 | font-size: 24px; 29 | font-weight: normal; 30 | .opacity(50); 31 | } 32 | h1 a,h2 a{color:#505358} 33 | .fullScreen { 34 | height: 100%; 35 | } 36 | a.logo { 37 | position: absolute; 38 | bottom: 50px; 39 | right: 50px; 40 | width: 250px; 41 | text-decoration: none; 42 | border-bottom: none; 43 | } 44 | img.rotating { 45 | position: absolute; 46 | left: 50%; 47 | top: 50%; 48 | margin-left: -256px; 49 | margin-top: -256px; 50 | 51 | -webkit-transition: opacity 2s ease-in; 52 | -moz-transition: opacity 2s ease-in; 53 | -o-transition: opacity 2s ease-in; 54 | -ms-transition: opacity 2s ease-in; 55 | transition: opacity 2s ease-in; 56 | } 57 | 58 | @-webkit-keyframes rotating { 59 | from{ 60 | -webkit-transform: rotate(0deg); 61 | } 62 | to{ 63 | -webkit-transform: rotate(360deg); 64 | } 65 | } 66 | 67 | @-moz-keyframes rotating { 68 | from{ 69 | -moz-transform: rotate(0deg); 70 | } 71 | to{ 72 | -moz-transform: rotate(360deg); 73 | } 74 | } 75 | 76 | @-o-keyframes rotating { 77 | from{ 78 | -o-transform: rotate(0deg); 79 | } 80 | to{ 81 | -o-transform: rotate(360deg); 82 | } 83 | } 84 | 85 | @-ms-keyframes rotating { 86 | from{ 87 | -ms-transform: rotate(0deg); 88 | } 89 | to{ 90 | -ms-transform: rotate(360deg); 91 | } 92 | } 93 | 94 | .rotating { 95 | -webkit-animation: rotating 120s linear infinite; 96 | -moz-animation: rotating 120s linear infinite; 97 | } 98 | 99 | div.pagenotfound-text { 100 | position: absolute; 101 | bottom: 50px; 102 | left: 50px; 103 | } -------------------------------------------------------------------------------- /app/static/css/font.css: -------------------------------------------------------------------------------- 1 | @font-face { 2 | font-family: 'iconfont'; 3 | src: url('../fonts/iconfont.eot'); 4 | src: url('../fonts/iconfont.eot?#iefix') format('embedded-opentype'), 5 | url('../fonts/iconfont.woff') format('woff'), 6 | url('../fonts/iconfont.ttf') format('truetype'), 7 | url('../fonts/iconfont.svg#iconfont') format('svg'); 8 | } 9 | .iconfont{ 10 | font-family:"iconfont" !important; 11 | font-size:16px;font-style:normal; 12 | -webkit-font-smoothing: antialiased; 13 | -webkit-text-stroke-width: 0.2px; 14 | -moz-osx-font-smoothing: grayscale; 15 | } 16 | 17 | -------------------------------------------------------------------------------- /app/static/css/login.css: -------------------------------------------------------------------------------- 1 | /* 2 | * @Author: xuebingsi 3 | * @Date: 2019-04-01 13:37:17 4 | * @Last Modified by: zhibinm 5 | * @Last Modified time: 2019-04-01 13:37:19 6 | */ 7 | .login-bg{ 8 | /*background: #eeeeee url() 0 0 no-repeat;*/ 9 | background:url(../images/bg.png) no-repeat center; 10 | background-size: cover; 11 | overflow: hidden; 12 | } 13 | .login{ 14 | margin: 120px auto 0 auto; 15 | min-height: 420px; 16 | max-width: 420px; 17 | padding: 40px; 18 | background-color: #ffffff; 19 | margin-left: auto; 20 | margin-right: auto; 21 | border-radius: 4px; 22 | /* overflow-x: hidden; */ 23 | box-sizing: border-box; 24 | } 25 | .login a.logo{ 26 | display: block; 27 | height: 58px; 28 | width: 167px; 29 | margin: 0 auto 30px auto; 30 | background-size: 167px 42px; 31 | } 32 | .login .message { 33 | margin: 10px 0 0 -58px; 34 | padding: 18px 10px 18px 60px; 35 | background: #189F92; 36 | position: relative; 37 | color: #fff; 38 | font-size: 16px; 39 | } 40 | .login #darkbannerwrap { 41 | background: url(../images/aiwrap.png); 42 | width: 18px; 43 | height: 10px; 44 | margin: 0 0 20px -58px; 45 | position: relative; 46 | } 47 | 48 | .login input[type=text], 49 | .login input[type=file], 50 | .login input[type=password], 51 | .login input[type=email], select { 52 | border: 1px solid #DCDEE0; 53 | vertical-align: middle; 54 | border-radius: 3px; 55 | height: 50px; 56 | padding: 0px 16px; 57 | font-size: 14px; 58 | color: #555555; 59 | outline:none; 60 | width:100%; 61 | box-sizing: border-box; 62 | } 63 | .login input[type=text]:focus, 64 | .login input[type=file]:focus, 65 | .login input[type=password]:focus, 66 | .login input[type=email]:focus, select:focus { 67 | border: 1px solid #27A9E3; 68 | } 69 | .login input[type=submit], 70 | .login input[type=button]{ 71 | display: inline-block; 72 | vertical-align: middle; 73 | padding: 12px 24px; 74 | margin: 0px; 75 | font-size: 18px; 76 | line-height: 24px; 77 | text-align: center; 78 | white-space: nowrap; 79 | vertical-align: middle; 80 | cursor: pointer; 81 | color: #ffffff; 82 | background-color: #189F92; 83 | border-radius: 3px; 84 | border: none; 85 | -webkit-appearance: none; 86 | outline:none; 87 | width:100%; 88 | } 89 | .login hr { 90 | background: #fff url() 0 0 no-repeat; 91 | } 92 | .login hr.hr15 { 93 | height: 15px; 94 | border: none; 95 | margin: 0px; 96 | padding: 0px; 97 | width: 100%; 98 | } 99 | .login hr.hr20 { 100 | height: 20px; 101 | border: none; 102 | margin: 0px; 103 | padding: 0px; 104 | width: 100%; 105 | } -------------------------------------------------------------------------------- /app/static/css/theme1.css: -------------------------------------------------------------------------------- 1 | body{ 2 | background:#F2F1F2; 3 | } 4 | .container{ 5 | background:#1A1B20; 6 | } 7 | .left-nav{ 8 | background:#1A1B20; 9 | } 10 | 11 | .left-nav a{ 12 | color:rgba(255,255,255,.7); 13 | } 14 | ..left-nav a.active{ 15 | background: #009688 !important; 16 | color: #fff; 17 | } 18 | .left-nav a:hover{ 19 | background: #009688 !important; 20 | color: #fff; 21 | } -------------------------------------------------------------------------------- /app/static/css/theme2.css: -------------------------------------------------------------------------------- 1 | body{ 2 | background:#EEF5F9; 3 | } 4 | .container{ 5 | background:#323640; 6 | } 7 | .left-nav{ 8 | background:#fff; 9 | } 10 | 11 | .left-nav a{ 12 | color:#686a76; 13 | } 14 | .left-nav a.active{ 15 | background: #786AED !important; 16 | color: #fff; 17 | } 18 | .left-nav a:hover{ 19 | background: #786AED !important; 20 | color: #fff; 21 | } 22 | -------------------------------------------------------------------------------- /app/static/css/theme3.css: -------------------------------------------------------------------------------- 1 | body{ 2 | background:#E8E8E8; 3 | } 4 | .container{ 5 | background:#F34743; 6 | } 7 | 8 | .left-nav{ 9 | background:#F4F4F4; 10 | } 11 | 12 | .left-nav a{ 13 | color:#686a76; 14 | } 15 | .left-nav a.active{ 16 | background: #FEFEFE !important; 17 | color: #F34743; 18 | } 19 | .left-nav a:hover{ 20 | background: #FEFEFE !important; 21 | color: #F34743; 22 | } -------------------------------------------------------------------------------- /app/static/css/theme4.css: -------------------------------------------------------------------------------- 1 | body{ 2 | background:#E4E4E4; 3 | } 4 | .container{ 5 | background:#019587; 6 | } 7 | .left-nav{ 8 | background:#263035; 9 | } 10 | 11 | .left-nav a{ 12 | color:#fff; 13 | } 14 | .left-nav a.active{ 15 | background: #212525 !important; 16 | color: #fff !important; 17 | } 18 | .left-nav a:hover{ 19 | background: #212525 !important; 20 | color: #fff !important; 21 | } -------------------------------------------------------------------------------- /app/static/css/theme5.css: -------------------------------------------------------------------------------- 1 | body{ 2 | background:#EEF5F9 !important; 3 | } 4 | .container{ 5 | background:linear-gradient(to left, #7b4397, #2196f3); 6 | } 7 | 8 | .left-nav{ 9 | background:#fff !important; 10 | } 11 | 12 | .left-nav a{ 13 | color:#686a76 !important; 14 | } 15 | .left-nav a.active{ 16 | background: linear-gradient(to left, #7c8ce4, #2196f3) !important; 17 | color: #fff !important; 18 | border-color: #7b4397 !important; 19 | } 20 | .left-nav a:hover{ 21 | background: linear-gradient(to left, #7c8ce4, #2196f3) !important; 22 | color: #fff !important; 23 | border-color: #7b4397 !important; 24 | } 25 | .container .logo a{ 26 | background: rgba(0,0,0,0) !important; 27 | } -------------------------------------------------------------------------------- /app/static/downloads/6bf9bc68-5162-463d-a3b2-3b1300a9389b.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ddosi/Voyager/a9c63235967b64c79b04af09f976ec35945b4f57/app/static/downloads/6bf9bc68-5162-463d-a3b2-3b1300a9389b.xlsx -------------------------------------------------------------------------------- /app/static/fonts/iconfont.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ddosi/Voyager/a9c63235967b64c79b04af09f976ec35945b4f57/app/static/fonts/iconfont.eot -------------------------------------------------------------------------------- /app/static/fonts/iconfont.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ddosi/Voyager/a9c63235967b64c79b04af09f976ec35945b4f57/app/static/fonts/iconfont.ttf -------------------------------------------------------------------------------- /app/static/fonts/iconfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ddosi/Voyager/a9c63235967b64c79b04af09f976ec35945b4f57/app/static/fonts/iconfont.woff -------------------------------------------------------------------------------- /app/static/images/aiwrap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ddosi/Voyager/a9c63235967b64c79b04af09f976ec35945b4f57/app/static/images/aiwrap.png -------------------------------------------------------------------------------- /app/static/images/bg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ddosi/Voyager/a9c63235967b64c79b04af09f976ec35945b4f57/app/static/images/bg.png -------------------------------------------------------------------------------- /app/static/lib/layui/css/modules/code.css: -------------------------------------------------------------------------------- 1 | /** layui-v2.4.5 MIT License By https://www.layui.com */ 2 | html #layuicss-skincodecss{display:none;position:absolute;width:1989px}.layui-code-h3,.layui-code-view{position:relative;font-size:12px}.layui-code-view{display:block;margin:10px 0;padding:0;border:1px solid #e2e2e2;border-left-width:6px;background-color:#F2F2F2;color:#333;font-family:Courier New}.layui-code-h3{padding:0 10px;height:32px;line-height:32px;border-bottom:1px solid #e2e2e2}.layui-code-h3 a{position:absolute;right:10px;top:0;color:#999}.layui-code-view .layui-code-ol{position:relative;overflow:auto}.layui-code-view .layui-code-ol li{position:relative;margin-left:45px;line-height:20px;padding:0 5px;border-left:1px solid #e2e2e2;list-style-type:decimal-leading-zero;*list-style-type:decimal;background-color:#fff}.layui-code-view pre{margin:0}.layui-code-notepad{border:1px solid #0C0C0C;border-left-color:#3F3F3F;background-color:#0C0C0C;color:#C2BE9E}.layui-code-notepad .layui-code-h3{border-bottom:none}.layui-code-notepad .layui-code-ol li{background-color:#3F3F3F;border-left:none} -------------------------------------------------------------------------------- /app/static/lib/layui/css/modules/laydate/default/laydate.css: -------------------------------------------------------------------------------- 1 | /** layui-v2.4.5 MIT License By https://www.layui.com */ 2 | .laydate-set-ym,.layui-laydate,.layui-laydate *,.layui-laydate-list{box-sizing:border-box}html #layuicss-laydate{display:none;position:absolute;width:1989px}.layui-laydate *{margin:0;padding:0}.layui-laydate{position:absolute;z-index:66666666;margin:5px 0;border-radius:2px;font-size:14px;-webkit-animation-duration:.3s;animation-duration:.3s;-webkit-animation-fill-mode:both;animation-fill-mode:both;-webkit-animation-name:laydate-upbit;animation-name:laydate-upbit}.layui-laydate-main{width:272px}.layui-laydate-content td,.layui-laydate-header *,.layui-laydate-list li{transition-duration:.3s;-webkit-transition-duration:.3s}@-webkit-keyframes laydate-upbit{from{-webkit-transform:translate3d(0,20px,0);opacity:.3}to{-webkit-transform:translate3d(0,0,0);opacity:1}}@keyframes laydate-upbit{from{transform:translate3d(0,20px,0);opacity:.3}to{transform:translate3d(0,0,0);opacity:1}}.layui-laydate-static{position:relative;z-index:0;display:inline-block;margin:0;-webkit-animation:none;animation:none}.laydate-ym-show .laydate-next-m,.laydate-ym-show .laydate-prev-m{display:none!important}.laydate-ym-show .laydate-next-y,.laydate-ym-show .laydate-prev-y{display:inline-block!important}.laydate-time-show .laydate-set-ym span[lay-type=month],.laydate-time-show .laydate-set-ym span[lay-type=year],.laydate-time-show .layui-laydate-header .layui-icon,.laydate-ym-show .laydate-set-ym span[lay-type=month]{display:none!important}.layui-laydate-header{position:relative;line-height:30px;padding:10px 70px 5px}.laydate-set-ym span,.layui-laydate-header i{padding:0 5px;cursor:pointer}.layui-laydate-header *{display:inline-block;vertical-align:bottom}.layui-laydate-header i{position:absolute;top:10px;color:#999;font-size:18px}.layui-laydate-header i.laydate-prev-y{left:15px}.layui-laydate-header i.laydate-prev-m{left:45px}.layui-laydate-header i.laydate-next-y{right:15px}.layui-laydate-header i.laydate-next-m{right:45px}.laydate-set-ym{width:100%;text-align:center;text-overflow:ellipsis;overflow:hidden;white-space:nowrap}.laydate-time-text{cursor:default!important}.layui-laydate-content{position:relative;padding:10px;-moz-user-select:none;-webkit-user-select:none;-ms-user-select:none}.layui-laydate-content table{border-collapse:collapse;border-spacing:0}.layui-laydate-content td,.layui-laydate-content th{width:36px;height:30px;padding:5px;text-align:center}.layui-laydate-content td{position:relative;cursor:pointer}.laydate-day-mark{position:absolute;left:0;top:0;width:100%;height:100%;line-height:30px;font-size:12px;overflow:hidden}.laydate-day-mark::after{position:absolute;content:'';right:2px;top:2px;width:5px;height:5px;border-radius:50%}.layui-laydate-footer{position:relative;height:46px;line-height:26px;padding:10px 20px}.layui-laydate-footer span{margin-right:15px;display:inline-block;cursor:pointer;font-size:12px}.layui-laydate-footer span:hover{color:#5FB878}.laydate-footer-btns{position:absolute;right:10px;top:10px}.laydate-footer-btns span{height:26px;line-height:26px;margin:0 0 0 -1px;padding:0 10px;border:1px solid #C9C9C9;background-color:#fff;white-space:nowrap;vertical-align:top;border-radius:2px}.layui-laydate-list>li,.layui-laydate-range .layui-laydate-main{display:inline-block;vertical-align:middle}.layui-laydate-list{position:absolute;left:0;top:0;width:100%;height:100%;padding:10px;background-color:#fff}.layui-laydate-list>li{position:relative;width:33.3%;height:36px;line-height:36px;margin:3px 0;text-align:center;cursor:pointer}.laydate-month-list>li{width:25%;margin:17px 0}.laydate-time-list>li{height:100%;margin:0;line-height:normal;cursor:default}.laydate-time-list p{position:relative;top:-4px;line-height:29px}.laydate-time-list ol{height:181px;overflow:hidden}.laydate-time-list>li:hover ol{overflow-y:auto}.laydate-time-list ol li{width:130%;padding-left:33px;line-height:30px;text-align:left;cursor:pointer}.layui-laydate-hint{position:absolute;top:115px;left:50%;width:250px;margin-left:-125px;line-height:20px;padding:15px;text-align:center;font-size:12px}.layui-laydate-range{width:546px}.layui-laydate-range .laydate-main-list-0 .laydate-next-m,.layui-laydate-range .laydate-main-list-0 .laydate-next-y,.layui-laydate-range .laydate-main-list-1 .laydate-prev-m,.layui-laydate-range .laydate-main-list-1 .laydate-prev-y{display:none}.layui-laydate-range .laydate-main-list-1 .layui-laydate-content{border-left:1px solid #e2e2e2}.layui-laydate,.layui-laydate-hint{border:1px solid #d2d2d2;box-shadow:0 2px 4px rgba(0,0,0,.12);background-color:#fff;color:#666}.layui-laydate-header{border-bottom:1px solid #e2e2e2}.layui-laydate-header i:hover,.layui-laydate-header span:hover{color:#5FB878}.layui-laydate-content{border-top:none 0;border-bottom:none 0}.layui-laydate-content th{font-weight:400;color:#333}.layui-laydate-content td{color:#666}.layui-laydate-content td.laydate-selected{background-color:#00F7DE}.laydate-selected:hover{background-color:#00F7DE!important}.layui-laydate-content td:hover,.layui-laydate-list li:hover{background-color:#eaeaea;color:#333}.laydate-time-list li ol{margin:0;padding:0;border:1px solid #e2e2e2;border-left-width:0}.laydate-time-list li:first-child ol{border-left-width:1px}.laydate-time-list>li:hover{background:0 0}.layui-laydate-content .laydate-day-next,.layui-laydate-content .laydate-day-prev{color:#d2d2d2}.laydate-selected.laydate-day-next,.laydate-selected.laydate-day-prev{background-color:#f8f8f8!important}.layui-laydate-footer{border-top:1px solid #e2e2e2}.layui-laydate-hint{color:#FF5722}.laydate-day-mark::after{background-color:#5FB878}.layui-laydate-content td.layui-this .laydate-day-mark::after{display:none}.layui-laydate-footer span[lay-type=date]{color:#5FB878}.layui-laydate .layui-this{background-color:#009688!important;color:#fff!important}.layui-laydate .laydate-disabled,.layui-laydate .laydate-disabled:hover{background:0 0!important;color:#d2d2d2!important;cursor:not-allowed!important;-moz-user-select:none;-webkit-user-select:none;-ms-user-select:none}.laydate-theme-molv{border:none}.laydate-theme-molv.layui-laydate-range{width:548px}.laydate-theme-molv .layui-laydate-main{width:274px}.laydate-theme-molv .layui-laydate-header{border:none;background-color:#009688}.laydate-theme-molv .layui-laydate-header i,.laydate-theme-molv .layui-laydate-header span{color:#f6f6f6}.laydate-theme-molv .layui-laydate-header i:hover,.laydate-theme-molv .layui-laydate-header span:hover{color:#fff}.laydate-theme-molv .layui-laydate-content{border:1px solid #e2e2e2;border-top:none;border-bottom:none}.laydate-theme-molv .laydate-main-list-1 .layui-laydate-content{border-left:none}.laydate-theme-grid .laydate-month-list>li,.laydate-theme-grid .laydate-year-list>li,.laydate-theme-grid .layui-laydate-content td,.laydate-theme-grid .layui-laydate-content thead,.laydate-theme-molv .layui-laydate-footer{border:1px solid #e2e2e2}.laydate-theme-grid .laydate-selected,.laydate-theme-grid .laydate-selected:hover{background-color:#f2f2f2!important;color:#009688!important}.laydate-theme-grid .laydate-selected.laydate-day-next,.laydate-theme-grid .laydate-selected.laydate-day-prev{color:#d2d2d2!important}.laydate-theme-grid .laydate-month-list,.laydate-theme-grid .laydate-year-list{margin:1px 0 0 1px}.laydate-theme-grid .laydate-month-list>li,.laydate-theme-grid .laydate-year-list>li{margin:0 -1px -1px 0}.laydate-theme-grid .laydate-year-list>li{height:43px;line-height:43px}.laydate-theme-grid .laydate-month-list>li{height:71px;line-height:71px} -------------------------------------------------------------------------------- /app/static/lib/layui/css/modules/layer/default/icon-ext.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ddosi/Voyager/a9c63235967b64c79b04af09f976ec35945b4f57/app/static/lib/layui/css/modules/layer/default/icon-ext.png -------------------------------------------------------------------------------- /app/static/lib/layui/css/modules/layer/default/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ddosi/Voyager/a9c63235967b64c79b04af09f976ec35945b4f57/app/static/lib/layui/css/modules/layer/default/icon.png -------------------------------------------------------------------------------- /app/static/lib/layui/css/modules/layer/default/loading-0.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ddosi/Voyager/a9c63235967b64c79b04af09f976ec35945b4f57/app/static/lib/layui/css/modules/layer/default/loading-0.gif -------------------------------------------------------------------------------- /app/static/lib/layui/css/modules/layer/default/loading-1.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ddosi/Voyager/a9c63235967b64c79b04af09f976ec35945b4f57/app/static/lib/layui/css/modules/layer/default/loading-1.gif -------------------------------------------------------------------------------- /app/static/lib/layui/css/modules/layer/default/loading-2.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ddosi/Voyager/a9c63235967b64c79b04af09f976ec35945b4f57/app/static/lib/layui/css/modules/layer/default/loading-2.gif -------------------------------------------------------------------------------- /app/static/lib/layui/font/iconfont.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ddosi/Voyager/a9c63235967b64c79b04af09f976ec35945b4f57/app/static/lib/layui/font/iconfont.eot -------------------------------------------------------------------------------- /app/static/lib/layui/font/iconfont.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ddosi/Voyager/a9c63235967b64c79b04af09f976ec35945b4f57/app/static/lib/layui/font/iconfont.ttf -------------------------------------------------------------------------------- /app/static/lib/layui/font/iconfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ddosi/Voyager/a9c63235967b64c79b04af09f976ec35945b4f57/app/static/lib/layui/font/iconfont.woff -------------------------------------------------------------------------------- /app/static/lib/layui/images/face/0.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ddosi/Voyager/a9c63235967b64c79b04af09f976ec35945b4f57/app/static/lib/layui/images/face/0.gif -------------------------------------------------------------------------------- /app/static/lib/layui/images/face/1.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ddosi/Voyager/a9c63235967b64c79b04af09f976ec35945b4f57/app/static/lib/layui/images/face/1.gif -------------------------------------------------------------------------------- /app/static/lib/layui/images/face/10.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ddosi/Voyager/a9c63235967b64c79b04af09f976ec35945b4f57/app/static/lib/layui/images/face/10.gif -------------------------------------------------------------------------------- /app/static/lib/layui/images/face/11.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ddosi/Voyager/a9c63235967b64c79b04af09f976ec35945b4f57/app/static/lib/layui/images/face/11.gif -------------------------------------------------------------------------------- /app/static/lib/layui/images/face/12.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ddosi/Voyager/a9c63235967b64c79b04af09f976ec35945b4f57/app/static/lib/layui/images/face/12.gif -------------------------------------------------------------------------------- /app/static/lib/layui/images/face/13.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ddosi/Voyager/a9c63235967b64c79b04af09f976ec35945b4f57/app/static/lib/layui/images/face/13.gif -------------------------------------------------------------------------------- /app/static/lib/layui/images/face/14.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ddosi/Voyager/a9c63235967b64c79b04af09f976ec35945b4f57/app/static/lib/layui/images/face/14.gif -------------------------------------------------------------------------------- /app/static/lib/layui/images/face/15.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ddosi/Voyager/a9c63235967b64c79b04af09f976ec35945b4f57/app/static/lib/layui/images/face/15.gif -------------------------------------------------------------------------------- /app/static/lib/layui/images/face/16.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ddosi/Voyager/a9c63235967b64c79b04af09f976ec35945b4f57/app/static/lib/layui/images/face/16.gif -------------------------------------------------------------------------------- /app/static/lib/layui/images/face/17.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ddosi/Voyager/a9c63235967b64c79b04af09f976ec35945b4f57/app/static/lib/layui/images/face/17.gif -------------------------------------------------------------------------------- /app/static/lib/layui/images/face/18.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ddosi/Voyager/a9c63235967b64c79b04af09f976ec35945b4f57/app/static/lib/layui/images/face/18.gif -------------------------------------------------------------------------------- /app/static/lib/layui/images/face/19.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ddosi/Voyager/a9c63235967b64c79b04af09f976ec35945b4f57/app/static/lib/layui/images/face/19.gif -------------------------------------------------------------------------------- /app/static/lib/layui/images/face/2.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ddosi/Voyager/a9c63235967b64c79b04af09f976ec35945b4f57/app/static/lib/layui/images/face/2.gif -------------------------------------------------------------------------------- /app/static/lib/layui/images/face/20.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ddosi/Voyager/a9c63235967b64c79b04af09f976ec35945b4f57/app/static/lib/layui/images/face/20.gif -------------------------------------------------------------------------------- /app/static/lib/layui/images/face/21.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ddosi/Voyager/a9c63235967b64c79b04af09f976ec35945b4f57/app/static/lib/layui/images/face/21.gif -------------------------------------------------------------------------------- /app/static/lib/layui/images/face/22.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ddosi/Voyager/a9c63235967b64c79b04af09f976ec35945b4f57/app/static/lib/layui/images/face/22.gif -------------------------------------------------------------------------------- /app/static/lib/layui/images/face/23.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ddosi/Voyager/a9c63235967b64c79b04af09f976ec35945b4f57/app/static/lib/layui/images/face/23.gif -------------------------------------------------------------------------------- /app/static/lib/layui/images/face/24.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ddosi/Voyager/a9c63235967b64c79b04af09f976ec35945b4f57/app/static/lib/layui/images/face/24.gif -------------------------------------------------------------------------------- /app/static/lib/layui/images/face/25.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ddosi/Voyager/a9c63235967b64c79b04af09f976ec35945b4f57/app/static/lib/layui/images/face/25.gif -------------------------------------------------------------------------------- /app/static/lib/layui/images/face/26.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ddosi/Voyager/a9c63235967b64c79b04af09f976ec35945b4f57/app/static/lib/layui/images/face/26.gif -------------------------------------------------------------------------------- /app/static/lib/layui/images/face/27.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ddosi/Voyager/a9c63235967b64c79b04af09f976ec35945b4f57/app/static/lib/layui/images/face/27.gif -------------------------------------------------------------------------------- /app/static/lib/layui/images/face/28.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ddosi/Voyager/a9c63235967b64c79b04af09f976ec35945b4f57/app/static/lib/layui/images/face/28.gif -------------------------------------------------------------------------------- /app/static/lib/layui/images/face/29.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ddosi/Voyager/a9c63235967b64c79b04af09f976ec35945b4f57/app/static/lib/layui/images/face/29.gif -------------------------------------------------------------------------------- /app/static/lib/layui/images/face/3.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ddosi/Voyager/a9c63235967b64c79b04af09f976ec35945b4f57/app/static/lib/layui/images/face/3.gif -------------------------------------------------------------------------------- /app/static/lib/layui/images/face/30.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ddosi/Voyager/a9c63235967b64c79b04af09f976ec35945b4f57/app/static/lib/layui/images/face/30.gif -------------------------------------------------------------------------------- /app/static/lib/layui/images/face/31.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ddosi/Voyager/a9c63235967b64c79b04af09f976ec35945b4f57/app/static/lib/layui/images/face/31.gif -------------------------------------------------------------------------------- /app/static/lib/layui/images/face/32.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ddosi/Voyager/a9c63235967b64c79b04af09f976ec35945b4f57/app/static/lib/layui/images/face/32.gif -------------------------------------------------------------------------------- /app/static/lib/layui/images/face/33.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ddosi/Voyager/a9c63235967b64c79b04af09f976ec35945b4f57/app/static/lib/layui/images/face/33.gif -------------------------------------------------------------------------------- /app/static/lib/layui/images/face/34.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ddosi/Voyager/a9c63235967b64c79b04af09f976ec35945b4f57/app/static/lib/layui/images/face/34.gif -------------------------------------------------------------------------------- /app/static/lib/layui/images/face/35.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ddosi/Voyager/a9c63235967b64c79b04af09f976ec35945b4f57/app/static/lib/layui/images/face/35.gif -------------------------------------------------------------------------------- /app/static/lib/layui/images/face/36.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ddosi/Voyager/a9c63235967b64c79b04af09f976ec35945b4f57/app/static/lib/layui/images/face/36.gif -------------------------------------------------------------------------------- /app/static/lib/layui/images/face/37.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ddosi/Voyager/a9c63235967b64c79b04af09f976ec35945b4f57/app/static/lib/layui/images/face/37.gif -------------------------------------------------------------------------------- /app/static/lib/layui/images/face/38.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ddosi/Voyager/a9c63235967b64c79b04af09f976ec35945b4f57/app/static/lib/layui/images/face/38.gif -------------------------------------------------------------------------------- /app/static/lib/layui/images/face/39.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ddosi/Voyager/a9c63235967b64c79b04af09f976ec35945b4f57/app/static/lib/layui/images/face/39.gif -------------------------------------------------------------------------------- /app/static/lib/layui/images/face/4.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ddosi/Voyager/a9c63235967b64c79b04af09f976ec35945b4f57/app/static/lib/layui/images/face/4.gif -------------------------------------------------------------------------------- /app/static/lib/layui/images/face/40.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ddosi/Voyager/a9c63235967b64c79b04af09f976ec35945b4f57/app/static/lib/layui/images/face/40.gif -------------------------------------------------------------------------------- /app/static/lib/layui/images/face/41.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ddosi/Voyager/a9c63235967b64c79b04af09f976ec35945b4f57/app/static/lib/layui/images/face/41.gif -------------------------------------------------------------------------------- /app/static/lib/layui/images/face/42.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ddosi/Voyager/a9c63235967b64c79b04af09f976ec35945b4f57/app/static/lib/layui/images/face/42.gif -------------------------------------------------------------------------------- /app/static/lib/layui/images/face/43.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ddosi/Voyager/a9c63235967b64c79b04af09f976ec35945b4f57/app/static/lib/layui/images/face/43.gif -------------------------------------------------------------------------------- /app/static/lib/layui/images/face/44.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ddosi/Voyager/a9c63235967b64c79b04af09f976ec35945b4f57/app/static/lib/layui/images/face/44.gif -------------------------------------------------------------------------------- /app/static/lib/layui/images/face/45.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ddosi/Voyager/a9c63235967b64c79b04af09f976ec35945b4f57/app/static/lib/layui/images/face/45.gif -------------------------------------------------------------------------------- /app/static/lib/layui/images/face/46.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ddosi/Voyager/a9c63235967b64c79b04af09f976ec35945b4f57/app/static/lib/layui/images/face/46.gif -------------------------------------------------------------------------------- /app/static/lib/layui/images/face/47.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ddosi/Voyager/a9c63235967b64c79b04af09f976ec35945b4f57/app/static/lib/layui/images/face/47.gif -------------------------------------------------------------------------------- /app/static/lib/layui/images/face/48.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ddosi/Voyager/a9c63235967b64c79b04af09f976ec35945b4f57/app/static/lib/layui/images/face/48.gif -------------------------------------------------------------------------------- /app/static/lib/layui/images/face/49.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ddosi/Voyager/a9c63235967b64c79b04af09f976ec35945b4f57/app/static/lib/layui/images/face/49.gif -------------------------------------------------------------------------------- /app/static/lib/layui/images/face/5.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ddosi/Voyager/a9c63235967b64c79b04af09f976ec35945b4f57/app/static/lib/layui/images/face/5.gif -------------------------------------------------------------------------------- /app/static/lib/layui/images/face/50.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ddosi/Voyager/a9c63235967b64c79b04af09f976ec35945b4f57/app/static/lib/layui/images/face/50.gif -------------------------------------------------------------------------------- /app/static/lib/layui/images/face/51.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ddosi/Voyager/a9c63235967b64c79b04af09f976ec35945b4f57/app/static/lib/layui/images/face/51.gif -------------------------------------------------------------------------------- /app/static/lib/layui/images/face/52.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ddosi/Voyager/a9c63235967b64c79b04af09f976ec35945b4f57/app/static/lib/layui/images/face/52.gif -------------------------------------------------------------------------------- /app/static/lib/layui/images/face/53.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ddosi/Voyager/a9c63235967b64c79b04af09f976ec35945b4f57/app/static/lib/layui/images/face/53.gif -------------------------------------------------------------------------------- /app/static/lib/layui/images/face/54.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ddosi/Voyager/a9c63235967b64c79b04af09f976ec35945b4f57/app/static/lib/layui/images/face/54.gif -------------------------------------------------------------------------------- /app/static/lib/layui/images/face/55.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ddosi/Voyager/a9c63235967b64c79b04af09f976ec35945b4f57/app/static/lib/layui/images/face/55.gif -------------------------------------------------------------------------------- /app/static/lib/layui/images/face/56.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ddosi/Voyager/a9c63235967b64c79b04af09f976ec35945b4f57/app/static/lib/layui/images/face/56.gif -------------------------------------------------------------------------------- /app/static/lib/layui/images/face/57.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ddosi/Voyager/a9c63235967b64c79b04af09f976ec35945b4f57/app/static/lib/layui/images/face/57.gif -------------------------------------------------------------------------------- /app/static/lib/layui/images/face/58.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ddosi/Voyager/a9c63235967b64c79b04af09f976ec35945b4f57/app/static/lib/layui/images/face/58.gif -------------------------------------------------------------------------------- /app/static/lib/layui/images/face/59.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ddosi/Voyager/a9c63235967b64c79b04af09f976ec35945b4f57/app/static/lib/layui/images/face/59.gif -------------------------------------------------------------------------------- /app/static/lib/layui/images/face/6.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ddosi/Voyager/a9c63235967b64c79b04af09f976ec35945b4f57/app/static/lib/layui/images/face/6.gif -------------------------------------------------------------------------------- /app/static/lib/layui/images/face/60.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ddosi/Voyager/a9c63235967b64c79b04af09f976ec35945b4f57/app/static/lib/layui/images/face/60.gif -------------------------------------------------------------------------------- /app/static/lib/layui/images/face/61.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ddosi/Voyager/a9c63235967b64c79b04af09f976ec35945b4f57/app/static/lib/layui/images/face/61.gif -------------------------------------------------------------------------------- /app/static/lib/layui/images/face/62.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ddosi/Voyager/a9c63235967b64c79b04af09f976ec35945b4f57/app/static/lib/layui/images/face/62.gif -------------------------------------------------------------------------------- /app/static/lib/layui/images/face/63.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ddosi/Voyager/a9c63235967b64c79b04af09f976ec35945b4f57/app/static/lib/layui/images/face/63.gif -------------------------------------------------------------------------------- /app/static/lib/layui/images/face/64.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ddosi/Voyager/a9c63235967b64c79b04af09f976ec35945b4f57/app/static/lib/layui/images/face/64.gif -------------------------------------------------------------------------------- /app/static/lib/layui/images/face/65.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ddosi/Voyager/a9c63235967b64c79b04af09f976ec35945b4f57/app/static/lib/layui/images/face/65.gif -------------------------------------------------------------------------------- /app/static/lib/layui/images/face/66.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ddosi/Voyager/a9c63235967b64c79b04af09f976ec35945b4f57/app/static/lib/layui/images/face/66.gif -------------------------------------------------------------------------------- /app/static/lib/layui/images/face/67.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ddosi/Voyager/a9c63235967b64c79b04af09f976ec35945b4f57/app/static/lib/layui/images/face/67.gif -------------------------------------------------------------------------------- /app/static/lib/layui/images/face/68.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ddosi/Voyager/a9c63235967b64c79b04af09f976ec35945b4f57/app/static/lib/layui/images/face/68.gif -------------------------------------------------------------------------------- /app/static/lib/layui/images/face/69.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ddosi/Voyager/a9c63235967b64c79b04af09f976ec35945b4f57/app/static/lib/layui/images/face/69.gif -------------------------------------------------------------------------------- /app/static/lib/layui/images/face/7.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ddosi/Voyager/a9c63235967b64c79b04af09f976ec35945b4f57/app/static/lib/layui/images/face/7.gif -------------------------------------------------------------------------------- /app/static/lib/layui/images/face/70.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ddosi/Voyager/a9c63235967b64c79b04af09f976ec35945b4f57/app/static/lib/layui/images/face/70.gif -------------------------------------------------------------------------------- /app/static/lib/layui/images/face/71.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ddosi/Voyager/a9c63235967b64c79b04af09f976ec35945b4f57/app/static/lib/layui/images/face/71.gif -------------------------------------------------------------------------------- /app/static/lib/layui/images/face/8.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ddosi/Voyager/a9c63235967b64c79b04af09f976ec35945b4f57/app/static/lib/layui/images/face/8.gif -------------------------------------------------------------------------------- /app/static/lib/layui/images/face/9.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ddosi/Voyager/a9c63235967b64c79b04af09f976ec35945b4f57/app/static/lib/layui/images/face/9.gif -------------------------------------------------------------------------------- /app/static/lib/layui/lay/modules/carousel.js: -------------------------------------------------------------------------------- 1 | /** layui-v2.4.5 MIT License By https://www.layui.com */ 2 | ;layui.define("jquery",function(e){"use strict";var i=layui.$,n=(layui.hint(),layui.device(),{config:{},set:function(e){var n=this;return n.config=i.extend({},n.config,e),n},on:function(e,i){return layui.onevent.call(this,t,e,i)}}),t="carousel",a="layui-this",l=">*[carousel-item]>*",o="layui-carousel-left",r="layui-carousel-right",d="layui-carousel-prev",s="layui-carousel-next",u="layui-carousel-arrow",c="layui-carousel-ind",m=function(e){var t=this;t.config=i.extend({},t.config,n.config,e),t.render()};m.prototype.config={width:"600px",height:"280px",full:!1,arrow:"hover",indicator:"inside",autoplay:!0,interval:3e3,anim:"",trigger:"click",index:0},m.prototype.render=function(){var e=this,n=e.config;n.elem=i(n.elem),n.elem[0]&&(e.elemItem=n.elem.find(l),n.index<0&&(n.index=0),n.index>=e.elemItem.length&&(n.index=e.elemItem.length-1),n.interval<800&&(n.interval=800),n.full?n.elem.css({position:"fixed",width:"100%",height:"100%",zIndex:9999}):n.elem.css({width:n.width,height:n.height}),n.elem.attr("lay-anim",n.anim),e.elemItem.eq(n.index).addClass(a),e.elemItem.length<=1||(e.indicator(),e.arrow(),e.autoplay(),e.events()))},m.prototype.reload=function(e){var n=this;clearInterval(n.timer),n.config=i.extend({},n.config,e),n.render()},m.prototype.prevIndex=function(){var e=this,i=e.config,n=i.index-1;return n<0&&(n=e.elemItem.length-1),n},m.prototype.nextIndex=function(){var e=this,i=e.config,n=i.index+1;return n>=e.elemItem.length&&(n=0),n},m.prototype.addIndex=function(e){var i=this,n=i.config;e=e||1,n.index=n.index+e,n.index>=i.elemItem.length&&(n.index=0)},m.prototype.subIndex=function(e){var i=this,n=i.config;e=e||1,n.index=n.index-e,n.index<0&&(n.index=i.elemItem.length-1)},m.prototype.autoplay=function(){var e=this,i=e.config;i.autoplay&&(e.timer=setInterval(function(){e.slide()},i.interval))},m.prototype.arrow=function(){var e=this,n=e.config,t=i(['",'"].join(""));n.elem.attr("lay-arrow",n.arrow),n.elem.find("."+u)[0]&&n.elem.find("."+u).remove(),n.elem.append(t),t.on("click",function(){var n=i(this),t=n.attr("lay-type");e.slide(t)})},m.prototype.indicator=function(){var e=this,n=e.config,t=e.elemInd=i(['
序列 | 47 |ID | 48 |项目名称 | 49 |创建用户 | 50 |创建时间 | 51 |操作 | 52 |
---|---|---|---|---|---|
{{ loop.index }} | 59 |{{ i.id }} | 60 |{{ i.project }} | 61 |{{ i.user }} | 62 |{{ i.create_date.strftime("%Y-%m-%d %H:%M:%S") }} | 63 | 64 |65 | 66 | 67 | 68 | | 69 |
序列 | 41 |所属项目 | 42 |攻击类型 | 43 |状态 | 44 |创建时间 | 45 |用户 | 46 | 47 |操作 | 48 |
---|---|---|---|---|---|---|
{{ loop.index }} | 55 |{{ i.parent_name }} | 56 |{{ i.hack_type }} | 57 | 58 |{{ i.status }} | 59 |{{ i.create_date.strftime("%Y-%m-%d %H:%M:%S") }} | 60 | 61 | 62 |{{ i.user }} | 63 | 64 |65 | 66 | 67 | 68 | 69 | | 70 |
欢迎管理员: 28 | {{ session['admin'] }} !当前时间:{{ current_time.strftime("%Y-%m-%d %H:%M:%S") }} 29 |30 |
42 | {{ items_count }}
43 | 44 |49 | {{ tasks_count }}
50 | 51 |56 | {{ domains_count }}
57 | 58 |63 | {{ ports_count }}
64 | 65 |70 | {{ vuls_count }}
71 | 72 |77 | 0
78 | 79 |xxx版本 | 93 |1.0.180420 | 94 |
---|---|
服务器地址 | 97 |x.xuebingsi.com | 98 |
操作系统 | 101 |WINNT | 102 |
运行环境 | 105 |Apache/2.4.23 (Win32) OpenSSL/1.0.2j mod_fcgid/2.3.9 | 106 |
PHP版本 | 109 |5.6.27 | 110 |
PHP运行方式 | 113 |cgi-fcgi | 114 |
MYSQL版本 | 117 |5.5.53 | 118 |
ThinkPHP | 121 |5.0.18 | 122 |
上传附件限制 | 125 |2M | 126 |
执行时间限制 | 129 |30s | 130 |
剩余空间 | 133 |86015.2M | 134 |