Beispiel #1
0
    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
Beispiel #2
0
 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
Beispiel #3
0
    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
Beispiel #4
0
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)
Beispiel #5
0
    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
Beispiel #6
0
    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
Beispiel #7
0
    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)
Beispiel #8
0
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:")