mirror of
https://github.com/ShutdownRepo/dcshadow
synced 2026-06-06 16:44:32 +00:00
90 lines
4.5 KiB
Python
90 lines
4.5 KiB
Python
#!/usr/bin/env python3
|
|
# -*- coding: utf-8 -*-
|
|
import argparse
|
|
import sys
|
|
from typing import Tuple
|
|
|
|
from R2Log import logger, console
|
|
|
|
from dcshadow.manager.Controller import ExecManager
|
|
|
|
|
|
def parse_args():
|
|
parser = argparse.ArgumentParser(add_help=True, description='DCShadow attack tool')
|
|
|
|
# general arguments
|
|
parser.add_argument("-v", "--verbose", dest="verbosity", action="count", default=0, help="Verbosity level (-v for verbose, -vv for advanced, -vvv for debug)")
|
|
parser.add_argument("-q", "--quiet", dest="quiet", action="store_true", default=False, help="Show no information at all")
|
|
|
|
# arguments related to the domain controllers involved in the replication process
|
|
rogue_dc = parser.add_argument_group('rogue domain controller')
|
|
rogue_dc.add_argument('--legit-dc-fqdn', action='store', metavar="dc.domain.local", help='Fully Qualified Domain Name of the legitimate domain controller to replicate to')
|
|
legit_dc = parser.add_argument_group('legit domain controller')
|
|
legit_dc.add_argument('--rogue-dc-name', action='store', metavar="dc.domain.local", help='NetBIOS name of the rogue DC to use or create')
|
|
|
|
# arguments related to the objects or attributes to replicate
|
|
repl = parser.add_argument_group('replication')
|
|
repl.add_argument('-ro', '--object', dest='repl_object', action='store', help='object to replicate (specified by sAMAccountName)')
|
|
repl.add_argument('-rodn', '--object-dn', dest='repl_object_dn', action='store', help='object to replicate (specified by distinguishedName)')
|
|
repl.add_argument('-ra', '--attribute', dest='repl_attribute', action='store', help="object's attribute to replicate")
|
|
repl.add_argument('-rv', '--value', dest='repl_value', action='store', help='value to set for the attribute')
|
|
repl.add_argument('-rj', '--json', dest='repl_json', action='store', help='path to JSON file containing objects and attributes to replicate')
|
|
|
|
# authentication-related arguments
|
|
auth = parser.add_argument_group('authentication')
|
|
auth.add_argument("-d", "--domain", metavar="DOMAIN", action="store", help="(FQDN) domain to authenticate to")
|
|
auth.add_argument("-u", "--user", metavar="USER", action="store", help="user to authenticate with")
|
|
auth.add_argument("-p", "--password", metavar="PASSWORD", action="store", help="password to authenticate with")
|
|
auth.add_argument("-H", "--hashes", action="store", metavar="[LMHASH:]NTHASH", help='NT/LM hashes, format is LMhash:NThash')
|
|
auth.add_argument("-k", "--kerberos", dest="use_kerberos", action="store_true", help='Use Kerberos authentication. Grabs credentials from .ccache file (KRB5CCNAME) based on target parameters. If valid credentials cannot be found, it will use the ones specified in the command line')
|
|
auth.add_argument("--aes-key", action="store", metavar="hex key", help='AES key to use for Kerberos Authentication (128 or 256 bits)')
|
|
auth.add_argument("--no-pass", action="store_true", help='don\'t ask for password (useful for -k)')
|
|
auth.add_argument("-td", "--target-domain", dest="target_domain", help="Target domain (if different than the domain of the authenticating user)")
|
|
|
|
# connection-related arguments
|
|
con = parser.add_argument_group('connection')
|
|
con.add_argument('--use-ldaps', action='store_true', help='Use LDAPS instead of LDAP')
|
|
con.add_argument('--dc-ip', action='store', metavar="ip address", help='IP address of the DC/KDC to authenticate to')
|
|
|
|
if len(sys.argv) == 1:
|
|
parser.print_help()
|
|
sys.exit(1)
|
|
|
|
return parser.parse_args()
|
|
|
|
|
|
def parse_hashes(hashes: str) -> Tuple[str, str]:
|
|
if hashes is not None:
|
|
lmhash, nthash = hashes.split(':')
|
|
if lmhash == '':
|
|
lmhash = "aad3b435b51404eeaad3b435b51404ee"
|
|
else:
|
|
lmhash = ''
|
|
nthash = ''
|
|
return lmhash, nthash
|
|
|
|
|
|
def main():
|
|
"""main console entrypoint"""
|
|
try:
|
|
args = parse_args()
|
|
args.lm_hash, args.nt_hash = parse_hashes(hashes=args.hashes)
|
|
# Set logger verbosity depending on user input
|
|
logger.setVerbosity(args.verbosity, args.quiet)
|
|
console.width = 250
|
|
# Start the work
|
|
logger.info("Starting DCShadow attack")
|
|
logger.debug(f"Arguments: {args}")
|
|
ExecManager.main(args=args)
|
|
except KeyboardInterrupt:
|
|
logger.empty_line()
|
|
logger.info("Exiting")
|
|
# except Exception:
|
|
# console.print_exception(show_locals=True)
|
|
# # console.print_exception(show_locals=True, suppress=[requests])
|
|
# exit(1)
|
|
|
|
|
|
if __name__ == '__main__':
|
|
main()
|