2024-07-05 13:47:43 +00:00
|
|
|
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()
|
2024-10-21 09:53:16 +00:00
|
|
|
with open(filename, "r") as lines:
|
2024-07-05 13:47:43 +00:00
|
|
|
for line in lines:
|
2024-10-21 09:53:16 +00:00
|
|
|
line_modified = line.rstrip("\n")
|
|
|
|
line_modified = line_modified.split(":" ,1)
|
2024-07-05 13:47:43 +00:00
|
|
|
arr[line_modified[0]]=line_modified[1]
|
|
|
|
return arr
|
|
|
|
|
|
|
|
def parse_credentials_files(pvkfile, passwords_file, nthashes_file, masterkeys_file, username, password, nthash):
|
2024-07-11 12:38:28 +00:00
|
|
|
pvkbytes = None
|
|
|
|
passwords = {}
|
|
|
|
nthashes = {}
|
|
|
|
masterkeys = []
|
2024-07-05 13:47:43 +00:00
|
|
|
|
|
|
|
if pvkfile is not None:
|
|
|
|
try:
|
2024-10-21 09:53:16 +00:00
|
|
|
pvkbytes = open(pvkfile, "rb").read()
|
2024-07-05 13:47:43 +00:00
|
|
|
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:
|
2024-10-21 09:53:16 +00:00
|
|
|
if password is not None and password != "":
|
2024-07-05 13:47:43 +00:00
|
|
|
if passwords is None:
|
|
|
|
passwords = dict()
|
|
|
|
passwords[username] = password
|
|
|
|
|
2024-10-21 09:53:16 +00:00
|
|
|
if nthash is not None and nthash != "":
|
2024-07-05 13:47:43 +00:00
|
|
|
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:
|
2024-10-21 08:54:33 +00:00
|
|
|
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)
|