diff --git a/CHANGELOG.md b/CHANGELOG.md index 4c9b0d53..a30bdf94 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -27,6 +27,7 @@ ### Bug Fixes - cape: make some fields optional @williballenthin #2631 #2632 - lint: add WARN for regex features that contain unescaped dot #2635 +- lint: add ERROR for incomplete registry control set regex #2643 ### capa Explorer Web diff --git a/scripts/lint.py b/scripts/lint.py index 0f69d246..1a64ad64 100644 --- a/scripts/lint.py +++ b/scripts/lint.py @@ -721,6 +721,29 @@ class FeatureStringTooShort(Lint): return False +class FeatureRegexRegistryControlSetMatchIncomplete(Lint): + name = "feature regex registry control set match incomplete" + recommendation = ( + 'use "(ControlSet\\d{3}|CurrentControlSet)" to match both indirect references ' + + 'via "CurrentControlSet" and direct references via "ControlSetXXX"' + ) + + def check_features(self, ctx: Context, features: list[Feature]): + for feature in features: + if not isinstance(feature, (Regex,)): + continue + + assert isinstance(feature.value, str) + + pat = feature.value.lower() + + if "system\\\\" in pat and "controlset" in pat or "currentcontrolset" in pat: + if "system\\\\(controlset\\d{3}|currentcontrolset)" not in pat: + return True + + return False + + class FeatureRegexContainsUnescapedPeriod(Lint): name = "feature regex contains unescaped period" recommendation_template = 'escape the period in "{:s}" unless it should be treated as a regex dot operator' @@ -983,6 +1006,7 @@ FEATURE_LINTS = ( FeatureNegativeNumber(), FeatureNtdllNtoskrnlApi(), FeatureRegexContainsUnescapedPeriod(), + FeatureRegexRegistryControlSetMatchIncomplete(), )