fix: capabilities/common.py: if va: drops address 0x0

Closes #3015
This commit is contained in:
Willi Ballenthin
2026-04-22 09:13:17 +03:00
committed by Willi Ballenthin
parent 0345a15744
commit d3e2bac803
3 changed files with 38 additions and 4 deletions

View File

@@ -16,6 +16,8 @@
- fix: _NoAddress.__eq__ unconditionally returns True @williballenthin #3014
- fix: capabilities/common.py: if va: drops address 0x0 @williballenthin #3015
### capa Explorer Web
### capa Explorer IDA Pro plugin

View File

@@ -43,11 +43,11 @@ def find_file_capabilities(
# not all file features may have virtual addresses.
# if not, then at least ensure the feature shows up in the index.
# the set of addresses will still be empty.
if va:
file_features[feature].add(va)
else:
if va is NO_ADDRESS:
if feature not in file_features:
file_features[feature] = set()
else:
file_features[feature].add(va)
logger.debug("analyzed file and extracted %d features", len(file_features))

View File

@@ -15,8 +15,11 @@
import textwrap
import capa.rules
import capa.features.common
import capa.capabilities.common
from capa.features.extractors.base_extractor import FunctionFilter
import capa.features.extractors.null
from capa.features.address import AbsoluteVirtualAddress
from capa.features.extractors.base_extractor import SampleHashes, FunctionFilter
def test_match_across_scopes_file_function(z9324d_extractor):
@@ -302,3 +305,32 @@ def test_instruction_subscope(z9324d_extractor):
capabilities = capa.capabilities.common.find_capabilities(rules, z9324d_extractor)
assert "push 1000 on i386" in capabilities.matches
assert 0x406F60 in {result[0] for result in capabilities.matches["push 1000 on i386"]}
def test_find_file_capabilities_preserves_address_zero():
feature = capa.features.common.Characteristic("embedded pe")
addr = AbsoluteVirtualAddress(0)
extractor = capa.features.extractors.null.NullStaticFeatureExtractor(
base_address=AbsoluteVirtualAddress(0),
sample_hashes=SampleHashes(md5="a" * 32, sha1="b" * 40, sha256="c" * 64),
global_features=[],
file_features=[(addr, feature)],
functions={},
)
rules = capa.rules.RuleSet([
capa.rules.Rule.from_yaml(
textwrap.dedent("""
rule:
meta:
name: embedded pe
scopes:
static: file
dynamic: process
features:
- characteristic: embedded pe
""")
)
])
caps = capa.capabilities.common.find_file_capabilities(rules, extractor, {})
assert feature in caps.features
assert addr in caps.features[feature]