DonPAPI/donpapi/lib/utils.py

131 lines
4.5 KiB
Python

import os
import re
from ipaddress import ip_address, ip_network, summarize_address_range, ip_interface
import time
from typing import Dict
import json
from donpapi.lib.paths import DPP_RECOVER_DIR_NAME
from dploot.triage.masterkeys import parse_masterkey_file
from donpapi.lib.logger import donpapi_logger
def create_recover_file(dirpath, targets, options):
timestamp = int(time.time())
filepath = os.path.join(dirpath, DPP_RECOVER_DIR_NAME, f"recover_{timestamp}")
with open(filepath, "w") as f:
write_recover_file(f, [f"{json.dumps(vars(options))}\n", ",".join(targets)])
return filepath
def update_recover_file(recover_file_handle, targets):
recover_file_handle.seek(0)
recover_file_lines = recover_file_handle.readlines()
recover_file_lines[1] = ",".join(targets)
write_recover_file(recover_file_handle, recover_file_lines)
def write_recover_file(recover_file_handle, lines):
recover_file_handle.seek(0)
recover_file_handle.truncate()
recover_file_handle.writelines(lines)
def load_recover_file(recover_file_path):
options = None
targets_todo = None
with open(recover_file_path, "r") as f:
lines = f.readlines()
options = json.loads(lines[0])
targets_todo = lines[1].split(",")
return options, targets_todo
def parse_targets(target):
try:
if "-" in target:
start_ip, end_ip = target.split("-")
try:
end_ip = ip_address(end_ip)
except ValueError:
first_three_octets = start_ip.split(".")[:-1]
first_three_octets.append(end_ip)
end_ip = ip_address(".".join(first_three_octets))
for ip_range in summarize_address_range(ip_address(start_ip), end_ip):
for ip in ip_range:
yield str(ip)
else:
if ip_interface(target).ip.version == 6 and ip_address(target).is_link_local:
yield str(target)
else:
for ip in ip_network(target, strict=False):
yield str(ip)
except ValueError:
yield str(target)
def parse_file_as_dict(filename: str) -> Dict[str,str]:
arr = dict()
with open(filename, "r") as lines:
for line in lines:
line_modified = line.rstrip("\n")
line_modified = line_modified.split(":" ,1)
arr[line_modified[0]]=line_modified[1]
return arr
def parse_credentials_files(pvkfile, passwords_file, nthashes_file, masterkeys_file, username, password, nthash):
pvkbytes = None
passwords = {}
nthashes = {}
masterkeys = []
if pvkfile is not None:
try:
pvkbytes = open(pvkfile, "rb").read()
except Exception as e:
donpapi_logger.error(f"Error while reading file {passwords_file}: {e}")
if passwords_file is not None:
try:
passwords = parse_file_as_dict(passwords_file)
except Exception as e:
donpapi_logger.error(f"Error while reading file {passwords_file}: {e}")
if nthashes_file is not None:
try:
nthashes = parse_file_as_dict(nthashes_file)
except Exception as e:
donpapi_logger.error(f"Error while reading file {nthashes_file}: {e}")
if masterkeys_file is not None:
try:
masterkeys = parse_masterkey_file(masterkeys_file)
except Exception as e:
donpapi_logger.error(f"Error while reading file {masterkeys_file}: {e}")
if username is not None:
if password is not None and password != "":
if passwords is None:
passwords = dict()
passwords[username] = password
if nthash is not None and nthash != "":
if nthashes is None:
nthashes = dict()
nthashes[username] = nthash.lower()
if nthashes is not None:
nthashes = {k.lower():v.lower() for k, v in nthashes.items()}
if passwords is not None:
passwords = {k.lower():v for k, v in passwords.items()}
return pvkbytes, passwords, nthashes, masterkeys
def is_guid(value: str):
GUID = re.compile(r'^(\{{0,1}([0-9a-fA-F]{8})-([0-9a-fA-F]{4})-([0-9a-fA-F]{4})-([0-9a-fA-F]{4})-([0-9a-fA-F]{12})\}{0,1})$')
if GUID.match(value):
return True
else:
return False
def dump_file_to_loot_directories(local_filepath: str, file_content: bytes=b"") -> None:
os.makedirs(os.path.dirname(local_filepath), exist_ok = True)
with open(local_filepath, "wb") as f:
f.write(file_content)