diff --git a/capa/features/address.py b/capa/features/address.py index 4df11f89..800cefcd 100644 --- a/capa/features/address.py +++ b/capa/features/address.py @@ -116,29 +116,6 @@ class DynamicCallAddress(Address): return (self.thread, self.id) < (other.thread, other.id) -class DynamicReturnAddress(Address): - """an address from a dynamic analysis trace""" - - def __init__(self, call: DynamicCallAddress, return_address: int): - assert return_address >= 0 - self.call = call - self.return_address = return_address - - def __repr__(self): - return f"{self.call}, dynamic-call(return-address: 0x{self.return_address:x})" - - def __hash__(self): - return hash((self.call, self.return_address)) - - def __eq__(self, other): - assert isinstance(other, DynamicReturnAddress) - return (self.call, self.return_address) == (other.call, other.return_address) - - def __lt__(self, other): - assert isinstance(other, DynamicReturnAddress) - return (self.call, self.return_address) < (other.call, other.return_address) - - class RelativeVirtualAddress(int, Address): """a memory address relative to a base address""" diff --git a/capa/features/extractors/cape/call.py b/capa/features/extractors/cape/call.py index 405902da..8e216730 100644 --- a/capa/features/extractors/cape/call.py +++ b/capa/features/extractors/cape/call.py @@ -15,7 +15,7 @@ import capa.features.extractors.cape.global_ import capa.features.extractors.cape.process from capa.features.insn import API, Number from capa.features.common import String, Feature -from capa.features.address import Address, DynamicReturnAddress +from capa.features.address import Address from capa.features.extractors.base_extractor import CallHandle, ThreadHandle, ProcessHandle logger = logging.getLogger(__name__) @@ -44,14 +44,13 @@ def extract_call_features( calls: List[Dict[str, Any]] = process["calls"] call = calls[ch.address.id] assert call["thread_id"] == str(th.address.tid) - caller = DynamicReturnAddress(call=ch.address, return_address=int(call["caller"], 16)) # list similar to disassembly: arguments right-to-left, call for arg in call["arguments"][::-1]: try: - yield Number(int(arg["value"], 16)), caller + yield Number(int(arg["value"], 16)), ch.address except ValueError: - yield String(arg["value"]), caller - yield API(call["api"]), caller + yield String(arg["value"]), ch.address + yield API(call["api"]), ch.address def extract_features( diff --git a/capa/features/freeze/__init__.py b/capa/features/freeze/__init__.py index 7af642f6..7b56751b 100644 --- a/capa/features/freeze/__init__.py +++ b/capa/features/freeze/__init__.py @@ -84,18 +84,6 @@ class Address(HashableModel): elif isinstance(a, capa.features.address.DynamicCallAddress): return cls(type=AddressType.CALL, value=(a.thread.process.ppid, a.thread.process.pid, a.thread.tid, a.id)) - elif isinstance(a, capa.features.address.DynamicReturnAddress): - return cls( - type=AddressType.DYNAMIC, - value=( - a.call.thread.process.ppid, - a.call.thread.process.pid, - a.call.thread.tid, - a.call.id, - a.return_address, - ), - ) - elif a == capa.features.address.NO_ADDRESS or isinstance(a, capa.features.address._NoAddress): return cls(type=AddressType.NO_ADDRESS, value=None) @@ -159,19 +147,6 @@ class Address(HashableModel): id=id_, ) - elif self.type is AddressType.DYNAMIC: - assert isinstance(self.value, tuple) - ppid, pid, tid, id_, return_address = self.value - return capa.features.address.DynamicReturnAddress( - call=capa.features.address.DynamicCallAddress( - thread=capa.features.address.ThreadAddress( - process=capa.features.address.ProcessAddress(ppid=ppid, pid=pid), tid=tid - ), - id=id_, - ), - return_address=return_address, - ) - elif self.type is AddressType.NO_ADDRESS: return capa.features.address.NO_ADDRESS @@ -233,8 +208,10 @@ class ThreadFeature(HashableModel): class CallFeature(HashableModel): """ args: - call: the call id to which this feature belongs. - address: the address at which this feature is found (it's dynamic return address). + call: the address of the call to which this feature belongs. + address: the address at which this feature is found. + + call != address for consistency with Process and Thread. """ call: Address @@ -279,8 +256,7 @@ class InstructionFeature(HashableModel): instruction: the address of the instruction to which this feature belongs. address: the address at which this feature is found. - instruction != address because, e.g., the feature may be found *within* the scope (basic block), - versus right at its starting address. + instruction != address because, for consistency with Function and BasicBlock. """ instruction: Address diff --git a/scripts/show-features.py b/scripts/show-features.py index 8f2e8767..d909d95b 100644 --- a/scripts/show-features.py +++ b/scripts/show-features.py @@ -273,8 +273,8 @@ def print_dynamic_features(processes, extractor: DynamicFeatureExtractor): continue if isinstance(feature, API): - assert isinstance(addr, capa.features.address.DynamicReturnAddress) - apis.append((addr.call.id, str(feature.value))) + assert isinstance(addr, capa.features.address.DynamicCallAddress) + apis.append((addr.id, str(feature.value))) if isinstance(feature, (Number, String)): arguments.append(str(feature.value))