diff --git a/CHANGELOG.md b/CHANGELOG.md index e8a37384..007c25f9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -303,7 +303,7 @@ For those that use capa as a library, we've introduced some limited breaking cha - [capa-rules v5.1.0...v6.0.0](https://github.com/mandiant/capa-rules/compare/v5.1.0...v6.0.0) ## v5.1.0 -capa version 5.1.0 adds a Protocol Buffers (protobuf) format for result documents. Additionally, the [Vector35](https://vector35.com/) team contributed a new feature extractor using Binary Ninja. Other new features are a new CLI flag to override the detected operating system, functionality to read and render existing result documents, and a output color format that's easier to read. +capa version 5.1.0 adds a Protocol Buffers (protobuf) format for result documents. Additionally, the [Vector35](https://vector35.com/) team contributed a new feature extractor using Binary Ninja. Other new features are a new CLI flag to override the detected operating system, functionality to read and render existing result documents, and an output color format that's easier to read. Over 25 capa rules have been added and improved. @@ -1502,7 +1502,7 @@ The IDA Pro integration is now distributed as a real plugin, instead of a script - updates distributed PyPI/`pip install --upgrade` without touching your `%IDADIR%` - generally doing thing the "right way" -How to get this new version? Its easy: download [capa_explorer.py](https://raw.githubusercontent.com/mandiant/capa/master/capa/ida/plugin/capa_explorer.py) to your IDA plugins directory and update your capa installation (incidentally, this is a good opportunity to migrate to `pip install flare-capa` instead of git checkouts). Now you should see the plugin listed in the `Edit > Plugins > FLARE capa explorer` menu in IDA. +How to get this new version? It's easy: download [capa_explorer.py](https://raw.githubusercontent.com/mandiant/capa/master/capa/ida/plugin/capa_explorer.py) to your IDA plugins directory and update your capa installation (incidentally, this is a good opportunity to migrate to `pip install flare-capa` instead of git checkouts). Now you should see the plugin listed in the `Edit > Plugins > FLARE capa explorer` menu in IDA. Please refer to the plugin [readme](https://github.com/mandiant/capa/blob/master/capa/ida/plugin/README.md) for additional information on installing and using the IDA Pro plugin. diff --git a/capa/features/common.py b/capa/features/common.py index 4b02b5ce..2e3762b6 100644 --- a/capa/features/common.py +++ b/capa/features/common.py @@ -128,7 +128,7 @@ class Feature(abc.ABC): # noqa: B024 def __lt__(self, other): # implementing sorting by serializing to JSON is a huge hack. - # its slow, inelegant, and probably doesn't work intuitively; + # it's slow, inelegant, and probably doesn't work intuitively; # however, we only use it for deterministic output, so it's good enough for now. # circular import @@ -227,7 +227,7 @@ class Substring(String): if self.value in feature.value: matches[feature.value].update(locations) if short_circuit: - # we found one matching string, thats sufficient to match. + # we found one matching string, that's sufficient to match. # don't collect other matching strings in this mode. break @@ -322,7 +322,7 @@ class Regex(String): if self.re.search(feature.value): matches[feature.value].update(locations) if short_circuit: - # we found one matching string, thats sufficient to match. + # we found one matching string, that's sufficient to match. # don't collect other matching strings in this mode. break diff --git a/capa/features/extractors/ghidra/extractor.py b/capa/features/extractors/ghidra/extractor.py index 0c3db587..c7ed637b 100644 --- a/capa/features/extractors/ghidra/extractor.py +++ b/capa/features/extractors/ghidra/extractor.py @@ -34,7 +34,7 @@ class GhidraFeatureExtractor(StaticFeatureExtractor): # https://ghidra.re/ghidra_docs/api/ghidra/program/model/listing/Program.html # # the hashes are stored in the database, not computed on the fly, - # so its probably not trivial to add SHA1. + # so it's probably not trivial to add SHA1. sha1="", sha256=capa.ghidra.helpers.get_file_sha256(), ) diff --git a/capa/features/freeze/__init__.py b/capa/features/freeze/__init__.py index 5dfa3fc7..ec0d6f60 100644 --- a/capa/features/freeze/__init__.py +++ b/capa/features/freeze/__init__.py @@ -485,7 +485,7 @@ def dumps_dynamic(extractor: DynamicFeatureExtractor) -> str: address=Address.from_capa(addr), feature=feature_from_capa(feature), ) # type: ignore - # Mypy is unable to recognise `basic_block` as a argument due to alias + # Mypy is unable to recognise `basic_block` as an argument due to alias for feature, addr in extractor.extract_thread_features(p, t) ] diff --git a/capa/ida/plugin/__init__.py b/capa/ida/plugin/__init__.py index a24e7d38..231fdf58 100644 --- a/capa/ida/plugin/__init__.py +++ b/capa/ida/plugin/__init__.py @@ -125,7 +125,7 @@ def install_icon(): return False # resource leak here. need to call `ida_kernwin.free_custom_icon`? - # however, since we're not cycling this icon a lot, its probably ok. + # however, since we're not cycling this icon a lot, it's probably ok. # expect to leak exactly one icon per application load. icon = ida_kernwin.load_custom_icon(data=ICON) diff --git a/capa/render/result_document.py b/capa/render/result_document.py index d2de49d7..975e3743 100644 --- a/capa/render/result_document.py +++ b/capa/render/result_document.py @@ -418,7 +418,7 @@ class Match(FrozenModel): # doc[locations] contains all matches for the given namespace. # for example, the feature might be `match: anti-analysis/packer` # which matches against "generic unpacker" and "UPX". - # in this case, doc[locations] contains locations for *both* of thse. + # in this case, doc[locations] contains locations for *both* of those. # # rule_matches contains the matches for the specific rule. # this is a subset of doc[locations]. diff --git a/capa/render/vverbose.py b/capa/render/vverbose.py index ac167467..2ee2af49 100644 --- a/capa/render/vverbose.py +++ b/capa/render/vverbose.py @@ -48,7 +48,7 @@ def hanging_indent(s: str, indent: int) -> str: def render_locations(ostream, layout: rd.Layout, locations: Iterable[frz.Address], indent: int): import capa.render.verbose as v - # its possible to have an empty locations array here, + # it's possible to have an empty locations array here, # such as when we're in MODE_FAILURE and showing the logic # under a `not` statement (which will have no matched locations). locations = sorted(locations) diff --git a/capa/rules/__init__.py b/capa/rules/__init__.py index 67d0b03e..4154cb3c 100644 --- a/capa/rules/__init__.py +++ b/capa/rules/__init__.py @@ -859,7 +859,7 @@ class Rule: # we'll give precedence to namespaces, and then assume if that does work, # that it must be a rule name. # - # we don't expect any collisions between namespaces and rule names, but its possible. + # we don't expect any collisions between namespaces and rule names, but it's possible. # most likely would be collision between top level namespace (e.g. `host-interaction`) and rule name. # but, namespaces tend to use `-` while rule names use ` `. so, unlikely, but possible. if statement.value in namespaces: @@ -1536,7 +1536,7 @@ class RuleSet: # don't consider it easy, and therefore, # don't index any of its features. # - # otherwise, its an easy rule, and index its features + # otherwise, it's an easy rule, and index its features for rules_with_feature in rules_by_feature.values(): rules_with_feature.difference_update(rules_with_hard_features) easy_rules_by_feature = rules_by_feature diff --git a/scripts/capa2yara.py b/scripts/capa2yara.py index 91eecdd9..ba694efb 100644 --- a/scripts/capa2yara.py +++ b/scripts/capa2yara.py @@ -194,7 +194,7 @@ def convert_rule(rule, rulename, cround, depth): yara_strings += "\t$" + var_name + ' = "' + string + '" ascii wide' + convert_description(kid) + "\n" yara_condition += "\t$" + var_name + " " elif s_type == "api" or s_type == "import": - # research needed to decide if its possible in YARA to make a difference between api & import? + # research needed to decide if it's possible in YARA to make a difference between api & import? # https://github.com/mandiant/capa-rules/blob/master/doc/format.md#api api = kid.value diff --git a/tests/test_ghidra_features.py b/tests/test_ghidra_features.py index dc51aef4..595cf4dc 100644 --- a/tests/test_ghidra_features.py +++ b/tests/test_ghidra_features.py @@ -6,7 +6,7 @@ # is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and limitations under the License. """ -Must invoke this script from within the Ghidra Runtime Enviornment +Must invoke this script from within the Ghidra Runtime Environment """ import sys import logging