def __init__(self, host, args):
        super(FileHashCollector, self).__init__(host, args)

        if 'path' not in args:
            raise ArgumentException('FileHashCollector requires path argument')

        if 'type' not in args:
            raise ArgumentException('FileHashCollector requires type argument')

        if args['type'] not in FileHashCollector.HASH_COMMANDS.keys():
            raise ArgumentException('Unknown hash type: ' + args['type'])
    def __init__(self, host, args):
        super(ResolveFilepathCollector, self).__init__(host, args)

        if 'filepath' not in args:
            raise ArgumentException('ResolveFilepathCollector requires filepath argument')

        for i in ('value_datatypes', 'value_masks', 'value_operations'):
            if i not in args:
                raise ArgumentException('ResolveFilepathCollector requires ' + i + ' argument')

        if args['value_datatypes']['filepath'] != 'string':
            raise ArgumentException('ResolveFilepathCollector requires string filepath')

        # NOTE: operation should be already validated by EntityObjectType

        if args['value_operations']['filepath'] == 'pattern match' and args['behavior_recurse_file_system'] == 'defined':
            raise ArgumentException('ResolveFilepathCollector behavior_recurse_file_system set to defined with pattern match operation')
Example #3
0
    def __init__(self, host, args):
        super(ResolvePathFilenameCollector, self).__init__(host, args)

        if 'path' not in args:
            raise ArgumentException('ResolvePathFilenameCollector requires path argument')

        if 'filename' not in args:
            raise ArgumentException('ResolvePathFilenameCollector requires filename argument')

        for i in ('value_datatypes', 'value_masks', 'value_operations'):
            if i not in args:
                raise ArgumentException('ResolvePathFilenameCollector requires ' + i + ' argument')

        if args['value_datatypes']['path'] != 'string':
            raise ArgumentException('ResolvePathFilenameCollector requires string path')

        if args['value_datatypes']['filename'] != 'string':
            raise ArgumentException('ResolvePathFilenameCollector requires string filename')

        # NOTE: operation should be already validated by EntityObjectType

        # TODO the max_depth behavior MUST not be used when a pattern match is used with a path entity
        # TODO the recurse behavior MUST not be used when a pattern match is used with a path entity
        # TODO the recurse_direction behavior MUST not be used when a pattern match is used with a path entity
        # the recurse_file_system behavior MUST not be set to 'defined' when a pattern match is used with a path entity
        if args['value_operations']['path'] == 'pattern match' and args['behavior_recurse_file_system'] == 'defined':
            raise ArgumentException('ResolvePathFilenameCollector behavior_recurse_file_system set to defined with path pattern match operation')
Example #4
0
    def collect(self):
        if self.args['value_operations']['path'] in ['equals', 'case insensitive equals']:
            # check if path exists
            col = self.host.load_collector('DirectoryExistsCollector', {'path': self.args['path']})
            if not col.collect():
                raise FileNotFoundError(self.args['path'] + ' was not found')

            paths = [self.args['path']]

        elif self.args['value_operations']['path'] in ['not equal', 'case insensitive not equal']:
            raise NotImplementedError(self.args['value_operations']['path'] + ' operation not supported for ResolvePathFilenameCollector')

        elif self.args['value_operations']['path'] == 'pattern match':
            path = self.args['path']
            logger.debug('Matching pattern ' + path)

            # strip off leading ^ or trailing $ as they are assumed
            if path.startswith('^'):
                path = path[1:]
            if path.endswith('$'):
                path = path[:-1]

            paths = []
            m = re.match(r'^([a-zA-Z]):\\', path)
            if m:
                # C:\ local abs path
                drive = m.group(1) + ':\\'
                logger.debug('Absolute path on drive ' + drive)

                cmd = "Get-PSDrive -PSProvider FileSystem | % { $_.Root }"
                return_code, out_lines, err_lines = self.host.exec_command('powershell -Command "' + cmd.replace('\"', '\\"') + '"')

                if drive not in out_lines:
                    # don't have the drive, so path won't match
                    raise FileNotFoundError(self.args['path'] + ' was not found')

                start = m.group(1) + ':'

                fp = path.split('\\')
                fp = fp[1:]
                for p in fp:
                    logger.debug('Checking if path component ' + p + ' exists')
                    cmd = "Get-Item -LiteralPath '" + start + '\\' + p + "' -ErrorAction Ignore | % { $_.Name }"
                    return_code, out_lines, err_lines = self.host.exec_command('powershell -Command "' + cmd.replace('\"', '\\"') + '"')
                    if return_code == 0 and len(out_lines) == 1:
                        logger.debug(p + ' exists')
                        start = start + '\\' + p
                    else:
                        logger.debug(p + ' does not exist; using ' + start + ' as starting point')
                        break

                logger.debug('Recursing from ' + start)
                cmd = "Get-ChildItem -LiteralPath '" + start + "' -Recurse -ErrorAction Ignore | % { $_.FullName }"
                return_code, out_lines, err_lines = self.host.exec_command('powershell -Command "' + cmd.replace('\"', '\\"') + '"')

                if return_code != 0 or len(out_lines) < 1:
                    raise FileNotFoundError(self.args['path'] + ' was not found')

                for l in out_lines:
                    m = re.fullmatch(self.args['path'], l)
                    if m:
                        logger.debug(l + ' matches ' + self.args['path'])
                        paths.append(l)

            elif path.startswith(r'\\\\\?\\UNC\\'):
                # \\?\UNC\ extended UNC length path
                raise NotImplementedError('extended UNC paths are not yet supported')

            elif path.startswith(r'\\\\\?\\'):
                # \\?\ extended length path
                raise NotImplementedError('extended paths are not yet supported')

            elif path.startswith(r'\\\\\.\\'):
                # \\.\ device namespace path
                raise NotImplementedError('device paths are not yet supported')

            elif path.startswith(r'\\\\'):
                # \\server\share UNC path
                m = re.match(r'^\\\\([^\\]+)\\')
                if not m:
                    raise ArgumentException('Invalid UNC path: ' + path)
                server = m.group(1)
                logger.debug('UNC path on server ' + server)

                start = '\\\\' + server

                fp = path.split('\\')
                fp = fp[3:]
                for p in fp:
                    logger.debug('Checking if path component ' + p + ' exists')
                    cmd = "Get-Item -LiteralPath '" + start + '\\' + p + "' -ErrorAction Ignore | % { $_.Name }"
                    return_code, out_lines, err_lines = self.host.exec_command('powershell -Command "' + cmd.replace('\"', '\\"') + '"')
                    if return_code == 0 and len(out_lines) == 1:
                        logger.debug(p + ' exists')
                        start = start + '\\' + p
                    else:
                        logger.debug(p + ' does not exist; using ' + start + ' as starting point')
                        break

                logger.debug('Recursing from ' + start)
                cmd = "Get-ChildItem -LiteralPath '" + start + "' -Recurse -ErrorAction Ignore | % { $_.FullName }"
                return_code, out_lines, err_lines = self.host.exec_command('powershell -Command "' + cmd.replace('\"', '\\"') + '"')

                if return_code != 0 or len(out_lines) < 1:
                    raise FileNotFoundError(self.args['path'] + ' was not found')

                for l in out_lines:
                    m = re.fullmatch(self.args['path'], l)
                    if m:
                        logger.debug(l + ' matches ' + self.args['path'])
                        paths.append(l)

            elif path.startswith(r'\.\.\\'):
                # ..\ relative parent path
                cmd = "(Get-Item -Path '..\\' -Verbose).FullName"
                return_code, out_lines, err_lines = self.host.exec_command('powershell -Command "' + cmd.replace('\"', '\\"') + '"')

                start = out_lines[0]

                logger.debug('Recursing from ' + start)
                cmd = "Get-ChildItem -LiteralPath '" + start + "' -Recurse -ErrorAction Ignore | % { $_.FullName }"
                return_code, out_lines, err_lines = self.host.exec_command('powershell -Command "' + cmd.replace('\"', '\\"') + '"')

                if return_code != 0 or len(out_lines) < 1:
                    raise FileNotFoundError(self.args['path'] + ' was not found')

                for l in out_lines:
                    m = re.fullmatch(self.args['path'], l.replace(start, '..'))
                    if m:
                        logger.debug(l + ' matches ' + self.args['path'])
                        paths.append(l)

            elif path.startswith(r'\.\\'):
                # .\ relative current path
                cmd = "(Get-Item -Path '.\\' -Verbose).FullName"
                return_code, out_lines, err_lines = self.host.exec_command('powershell -Command "' + cmd.replace('\"', '\\"') + '"')

                start = out_lines[0]

                logger.debug('Recursing from ' + start)
                cmd = "Get-ChildItem -LiteralPath '" + start + "' -Recurse -ErrorAction Ignore | % { $_.FullName }"
                return_code, out_lines, err_lines = self.host.exec_command('powershell -Command "' + cmd.replace('\"', '\\"') + '"')

                if return_code != 0 or len(out_lines) < 1:
                    raise FileNotFoundError(self.args['path'] + ' was not found')

                for l in out_lines:
                    m = re.fullmatch(self.args['path'], l.replace(start, '.'))
                    if m:
                        logger.debug(l + ' matches ' + self.args['path'])
                        paths.append(l)

            else:
                raise ArgumentException('Invalid path: ' + path)

        # TODO imp behavior_windows_view

        filepaths = []
        for path in paths:
            if self.args['behavior_recurse_file_system'] == 'local' and path.startswith('\\\\'):
                continue

            if self.args['value_operations']['filename'] in ['equals', 'case insensitive equals']:
                filepaths.extend(self.search_path_for(path, self.args['filename'], '-eq', self.args['behavior_max_depth'], self.args['behavior_recurse_direction']))

            elif self.args['value_operations']['filename'] in ['not equal', 'case insensitive not equal']:
                raise NotImplementedError(self.args['value_operations']['filename'] + ' operation not supported for ResolvePathFilenameCollector')

            elif self.args['value_operations']['filename'] == 'pattern match':
                filepaths.extend(self.search_path_for(path, self.args['filename'], '-match', self.args['behavior_max_depth'], self.args['behavior_recurse_direction']))

            else:
                raise NotImplementedError('Unknown operation not supported for ResolvePathFilenameCollector filename')

        return filepaths
Example #5
0
    def collect(self):
        if self.args['value_operations']['path'] == 'equals':
            # check if path exists
            col = self.host.load_collector('DirectoryExistsCollector',
                                           {'path': self.args['path']})
            if not col.collect():
                raise FileNotFoundError(self.args['path'] + ' was not found')

            paths = [self.args['path']]

        elif self.args['value_operations']['path'] == 'not equal':
            raise NotImplementedError(
                'not equal operation not supported for ResolvePathFilenameCollector'
            )

        elif self.args['value_operations'][
                'path'] == 'case insensitive equals':
            # check if path exists
            col = self.host.load_collector('DirectoryExistsCollector', {
                'path': self.args['path'],
                'case_insensitive': True
            })
            if not col.collect():
                raise FileNotFoundError(self.args['path'] + ' was not found')

            paths = [self.args['path']]

        elif self.args['value_operations'][
                'path'] == 'case insensitive not equal':
            raise NotImplementedError(
                'not equal operation not supported for ResolvePathFilenameCollector'
            )

        elif self.args['value_operations']['path'] == 'pattern match':
            path = self.args['path'].replace('\"', '\\"')

            cmd = 'find -H / -type d 2>/dev/null | grep --perl-regexp --line-regexp --colour=never "' + path + '"'
            logger.debug(cmd)
            return_code, out_lines, err_lines = self.host.exec_command(cmd)
            if return_code != 0 or len(out_lines) < 1:
                raise FileNotFoundError('Unable to find pattern ' +
                                        self.args['path'] +
                                        '; using base dir ' + basedir +
                                        '; regex ' + regex)

            paths = []
            for d in out_lines:
                col = self.host.load_collector('DirectoryExistsCollector',
                                               {'path': d})
                if col.collect():
                    paths.append(d)

        else:
            raise NotImplementedError(
                'Unknown operation not supported for ResolvePathFilenameCollector'
            )

        opts = []
        if self.args['behavior_recurse_direction'] == 'down':
            if self.args['behavior_max_depth'] == -1:
                pass
            elif self.args['behavior_max_depth'] >= 0:
                opts.append('-maxdepth ' +
                            str(self.args['behavior_max_depth']))
            else:
                raise ArgumentException(
                    'ResolvePathFilenameCollector arg behavior_max_depth is invalid '
                    + str(self.args['behavior_max_depth']))

            if self.args['behavior_recurse_file_system'] == 'defined':
                opts.append('-xdev')
            elif self.args['behavior_recurse_file_system'] == 'local':
                logger.warn(
                    'Local/remote filesystem detection is not yet implemented')
            elif self.args['behavior_recurse_file_system'] == 'all':
                pass
            else:
                raise ArgumentException(
                    'ResolvePathFilenameCollector arg behavior_recurse_file_system is invalid '
                    + str(self.args['behavior_recurse_file_system']))

        elif self.args['behavior_recurse_direction'] == 'none':
            pass
        elif self.args['behavior_recurse_direction'] == 'up':
            raise NotImplementedError(
                'Upward recursion is not yet implemented')
        else:
            raise ArgumentException(
                'ResolvePathFilenameCollector arg behavior_recurse_direction is invalid '
                + str(self.args['behavior_recurse_direction']))

        # NOTE: behavior_windows_view is ignored

        filepaths = []
        filename = self.args['filename'].replace("'", "\\'")
        for path in paths:
            path = path.replace("'", "\\'")
            if self.args['value_operations']['filename'] == 'equals':
                if self.args['behavior_recurse'] == 'directories':
                    # TODO might want to use -H
                    cmd = 'find \'' + path + '\' ' + ' '.join(
                        opts) + ' -name \'' + filename + '\''
                elif self.args['behavior_recurse'] in (
                        'symlinks', 'symlinks and directories'):
                    cmd = 'find -L \'' + path + '\' ' + ' '.join(
                        opts) + ' -name \'' + filename + '\''
                else:
                    raise ArgumentException(
                        'ResolvePathFilenameCollector arg behavior_recurse is invalid '
                        + str(self.args['behavior_recurse']))

                return_code, out_lines, err_lines = self.host.exec_command(cmd)
                if return_code != 0:
                    raise FileNotFoundError('Unable to find ' + filename +
                                            ' in ' + path)

                filepaths.extend(out_lines)

            elif self.args['value_operations']['filename'] == 'not equal':
                raise NotImplementedError(
                    'not equal operation not supported for ResolvePathFilenameCollector'
                )

            elif self.args['value_operations'][
                    'filename'] == 'case insensitive equals':
                if self.args['behavior_recurse'] == 'directories':
                    # TODO might want to use -H
                    cmd = 'find \'' + path + '\' ' + ' '.join(
                        opts) + ' -iname \'' + filename + '\''
                elif self.args['behavior_recurse'] in (
                        'symlinks', 'symlinks and directories'):
                    cmd = 'find -L \'' + path + '\' ' + ' '.join(
                        opts) + ' -iname \'' + filename + '\''
                else:
                    raise ArgumentException(
                        'ResolvePathFilenameCollector arg behavior_recurse is invalid '
                        + str(self.args['behavior_recurse']))

                return_code, out_lines, err_lines = self.host.exec_command(cmd)
                if return_code != 0:
                    raise FileNotFoundError('Unable to find ' + filename +
                                            ' in ' + path)

                filepaths.extend(out_lines)

            elif self.args['value_operations'][
                    'filename'] == 'case insensitive not equal':
                raise NotImplementedError(
                    'not equal operation not supported for ResolvePathFilenameCollector'
                )

            elif self.args['value_operations']['filename'] == 'pattern match':
                if self.args['behavior_recurse'] == 'directories':
                    # TODO might want to use -H
                    cmd = 'find \'' + path + '\' ' + ' '.join(
                        opts) + ' -regex \'' + filename + '\''
                elif self.args['behavior_recurse'] in (
                        'symlinks', 'symlinks and directories'):
                    cmd = 'find -L \'' + path + '\' ' + ' '.join(
                        opts) + ' -regex \'' + filename + '\''
                else:
                    raise ArgumentException(
                        'ResolvePathFilenameCollector arg behavior_recurse is invalid '
                        + str(self.args['behavior_recurse']))

                return_code, out_lines, err_lines = self.host.exec_command(cmd)
                if return_code != 0:
                    raise FileNotFoundError('Unable to find ' + filename +
                                            ' in ' + path)

                filepaths.extend(out_lines)

            else:
                raise NotImplementedError(
                    'Unknown operation not supported for ResolvePathFilenameCollector filename'
                )

        return filepaths
    def __init__(self, host, args):
        super(EnvironmentVariableCollector, self).__init__(host, args)

        if 'name' not in args:
            raise ArgumentException('EnvironmentVariableCollector requires name argument')
Example #7
0
    def __init__(self, host, args):
        super(DirectoryContentsCollector, self).__init__(host, args)

        if 'path' not in args:
            raise ArgumentException(
                'DirectoryContentsCollector requires path argument')