DonPAPI/donpapi/collectors/RecycleBin.py

84 lines
4.2 KiB
Python

import os
import ntpath
from typing import Any
from dploot.lib.target import Target
from dploot.lib.smb import DPLootSMBConnection
from donpapi.core import DonPAPICore
from donpapi.lib.logger import DonPAPIAdapter
from donpapi.lib.utils import dump_file_to_loot_directories
class RecycleBin:
def __init__(self, target: Target, conn: DPLootSMBConnection, masterkeys: list, options: Any, logger: DonPAPIAdapter, context: DonPAPICore, false_positive: list, max_filesize: int) -> None:
self.tag = self.__class__.__name__
self.target = target
self.conn = conn
self.masterkeys = masterkeys
self.options = options
self.logger = logger
self.context = context
self.found = 0
self.false_positive = false_positive
self.max_filesize = max_filesize
def run(self) -> None:
self.logger.display("Gathering recycle bins")
for sid_directory in self.conn.remote_list_dir(self.context.share, "\\$Recycle.Bin"):
sid = sid_directory.get_longname()
if sid_directory.get_longname() not in self.false_positive:
username = None
# Translates $Recycle.Bin SID's to usernames using remote registry keys
if self.context.remoteops_allowed:
username = self.translate_sid_to_username(sid)
self.dig_files(
directory_path = f"\\$Recycle.Bin\\{sid}",
sid = sid,
username = username,
recurse_level = 0,
recurse_max = 10,
)
if self.found > 0:
self.logger.secret(f"Found {self.found} files in recycle bin's", self.tag)
def translate_sid_to_username(self, sid) -> str:
username = None
path = f"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\ProfileList\\{sid}"
key = "ProfileImagePath\x00"
try:
username = self.context.reg_query_value(path, key)[-1].split("\\")[-1].rstrip("\x00")
except Exception as e:
if "ERROR_FILE_NOT_FOUND" not in str(e):
self.logger.error(f"Error while RegQueryValue {path}\\{key}: {e}")
return username
def dig_files(self, directory_path, sid, username = None, recurse_level = 0, recurse_max = 10) -> None:
directory_list = self.conn.remote_list_dir(self.context.share, directory_path)
if directory_list is not None:
for item in directory_list:
if item.get_longname() not in self.false_positive:
new_path = ntpath.join(directory_path, item.get_longname())
if item.is_directory() > 0:
if recurse_level < recurse_max:
self.dig_files(
directory_path = new_path,
sid = sid,
username = username ,
recurse_level = recurse_level+1,
recurse_max = recurse_max
)
else:
if item.get_filesize() < self.max_filesize:
file_content = self.conn.readFile(self.context.share, new_path)
if file_content is not None:
self.found += 1
absolute_local_filepath = os.path.join(self.context.target_output_dir, *(new_path.split('\\')))
if username:
absolute_local_filepath = absolute_local_filepath.replace(sid, username)
dump_file_to_loot_directories(absolute_local_filepath, file_content)
collector_dir_local_filepath = os.path.join(self.context.global_output_dir, self.tag, new_path.replace("\\", "_"))
if username:
absolute_local_filepath = absolute_local_filepath.replace(sid, username)
dump_file_to_loot_directories(collector_dir_local_filepath, file_content)