""" Root module This module contains the root namespace that IDA starts up with. Any thing defined within this module is used to replace the globals that IDA starts up with. This module also is responsible for assigning the default hooks in order to trap what the user is doing to perform any extra maintenance that needs to occur. """ ### ida-python specific modules import idaapi, ida ### detect which version of IDA is being used ## needed because IDA 6.95 is fucking stupid and sets the result of idaapi.get_kernel_version() to a string def __version__(): # api doesn't exist, go back to a crazy version. if not hasattr(idaapi, 'get_kernel_version'): return 6, 0, 6.0 import math res = str(idaapi.get_kernel_version()) # force it to a str because IDA 7.0 "fixed" it major, minor = map(int, res.split('.', 2)) minor = int("{:<02d}".format(minor)) if minor > 0: count = math.floor(math.log(minor) / math.log(10) + 1) return major, minor, float(major) + minor/10**count return major, minor, float(major) ## inject the version info into idaapi idaapi.__version_major__, idaapi.__version_minor__, idaapi.__version__ = __version__() ## now we can delete the function because we're done with it del __version__ ### Pre-populate the root namespace with a bunch of things that IDA requires ## IDA 6.9 requires the _idaapi module exists in the global namespace if idaapi.__version__ <= 6.9: import _idaapi ## IDA 6.95 requires these couple modules to exist in the global namespace if idaapi.__version__ >= 6.95: import ida_idaapi, ida_kernwin, ida_diskio ## Restore the displayhook that IDAPython obnoxiously replaces if hasattr(ida_idaapi, '_IDAPython_displayhook'): __import__('sys').displayhook = ida_idaapi._IDAPython_displayhook.orig_displayhook del(ida_idaapi._IDAPython_displayhook) ## IDA 7.4 requires that this module exists in the global namespace if idaapi.__version__ >= 7.4: import sys ### customize the root namespace import segment, database, function, instruction import structure, enumeration ## some aliases for them import database as db import function as func import instruction as ins import structure as struc import enumeration as enum import segment as seg ## default log setting for notifying the user # FIXME: actually use the logging module properly instead of assuming # control of the root logger. #__import__('logging').root.setLevel(__import__('logging').INFO) ## shortcuts h, top, go, goof = database.h, func.top, database.go, database.go_offset ## other useful things that we can grab from other modules # snag the fake utilities module to share some things with the user... utils = __import__('internal').utils # import all its combinators by copying them directly into locals() locals().update({name : item for name, item in utils.__dict__.iteritems() if name in utils.__all__}) # construct some pattern matching types AnyRegister = utils.PatternAnyType(__import__('internal').interface.register_t) AnyInteger = utils.PatternAnyType(__import__('six').integer_types) AnyString = utils.PatternAnyType(basestring) AnyBytes = utils.PatternAnyType(bytes) Any = utils.PatternAny() # ...and that's it for the utils del(utils) # some types that the user might want to compare with architecture_t, register_t, symbol_t = (getattr(__import__('internal').interface, _) for _ in ['architecture_t', 'register_t', 'symbol_t']) ref_t, opref_t = (getattr(__import__('internal').interface, _) for _ in ['ref_t', 'opref_t']) # other miscellaneous modules to expose to the user import ui, tools, custom ### Replace sys.displayhook with our own so that IDAPython can't tamper with ### our __repr__ implementations. __import__('sys').displayhook = ui.DisplayHook().displayhook ### Construct a priority notification handler, and inject into IDA because it ### needs to exist for everything to initialize/deinitialize properly. __notification__ = __import__('internal').interface.prioritynotification() idaapi.__notification__ = __notification__ ### Now we can install our hooks that initialize/uninitialize MINSC try: idaapi.__notification__.add(idaapi.NW_INITIDA, __import__('hooks').make_ida_not_suck_cocks, -1000) # If installing that hook failed, then register our hook with a timer, and warn # the user about this. except NameError: TIMEOUT = 5 __import__('logging').warn("Unable to add notification for idaapi.NW_INITIDA ({:d}). Registering a {:.1f} second timer to setup hooks...".format(idaapi.NW_INITIDA, TIMEOUT)) idaapi.register_timer(TIMEOUT, __import__('hooks').ida_is_busy_sucking_cocks) del(TIMEOUT) # If we were able to hook NW_INITIDA, then the NW_TERMIDA hook should also work. else: try: idaapi.__notification__.add(idaapi.NW_TERMIDA, __import__('hooks').make_ida_suck_cocks, +1000) # Installing the termination hook failed, but it's not really too important... except NameError: __import__('logging').warn("Unable to add notification for idaapi.NW_TERMIDA ({:d}).".format(idaapi.NW_TERMIDA))