Skip to content

Commit

Permalink
IDA 9.0 compatibility
Browse files Browse the repository at this point in the history
  • Loading branch information
af-airbus committed Oct 2, 2024
1 parent d7b275d commit 141bcd6
Show file tree
Hide file tree
Showing 6 changed files with 61 additions and 119 deletions.
36 changes: 15 additions & 21 deletions python/idabincat/analyzer_conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,8 @@
import idautils
import ida_segment
import ida_kernwin
import ida_ida
import idabincat.netnode
from builtins import bytes
from idabincat.plugin_options import PluginOptions
# Python 2/3 compat
if sys.version_info > (2, 8):
Expand Down Expand Up @@ -86,8 +86,7 @@ class ConfigHelpers(object):

@staticmethod
def get_file_type():
ida_db_info_structure = idaapi.get_inf_structure()
f_type = ida_db_info_structure.filetype
f_type = ida_ida.inf_get_filetype()
if f_type in ConfigHelpers.ftypes:
return ConfigHelpers.ftypes[f_type]
else:
Expand Down Expand Up @@ -136,17 +135,15 @@ def guess_file_path():

@staticmethod
def get_memory_model():
ida_db_info_structure = idaapi.get_inf_structure()
compiler_info = ida_db_info_structure.cc
if compiler_info.cm & idaapi.C_PC_FLAT == idaapi.C_PC_FLAT:
cm = ida_ida.inf_get_cc_cm()
if cm & idaapi.C_PC_FLAT == idaapi.C_PC_FLAT:
return "flat"
else:
return "segmented"

@staticmethod
def get_call_convention():
ida_db_info_structure = idaapi.get_inf_structure()
compiler_info = ida_db_info_structure.cc
cm = ida_ida.inf_get_cc_cm()
cc = {
idaapi.CM_CC_INVALID: "invalid",
idaapi.CM_CC_UNKNOWN: "unknown",
Expand All @@ -157,7 +154,7 @@ def get_call_convention():
idaapi.CM_CC_PASCAL: "pascal",
idaapi.CM_CC_FASTCALL: "fastcall",
idaapi.CM_CC_THISCALL: "thiscall",
}[compiler_info.cm & idaapi.CM_CC_MASK]
}[cm & idaapi.CM_CC_MASK]
# XXX
if ConfigHelpers.get_arch().startswith("powerpc") and ida_db_info_structure.abiname == "sysv":
return "svr"
Expand All @@ -183,17 +180,15 @@ def get_bitness(ea):

@staticmethod
def get_endianness():
ida_db_info_structure = idaapi.get_inf_structure()
return "big" if ida_db_info_structure.is_be() else "little"
return "big" if ida_ida.inf_is_be() else "little"


@staticmethod
def get_stack_width():
ida_db_info_structure = idaapi.get_inf_structure()
if ida_db_info_structure.is_64bit():
if ida_ida.inf_is_64bit():
return 8*8
else:
if ida_db_info_structure.is_32bit():
if ida_ida.inf_is_32bit_exactly():
return 4*8
else:
return 2*8
Expand Down Expand Up @@ -405,20 +400,19 @@ def get_initial_mem(arch=None):

@staticmethod
def get_arch():
info = idaapi.get_inf_structure()
procname = info.procname.lower()
procname = ida_ida.inf_get_procname().lower()
if procname == "metapc":
if info.is_64bit():
if ida_ida.inf_is_64bit():
return "x64"
else:
return "x86"
if procname == "ppc":
if info.is_64bit():
if ida_ida.inf_is_64bit():
return "powerpc64"
else:
return "powerpc"
elif procname.startswith("arm"):
if info.is_64bit():
if ida_ida.inf_is_64bit():
return "armv8"
else:
return "armv7"
Expand Down Expand Up @@ -649,7 +643,7 @@ def nops(self):
def remap(self):
if not self._config.has_option('IDA', 'remap_binary'):
return False
return self._config.get('IDA', 'remap_binary').lower() == "true";
return self._config.get('IDA', 'remap_binary').lower() == "true"

@remap.setter
def remap(self, value):
Expand Down Expand Up @@ -778,7 +772,7 @@ def load_from_str(string):
sio = StringIO(string)
parser = ConfigParser.RawConfigParser()
parser.optionxform = str
parser.readfp(sio)
parser.read_file(sio)
return AnalyzerConfig(parser)

def write(self, filepath):
Expand Down
40 changes: 19 additions & 21 deletions python/idabincat/bcplugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,8 @@
# log message will be displayed later
pass

import ida_ida
import idaapi
from idaapi import NW_OPENIDB, NW_CLOSEIDB, NW_TERMIDA, NW_REMOVE
import idabincat.netnode
import idabincat.npkgen
from idabincat.plugin_options import PluginOptions
Expand Down Expand Up @@ -87,13 +87,13 @@ def flush_staging():
if not loglines:
flush_staging()
break
l = loglines.pop()
if l == staging:
line = loglines.pop()
if line == staging:
n += 1
else:
if flush_staging():
break
staging = l
staging = line
n = 1
res.reverse()
return res
Expand All @@ -118,8 +118,7 @@ def __init__(self):

# IDA API methods: init, run, term
def init(self):
info = idaapi.get_inf_structure()
procname = info.procname
procname = ida_ida.inf_get_procname()
if procname != 'metapc' and procname != 'ARM' and procname != 'ARMB' and procname != 'PPC':
bc_log.info("CPU '%s' is not supported, not loading BinCAT", procname)
return idaapi.PLUGIN_SKIP
Expand Down Expand Up @@ -240,20 +239,13 @@ def __call__(self):
def destroy(self):
idaapi.unregister_timer(self.timer)


class LocalAnalyzer(Analyzer, QtCore.QProcess):
class LocalAnalyzer(Analyzer):
"""
Runs BinCAT locally using QProcess.
"""

def __init__(self, *args, **kwargs):
QtCore.QProcess.__init__(self)
Analyzer.__init__(self, *args, **kwargs)
# Qprocess signal handlers
self.error.connect(self.procanalyzer_on_error)
self.stateChanged.connect(self.procanalyzer_on_state_change)
self.started.connect(self.procanalyzer_on_start)
self.finished.connect(self.procanalyzer_on_finish)

def generate_tnpk(self, fname=None, destfname=None):
if fname:
Expand All @@ -272,16 +264,23 @@ def generate_tnpk(self, fname=None, destfname=None):
def run(self):
idaapi.show_wait_box("Running analysis")

self.process = QtCore.QProcess()
# Qprocess signal handlers
self.process.error.connect(self.procanalyzer_on_error)
self.process.stateChanged.connect(self.procanalyzer_on_state_change)
self.process.started.connect(self.procanalyzer_on_start)
self.process.finished.connect(self.procanalyzer_on_finish)

# Create a timer to allow for cancellation
self.timer = LocalAnalyzerTimer(self)
self.timer = LocalAnalyzerTimer(self.process)

cmdline = ["bincat",
[self.initfname, self.outfname, self.logfname]]
# start the process
bc_log.debug(
"Analyzer cmdline: [%s %s]", cmdline[0], " ".join(cmdline[1]))
try:
self.start(*cmdline)
self.process.start(*cmdline)
except Exception as e:
bc_log.error("BinCAT failed to launch the analyzer.py")
bc_log.warning("Exception: %s\n%s", str(e), traceback.format_exc())
Expand All @@ -296,7 +295,7 @@ def procanalyzer_on_error(self, err):
except IndexError:
errtxt = "Unspecified error %s" % err
bc_log.error("Analyzer error: %s", errtxt)
self.process_output()
self.process.process_output()

def procanalyzer_on_state_change(self, new_state):
states = ["Not running", "Starting", "Running"]
Expand All @@ -307,7 +306,7 @@ def procanalyzer_on_start(self):

def procanalyzer_on_finish(self):
bc_log.info("Analyzer process finished")
exitcode = self.exitCode()
exitcode = self.process.exitCode()
if exitcode != 0:
bc_log.error("analyzer returned exit code=%i", exitcode)
try:
Expand All @@ -322,9 +321,9 @@ def process_output(self):
"""
self.timer.destroy()
bc_log.info("---- stdout ----------------")
bc_log.info(str(self.readAllStandardOutput()))
bc_log.info(str(self.process.readAllStandardOutput()))
bc_log.info("---- stderr ----------------")
bc_log.info(str(self.readAllStandardError()))
bc_log.info(str(self.process.readAllStandardError()))
bc_log.info("---- logfile ---------------")
if os.path.exists(self.logfname):
with open(self.logfname, 'r') as f:
Expand Down Expand Up @@ -450,7 +449,6 @@ def run(self):
if not files["out.ini"]: # try to parse out.ini if it exists
return
with open(self.outfname, 'w') as outfp:

outfp.write(self.download_file(files["out.ini"]))
analyzer_log_contents = self.download_file(files["analyzer.log"])
with open(self.logfname, 'w') as logfp:
Expand Down
28 changes: 24 additions & 4 deletions python/idabincat/hexview/hexview.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@
from PyQt5.QtCore import QItemSelectionModel
from PyQt5.QtCore import QRectF
from PyQt5.QtCore import QAbstractTableModel
import PyQt5.QtWidgets as QtWidgets
from PyQt5.QtWidgets import QMenu
from PyQt5.QtWidgets import QStyle
from PyQt5.QtWidgets import QAction
Expand All @@ -60,7 +61,6 @@
from PyQt5.QtWidgets import QStyledItemDelegate
from PyQt5.QtWidgets import QAbstractItemView

from .hexview_auto import Ui_Form as HexViewBase
from .common import h
from .common import LoggingObject

Expand Down Expand Up @@ -465,8 +465,7 @@ def _handle_mouse_released(self, qindex):
self._update_selection(self._start_qindex, qindex)
self._start_qindex = None


class HexTableView(QTableView, LoggingObject):
class HexTableView(QTableView):
""" table view that handles click events for better selection handling """
leftMousePressed = pyqtSignal([QMouseEvent])
leftMousePressedIndex = pyqtSignal([QModelIndex])
Expand Down Expand Up @@ -603,7 +602,7 @@ def _handle_mouse_release(self, key_event):
Origin = namedtuple("Origin", ["offset", "name"])


class HexViewWidget(QWidget, HexViewBase, LoggingObject):
class HexViewWidget(QWidget):
originsChanged = pyqtSignal()
newOverride = pyqtSignal(int, int, bool)

Expand Down Expand Up @@ -672,6 +671,27 @@ def __init__(self, meminfo, parent=None):

self.statusLabel.setText("")

def setupUi(self, Form):
Form.setObjectName("Form")
Form.resize(400, 300)
self.verticalLayout = QtWidgets.QVBoxLayout(Form)
self.verticalLayout.setObjectName("verticalLayout")
self.mainLayout = QtWidgets.QVBoxLayout()
self.mainLayout.setObjectName("mainLayout")
self.statusLabel = QtWidgets.QLabel(Form)
self.statusLabel.setMaximumSize(QtCore.QSize(16777215, 15))
self.statusLabel.setObjectName("statusLabel")
self.mainLayout.addWidget(self.statusLabel)
self.verticalLayout.addLayout(self.mainLayout)

self.retranslateUi(Form)
QtCore.QMetaObject.connectSlotsByName(Form)

def retranslateUi(self, Form):
_translate = QtCore.QCoreApplication.translate
Form.setWindowTitle(_translate("Form", "Form"))
self.statusLabel.setText(_translate("Form", "TextLabel"))

def setNewMem(self, meminfo):
self._model.beginResetModel()
self._meminfo = meminfo
Expand Down
38 changes: 0 additions & 38 deletions python/idabincat/hexview/hexview.ui

This file was deleted.

33 changes: 0 additions & 33 deletions python/idabincat/hexview/hexview_auto.py

This file was deleted.

5 changes: 3 additions & 2 deletions python/idabincat/npkgen.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
try:
import idaapi
from ida_typeinf import PRTYPE_1LINE
import idc
except ImportError:
# imported outside ida - for instance, from wsgi.py
pass
Expand Down Expand Up @@ -167,7 +168,7 @@ def import_name(self, type_name):
helper do import a type by name into local types
"""
# print "import_name : "+type_name
idaapi.import_type(idaapi.cvar.idati, -1, type_name, 0)
idc.import_type(-1, type_name)

def imp_cb(self, ea, name, ord_nb):
"""
Expand Down Expand Up @@ -251,7 +252,7 @@ def analyze_type(self, tinfo):
def add_types(self):
local_type = idaapi.tinfo_t()
count = 0
for ordinal in range(1, idaapi.get_ordinal_qty(idaapi.cvar.idati)):
for ordinal in range(1, idaapi.get_ordinal_limit(idaapi.cvar.idati)):
local_type.get_numbered_type(idaapi.cvar.idati, ordinal)
if self.analyze_type(local_type):
count += 1
Expand Down

0 comments on commit 141bcd6

Please sign in to comment.