mirror of
https://github.com/mandiant/capa.git
synced 2025-12-12 15:49:46 -08:00
dnfile: fix types
This commit is contained in:
@@ -12,8 +12,6 @@ import capa.features.extractors.pefile
|
|||||||
from capa.features.common import OS, FORMAT_PE, FORMAT_ELF, OS_WINDOWS, FORMAT_FREEZE, Arch, Format, String, Feature
|
from capa.features.common import OS, FORMAT_PE, FORMAT_ELF, OS_WINDOWS, FORMAT_FREEZE, Arch, Format, String, Feature
|
||||||
from capa.features.freeze import is_freeze
|
from capa.features.freeze import is_freeze
|
||||||
from capa.features.address import NO_ADDRESS, Address, FileOffsetAddress
|
from capa.features.address import NO_ADDRESS, Address, FileOffsetAddress
|
||||||
from capa.features.common import OS, FORMAT_PE, FORMAT_ELF, OS_WINDOWS, FORMAT_FREEZE, Arch, Format, String
|
|
||||||
from capa.features.freeze import is_freeze
|
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|||||||
@@ -14,22 +14,23 @@ if TYPE_CHECKING:
|
|||||||
import dnfile
|
import dnfile
|
||||||
from capa.features.common import Feature, Format
|
from capa.features.common import Feature, Format
|
||||||
from capa.features.file import Import
|
from capa.features.file import Import
|
||||||
|
from capa.features.address import Address
|
||||||
|
|
||||||
import capa.features.extractors
|
import capa.features.extractors
|
||||||
|
|
||||||
|
|
||||||
def extract_file_import_names(pe: dnfile.dnPE) -> Iterator[Tuple[Import, int]]:
|
def extract_file_import_names(pe: dnfile.dnPE) -> Iterator[Tuple[Import, Address]]:
|
||||||
yield from capa.features.extractors.dotnetfile.extract_file_import_names(pe)
|
yield from capa.features.extractors.dotnetfile.extract_file_import_names(pe)
|
||||||
|
|
||||||
|
|
||||||
def extract_file_format(pe: dnfile.dnPE) -> Iterator[Tuple[Format, int]]:
|
def extract_file_format(pe: dnfile.dnPE) -> Iterator[Tuple[Format, Address]]:
|
||||||
yield from capa.features.extractors.dotnetfile.extract_file_format(pe=pe)
|
yield from capa.features.extractors.dotnetfile.extract_file_format(pe=pe)
|
||||||
|
|
||||||
|
|
||||||
def extract_features(pe: dnfile.dnPE) -> Iterator[Tuple[Feature, int]]:
|
def extract_features(pe: dnfile.dnPE) -> Iterator[Tuple[Feature, Address]]:
|
||||||
for file_handler in FILE_HANDLERS:
|
for file_handler in FILE_HANDLERS:
|
||||||
for (feature, token) in file_handler(pe):
|
for (feature, address) in file_handler(pe):
|
||||||
yield feature, token
|
yield feature, address
|
||||||
|
|
||||||
|
|
||||||
FILE_HANDLERS = (
|
FILE_HANDLERS = (
|
||||||
|
|||||||
@@ -152,12 +152,12 @@ def get_dotnet_unmanaged_imports(pe: dnfile.dnPE) -> Iterator[Tuple[int, str]]:
|
|||||||
yield token, imp
|
yield token, imp
|
||||||
|
|
||||||
|
|
||||||
def get_dotnet_managed_method_bodies(pe: dnfile.dnPE) -> Iterator[CilMethodBody]:
|
def get_dotnet_managed_method_bodies(pe: dnfile.dnPE) -> Iterator[Tuple[int, CilMethodBody]]:
|
||||||
"""get managed methods from MethodDef table"""
|
"""get managed methods from MethodDef table"""
|
||||||
if not hasattr(pe.net.mdtables, "MethodDef"):
|
if not hasattr(pe.net.mdtables, "MethodDef"):
|
||||||
return
|
return
|
||||||
|
|
||||||
for row in pe.net.mdtables.MethodDef:
|
for (rid, row) in enumerate(pe.net.mdtables.MethodDef):
|
||||||
if not row.ImplFlags.miIL or any((row.Flags.mdAbstract, row.Flags.mdPinvokeImpl)):
|
if not row.ImplFlags.miIL or any((row.Flags.mdAbstract, row.Flags.mdPinvokeImpl)):
|
||||||
# skip methods that do not have a method body
|
# skip methods that do not have a method body
|
||||||
continue
|
continue
|
||||||
@@ -166,4 +166,5 @@ def get_dotnet_managed_method_bodies(pe: dnfile.dnPE) -> Iterator[CilMethodBody]
|
|||||||
if body is None:
|
if body is None:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
yield body
|
token: int = calculate_dotnet_token_value(dnfile.enums.MetadataTables.MethodDef.value, rid + 1)
|
||||||
|
yield token, body
|
||||||
|
|||||||
@@ -11,15 +11,15 @@ from capa.features.extractors.base_extractor import FeatureExtractor
|
|||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
def extract_file_format(**kwargs):
|
def extract_file_format(**kwargs) -> Iterator[Tuple[Feature, Address]]:
|
||||||
yield Format(FORMAT_DOTNET), NO_ADDRESS
|
yield Format(FORMAT_DOTNET), NO_ADDRESS
|
||||||
|
|
||||||
|
|
||||||
def extract_file_os(**kwargs):
|
def extract_file_os(**kwargs) -> Iterator[Tuple[Feature, Address]]:
|
||||||
yield OS(OS_ANY), NO_ADDRESS
|
yield OS(OS_ANY), NO_ADDRESS
|
||||||
|
|
||||||
|
|
||||||
def extract_file_arch(pe, **kwargs):
|
def extract_file_arch(pe, **kwargs) -> Iterator[Tuple[Feature, Address]]:
|
||||||
# to distinguish in more detail, see https://stackoverflow.com/a/23614024/10548020
|
# to distinguish in more detail, see https://stackoverflow.com/a/23614024/10548020
|
||||||
# .NET 4.5 added option: any CPU, 32-bit preferred
|
# .NET 4.5 added option: any CPU, 32-bit preferred
|
||||||
if pe.net.Flags.CLR_32BITREQUIRED and pe.PE_TYPE == pefile.OPTIONAL_HEADER_MAGIC_PE:
|
if pe.net.Flags.CLR_32BITREQUIRED and pe.PE_TYPE == pefile.OPTIONAL_HEADER_MAGIC_PE:
|
||||||
|
|||||||
@@ -12,8 +12,6 @@ import idautils
|
|||||||
|
|
||||||
import capa.features.extractors.helpers
|
import capa.features.extractors.helpers
|
||||||
import capa.features.extractors.ida.helpers
|
import capa.features.extractors.ida.helpers
|
||||||
from capa.features.insn import API, Number, Offset, Mnemonic, OperandNumber, OperandOffset
|
|
||||||
from capa.features.common import MAX_BYTES_FEATURE_SIZE, THUNK_CHAIN_DEPTH_DELTA, Bytes, String, Characteristic
|
|
||||||
from capa.features.insn import API, MAX_STRUCTURE_SIZE, Number, Offset, Mnemonic, OperandNumber, OperandOffset
|
from capa.features.insn import API, MAX_STRUCTURE_SIZE, Number, Offset, Mnemonic, OperandNumber, OperandOffset
|
||||||
from capa.features.common import MAX_BYTES_FEATURE_SIZE, THUNK_CHAIN_DEPTH_DELTA, Bytes, String, Characteristic
|
from capa.features.common import MAX_BYTES_FEATURE_SIZE, THUNK_CHAIN_DEPTH_DELTA, Bytes, String, Characteristic
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import struct
|
|||||||
from typing import Tuple, Iterator
|
from typing import Tuple, Iterator
|
||||||
|
|
||||||
from capa.features.common import Feature, Characteristic
|
from capa.features.common import Feature, Characteristic
|
||||||
from capa.features.address import Address, AbsoluteVirtualAddress
|
from capa.features.address import Address
|
||||||
from capa.features.basicblock import BasicBlock
|
from capa.features.basicblock import BasicBlock
|
||||||
from capa.features.extractors.helpers import MIN_STACKSTRING_LEN
|
from capa.features.extractors.helpers import MIN_STACKSTRING_LEN
|
||||||
from capa.features.extractors.base_extractor import BBHandle, FunctionHandle
|
from capa.features.extractors.base_extractor import BBHandle, FunctionHandle
|
||||||
|
|||||||
@@ -10,8 +10,6 @@ from capa.features.insn import API, MAX_STRUCTURE_SIZE, Number, Offset, Mnemonic
|
|||||||
from capa.features.common import MAX_BYTES_FEATURE_SIZE, THUNK_CHAIN_DEPTH_DELTA, Bytes, String, Feature, Characteristic
|
from capa.features.common import MAX_BYTES_FEATURE_SIZE, THUNK_CHAIN_DEPTH_DELTA, Bytes, String, Feature, Characteristic
|
||||||
from capa.features.address import Address, AbsoluteVirtualAddress
|
from capa.features.address import Address, AbsoluteVirtualAddress
|
||||||
from capa.features.extractors.base_extractor import BBHandle, InsnHandle, FunctionHandle
|
from capa.features.extractors.base_extractor import BBHandle, InsnHandle, FunctionHandle
|
||||||
from capa.features.insn import API, MAX_STRUCTURE_SIZE, Number, Offset, Mnemonic, OperandNumber, OperandOffset
|
|
||||||
from capa.features.common import MAX_BYTES_FEATURE_SIZE, THUNK_CHAIN_DEPTH_DELTA, Bytes, String, Characteristic
|
|
||||||
|
|
||||||
# security cookie checks may perform non-zeroing XORs, these are expected within a certain
|
# security cookie checks may perform non-zeroing XORs, these are expected within a certain
|
||||||
# byte range within the first and returning basic blocks, this helps to reduce FP features
|
# byte range within the first and returning basic blocks, this helps to reduce FP features
|
||||||
|
|||||||
@@ -19,26 +19,10 @@ import envi.archs.amd64.disasm
|
|||||||
|
|
||||||
import capa.features.extractors.helpers
|
import capa.features.extractors.helpers
|
||||||
import capa.features.extractors.viv.helpers
|
import capa.features.extractors.viv.helpers
|
||||||
<<<<<<< HEAD
|
|
||||||
from capa.features.insn import API, MAX_STRUCTURE_SIZE, Number, Offset, Mnemonic, OperandNumber, OperandOffset
|
from capa.features.insn import API, MAX_STRUCTURE_SIZE, Number, Offset, Mnemonic, OperandNumber, OperandOffset
|
||||||
from capa.features.common import MAX_BYTES_FEATURE_SIZE, THUNK_CHAIN_DEPTH_DELTA, Bytes, String, Feature, Characteristic
|
from capa.features.common import MAX_BYTES_FEATURE_SIZE, THUNK_CHAIN_DEPTH_DELTA, Bytes, String, Feature, Characteristic
|
||||||
from capa.features.address import Address, AbsoluteVirtualAddress
|
from capa.features.address import Address, AbsoluteVirtualAddress
|
||||||
from capa.features.extractors.base_extractor import BBHandle, InsnHandle, FunctionHandle
|
from capa.features.extractors.base_extractor import BBHandle, InsnHandle, FunctionHandle
|
||||||
||||||| de312d8
|
|
||||||
from capa.features.insn import API, Number, Offset, Mnemonic, OperandNumber, OperandOffset
|
|
||||||
from capa.features.common import (
|
|
||||||
BITNESS_X32,
|
|
||||||
BITNESS_X64,
|
|
||||||
MAX_BYTES_FEATURE_SIZE,
|
|
||||||
THUNK_CHAIN_DEPTH_DELTA,
|
|
||||||
Bytes,
|
|
||||||
String,
|
|
||||||
Characteristic,
|
|
||||||
)
|
|
||||||
=======
|
|
||||||
from capa.features.insn import API, MAX_STRUCTURE_SIZE, Number, Offset, Mnemonic, OperandNumber, OperandOffset
|
|
||||||
from capa.features.common import MAX_BYTES_FEATURE_SIZE, THUNK_CHAIN_DEPTH_DELTA, Bytes, String, Characteristic
|
|
||||||
>>>>>>> 580a2d7e4519ea5d353650d66468020968f0f27d
|
|
||||||
from capa.features.extractors.viv.indirect_calls import NotFoundError, resolve_indirect_call
|
from capa.features.extractors.viv.indirect_calls import NotFoundError, resolve_indirect_call
|
||||||
|
|
||||||
# security cookie checks may perform non-zeroing XORs, these are expected within a certain
|
# security cookie checks may perform non-zeroing XORs, these are expected within a certain
|
||||||
@@ -46,23 +30,7 @@ from capa.features.extractors.viv.indirect_calls import NotFoundError, resolve_i
|
|||||||
SECURITY_COOKIE_BYTES_DELTA = 0x40
|
SECURITY_COOKIE_BYTES_DELTA = 0x40
|
||||||
|
|
||||||
|
|
||||||
<<<<<<< HEAD
|
|
||||||
def interface_extract_instruction_XXX(
|
|
||||||
f: FunctionHandle, bb: BBHandle, insn: InsnHandle
|
|
||||||
) -> Iterator[Tuple[Feature, Address]]:
|
|
||||||
||||||| de312d8
|
|
||||||
def get_bitness(vw):
|
|
||||||
bitness = vw.getMeta("Architecture")
|
|
||||||
if bitness == "i386":
|
|
||||||
return BITNESS_X32
|
|
||||||
elif bitness == "amd64":
|
|
||||||
return BITNESS_X64
|
|
||||||
|
|
||||||
|
|
||||||
def interface_extract_instruction_XXX(f, bb, insn):
|
def interface_extract_instruction_XXX(f, bb, insn):
|
||||||
=======
|
|
||||||
def interface_extract_instruction_XXX(f, bb, insn):
|
|
||||||
>>>>>>> 580a2d7e4519ea5d353650d66468020968f0f27d
|
|
||||||
"""
|
"""
|
||||||
parse features from the given instruction.
|
parse features from the given instruction.
|
||||||
|
|
||||||
|
|||||||
18
capa/main.py
18
capa/main.py
@@ -65,24 +65,6 @@ from capa.features.common import (
|
|||||||
FORMAT_FREEZE,
|
FORMAT_FREEZE,
|
||||||
)
|
)
|
||||||
from capa.features.address import NO_ADDRESS
|
from capa.features.address import NO_ADDRESS
|
||||||
from capa.helpers import (
|
|
||||||
get_format,
|
|
||||||
get_file_taste,
|
|
||||||
get_auto_format,
|
|
||||||
log_unsupported_os_error,
|
|
||||||
log_unsupported_arch_error,
|
|
||||||
log_unsupported_format_error,
|
|
||||||
)
|
|
||||||
from capa.exceptions import UnsupportedOSError, UnsupportedArchError, UnsupportedFormatError, UnsupportedRuntimeError
|
|
||||||
from capa.features.common import (
|
|
||||||
FORMAT_PE,
|
|
||||||
FORMAT_ELF,
|
|
||||||
FORMAT_AUTO,
|
|
||||||
FORMAT_SC32,
|
|
||||||
FORMAT_SC64,
|
|
||||||
FORMAT_DOTNET,
|
|
||||||
FORMAT_FREEZE,
|
|
||||||
)
|
|
||||||
from capa.features.extractors.base_extractor import BBHandle, InsnHandle, FunctionHandle, FeatureExtractor
|
from capa.features.extractors.base_extractor import BBHandle, InsnHandle, FunctionHandle, FeatureExtractor
|
||||||
|
|
||||||
RULES_PATH_DEFAULT_STRING = "(embedded rules)"
|
RULES_PATH_DEFAULT_STRING = "(embedded rules)"
|
||||||
|
|||||||
@@ -325,21 +325,21 @@ def sample(request):
|
|||||||
|
|
||||||
def get_function(extractor, fva):
|
def get_function(extractor, fva):
|
||||||
for f in extractor.get_functions():
|
for f in extractor.get_functions():
|
||||||
if int(f) == fva:
|
if str(f) == fva:
|
||||||
return f
|
return f
|
||||||
raise ValueError("function not found")
|
raise ValueError("function not found")
|
||||||
|
|
||||||
|
|
||||||
def get_basic_block(extractor, f, va):
|
def get_basic_block(extractor, f, va):
|
||||||
for bb in extractor.get_basic_blocks(f):
|
for bb in extractor.get_basic_blocks(f):
|
||||||
if int(bb) == va:
|
if str(bb) == va:
|
||||||
return bb
|
return bb
|
||||||
raise ValueError("basic block not found")
|
raise ValueError("basic block not found")
|
||||||
|
|
||||||
|
|
||||||
def get_instruction(extractor, f, bb, va):
|
def get_instruction(extractor, f, bb, va):
|
||||||
for insn in extractor.get_instructions(f, bb):
|
for insn in extractor.get_instructions(f, bb):
|
||||||
if int(insn) == va:
|
if str(insn) == va:
|
||||||
return insn
|
return insn
|
||||||
raise ValueError("instruction not found")
|
raise ValueError("instruction not found")
|
||||||
|
|
||||||
@@ -824,10 +824,10 @@ def mixed_mode_64_dotnetfile_extractor():
|
|||||||
|
|
||||||
|
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
def hello_world_dnfile_extractor():
|
def hello_world_dotnetfile_extractor():
|
||||||
return get_dnfile_extractor(get_data_path_by_name("hello-world"))
|
return get_dnfile_extractor(get_data_path_by_name("hello-world"))
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
def _1c444_dnfile_extractor():
|
def _1c444_dotnetfile_extractor():
|
||||||
return get_dnfile_extractor(get_data_path_by_name("1c444..."))
|
return get_dnfile_extractor(get_data_path_by_name("1c444..."))
|
||||||
|
|||||||
@@ -24,12 +24,12 @@ def test_dnfile_features(sample, scope, feature, expected):
|
|||||||
@parametrize(
|
@parametrize(
|
||||||
"extractor,function,expected",
|
"extractor,function,expected",
|
||||||
[
|
[
|
||||||
("b9f5b_dnfile_extractor", "is_dotnet_file", True),
|
("b9f5b_dotnetfile_extractor", "is_dotnet_file", True),
|
||||||
("b9f5b_dnfile_extractor", "is_mixed_mode", False),
|
("b9f5b_dotnetfile_extractor", "is_mixed_mode", False),
|
||||||
("mixed_mode_64_dnfile_extractor", "is_mixed_mode", True),
|
("mixed_mode_64_dotnetfile_extractor", "is_mixed_mode", True),
|
||||||
("b9f5b_dnfile_extractor", "get_entry_point", 0x6000007),
|
("b9f5b_dotnetfile_extractor", "get_entry_point", 0x6000007),
|
||||||
("b9f5b_dnfile_extractor", "get_runtime_version", (2, 5)),
|
("b9f5b_dotnetfile_extractor", "get_runtime_version", (2, 5)),
|
||||||
("b9f5b_dnfile_extractor", "get_meta_version_string", "v2.0.50727"),
|
("b9f5b_dotnetfile_extractor", "get_meta_version_string", "v2.0.50727"),
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
def test_dnfile_extractor(request, extractor, function, expected):
|
def test_dnfile_extractor(request, extractor, function, expected):
|
||||||
|
|||||||
Reference in New Issue
Block a user