diff --git a/volatility/framework/layers/scanners/__init__.py b/volatility/framework/layers/scanners/__init__.py index 21e78f559..0c204bad4 100644 --- a/volatility/framework/layers/scanners/__init__.py +++ b/volatility/framework/layers/scanners/__init__.py @@ -2,7 +2,7 @@ import re import typing from volatility.framework.interfaces import layers -from volatility.framework.layers.scanners import wumanber +from volatility.framework.layers.scanners import multiregexp class BytesScanner(layers.ScannerInterface): @@ -44,7 +44,7 @@ class MultiStringScanner(layers.ScannerInterface): def __init__(self, patterns: typing.List[bytes]) -> None: super().__init__() self._check_type(patterns, list) - self._patterns = wumanber.WuManber() + self._patterns = multiregexp.MultiRegexp() for pattern in patterns: self._check_type(pattern, bytes) self._patterns.add_pattern(pattern) diff --git a/volatility/framework/layers/scanners/multiregexp.py b/volatility/framework/layers/scanners/multiregexp.py new file mode 100644 index 000000000..07206cae2 --- /dev/null +++ b/volatility/framework/layers/scanners/multiregexp.py @@ -0,0 +1,23 @@ +import re +import typing + + +class MultiRegexp(object): + """Algorithm for multi-string matching""" + + def __init__(self) -> None: + self._pattern_strings = [] # type: typing.List[bytes] + self._regex = re.compile(b'') + + def add_pattern(self, pattern: bytes) -> None: + self._pattern_strings.append(pattern) + + def preprocess(self) -> None: + self._regex = re.compile(b'|'.join(map(re.escape, self._pattern_strings))) + + def search(self, haystack: bytes) \ + -> typing.Generator[typing.Tuple[int, typing.Union[str, bytes]], None, None]: + if not isinstance(haystack, bytes): + raise TypeError("Search haystack must be a byte string") + for match in re.finditer(self._regex, haystack): + yield (match.start(0), match.group())