使用 PySide 向 IDA 添加工具栏

逆向工程 艾达 蟒蛇 idapro插件 Python
2021-07-05 08:50:00

所以我正在尝试使用他们的 PySide 下载和 IDAAPI 向 IDA 6.4 添加自定义工具栏。我已经尝试通过创建一个工具栏来添加一个工具栏,但由于它没有 exec_() 方法我无法在屏幕上显示它,看起来我需要将它加载到一个窗口中

self.toolbar = self.addToolBar('var')

虽然在这种情况下,“自我”是一个窗口,这让我觉得我需要引用 IDA 的主窗口。有谁知道我怎么能得到那个参考?

1个回答

新的 IDA 6.95 API

也许是因为他们看到了这个问题,也许是因为用户的请求,版本6.95中有两个IDAPython API函数发布用于创建菜单和工具栏:create_menucreate_toolbar所以现在这些都可以很简单完成。

老把戏 - 6.95 之前

我一直在使用的一个技巧是手动找到应用程序的主窗口,然后直接使用 QT 添加一个工具栏。IDA 只有一个主窗口。

据我所知,添加这样的工具栏可以让 IDA 完全识别。您可以打开和关闭它,您可以停靠和取消停靠它,更改为高级模式也会自动显示它。但是,IDA 不允许您在 IDA 6.7 及更高版本中向其添加操作(如hexblog.com/?p=886 所述

示例代码可能如下所示:

 for widget in QtGui.qApp.topLevelWidgets():
     if type(widget) == QtGui.QMainWindow:
         mainWindow = widget
         toolbar = mainWindow.addToolBar("My toolbar")

         # and now for adding stuff to our toolbar
         toolbar.addSeparator()
         toolbar.addWidget(...)

免责声明:请记住,如果有风险、没有记录并且可能并不总是有效,请记住以这种方式找到主窗口。IDA 可能不喜欢你改变它下面的东西。我确实使用它并且它正在工作,但是 YMMV 和 UAYOR。

使此 hack 起作用的两个额外提示:

  1. 由于加载插件时 IDA 的主窗口并不总是可见的,因此您可能希望在查找主窗口时设置 QTimer。
  2. 因为它没有记录,我使用更多的方法来找到主窗口。使用qApp.activeWindow()和/或qApp.focusWidget()迭代它们的.parent()s 是很好的附加选择。

编辑:

这是一个更完整的示例,说明如何从 IDA 插件中破解工具栏和菜单,处理不同的加载模式并在 IDA 应用程序尚未完全设置的情况下重新绑定:

  def init(self):
    self.setup()

    return idaapi.PLUGIN_KEEP

  def setup(self):
    if not self.get_mainwindow():
      self.delay_setup()
      return

    # Add a toolbar like OP requested
    self.toolbar = self.get_mainwindow().addToolBar("My toolbar")
    self.toolbar.setIconSize(QtCore.QSize(16, 16))

    # Bonus: add a menue
    self.menu = QtGui.QMenu("My menu")
    self.get_mainwindow().menuWidget().addMenu(self.menu)

  def delay_setup(self):
    QtCore.QTimer.singleShot(1000, self.setup)

  def get_mainwindow(self):
    if self.mainwindow:
      return self.mainwindow

    app = QtGui.qApp
    widgets = [app.focusWidget(), app.activeWindow()] + app.topLevelWidgets()
    mainwidgets = filter(None, map(self.search_mainwindow, widgets))

    if mainwidgets:
      self.mainwindow = mainwidgets[0]

    return self.mainwindow

  def search_mainwindow(self, widget):
    while widget != None:
      if isinstance(widget, QtGui.QMainWindow):
        return widget
      widget = widget.parent()
    return None