mirror of
https://github.com/mandiant/capa.git
synced 2025-12-22 23:26:21 -08:00
black 20.8b1 updates
This commit is contained in:
@@ -84,7 +84,16 @@ def dumps(extractor):
|
|||||||
returns:
|
returns:
|
||||||
str: the serialized features.
|
str: the serialized features.
|
||||||
"""
|
"""
|
||||||
ret = {"version": 1, "functions": {}, "scopes": {"file": [], "function": [], "basic block": [], "instruction": [],}}
|
ret = {
|
||||||
|
"version": 1,
|
||||||
|
"functions": {},
|
||||||
|
"scopes": {
|
||||||
|
"file": [],
|
||||||
|
"function": [],
|
||||||
|
"basic block": [],
|
||||||
|
"instruction": [],
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
for feature, va in extractor.extract_file_features():
|
for feature, va in extractor.extract_file_features():
|
||||||
ret["scopes"]["file"].append(serialize_feature(feature) + (hex(va), ()))
|
ret["scopes"]["file"].append(serialize_feature(feature) + (hex(va), ()))
|
||||||
@@ -99,7 +108,16 @@ def dumps(extractor):
|
|||||||
ret["functions"][hex(f)][hex(bb)] = []
|
ret["functions"][hex(f)][hex(bb)] = []
|
||||||
|
|
||||||
for feature, va in extractor.extract_basic_block_features(f, bb):
|
for feature, va in extractor.extract_basic_block_features(f, bb):
|
||||||
ret["scopes"]["basic block"].append(serialize_feature(feature) + (hex(va), (hex(f), hex(bb),)))
|
ret["scopes"]["basic block"].append(
|
||||||
|
serialize_feature(feature)
|
||||||
|
+ (
|
||||||
|
hex(va),
|
||||||
|
(
|
||||||
|
hex(f),
|
||||||
|
hex(bb),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
for insnva, insn in sorted(
|
for insnva, insn in sorted(
|
||||||
[(insn.__int__(), insn) for insn in extractor.get_instructions(f, bb)], key=lambda p: p[0]
|
[(insn.__int__(), insn) for insn in extractor.get_instructions(f, bb)], key=lambda p: p[0]
|
||||||
@@ -108,7 +126,15 @@ def dumps(extractor):
|
|||||||
|
|
||||||
for feature, va in extractor.extract_insn_features(f, bb, insn):
|
for feature, va in extractor.extract_insn_features(f, bb, insn):
|
||||||
ret["scopes"]["instruction"].append(
|
ret["scopes"]["instruction"].append(
|
||||||
serialize_feature(feature) + (hex(va), (hex(f), hex(bb), hex(insnva),))
|
serialize_feature(feature)
|
||||||
|
+ (
|
||||||
|
hex(va),
|
||||||
|
(
|
||||||
|
hex(f),
|
||||||
|
hex(bb),
|
||||||
|
hex(insnva),
|
||||||
|
),
|
||||||
|
)
|
||||||
)
|
)
|
||||||
return json.dumps(ret)
|
return json.dumps(ret)
|
||||||
|
|
||||||
|
|||||||
@@ -497,7 +497,13 @@ class CapaExplorerDataModel(QtCore.QAbstractItemModel):
|
|||||||
|
|
||||||
if len(locations) == 1:
|
if len(locations) == 1:
|
||||||
# only one location for feature so no need to nest children
|
# only one location for feature so no need to nest children
|
||||||
parent2 = self.render_capa_doc_feature(parent, feature, next(iter(locations)), doc, display=display,)
|
parent2 = self.render_capa_doc_feature(
|
||||||
|
parent,
|
||||||
|
feature,
|
||||||
|
next(iter(locations)),
|
||||||
|
doc,
|
||||||
|
display=display,
|
||||||
|
)
|
||||||
else:
|
else:
|
||||||
# feature has multiple children, nest under one parent feature node
|
# feature has multiple children, nest under one parent feature node
|
||||||
parent2 = CapaExplorerFeatureItem(parent, display)
|
parent2 = CapaExplorerFeatureItem(parent, display)
|
||||||
|
|||||||
@@ -102,6 +102,9 @@ def collect_metadata():
|
|||||||
"sha256": sha256,
|
"sha256": sha256,
|
||||||
"path": idaapi.get_input_file_path(),
|
"path": idaapi.get_input_file_path(),
|
||||||
},
|
},
|
||||||
"analysis": {"format": idaapi.get_file_type_name(), "extractor": "ida",},
|
"analysis": {
|
||||||
|
"format": idaapi.get_file_type_name(),
|
||||||
|
"extractor": "ida",
|
||||||
|
},
|
||||||
"version": capa.version.__version__,
|
"version": capa.version.__version__,
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -105,7 +105,12 @@ def find_capabilities(ruleset, extractor, disable_progress=None):
|
|||||||
all_function_matches = collections.defaultdict(list)
|
all_function_matches = collections.defaultdict(list)
|
||||||
all_bb_matches = collections.defaultdict(list)
|
all_bb_matches = collections.defaultdict(list)
|
||||||
|
|
||||||
meta = {"feature_counts": {"file": 0, "functions": {},}}
|
meta = {
|
||||||
|
"feature_counts": {
|
||||||
|
"file": 0,
|
||||||
|
"functions": {},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for f in tqdm.tqdm(list(extractor.get_functions()), disable=disable_progress, desc="matching", unit=" functions"):
|
for f in tqdm.tqdm(list(extractor.get_functions()), disable=disable_progress, desc="matching", unit=" functions"):
|
||||||
function_matches, bb_matches, feature_count = find_function_capabilities(ruleset, extractor, f)
|
function_matches, bb_matches, feature_count = find_function_capabilities(ruleset, extractor, f)
|
||||||
|
|||||||
@@ -152,7 +152,10 @@ def convert_match_to_result_document(rules, capabilities, result):
|
|||||||
scope = rule.meta["scope"]
|
scope = rule.meta["scope"]
|
||||||
doc["node"] = {
|
doc["node"] = {
|
||||||
"type": "statement",
|
"type": "statement",
|
||||||
"statement": {"type": "subscope", "subscope": scope,},
|
"statement": {
|
||||||
|
"type": "subscope",
|
||||||
|
"subscope": scope,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
for location in doc["locations"]:
|
for location in doc["locations"]:
|
||||||
@@ -257,5 +260,7 @@ class CapaJsonObjectEncoder(json.JSONEncoder):
|
|||||||
|
|
||||||
def render_json(meta, rules, capabilities):
|
def render_json(meta, rules, capabilities):
|
||||||
return json.dumps(
|
return json.dumps(
|
||||||
convert_capabilities_to_result_document(meta, rules, capabilities), cls=CapaJsonObjectEncoder, sort_keys=True,
|
convert_capabilities_to_result_document(meta, rules, capabilities),
|
||||||
|
cls=CapaJsonObjectEncoder,
|
||||||
|
sort_keys=True,
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -109,7 +109,12 @@ def render_attack(doc, ostream):
|
|||||||
inner_rows.append("%s::%s %s" % (rutils.bold(technique), subtechnique, id))
|
inner_rows.append("%s::%s %s" % (rutils.bold(technique), subtechnique, id))
|
||||||
else:
|
else:
|
||||||
raise RuntimeError("unexpected ATT&CK spec format")
|
raise RuntimeError("unexpected ATT&CK spec format")
|
||||||
rows.append((rutils.bold(tactic.upper()), "\n".join(inner_rows),))
|
rows.append(
|
||||||
|
(
|
||||||
|
rutils.bold(tactic.upper()),
|
||||||
|
"\n".join(inner_rows),
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
if rows:
|
if rows:
|
||||||
ostream.write(
|
ostream.write(
|
||||||
|
|||||||
@@ -399,7 +399,11 @@ def lint_rule(ctx, rule):
|
|||||||
print("")
|
print("")
|
||||||
print(
|
print(
|
||||||
"%s%s %s"
|
"%s%s %s"
|
||||||
% (" (nursery) " if is_nursery_rule(rule) else "", rule.name, ("(%s)" % category) if category else "",)
|
% (
|
||||||
|
" (nursery) " if is_nursery_rule(rule) else "",
|
||||||
|
rule.name,
|
||||||
|
("(%s)" % category) if category else "",
|
||||||
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
level = "WARN" if is_nursery_rule(rule) else "FAIL"
|
level = "WARN" if is_nursery_rule(rule) else "FAIL"
|
||||||
@@ -407,7 +411,12 @@ def lint_rule(ctx, rule):
|
|||||||
for violation in violations:
|
for violation in violations:
|
||||||
print(
|
print(
|
||||||
"%s %s: %s: %s"
|
"%s %s: %s: %s"
|
||||||
% (" " if is_nursery_rule(rule) else "", level, violation.name, violation.recommendation,)
|
% (
|
||||||
|
" " if is_nursery_rule(rule) else "",
|
||||||
|
level,
|
||||||
|
violation.name,
|
||||||
|
violation.recommendation,
|
||||||
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
elif len(violations) == 0 and is_nursery_rule(rule):
|
elif len(violations) == 0 and is_nursery_rule(rule):
|
||||||
@@ -487,7 +496,9 @@ def main(argv=None):
|
|||||||
parser.add_argument("rules", type=str, help="Path to rules")
|
parser.add_argument("rules", type=str, help="Path to rules")
|
||||||
parser.add_argument("--samples", type=str, default=samples_path, help="Path to samples")
|
parser.add_argument("--samples", type=str, default=samples_path, help="Path to samples")
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
"--thorough", action="store_true", help="Enable thorough linting - takes more time, but does a better job",
|
"--thorough",
|
||||||
|
action="store_true",
|
||||||
|
help="Enable thorough linting - takes more time, but does a better job",
|
||||||
)
|
)
|
||||||
parser.add_argument("-v", "--verbose", action="store_true", help="Enable debug logging")
|
parser.add_argument("-v", "--verbose", action="store_true", help="Enable debug logging")
|
||||||
parser.add_argument("-q", "--quiet", action="store_true", help="Disable all output but errors")
|
parser.add_argument("-q", "--quiet", action="store_true", help="Disable all output but errors")
|
||||||
|
|||||||
6
setup.py
6
setup.py
@@ -42,7 +42,11 @@ setuptools.setup(
|
|||||||
url="https://www.github.com/fireeye/capa",
|
url="https://www.github.com/fireeye/capa",
|
||||||
packages=setuptools.find_packages(exclude=["tests"]),
|
packages=setuptools.find_packages(exclude=["tests"]),
|
||||||
package_dir={"capa": "capa"},
|
package_dir={"capa": "capa"},
|
||||||
entry_points={"console_scripts": ["capa=capa.main:main",]},
|
entry_points={
|
||||||
|
"console_scripts": [
|
||||||
|
"capa=capa.main:main",
|
||||||
|
]
|
||||||
|
},
|
||||||
include_package_data=True,
|
include_package_data=True,
|
||||||
install_requires=requirements,
|
install_requires=requirements,
|
||||||
extras_require={
|
extras_require={
|
||||||
|
|||||||
@@ -340,10 +340,20 @@ FEATURE_PRESENCE_TESTS = [
|
|||||||
("mimikatz", "function=0x4556E5", capa.features.insn.API("advapi32.LsaQueryInformationPolicy"), True),
|
("mimikatz", "function=0x4556E5", capa.features.insn.API("advapi32.LsaQueryInformationPolicy"), True),
|
||||||
("mimikatz", "function=0x4556E5", capa.features.insn.API("LsaQueryInformationPolicy"), True),
|
("mimikatz", "function=0x4556E5", capa.features.insn.API("LsaQueryInformationPolicy"), True),
|
||||||
# insn/api: x64
|
# insn/api: x64
|
||||||
("kernel32-64", "function=0x180001010", capa.features.insn.API("RtlVirtualUnwind"), True,),
|
(
|
||||||
|
"kernel32-64",
|
||||||
|
"function=0x180001010",
|
||||||
|
capa.features.insn.API("RtlVirtualUnwind"),
|
||||||
|
True,
|
||||||
|
),
|
||||||
("kernel32-64", "function=0x180001010", capa.features.insn.API("RtlVirtualUnwind"), True),
|
("kernel32-64", "function=0x180001010", capa.features.insn.API("RtlVirtualUnwind"), True),
|
||||||
# insn/api: x64 thunk
|
# insn/api: x64 thunk
|
||||||
("kernel32-64", "function=0x1800202B0", capa.features.insn.API("RtlCaptureContext"), True,),
|
(
|
||||||
|
"kernel32-64",
|
||||||
|
"function=0x1800202B0",
|
||||||
|
capa.features.insn.API("RtlCaptureContext"),
|
||||||
|
True,
|
||||||
|
),
|
||||||
("kernel32-64", "function=0x1800202B0", capa.features.insn.API("RtlCaptureContext"), True),
|
("kernel32-64", "function=0x1800202B0", capa.features.insn.API("RtlCaptureContext"), True),
|
||||||
# insn/api: resolve indirect calls
|
# insn/api: resolve indirect calls
|
||||||
("c91887...", "function=0x401A77", capa.features.insn.API("kernel32.CreatePipe"), True),
|
("c91887...", "function=0x401A77", capa.features.insn.API("kernel32.CreatePipe"), True),
|
||||||
|
|||||||
@@ -59,7 +59,13 @@ def test_some():
|
|||||||
)
|
)
|
||||||
assert (
|
assert (
|
||||||
Some(2, [Number(1), Number(2), Number(3)]).evaluate(
|
Some(2, [Number(1), Number(2), Number(3)]).evaluate(
|
||||||
{Number(0): {1}, Number(1): {1}, Number(2): {1}, Number(3): {1}, Number(4): {1},}
|
{
|
||||||
|
Number(0): {1},
|
||||||
|
Number(1): {1},
|
||||||
|
Number(2): {1},
|
||||||
|
Number(3): {1},
|
||||||
|
Number(4): {1},
|
||||||
|
}
|
||||||
)
|
)
|
||||||
== True
|
== True
|
||||||
)
|
)
|
||||||
@@ -258,7 +264,9 @@ def test_match_matched_rules():
|
|||||||
]
|
]
|
||||||
|
|
||||||
features, matches = capa.engine.match(
|
features, matches = capa.engine.match(
|
||||||
capa.engine.topologically_order_rules(rules), {capa.features.insn.Number(100): {1}}, 0x0,
|
capa.engine.topologically_order_rules(rules),
|
||||||
|
{capa.features.insn.Number(100): {1}},
|
||||||
|
0x0,
|
||||||
)
|
)
|
||||||
assert capa.features.MatchedRule("test rule1") in features
|
assert capa.features.MatchedRule("test rule1") in features
|
||||||
assert capa.features.MatchedRule("test rule2") in features
|
assert capa.features.MatchedRule("test rule2") in features
|
||||||
@@ -266,7 +274,9 @@ def test_match_matched_rules():
|
|||||||
# the ordering of the rules must not matter,
|
# the ordering of the rules must not matter,
|
||||||
# the engine should match rules in an appropriate order.
|
# the engine should match rules in an appropriate order.
|
||||||
features, matches = capa.engine.match(
|
features, matches = capa.engine.match(
|
||||||
capa.engine.topologically_order_rules(reversed(rules)), {capa.features.insn.Number(100): {1}}, 0x0,
|
capa.engine.topologically_order_rules(reversed(rules)),
|
||||||
|
{capa.features.insn.Number(100): {1}},
|
||||||
|
0x0,
|
||||||
)
|
)
|
||||||
assert capa.features.MatchedRule("test rule1") in features
|
assert capa.features.MatchedRule("test rule1") in features
|
||||||
assert capa.features.MatchedRule("test rule2") in features
|
assert capa.features.MatchedRule("test rule2") in features
|
||||||
@@ -312,22 +322,30 @@ def test_regex():
|
|||||||
),
|
),
|
||||||
]
|
]
|
||||||
features, matches = capa.engine.match(
|
features, matches = capa.engine.match(
|
||||||
capa.engine.topologically_order_rules(rules), {capa.features.insn.Number(100): {1}}, 0x0,
|
capa.engine.topologically_order_rules(rules),
|
||||||
|
{capa.features.insn.Number(100): {1}},
|
||||||
|
0x0,
|
||||||
)
|
)
|
||||||
assert capa.features.MatchedRule("test rule") not in features
|
assert capa.features.MatchedRule("test rule") not in features
|
||||||
|
|
||||||
features, matches = capa.engine.match(
|
features, matches = capa.engine.match(
|
||||||
capa.engine.topologically_order_rules(rules), {capa.features.String("aaaa"): {1}}, 0x0,
|
capa.engine.topologically_order_rules(rules),
|
||||||
|
{capa.features.String("aaaa"): {1}},
|
||||||
|
0x0,
|
||||||
)
|
)
|
||||||
assert capa.features.MatchedRule("test rule") not in features
|
assert capa.features.MatchedRule("test rule") not in features
|
||||||
|
|
||||||
features, matches = capa.engine.match(
|
features, matches = capa.engine.match(
|
||||||
capa.engine.topologically_order_rules(rules), {capa.features.String("aBBBBa"): {1}}, 0x0,
|
capa.engine.topologically_order_rules(rules),
|
||||||
|
{capa.features.String("aBBBBa"): {1}},
|
||||||
|
0x0,
|
||||||
)
|
)
|
||||||
assert capa.features.MatchedRule("test rule") not in features
|
assert capa.features.MatchedRule("test rule") not in features
|
||||||
|
|
||||||
features, matches = capa.engine.match(
|
features, matches = capa.engine.match(
|
||||||
capa.engine.topologically_order_rules(rules), {capa.features.String("abbbba"): {1}}, 0x0,
|
capa.engine.topologically_order_rules(rules),
|
||||||
|
{capa.features.String("abbbba"): {1}},
|
||||||
|
0x0,
|
||||||
)
|
)
|
||||||
assert capa.features.MatchedRule("test rule") in features
|
assert capa.features.MatchedRule("test rule") in features
|
||||||
assert capa.features.MatchedRule("rule with implied wildcards") in features
|
assert capa.features.MatchedRule("rule with implied wildcards") in features
|
||||||
@@ -350,7 +368,9 @@ def test_regex_ignorecase():
|
|||||||
),
|
),
|
||||||
]
|
]
|
||||||
features, matches = capa.engine.match(
|
features, matches = capa.engine.match(
|
||||||
capa.engine.topologically_order_rules(rules), {capa.features.String("aBBBBa"): {1}}, 0x0,
|
capa.engine.topologically_order_rules(rules),
|
||||||
|
{capa.features.String("aBBBBa"): {1}},
|
||||||
|
0x0,
|
||||||
)
|
)
|
||||||
assert capa.features.MatchedRule("test rule") in features
|
assert capa.features.MatchedRule("test rule") in features
|
||||||
|
|
||||||
@@ -429,7 +449,9 @@ def test_match_namespace():
|
|||||||
]
|
]
|
||||||
|
|
||||||
features, matches = capa.engine.match(
|
features, matches = capa.engine.match(
|
||||||
capa.engine.topologically_order_rules(rules), {capa.features.insn.API("CreateFile"): {1}}, 0x0,
|
capa.engine.topologically_order_rules(rules),
|
||||||
|
{capa.features.insn.API("CreateFile"): {1}},
|
||||||
|
0x0,
|
||||||
)
|
)
|
||||||
assert "CreateFile API" in matches
|
assert "CreateFile API" in matches
|
||||||
assert "file-create" in matches
|
assert "file-create" in matches
|
||||||
@@ -439,7 +461,9 @@ def test_match_namespace():
|
|||||||
assert capa.features.MatchedRule("file/create/CreateFile") in features
|
assert capa.features.MatchedRule("file/create/CreateFile") in features
|
||||||
|
|
||||||
features, matches = capa.engine.match(
|
features, matches = capa.engine.match(
|
||||||
capa.engine.topologically_order_rules(rules), {capa.features.insn.API("WriteFile"): {1}}, 0x0,
|
capa.engine.topologically_order_rules(rules),
|
||||||
|
{capa.features.insn.API("WriteFile"): {1}},
|
||||||
|
0x0,
|
||||||
)
|
)
|
||||||
assert "WriteFile API" in matches
|
assert "WriteFile API" in matches
|
||||||
assert "file-create" not in matches
|
assert "file-create" not in matches
|
||||||
|
|||||||
@@ -21,13 +21,19 @@ import capa.features.extractors
|
|||||||
EXTRACTOR = capa.features.extractors.NullFeatureExtractor(
|
EXTRACTOR = capa.features.extractors.NullFeatureExtractor(
|
||||||
{
|
{
|
||||||
"base address": 0x401000,
|
"base address": 0x401000,
|
||||||
"file features": [(0x402345, capa.features.Characteristic("embedded pe")),],
|
"file features": [
|
||||||
|
(0x402345, capa.features.Characteristic("embedded pe")),
|
||||||
|
],
|
||||||
"functions": {
|
"functions": {
|
||||||
0x401000: {
|
0x401000: {
|
||||||
"features": [(0x401000, capa.features.Characteristic("indirect call")),],
|
"features": [
|
||||||
|
(0x401000, capa.features.Characteristic("indirect call")),
|
||||||
|
],
|
||||||
"basic blocks": {
|
"basic blocks": {
|
||||||
0x401000: {
|
0x401000: {
|
||||||
"features": [(0x401000, capa.features.Characteristic("tight loop")),],
|
"features": [
|
||||||
|
(0x401000, capa.features.Characteristic("tight loop")),
|
||||||
|
],
|
||||||
"instructions": {
|
"instructions": {
|
||||||
0x401000: {
|
0x401000: {
|
||||||
"features": [
|
"features": [
|
||||||
@@ -35,7 +41,11 @@ EXTRACTOR = capa.features.extractors.NullFeatureExtractor(
|
|||||||
(0x401000, capa.features.Characteristic("nzxor")),
|
(0x401000, capa.features.Characteristic("nzxor")),
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
0x401002: {"features": [(0x401002, capa.features.insn.Mnemonic("mov")),],},
|
0x401002: {
|
||||||
|
"features": [
|
||||||
|
(0x401002, capa.features.insn.Mnemonic("mov")),
|
||||||
|
],
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -44,7 +44,17 @@ def test_main_single_rule(z9324d_extractor, tmpdir):
|
|||||||
path = z9324d_extractor.path
|
path = z9324d_extractor.path
|
||||||
rule_file = tmpdir.mkdir("capa").join("rule.yml")
|
rule_file = tmpdir.mkdir("capa").join("rule.yml")
|
||||||
rule_file.write(RULE_CONTENT)
|
rule_file.write(RULE_CONTENT)
|
||||||
assert capa.main.main([path, "-v", "-r", rule_file.strpath,]) == 0
|
assert (
|
||||||
|
capa.main.main(
|
||||||
|
[
|
||||||
|
path,
|
||||||
|
"-v",
|
||||||
|
"-r",
|
||||||
|
rule_file.strpath,
|
||||||
|
]
|
||||||
|
)
|
||||||
|
== 0
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.xfail(sys.version_info >= (3, 0), reason="vivsect only works on py2")
|
@pytest.mark.xfail(sys.version_info >= (3, 0), reason="vivsect only works on py2")
|
||||||
|
|||||||
@@ -680,12 +680,16 @@ def test_regex_values_always_string():
|
|||||||
),
|
),
|
||||||
]
|
]
|
||||||
features, matches = capa.engine.match(
|
features, matches = capa.engine.match(
|
||||||
capa.engine.topologically_order_rules(rules), {capa.features.String("123"): {1}}, 0x0,
|
capa.engine.topologically_order_rules(rules),
|
||||||
|
{capa.features.String("123"): {1}},
|
||||||
|
0x0,
|
||||||
)
|
)
|
||||||
assert capa.features.MatchedRule("test rule") in features
|
assert capa.features.MatchedRule("test rule") in features
|
||||||
|
|
||||||
features, matches = capa.engine.match(
|
features, matches = capa.engine.match(
|
||||||
capa.engine.topologically_order_rules(rules), {capa.features.String("0x123"): {1}}, 0x0,
|
capa.engine.topologically_order_rules(rules),
|
||||||
|
{capa.features.String("0x123"): {1}},
|
||||||
|
0x0,
|
||||||
)
|
)
|
||||||
assert capa.features.MatchedRule("test rule") in features
|
assert capa.features.MatchedRule("test rule") in features
|
||||||
|
|
||||||
|
|||||||
@@ -11,7 +11,9 @@ from fixtures import *
|
|||||||
|
|
||||||
|
|
||||||
@parametrize(
|
@parametrize(
|
||||||
"sample,scope,feature,expected", FEATURE_PRESENCE_TESTS, indirect=["sample", "scope"],
|
"sample,scope,feature,expected",
|
||||||
|
FEATURE_PRESENCE_TESTS,
|
||||||
|
indirect=["sample", "scope"],
|
||||||
)
|
)
|
||||||
def test_viv_features(sample, scope, feature, expected):
|
def test_viv_features(sample, scope, feature, expected):
|
||||||
with xfail(sys.version_info >= (3, 0), reason="vivsect only works on py2"):
|
with xfail(sys.version_info >= (3, 0), reason="vivsect only works on py2"):
|
||||||
@@ -19,7 +21,9 @@ def test_viv_features(sample, scope, feature, expected):
|
|||||||
|
|
||||||
|
|
||||||
@parametrize(
|
@parametrize(
|
||||||
"sample,scope,feature,expected", FEATURE_COUNT_TESTS, indirect=["sample", "scope"],
|
"sample,scope,feature,expected",
|
||||||
|
FEATURE_COUNT_TESTS,
|
||||||
|
indirect=["sample", "scope"],
|
||||||
)
|
)
|
||||||
def test_viv_feature_counts(sample, scope, feature, expected):
|
def test_viv_feature_counts(sample, scope, feature, expected):
|
||||||
with xfail(sys.version_info >= (3, 0), reason="vivsect only works on py2"):
|
with xfail(sys.version_info >= (3, 0), reason="vivsect only works on py2"):
|
||||||
|
|||||||
Reference in New Issue
Block a user