|
18 | 18 |
|
19 | 19 | import idc |
20 | 20 | import idaapi |
| 21 | +import ida_loader |
21 | 22 |
|
22 | 23 | import capa.rules |
23 | 24 | import capa.engine |
24 | 25 | import capa.ida.helpers |
25 | 26 | import capa.features.common |
26 | 27 | import capa.features.basicblock |
27 | 28 | from capa.ida.plugin.item import CapaExplorerFunctionItem |
28 | | -from capa.features.address import AbsoluteVirtualAddress, _NoAddress |
| 29 | +from capa.features.address import FileOffsetAddress, AbsoluteVirtualAddress, _NoAddress |
29 | 30 | from capa.ida.plugin.model import CapaExplorerDataModel |
30 | 31 | from capa.ida.plugin.qt_compat import QtGui, QtCore, Signal, QAction, QtWidgets |
31 | 32 |
|
@@ -905,7 +906,22 @@ def slot_custom_context_menu_requested(self, pos): |
905 | 906 | def slot_item_double_clicked(self, o, column): |
906 | 907 | """ """ |
907 | 908 | if column == CapaExplorerRulegenFeatures.get_column_address_index() and o.text(column): |
908 | | - idc.jumpto(int(o.text(column), 0x10)) |
| 909 | + addr_text = o.text(column).strip() |
| 910 | + |
| 911 | + if addr_text.startswith("file:"): |
| 912 | + try: |
| 913 | + file_offset = int(addr_text[len("file:") :], 16) |
| 914 | + except (ValueError, TypeError): |
| 915 | + return |
| 916 | + |
| 917 | + ea = ida_loader.get_fileregion_ea(file_offset) |
| 918 | + if ea != idc.BADADDR: |
| 919 | + idc.jumpto(ea) |
| 920 | + else: |
| 921 | + try: |
| 922 | + idc.jumpto(int(addr_text, 16)) |
| 923 | + except (ValueError, TypeError): |
| 924 | + return |
909 | 925 | elif o.capa_type == CapaExplorerRulegenFeatures.get_node_type_leaf(): |
910 | 926 | self.editor.update_features([o.data(0, 0x100)]) |
911 | 927 |
|
@@ -955,13 +971,18 @@ def show_item_and_parents(_o): |
955 | 971 | # read ea from "Address" column |
956 | 972 | o_ea = o.text(CapaExplorerRulegenFeatures.get_column_address_index()) |
957 | 973 |
|
958 | | - if o_ea == "": |
959 | | - # ea may be empty, hide by default |
| 974 | + if o_ea == "" or o_ea.startswith("file:"): |
| 975 | + # ea may be empty or a file offset, hide by default when filtering by VA |
960 | 976 | if not o.isHidden(): |
961 | 977 | o.setHidden(True) |
962 | 978 | continue |
963 | 979 |
|
964 | | - o_ea = int(o_ea, 16) |
| 980 | + try: |
| 981 | + o_ea = int(o_ea, 16) |
| 982 | + except (ValueError, TypeError): |
| 983 | + if not o.isHidden(): |
| 984 | + o.setHidden(True) |
| 985 | + continue |
965 | 986 |
|
966 | 987 | if max_ea is not None and min_ea <= o_ea <= max_ea: |
967 | 988 | show_item_and_parents(o) |
@@ -1045,8 +1066,9 @@ def parse_features_for_tree(self, parent, features): |
1045 | 1066 | def format_address(e): |
1046 | 1067 | if isinstance(e, AbsoluteVirtualAddress): |
1047 | 1068 | return f"{hex(int(e))}" |
1048 | | - else: |
1049 | | - return "" |
| 1069 | + if isinstance(e, FileOffsetAddress): |
| 1070 | + return f"file:{hex(int(e))}" |
| 1071 | + return "" |
1050 | 1072 |
|
1051 | 1073 | def format_feature(feature): |
1052 | 1074 | """ """ |
|
0 commit comments