Files
capa/tests/test_helpers.py
2026-04-23 18:04:10 +03:00

146 lines
4.9 KiB
Python

# Copyright 2020 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License 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.
import codecs
from pathlib import Path
import pytest
import capa.helpers
from capa.helpers import (
EXTENSIONS_ELF,
EXTENSIONS_FREEZE,
EXTENSIONS_DYNAMIC,
EXTENSIONS_BINJA_DB,
EXTENSIONS_BINEXPORT2,
EXTENSIONS_SHELLCODE_32,
EXTENSIONS_SHELLCODE_64,
)
from capa.features.extractors import helpers
CD = Path(__file__).resolve().parent
DRAKVUF_LOG_GZ = (
CD / "data" / "dynamic" / "drakvuf" / "93b2d1840566f45fab674ebc79a9d19c88993bcb645e0357f3cb584d16e7c795.log.gz"
)
def test_all_zeros():
a = b"\x00\x00\x00\x00"
b = codecs.decode(b"00000000", "hex")
c = b"\x01\x00\x00\x00"
d = codecs.decode(b"01000000", "hex")
assert helpers.all_zeros(a) is True
assert helpers.all_zeros(b) is True
assert helpers.all_zeros(c) is False
assert helpers.all_zeros(d) is False
def test_generate_symbols():
assert list(helpers.generate_symbols("name.dll", "api", include_dll=True)) == list(
helpers.generate_symbols("name", "api", include_dll=True)
)
assert list(helpers.generate_symbols("name.dll", "api", include_dll=False)) == list(
helpers.generate_symbols("name", "api", include_dll=False)
)
# A/W import
symbols = list(helpers.generate_symbols("kernel32", "CreateFileA", include_dll=True))
assert len(symbols) == 4
assert "kernel32.CreateFileA" in symbols
assert "kernel32.CreateFile" in symbols
assert "CreateFileA" in symbols
assert "CreateFile" in symbols
# import
symbols = list(helpers.generate_symbols("kernel32", "WriteFile", include_dll=True))
assert len(symbols) == 2
assert "kernel32.WriteFile" in symbols
assert "WriteFile" in symbols
# ordinal import
symbols = list(helpers.generate_symbols("ws2_32", "#1", include_dll=True))
assert len(symbols) == 1
assert "ws2_32.#1" in symbols
# A/W api
symbols = list(helpers.generate_symbols("kernel32", "CreateFileA", include_dll=False))
assert len(symbols) == 2
assert "CreateFileA" in symbols
assert "CreateFile" in symbols
# api
symbols = list(helpers.generate_symbols("kernel32", "WriteFile", include_dll=False))
assert len(symbols) == 1
assert "WriteFile" in symbols
# ordinal api
symbols = list(helpers.generate_symbols("ws2_32", "#1", include_dll=False))
assert len(symbols) == 1
assert "ws2_32.#1" in symbols
def test_is_dev_environment():
# testing environment should be a dev environment
assert capa.helpers.is_dev_environment() is True
def test_load_one_jsonl_from_path_gz():
result = capa.helpers.load_one_jsonl_from_path(DRAKVUF_LOG_GZ)
assert isinstance(result, dict)
assert "Plugin" in result
def test_load_one_jsonl_from_path_plain(tmp_path):
p = tmp_path / "sample.jsonl"
p.write_bytes(b'{"key": "value"}\n{"key": "second"}\n')
result = capa.helpers.load_one_jsonl_from_path(p)
assert result == {"key": "value"}
def test_load_one_jsonl_from_path_empty_raises(tmp_path):
p = tmp_path / "empty.jsonl"
p.write_bytes(b"")
with pytest.raises(StopIteration):
capa.helpers.load_one_jsonl_from_path(p)
def test_extensions_dot_prefix():
for ext_group in (
EXTENSIONS_SHELLCODE_32,
EXTENSIONS_SHELLCODE_64,
EXTENSIONS_DYNAMIC,
EXTENSIONS_BINEXPORT2,
(EXTENSIONS_ELF,),
(EXTENSIONS_FREEZE,),
(EXTENSIONS_BINJA_DB,),
):
for ext in ext_group:
assert ext.startswith("."), f"extension {ext!r} must start with a dot"
assert Path("sample.log").name.endswith(EXTENSIONS_DYNAMIC)
assert not Path("dialog").name.endswith(EXTENSIONS_DYNAMIC)
assert not Path("catalog").name.endswith(EXTENSIONS_DYNAMIC)
assert Path("report.json").name.endswith(EXTENSIONS_DYNAMIC)
assert not Path("notajson").name.endswith(EXTENSIONS_DYNAMIC)
assert Path("sample.sc32").name.endswith(EXTENSIONS_SHELLCODE_32)
assert Path("sample.raw32").name.endswith(EXTENSIONS_SHELLCODE_32)
assert Path("sample.sc64").name.endswith(EXTENSIONS_SHELLCODE_64)
assert Path("sample.raw64").name.endswith(EXTENSIONS_SHELLCODE_64)
assert Path("sample.BinExport").name.endswith(EXTENSIONS_BINEXPORT2)
assert Path("sample.BinExport2").name.endswith(EXTENSIONS_BINEXPORT2)
assert Path("sample.elf_").name.endswith(EXTENSIONS_ELF)
assert Path("sample.frz").name.endswith(EXTENSIONS_FREEZE)
assert Path("sample.bndb").name.endswith(EXTENSIONS_BINJA_DB)