Lighthouse is a powerful code coverage explorer for IDA Pro and Binary Ninja, providing software researchers with uniquely interactive controls to study execution maps for native applications without requiring symbols or source.
This project placed 2nd in IDA's 2017 Plug-In Contest and was later nominated in the 2021 Pwnie Awards for its contributions to the security research industry.
Special thanks to @0vercl0k for the inspiration.
- v0.9 -- Python 3 support, custom coverage formats, coverage cross-refs, theming subsystem, much more.
- v0.8 -- Binary Ninja support, HTML coverage reports, consistent styling, many tweaks, bugfixes.
- v0.7 -- Frida, C++ demangling, context menu, function prefixing, tweaks, bugfixes.
- v0.6 -- Intel pintool, cyclomatic complexity, batch load, bugfixes.
- v0.5 -- Search, IDA 7 support, many improvements, stability.
- v0.4 -- Most compute is now asynchronous, bugfixes.
- v0.3 -- Coverage composition, interactive composing shell.
- v0.2 -- Multifile support, performance improvements, bugfixes.
- v0.1 -- Initial release
Lighthouse is a cross-platform (Windows, macOS, Linux) Python 2/3 plugin. It takes zero third party dependencies, making the code both portable and easy to install.
Use the instructions below for your respective disassembler.
- From IDA's Python console, run the following command to find its plugin directory:
import idaapi, os; print(os.path.join(idaapi.get_user_idadir(), "plugins"))
- Copy the contents of this repository's
/plugins/
folder to the listed directory. - Restart your disassembler.
Lighthouse can be installed through the plugin manager on newer versions of Binary Ninja (>2.4.2918). The plugin will have to be installed manually on older versions.
- Open Binary Ninja's plugin manager by navigating the following submenus:
Edit
->Preferences
->Manage Plugins
- Search for Lighthouse in the plugin manager, and click the
Enable
button in the bottom right. - Restart your disassembler.
- Open Binary Ninja's plugin folder by navigating the following submenus:
Tools
->Open Plugins Folder...
- Copy the contents of this repository's
/plugins/
folder to the listed directory. - Restart your disassembler.
Once properly installed, there will be a few new menu entries available in the disassembler. These are the entry points for a user to load coverage data and start using Lighthouse.
Lighthouse is able to load a few different 'flavors' of coverage data. To generate coverage data that can be loaded into Lighthouse, please look at the README in the coverage directory of this repository.
While Lighthouse is in use, it will 'paint' the active coverage data across all of the code viewers available in the disassembler. Specifically, this will apply to your linear disassembly, graph, and decompiler windows.
In Binary Ninja, only the linear disassembly, graph, and IL views are supported. Support for painting decompiler output in Binary Ninja will be added to Lighthouse in the near future as the feature stabilizes.
The Coverage Overview is a dockable widget that will open up once coverage has been loaded into Lighthouse.
This interactive widget provides a function level view of the loaded coverage data. It also houses a number of tools to manage loaded data and drive more advanced forms of coverage analysis.
Right clicking the table in the Coverage Overview will produce a context menu with a few basic amenities to extract information from the table, or manipulate the database as part of your reverse engineering process.
If there are any other actions that you think might be useful to add to this context menu, please file an issue and they will be considered for a future release of Lighthouse.
Loaded coverage and user constructed compositions can be selected or deleted through the coverage combobox.
Lighthouse can generate rudimentary HTML coverage reports. A sample report can be seen here.
At the bottom of the coverage overview window is the coverage shell. This shell can be used to perform logic-based operations that combine or manipulate the loaded coverage sets.
This feature is extremely useful in exploring the relationships of program execution across multiple runs. In other words, the shell can be used to 'diff' execution between coverage sets and extract a deeper meaning that is otherwise obscured within the noise of their individual parts.
Coverage composition, or Composing as demonstrated above is achieved through a simple expression grammar and 'shorthand' coverage symbols (A to Z) on the composing shell.
- Logical Operators:
|, &, ^, -
- Coverage Symbol:
A, B, C, ..., Z, *
- Parenthesis:
(...)
- Executed code that is shared between coverage
A
and coverageB
:
A & B
- Executed code that is unique only to coverage
A
:
A - B
- Executed code that is unique to
A
orB
, but notC
:
(A | B) - C
Expressions can be of arbitrary length or complexity, but the evaluation of the composition may occur right to left. So parenthesis are suggested for potentially ambiguous expressions.
Additionally, there is a 'Hot Shell' mode that asynchronously evaluates and caches user compositions in real-time.
The hot shell serves as a natural gateway into the unguided exploration of composed relationships.
Using the shell, you can search and filter the functions listed in the coverage table by prefixing their query with /
.
The head of the shell will show an updated coverage % computed only from the remaining functions. This is useful when analyzing coverage for specific function families.
Entering an address or function name into the shell can be used to jump to corresponding function entries in the table.
While using Lighthouse, you can right click any basic block (or instruction) and use the 'Coverage Xref' action to see which coverage sets executed the selected block. Double clicking any of the listed entries will instantly switch to that coverage set.
This pairs well with the 'Coverage Batch' feature, which allows you to quickly load and aggregate thousands of coverage files into Lighthouse. Cross-referencing a block and selecting a 'set' will load the 'guilty' set from disk as a new coverage set for you to explore separate from the batch.
Lighthouse ships with two default themes -- a 'light' theme, and a 'dark' one. Depending on the colors currently used by your disassembler, Lighthouse will attempt to select the theme that seems most appropriate.
The theme files are stored as simple JSON on disk and are highly configurable. If you are not happy with the default themes or colors, you can create your own themes and simply drop them in the user theme directory.
Lighthouse will remember your theme preference for future loads and uses.
Time and motivation permitting, future work may include:
Asynchronous composition, painting, metadata collectionMultifile/coverage support- Profiling based heatmaps/painting
- Coverage & profiling treemaps
Additional coverage sources, trace formats, etc- Improved pseudocode painting
Lighthouse console access, headless usageCustom themesPython 3 support
I welcome external contributions, issues, and feature requests. Please make any pull requests to the develop
branch of this repository if you would like them to be considered for a future release.
- Markus Gaasedelen (@gaasedelen)