Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
### capa Explorer Web

### capa Explorer IDA Pro plugin
- ida: display file-scope feature addresses (`file:0x...`) in rule generator tree and safely handle file-offset navigation/filtering @vee1e #3009

### Development
- tests: update binja version to 5.3 @mr-tz #3011
Expand Down Expand Up @@ -187,7 +188,7 @@ Additionally a Binary Ninja bug has been fixed. Released binaries now include AR

### Bug Fixes

- binja: fix a crash during feature extraction when the MLIL is unavailable @xusheng6 #2714
- binja: fix a crash during feature extraction when the MLIL is unavailable @xusheng6 #2714

### capa Explorer Web

Expand Down
36 changes: 29 additions & 7 deletions capa/ida/plugin/view.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,15 @@

import idc
import idaapi
import ida_loader

import capa.rules
import capa.engine
import capa.ida.helpers
import capa.features.common
import capa.features.basicblock
from capa.ida.plugin.item import CapaExplorerFunctionItem
from capa.features.address import AbsoluteVirtualAddress, _NoAddress
from capa.features.address import FileOffsetAddress, AbsoluteVirtualAddress, _NoAddress
from capa.ida.plugin.model import CapaExplorerDataModel
from capa.ida.plugin.qt_compat import QtGui, QtCore, Signal, QAction, QtWidgets

Expand Down Expand Up @@ -905,7 +906,22 @@ def slot_custom_context_menu_requested(self, pos):
def slot_item_double_clicked(self, o, column):
""" """
if column == CapaExplorerRulegenFeatures.get_column_address_index() and o.text(column):
idc.jumpto(int(o.text(column), 0x10))
addr_text = o.text(column).strip()

if addr_text.startswith("file:"):
try:
file_offset = int(addr_text[len("file:") :], 16)
except (ValueError, TypeError):
return

ea = ida_loader.get_fileregion_ea(file_offset)
if ea != idc.BADADDR:
idc.jumpto(ea)
else:
try:
idc.jumpto(int(addr_text, 16))
except (ValueError, TypeError):
return
elif o.capa_type == CapaExplorerRulegenFeatures.get_node_type_leaf():
self.editor.update_features([o.data(0, 0x100)])

Expand Down Expand Up @@ -955,13 +971,18 @@ def show_item_and_parents(_o):
# read ea from "Address" column
o_ea = o.text(CapaExplorerRulegenFeatures.get_column_address_index())

if o_ea == "":
# ea may be empty, hide by default
if o_ea == "" or o_ea.startswith("file:"):
# ea may be empty or a file offset, hide by default when filtering by VA
if not o.isHidden():
o.setHidden(True)
continue

o_ea = int(o_ea, 16)
try:
o_ea = int(o_ea, 16)
except (ValueError, TypeError):
if not o.isHidden():
o.setHidden(True)
continue

if max_ea is not None and min_ea <= o_ea <= max_ea:
show_item_and_parents(o)
Expand Down Expand Up @@ -1045,8 +1066,9 @@ def parse_features_for_tree(self, parent, features):
def format_address(e):
if isinstance(e, AbsoluteVirtualAddress):
return f"{hex(int(e))}"
else:
return ""
if isinstance(e, FileOffsetAddress):
return f"file:{hex(e)}"
return ""

def format_feature(feature):
""" """
Expand Down
Loading