def _cache_functions(self, addresses_chunk): """ Lift and cache function metadata for the given list of function addresses. """ disassembler_ctx = disassembler[self.lctx] for address in addresses_chunk: # attempt to 'lift' the function from the database try: function_metadata = FunctionMetadata(address, disassembler_ctx) # # this is not exactly a good thing but it indicates that the # disassembler didn't see the a function that we thought should # have been there based on what it told us previously... # # this means the database might have changed, while the refresh # was running. it's not the end of the world, but it might mean # the cache will not be fully accurate... # except Exception: lmsg(" - Caching function at 0x%08X failed..." % address) logger.exception("FunctionMetadata Error:") continue # add the updated info self.nodes.update(function_metadata.nodes) self.functions[address] = function_metadata
def init(self): """ This is called by IDA when it is loading the plugin. """ try: self._lighthouse = LighthouseIDA() self._lighthouse.load() except Exception as e: lmsg("Failed to initialize Lighthouse") logger.exception("Exception details:") return idaapi.PLUGIN_KEEP
def _load_theme(self, filepath): """ Load and apply the Lighthouse theme at the given filepath. """ # attempt to read json theme from disk try: theme = self._read_theme(filepath) # reading file from dsik failed except OSError: lmsg("Could not open theme file at '%s'" % filepath) return False # JSON decoding failed except JSONDecodeError as e: lmsg("Failed to decode theme '%s' to json" % filepath) lmsg(" - " + str(e)) return False # do some basic sanity checking on the given theme file if not self._validate_theme(theme): return False # try applying the loaded theme to Lighthouse try: self._apply_theme(theme) except Exception as e: lmsg("Failed to load Lighthouse user theme\n%s" % e) return False # return success self._notify_theme_changed() return True
def warn_errors(errors): """ Warn the user of any encountered errors with a messagebox. """ if not errors: return for error_type, error_list in iteritems(errors): # # loop through the individual instances/files that caused this error # and dump the results to the disassembler console... # lmsg("-"*50) lmsg("Files reporting %s:" % error_type.name) for error in error_list: lmsg(" - %s" % error.filepath) # # popup a more verbose error messagebox for the user to read regarding # this class of error they encountered # disassembler.warning(error.verbose) # done ... lmsg("-"*50)
def warmup(self): """ Warms up the theming system prior to initial use. """ if self._initialized: return logger.debug("Warming up theme subsystem...") # # attempt to load the user's preferred (or hinted) theme. if we are # successful, then there's nothing else to do! # self._refresh_theme_hints() if self._load_preferred_theme(): self._initialized = True logger.debug(" - warmup complete, using preferred theme!") return # # failed to load the preferred theme... so delete the 'active' # file (if there is one) and warn the user before falling back # try: os.remove(os.path.join(self.get_user_theme_dir(), ".active_theme")) except: pass disassembler.warning( "Failed to load Lighthouse user theme!\n\n" "Please check the console for more information..." ) # # if no theme is loaded, we will attempt to detect & load the in-box # themes based on the user's disassembler theme # loaded = self._load_preferred_theme(fallback=True) if not loaded: lmsg("Could not load Lighthouse fallback theme!") # this is a bad place to be... return logger.debug(" - warmup complete, using hint-recommended theme!") self._initialized = True
def _validate_theme(self, theme): """ Pefrom rudimentary theme validation. """ logger.debug(" - Validating theme fields for '%s'..." % theme["name"]) user_fields = theme.get("fields", None) if not user_fields: lmsg("Could not find theme 'fields' definition") return False # check that all the 'required' fields exist in the given theme for field in self._required_fields: if field not in user_fields: lmsg("Could not find required theme field '%s'" % field) return False # theme looks good enough for now... return True
def _scheduled_worker(self): """ A timed callback to watch for metadata-relevant database changes. """ logger.debug("In timed metadata callback...") disassembler_ctx = disassembler[self.lctx] # watch for rebase events current_imagebase = disassembler_ctx.get_imagebase() if (self.cached and current_imagebase != self.imagebase): # only attempt a rebase if the disassembler seems idle... if not disassembler_ctx.busy: lmsg("Rebasing Lighthouse (0x%X --> 0x%X)" % (self.imagebase, current_imagebase)) self.lctx.director.refresh() # schedule the next update (ms) if self._scheduled_timer: self._scheduled_timer.start(self._scheduled_interval)
logger = logging.getLogger("Lighthouse.Binja.Loader") #------------------------------------------------------------------------------ # Lighthouse Binja Loader #------------------------------------------------------------------------------ # # The Binary Ninja plugin loading process is less involved compared to IDA. # # When Binary Ninja is starting up, it will import all python files placed # in its root plugin folder. It will then attempt to import any *directory* # in the plugin folder as a python module. # # For this reason, you may see Binary Ninja attempting to load 'lighthouse' # and 'lighthouse_plugin' in your console. This is normal due to the way # we have structured Lighthouse and its loading process. # # In practice, lighthouse_plugin.py will import the contents of this file, # when Binary Ninja is starting up. As such, this is our only opportunity # to load & integrate Lighthouse. # # TODO/V35: it would be nice load/unload plugins with BNDB's like IDA # try: lighthouse = LighthouseBinja() lighthouse.load() except Exception as e: lmsg("Failed to initialize Lighthouse") logger.exception("Exception details:")