From 9f90266716493604185e3f34832b56ec27f664b7 Mon Sep 17 00:00:00 2001 From: Matthew Iverson Date: Thu, 28 Nov 2024 00:54:43 -0500 Subject: [PATCH] Upload files to "/" --- README.md | 81 +++++++++++++ app.py | 303 +++++++++++++++++++++++++++++++++++++++++++++++ requirements.txt | 1 + 3 files changed, 385 insertions(+) create mode 100644 README.md create mode 100644 app.py create mode 100644 requirements.txt diff --git a/README.md b/README.md new file mode 100644 index 0000000..98662d4 --- /dev/null +++ b/README.md @@ -0,0 +1,81 @@ +# Threat Hunting Artificial Intelligence + +**TLDR**: *find threats and be your electronic notebook to find the enemy **5x** quicker* + +HUNT-AI helps threat hunting to make sure analysts are checking their boxes and observing all possibilities that an attacker can use on their terrain. This bot will help with managing how to threat hunting while giving helpful advice and keeping track of what you have looked at. All of this knowledge is made possible from the amazing support I have been given. learning from my current role, SEC504, FOR508, 13Cubed and many more have allowed me to give this amazing information in one central location. + +
+ Threat Hunter +
+ +## minimum requirements +- 1 brain cell +- pc with atleast a 🐹 + +### Depenecies + +#### [Python](https://www.python.org/downloads/) + +# Directions + +1. Download zip in top right + +2. unzip Hunt-AI.zip + +3. Go to path `*/hunt-ai/` + - you should see `dco.py` + +4. Set Enviroment + - On Windows + `.\venv\Scripts\activate` + - On macOS/Linux + `source venv/bin/activate` + +5. Install requirements +`pip install -r requirements.txt` + +6. `python3 dco.py` + + +## Guidance + +``` +check off what you have looked at by pressing the number +-# to uncheck section + ex. -1 will uncheck 1 +#! will highlight section + ex. 1! will highlight 1 +``` + + + + + + +---- + + + + + + + + + + + + +## Todo + +#### IDEAS +- session management +- sysmon notes +- add more sections +- have ips be entered into links +- verify what links can be used + +#### REFACTORING +- allow all to be pressed if already pressed +- stop highlighting after green if it is the all one +- fix searching to find files and present them +- have the notebook and about be on **EVERY PAGE** \ No newline at end of file diff --git a/app.py b/app.py new file mode 100644 index 0000000..8d161bd --- /dev/null +++ b/app.py @@ -0,0 +1,303 @@ +import argparse +import sys +import os +from flask import Flask, render_template, request, redirect, url_for, abort + +from Modules.windows import get_windows_content + +from Modules.Persistence.persistence import get_persistence_menu +from Modules.Persistence.autostart import * + + + +from Modules.linux import get_linux_content +from Modules.tips import get_random_tip_or_joke +from Modules.methodology import get_methodology_content +from Modules.investigate import get_investigate_content + +from Modules.Investigate.threat import * +from Modules.Investigate.ip import * +from Modules.Investigate.domain import * +from Modules.Investigate.filehash import * +from Modules.Investigate.malware import * + + +from static.ascii_text_prompts import full_ascii_art_stripped, infinitei_stripped +from config.config import VERSION + + + +app = Flask(__name__) + +# In-memory data store for the notebook page +notebook = { + "notes": [], + "ips": [], + "domains": [], + "services": [], + "tasks": [] +} + +@app.context_processor +def inject_tip(): + """ + Add a random tip or joke to every page's context. + """ + return {"random_tip": get_random_tip_or_joke()} + +README_PATH = os.path.join(os.getcwd(), "README.md") + + +def get_readme_description(): + """ + Extract the description starting with "HUNT-AI" and stopping at the next blank line from the README.md file. + """ + if not os.path.exists(README_PATH): + return "No description available." + + description = [] + capture = False + + try: + with open(README_PATH, "r", encoding="utf-8") as readme_file: + for line in readme_file: + # Start capturing from the line containing "HUNT-AI" + if "HUNT-AI" in line: + capture = True + description.append(line.strip()) + # Continue capturing until a blank line is encountered + elif capture: + if line.strip() == "": + break + description.append(line.strip()) + except Exception as e: + return f"Error reading README.md: {e}" + + return " ".join(description) if description else "No description available." + + + + + + + + + + + + + +@app.route('/') +def home(): + # Read description from README.md + readme_description = get_readme_description() + + # Links to display on the home page + links = [ + {"name": "Visit Start.me", "url": "https://start.me/p/qbzw4e/cyber-security"}, + {"name": "Visit My Website", "url": "https://infinit3i.com/"} + ] + return render_template( + 'index.html', + full_ascii_art=full_ascii_art_stripped, + infinitei=infinitei_stripped, + links=links, + readme_description=readme_description + ) + +@app.route('/methodology') +def methodology(): + content = get_methodology_content() + return render_template('methodology.html', content=content) + +@app.route('/linux') +def linux(): + sections = get_linux_content() + return render_template('linux.html', sections=sections) + +@app.route('/linux/') +def linux_section(title): + sections = get_linux_content() + section = next((s for s in sections if s["title"].replace(" ", "_").lower() == title.lower()), None) + if not section: + abort(404) + return render_template('section.html', section=section) + +@app.route('/rule_creation') +def rule_creation(): + return render_template('rule_creation.html') + +@app.route('/windows') +def windows(): + # Load all sections + sections = get_windows_content() + return render_template('windows.html', sections=sections) + +@app.route('/windows/<title>') +def windows_section(title): + # Find the section matching the title + sections = get_windows_content() + section = next((s for s in sections if s["title"].replace(" ", "_").lower() == title.lower()), None) + + if not section: + abort(404) # Return a 404 if the section is not found + + return render_template('section.html', section=section) + + + + + + + + + +@app.route('/persistence') +def persistence_submenu(): + """ + Displays the submenu for all persistence methods. + """ + menu = get_persistence_menu() + return render_template('persistence_submenu.html', menu=menu) + +@app.route('/persistence/<method>') +def persistence_method(method): + """ + Dynamically load content for a specific persistence method. + """ + try: + # Dynamically import the requested method module + module = __import__(f"Modules.Persistence.{method}", fromlist=["get_content"]) + content = module.get_content() + return render_template('persistence_method.html', content=content) + except ModuleNotFoundError: + abort(404, description=f"Persistence method '{method}' not found.") + + + + + + + + + + + + + + + + + + + + + + + + + +@app.route('/investigate') +def investigate(): + content = get_investigate_content() + return render_template('investigate.html', content=content) + +@app.route('/investigate/threat') +def investigate_threat(): + content = get_threat_content() + return render_template('investigate.html', content=content) + +@app.route('/investigate/domain') +def investigate_domain(): + content = get_domain_content() + return render_template('investigate.html', content=content) + +@app.route('/investigate/filehash') +def investigate_filehash(): + content = get_filehash_content() + return render_template('investigate.html', content=content) + +@app.route('/investigate/ip') +def investigate_ip(): + content = get_ip_content() + return render_template('investigate.html', content=content) + +@app.route('/investigate/malware') +def investigate_malware(): + content = get_malware_content() + return render_template('investigate.html', content=content) + +def display_help(): + """ + Display help information for the command-line interface. + """ + help_text = f""" +Usage: + python3 app.py Start the Flask application + python3 app.py -v Display the current version + python3 app.py -h Show this help page + python3 app.py -f <file> Load the last session file for collaboration + """ + print(help_text) + +def get_version(): + """ + Display the version of the application. + """ + print(f"App Version: {VERSION}") + +def load_session(file_path): + """ + Load a session file and display its contents. + """ + try: + with open(file_path, "r") as file: + session_data = file.read() + print(f"Session loaded successfully from {file_path}:\n") + print(session_data) + except FileNotFoundError: + print(f"Error: File '{file_path}' not found.") + except Exception as e: + print(f"Error: {e}") + +def handle_arguments(): + """ + Parse and handle command-line arguments. + """ + parser = argparse.ArgumentParser( + description="App Runner - Threat AI Command Interface", + usage="python3 app.py [-v | -h | -f <file>]" + ) + parser.add_argument("-v", "--version", action="store_true", help="Display the current version") + parser.add_argument("-f", "--file", type=str, help="Load the last session file for collaboration") + args = parser.parse_args() + + if args.version: + get_version() + sys.exit(0) + elif args.file: + load_session(args.file) + sys.exit(0) + +@app.route('/notebook', methods=['GET', 'POST']) +def notebook_page(): + if request.method == 'POST': + # Capture data from form submission + category = request.form.get('category') + entry = request.form.get('entry') + if category in notebook and entry: + notebook[category].append(entry) + return render_template('notebook.html', notebook=notebook) + +@app.route('/delete/<category>/<int:index>') +def delete_entry(category, index): + if category in notebook and 0 <= index < len(notebook[category]): + notebook[category].pop(index) + return redirect(url_for('notebook_page')) + +if __name__ == '__main__': + # If arguments are passed, handle them; otherwise, run the Flask app. + if len(sys.argv) > 1: + handle_arguments() + else: + app.run(debug=True) \ No newline at end of file diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..7e10602 --- /dev/null +++ b/requirements.txt @@ -0,0 +1 @@ +flask