Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions donpapi/collectors/Certificates.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,12 +28,12 @@ def certificate_callback(certificate):
filename = f"{cert_username}_{certificate.filename[:16]}.pfx"
self.print_and_store(certificate, cert_username, filename)

certificates_triage = CertificatesTriage(target=self.target, conn=self.conn, masterkeys=self.masterkeys, per_certificate_callback=certificate_callback,)
certificates_triage = CertificatesTriage(target=self.target, conn=self.conn, masterkeys=self.masterkeys, per_certificate_callback=certificate_callback, false_positive=self.false_positive)

certificates_triage.triage_certificates()
if self.context.remoteops_allowed:
certificates_triage.triage_system_certificates()



def print_and_store(self, certificate, cert_username, filename) -> None:
absolute_local_filepath = path.join(self.context.target_output_dir, filename)
dump_file_to_loot_directories(absolute_local_filepath, certificate.pfx)
Expand Down
5 changes: 3 additions & 2 deletions donpapi/collectors/Chromium.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ def browser_callback(credential):
last_access_utc=credential.last_access_utc,
)

browser_triage = BrowserTriage(target=self.target, conn=self.conn, masterkeys=self.masterkeys, per_secret_callback=browser_callback)
browser_triage = BrowserTriage(target=self.target, conn=self.conn, masterkeys=self.masterkeys, per_secret_callback=browser_callback, false_positive=self.false_positive)

browser_triage.triage_browsers(gather_cookies=True)
dump_looted_files_to_disk(self.context.target_output_dir, browser_triage.looted_files)
dump_looted_files_to_disk(self.context.target_output_dir, browser_triage.looted_files)
7 changes: 5 additions & 2 deletions donpapi/collectors/CredMan.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,15 @@ def __init__(self, target: Target, conn: DPLootSMBConnection, masterkeys: list,

def run(self):
self.logger.display(f"Dumping User{' and Machine' if self.context.remoteops_allowed else ''} Credential Manager")

def credman_callback(credential):
self.logger.secret(f"[{credential.winuser}] {credential.target} - {credential.username}:{credential.password}", self.tag)
self.context.db.add_secret(computer=self.context.host, collector=self.tag, windows_user=credential.winuser, username=credential.username.rstrip("\x00"), password=credential.password.rstrip("\x00"), target=credential.target.rstrip("\x00"))
credentials_triage = CredentialsTriage(target=self.target, conn=self.conn, masterkeys=self.masterkeys, per_credential_callback=credman_callback)

credentials_triage = CredentialsTriage(target=self.target, conn=self.conn, masterkeys=self.masterkeys, per_credential_callback=credman_callback, false_positive=self.false_positive)

credentials_triage.triage_credentials()
if self.context.remoteops_allowed:
credentials_triage.triage_system_credentials()

dump_looted_files_to_disk(self.context.target_output_dir, credentials_triage.looted_files)
dump_looted_files_to_disk(self.context.target_output_dir, credentials_triage.looted_files)
7 changes: 5 additions & 2 deletions donpapi/collectors/MobaXTerm.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,17 +22,20 @@ def __init__(self, target: Target, conn: DPLootSMBConnection, masterkeys: list,
def run(self):
if self.context.remoteops_allowed:
self.logger.display("Dumping MobaXterm credentials")

def mobaxterm_callback(credential):
if isinstance(credential, MobaXtermCredential):
self.logger.secret(f"[Credential] [{credential.winuser}] {credential.name} - {credential.username}:{credential.password.decode('latin-1')}", self.tag)
self.context.db.add_secret(computer=self.context.host, collector=self.tag, windows_user=credential.winuser, program=self.tag, username=credential.username, password=credential.password.decode('latin-1'))
elif isinstance(credential, MobaXtermPassword):
self.logger.secret(f"[Password] [{credential.winuser}] {credential.username}:{credential.password.decode('latin-1')}", self.tag)
self.context.db.add_secret(computer=self.context.host, collector=self.tag, windows_user=credential.winuser, program=self.tag, username=credential.username, password=credential.password.decode('latin-1'))
mobaxterm_triage = MobaXtermTriage(target=self.target, conn=self.conn, masterkeys=self.masterkeys, per_secret_callback=mobaxterm_callback)

mobaxterm_triage = MobaXtermTriage(target=self.target, conn=self.conn, masterkeys=self.masterkeys, per_secret_callback=mobaxterm_callback, false_positive=self.false_positive)

try:
mobaxterm_triage.triage_mobaxterm()
dump_looted_files_to_disk(self.context.target_output_dir, mobaxterm_triage.looted_files)
except Exception as e:
if "ERROR_FILE_NOT_FOUND" not in str(e):
self.logger.error(f"Error while dumping mobaxterm: {e}")
self.logger.error(f"Error while dumping mobaxterm: {e}")
2 changes: 1 addition & 1 deletion donpapi/collectors/RDCMan.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ def __init__(self, target: Target, conn: DPLootSMBConnection, masterkeys: list,

def run(self):
self.logger.display("Dumping User's RDCManager")
rdg_triage = RDGTriage(target=self.target, conn=self.conn, masterkeys=self.masterkeys)
rdg_triage = RDGTriage(target=self.target, conn=self.conn, masterkeys=self.masterkeys, false_positive=self.false_positive)
rdcman_files, rdgfiles = rdg_triage.triage_rdcman()
for rdcman_file in rdcman_files:
if rdcman_file is None:
Expand Down
4 changes: 2 additions & 2 deletions donpapi/collectors/Vaults.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,10 +47,10 @@ def vaults_callback(vault):
target=vault.resource
)

vaults_triage = VaultsTriage(target=self.target, conn=self.conn, masterkeys=self.masterkeys)
vaults_triage = VaultsTriage(target=self.target, conn=self.conn, masterkeys=self.masterkeys, per_vault_callback=vaults_callback, false_positive=self.false_positive)

vaults_triage.triage_vaults()
if self.context.remoteops_allowed:
vaults_triage.triage_system_vaults()

dump_looted_files_to_disk(self.context.target_output_dir, vaults_triage.looted_files)

2 changes: 1 addition & 1 deletion donpapi/collectors/Wifi.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ def run(self):
if self.context.remoteops_allowed:
self.logger.display("Dumping Wifi profiles")
try:
wifi_triage = WifiTriage(target=self.target, conn=self.conn, masterkeys=self.masterkeys)
wifi_triage = WifiTriage(target=self.target, conn=self.conn, masterkeys=self.masterkeys, false_positive=self.false_positive)
wifi_creds = wifi_triage.triage_wifi()
except Exception as e:
self.logger.debug(f"Error while looting wifi: {e}")
Expand Down
1 change: 1 addition & 0 deletions donpapi/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -250,6 +250,7 @@ def get_masterkeys(self):
passwords=self.plaintexts,
nthashes=self.nthashes,
dpapiSystem=self.dpapi_systemkey,
false_positive=self.false_positive,
)
masterkeys += masterkeys_triage.triage_masterkeys()
if self.remoteops_allowed and self.lsa_dump is not None:
Expand Down
25 changes: 9 additions & 16 deletions donpapi/entry.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
from donpapi.lib.first_run import first_run, init_output_dir
from donpapi.lib.utils import create_recover_file, load_recover_file, parse_credentials_files, parse_targets, update_recover_file
from donpapi.lib.logger import donpapi_logger, donpapi_console
from donpapi.lib.consts import FALSE_POSITIVES

from pkgutil import iter_modules
from importlib import import_module
Expand Down Expand Up @@ -197,6 +198,7 @@ def main():
collect_subparser.add_argument("--keep-collecting", type=int, action="store", metavar="seconds", help="Rerun the attack against all targets after X seconds, X being the value")
collect_subparser.add_argument("--threads", default=50, type=int, metavar="Number of threads", help="Number of threads (default: 50)")
collect_subparser.add_argument('--no-config', action="store_true", help="Do not load donpapi config file (~/.donpapi/donpapi.conf)")
collect_subparser.add_argument("--false-positive", default=FALSE_POSITIVES, action="extend", nargs="+", help=f"Specify a list of \"false positive\" usernames to avoid collecting them (will extend the existing list: {FALSE_POSITIVES}).")

group_authent = collect_subparser.add_argument_group("authentication")

Expand Down Expand Up @@ -231,29 +233,17 @@ def main():


set_main_logger(donpapi_logger)

# Stores the list of false positives usernames:
false_positivee = [
".",
"..",
"desktop.ini",
"Public",
"Default",
"Default User",
"All Users",
".NET v4.5",
".NET v4.5 Classic"
]

# Stores the maximum filesize
max_filesize = 5000000

# Parse args
if len(sys.argv)==1:
parser.print_help()
sys.exit(1)

options = parser.parse_args()

# Init Logger
if options.v == 1:
donpapi_logger.logger.setLevel(logging.INFO)
Expand Down Expand Up @@ -292,6 +282,9 @@ def main():
options = argparse.Namespace(**options_recovered)
current_target_recovered = target_recovered

# Remove duplicates from false positive list.
false_positive = list(set(options.false_positive))

# Handle account
if options.domain is None:
options.domain = ''
Expand Down Expand Up @@ -376,7 +369,7 @@ def main():
nthashes,
masterkeys,
donpapi_config,
false_positivee,
false_positive,
max_filesize,
output_dir
)
Expand Down
15 changes: 15 additions & 0 deletions donpapi/lib/consts.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
"""consts.py
File containing constant values that are used in the DonPAPI project.
"""

FALSE_POSITIVES = [
".",
"..",
"desktop.ini",
"Public",
"Default",
"Default User",
"All Users",
".NET v4.5",
".NET v4.5 Classic"
]