Skip to content

Instantly share code, notes, and snippets.

@Jinmo
Last active May 17, 2019 01:20
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save Jinmo/ef609b0c7478c0cfc613b03d6e6ccc15 to your computer and use it in GitHub Desktop.
Save Jinmo/ef609b0c7478c0cfc613b03d6e6ccc15 to your computer and use it in GitHub Desktop.
loading IDA colors (clr) file given a path to the file
from ctypes import c_ssize_t, c_void_p, c_int, c_void_p, create_string_buffer, cast, WINFUNCTYPE, CFUNCTYPE, windll, cdll, CDLL
from PyQt5.QtCore import Qt, QTimer, QObject
from PyQt5.QtGui import QResizeEvent, QFocusEvent
from PyQt5.QtWidgets import QWidget, QDialog, QDialogButtonBox, QPushButton, qApp
import os
import sys
import idaapi
import idc
IDADIR = idaapi.idadir('')
def _ida_lib_path(ea):
ea_name = 'ida64' if idc.__EA64__ else 'ida'
if sys.platform == 'win':
path = os.path.join(IDADIR, ea_name + ".dll")
elif sys.platform == 'darwin':
path = os.path.join(IDADIR, "lib" + ea_name + ".dylib")
else:
path = os.path.join(IDADIR, "lib" + ea_name + ".so")
return os.path.normpath(path)
def _ida_lib():
ea_name = 'ida64' if idc.__EA64__ else 'ida'
if sys.platform == 'win32':
functype = WINFUNCTYPE
lib = getattr(windll, ea_name)
elif sys.platform == 'darwin':
functype = CFUNCTYPE
lib = CDLL(_ida_lib_path(64 if idc.__EA64__ else 32))
else:
functype = CFUNCTYPE
lib = getattr(cdll, 'lib' + ea_name)
return functype, lib
functype, lib = _ida_lib()
hook_cb_t = functype(c_void_p, c_void_p, c_int, c_void_p)
hooker = lib.hook_to_notification_point
hooker.argtypes = [c_int, hook_cb_t, c_void_p]
unhooker = lib.unhook_from_notification_point
unhooker.argtypes = [c_int, hook_cb_t, c_void_p]
def _query(window, predicate):
results = []
def _recursive(widget):
for item in widget.children():
if not isinstance(item, QWidget):
continue
if predicate(item):
results.append(item)
_recursive(item)
_recursive(window)
return results
class TemporaryFilter(QObject):
def __init__(self, filepath):
super(TemporaryFilter, self).__init__()
filepath = os.path.abspath(filepath)
assert os.path.isfile(filepath)
self.filepath = filepath
def eventFilter(self, obj, event):
is_colors_dialog = lambda: isinstance(obj, QDialog) and 'IDA Colors' in obj.windowTitle()
if isinstance(event, QResizeEvent) and is_colors_dialog():
obj.setWindowFlags(Qt.Window | Qt.FramelessWindowHint)
obj.setFixedSize(0, 0)
obj.setGeometry(0, 0, 0, 0)
event.accept()
return 1
if isinstance(event, QFocusEvent) and is_colors_dialog():
qApp.removeEventFilter(self)
buttons = [widget for widget in obj.children() if isinstance(
widget, QDialogButtonBox)][0]
button = buttons.buttons()[-4]
with NativeHook(ask_file=self.ask_file_handler):
button.click()
QTimer.singleShot(0, lambda: obj.accept())
return 1
return 0
def ask_file_handler(self):
return create_string_buffer(self.filepath)
class NativeHook:
NAMES = {
'ask_file': 0x1d
}
def __init__(self, **kwargs):
self.hooks = {NativeHook.NAMES[key]
: value for key, value in kwargs.items()}
self._handler = hook_cb_t(self.handler)
def handler(self, user_data, code, va_args):
if code in self.hooks:
try:
res = self.hooks[code]()
return cast(res, c_void_p).value
except:
return 0
else:
return 0
def __enter__(self):
hooker(1, self._handler, None)
def __exit__(self, *args):
unhooker(1, self._handler, None)
def load_clr_file(filepath):
eventFilter = TemporaryFilter(filepath)
qApp.installEventFilter(eventFilter)
return idaapi.process_ui_action('SetColors')
load_clr_file('C:/Users/berry/Downloads/ida-consonance.clr.txt')
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment