diff --git a/README.md b/README.md index 387ba97..f85d532 100644 --- a/README.md +++ b/README.md @@ -128,9 +128,12 @@ $ ./avred.py --file test.ps1 --server amsi As a web server: ```sh -$ python3 avred-web.py --listenip 127.0.0.1 --listenport 8080 +$ python3 avredweb.py --listenip 127.0.0.1 --listenport 8080 ``` +For login, use username "admin" and password configured in `config.json` in key `password`. + + From command line: ```sh $ python3 avred.py --server amsi --file malware/evil.exe diff --git a/app/templates/includes/navigation.html b/app/templates/includes/navigation.html index 6f047fa..c83fe3b 100644 --- a/app/templates/includes/navigation.html +++ b/app/templates/includes/navigation.html @@ -15,10 +15,13 @@ diff --git a/app/templates/list_files.html b/app/templates/list_files.html index 99de128..8971878 100644 --- a/app/templates/list_files.html +++ b/app/templates/list_files.html @@ -11,6 +11,5 @@
  • {{filename}}
  • {% endfor %} - \ No newline at end of file diff --git a/app/templates/login.html b/app/templates/login.html new file mode 100644 index 0000000..5b05342 --- /dev/null +++ b/app/templates/login.html @@ -0,0 +1,33 @@ + + + + {% include 'includes/header.html' %} + + + {% include 'includes/navigation.html' %} + +

    Login

    + {% with messages = get_flashed_messages() %} + {% if messages %} + + {% endif %} + {% endwith %} +
    +
    + + +
    +
    + + +
    +
    + +
    +
    + + \ No newline at end of file diff --git a/app/views.py b/app/views.py index 30a91d6..8e6e39e 100644 --- a/app/views.py +++ b/app/views.py @@ -8,6 +8,7 @@ import requests import sys import zipfile import logging +from flask_login import LoginManager, UserMixin, login_user, logout_user, login_required, login_manager from model.model import * #from waitress import serve @@ -25,10 +26,8 @@ def index(): @views.route("/files") +@login_required def files(): - if not current_app.config['LIST_FILES']: - return render_template('index.html') - examples = get_filepaths(current_app.config['UPLOAD_FOLDER'], EXT_INFO) res = [] for example in examples: @@ -38,10 +37,8 @@ def files(): @views.route("/files_results") +@login_required def files_results(): - if not current_app.config['LIST_FILES']: - return render_template('index.html') - filepaths = get_filepaths(current_app.config['UPLOAD_FOLDER'], EXT_INFO) outcomes = [] for filepath in filepaths: @@ -70,9 +67,8 @@ def file(filename): @views.route("/file//download") +@login_required def fileDownload(filename): - if not current_app.config['DOWNLOAD_FILES']: - return render_template('index.html') filename = secure_filename(filename) filepath = os.path.join(current_app.config['UPLOAD_FOLDER'], filename) return send_file(filepath, as_attachment=True) @@ -111,8 +107,6 @@ def examples_list(): @views.route("/example//download") def fileDownloadExample(filename): - if not current_app.config['DOWNLOAD_FILES']: - return render_template('index.html') filename = secure_filename(filename) filepath = os.path.join(current_app.config['EXAMPLE_FOLDER'], filename) return send_file(filepath, as_attachment=True) diff --git a/app/views_auth.py b/app/views_auth.py new file mode 100644 index 0000000..aeb7852 --- /dev/null +++ b/app/views_auth.py @@ -0,0 +1,41 @@ +from flask import Blueprint, current_app, flash, request, redirect, url_for, render_template +from werkzeug.utils import secure_filename +import os +import random +import subprocess +import pickle +import requests +import sys +import zipfile +import logging +import psutil +from flask_login import LoginManager, UserMixin, login_user, logout_user, login_required + +views_auth = Blueprint('views_auth', __name__) + +login_manager = LoginManager() + + +class User(UserMixin): + def __init__(self, username, password): + self.id = 1 # Assuming a single user, so ID is hardcoded + self.username = username + self.password = password + + +@login_manager.user_loader +def load_user(user_id): + if user_id == '1': + return User('admin', 'password') + + +@views_auth.route('/login', methods=['GET', 'POST']) +def login(): + if request.method == 'POST': + username = request.form['username'] + password = request.form['password'] + user = load_user('1') + if user and user.password == password: + login_user(user) + return redirect('/') + return render_template('login.html') diff --git a/avred-web.py b/avredweb.py similarity index 81% rename from avred-web.py rename to avredweb.py index c8a1d9b..6f22bf4 100755 --- a/avred-web.py +++ b/avredweb.py @@ -7,6 +7,9 @@ from flask import Flask from config import Config from app.views import views from app.views_upload import views_upload +from app.views_auth import views_auth, login_manager +from flask_login import LoginManager, UserMixin, login_user, logout_user, login_required + if __name__ == "__main__": @@ -14,8 +17,6 @@ if __name__ == "__main__": parser.add_argument('--listenip', type=str, help='IP to listen on', default="0.0.0.0") parser.add_argument('--listenport', type=int, help='Port to listen on', default=5000) parser.add_argument('--debug', action='store_true', help='Debug', default=False) - parser.add_argument('--disable-listfiles', action='store_true', help='Disable List Files', default=False) - parser.add_argument('--disable-downloadfiles', action='store_true', help='Disable Download Files', default=False) args = parser.parse_args() config = Config() @@ -35,17 +36,20 @@ if __name__ == "__main__": app.config['SECRET_KEY'] = os.urandom(24) app.config['SESSION_TYPE'] = 'filesystem' app.config['AVRED_SERVERS'] = config.get('server') + app.config['PASSWORD'] = config.get('password') app.config['AVRED_SCANNER'] = os.path.join(root_folder, 'avred.py') app.config['ALLOWED_EXTENSIONS'] = { 'exe', 'dll', 'ps1', 'docm', 'bin', 'lnk' } - app.config['LIST_FILES'] = not args.disable_listfiles - app.config['DOWNLOAD_FILES'] = not args.disable_downloadfiles app.config.from_prefixed_env() - for key in ('UPLOAD_FOLDER', 'EXAMPLE_FOLDER', 'ALLOWED_EXTENSIONS', 'LIST_FILES'): + for key in ('UPLOAD_FOLDER', 'EXAMPLE_FOLDER', 'ALLOWED_EXTENSIONS',): print("{}: {}".format(key, app.config[key])) print("") app.register_blueprint(views) app.register_blueprint(views_upload) + app.register_blueprint(views_auth) + + login_manager.init_app(app) + app.run(host=args.listenip, port=args.listenport, debug=args.debug) diff --git a/config.json b/config.json index f7f995a..b7fbff3 100644 --- a/config.json +++ b/config.json @@ -1,6 +1,7 @@ { "server": { - "amsi": "http://192.168.88.127:8001/" - } + "amsi": "http://192.168.88.127:8001/", + }, + "password": "" } diff --git a/config.py b/config.py index 1e851a9..dfcbe6b 100644 --- a/config.py +++ b/config.py @@ -12,4 +12,7 @@ class Config(object): self.data = json.load(jsonfile) def get(self, value): - return self.data[value] + if value in self.data: + return self.data[value] + else: + return "" diff --git a/doc/analysis-issues.txt b/doc/analysis-issues.txt index 5db164f..89a7286 100644 --- a/doc/analysis-issues.txt +++ b/doc/analysis-issues.txt @@ -1,6 +1,47 @@ - # Analysis results +* long scans +* detected, but no matches + + +broken: +* mimikatz + +very long, in examples/broken.bin/: +* 072877b961e31e8792a296c63b9c7b56.bin -> ok, hash based +* 15FC009D9CAAA8F11D6C3DA2B69EA06E.bin -> incremental. header? +* 91FC9D1B635FDEE4E56AEC32688A0E6C.bin -> incremental, header, sections are fucked +bad hash based detection? + + +https://avred.r00ted.ch/example/286f7b377f5d0ca3505ed1ba6601c947.bin +* why doesnt it find anything? detected by amsi, but no matches +* same with: SharpHound! + + +what about self extracting rar archives? +* 091457444b7e7899c242c5125ddc0571.bin +-> do not scan for now + +---------------------------------------------- + +fucked endlessly: +[INFO ][2023/02/13 18:20][avred.py: 70] main() :: Using file: app/examples/075df4723073ff08cd3e90d2b1f11722.bin + + +* rubeus: only match 0 triggers? why.. (no .data) + +https://avred.yookiterm.ch/file/685805936d8744225f8c11965202de8e.bin +* good example with two (independant?) sections: code/data + +https://avred.yookiterm.ch/file/100cf902ac31766f7d8a521eeb6f8d68.bin +* last two work, but conclusion does not show it + +good signatures: +* https://avred.yookiterm.ch/file/03db29c71b0031af08081f5e2f7dcdf2.bin + + + * msf/test3 does never end, and needs --isolate? ## Sharphound @@ -53,4 +94,11 @@ Seems defender somehow realized it is malicious again! solution: Just ignore .text... - \ No newline at end of file + + -------------------- + + some PE files have zero detections? +* 070ef82a0bded089b6f996a392ca7b9a.bin +* 05a02e08cce99d3821574d8612f757fd.bin +-> fixed, recheck +-> fixed \ No newline at end of file