Lighthouse is a powerful code coverage plugin for IDA Pro and Binary Ninja. As an extension of the leading disassemblers, Lighthouse enables one to interactively explore code coverage data in new and innovative ways when symbols or source may not be available for a given binary.

This post documents the long overdue release of Lighthouse v0.9 – the largest update in the project’s history. The major additions include full Python 2/3 compatibility, support for loading simpler coverage file formats, the ability to cross-reference coverage, custom user-defined themes, and a huge refactor to properly support Binary Ninja 2.0.

Binary Ninja & IDA Pro using different Lighthouse themes

Python 3 Compatibility

Lighthouse now fully supports Python 3, while retaining Python 2 compatibility.

Lighthouse v0.9 loading under Python 3 in IDA Pro 7.4

Much of the Python 3 compat was contributed by @xarkes and the cutter/radare2 folk via pull request (#62). This work was to support an in-development (very experimental) pull request (#61) to add Cutter support to Lighthouse, but is directly applicable to IDA Pro and Binary Ninja.

New Coverage Formats

Lighthouse now supports loading Module + Offset (modoff) and Absolute Address style coverage files (issue #41). This will hopefully stem the unintended standardization of drcov (cf. [1], [2], [3], [4], [5], [6] …) that we caused.

Modoff is now the recommended coverage format for those who are building custom tooling around Lighthouse. This is because modoff traces are simple to implement, human readable, and super portable:

boombox.exe+0x3a06
boombox.exe+0x3a09
boombox.exe+0x3a0f
boombox.exe+0x3a15
...

Each line of the trace represents an executed instruction or basic block in the instrumented program. The line must name an executed module (e.g. boombox.exe) and a relative offset to the executed address from the imagebase. The offsets in the trace can either be basic blocks, or instruction addresses.

For more information about coverage formats, please checkout the coverage readme in the repo. If you are feeling adventurous, Lighthouse now has a somewhat extensible parser interface if you want to write your own loader.

Coverage Cross-references (Xref)

While using Lighthouse, you can now right click any basic block (or instruction) and use the ‘Coverage Xref’ menu entry to see which loaded coverage sets executed the selected block. Double clicking any of the listed entries will instantly switch to that coverage set:

Cross-referencing coverage can be used to identify which coverage files hit a target block

This pairs well with the ‘Load coverage batch’ feature, which allows you to quickly load and aggregate thousands of coverage files into Lighthouse. Cross-referencing a block with a batch loaded and double clicking an xref entry will load the ‘guilty’ set from disk as a new coverage set for you to explore separate from the batch.

Module Selector

One of most frustrating experiences with using Lighthouse is when it fails to correctly identify which coverage data to load from your files. What’s worse is that sometimes Lighthouse could load the wrong coverage data, making things even more confusing (issue #63).

As a result, the ‘fuzzy’ name matching has been made stricter and Lighthouse will now prompt you to ‘select’ the module that matches your database with the following dialog:

The new fallback 'module selector' dialog that may pop up when loading coverage in Lighthouse

This list of modules is generated from whatever the loaded coverage file claims to have coverage for. If you do not see a module name that you expect, it is possible you selected the wrong coverage file or there is simply no coverage data for your binary.

Binary Ninja 2.0

In the previous release of Lighthouse, we added ‘experimental’ support for Binary Ninja. It was a hacky proof-of-concept prior to Binary Ninja’s official support of ‘UI Plugins’ and the release of their new UI APIs.

With native UI integration now available, this release of Lighthouse introduces ‘official’ support for Binary Ninja 2.0!

Lighthouse supports multiple simultaneous databases in Binary Ninja 2.0

Properly supporting Binary Ninja means that Lighthouse can now handle multiple active databases within the same disassembler session. This required some internal restructuring of Lighthouse, but seeing it in action is pure magic.

Should you encounter any bugs with the Binary Ninja port, please file an issue on GitHub.

Custom Themes

Lighthouse now 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.

Binary Ninja & IDA Pro using different Lighthouse themes

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.

Interpreter Access (Experimental)

Per-request, I have exposed the internal Lighthouse plugin context to the disassembler console (issue #76). As an example, here’s a few things you can do through the Python console while Lighthouse is active:

import lighthouse

# get the current 'lighthouse context' from the plugin (pass the bv in Binja)
lctx = lighthouse.get_context()

# print the name of the *active* coverage set
print(lctx.director.coverage.name)

# print the nodes with coverage in the *active* coverage set
print(lctx.director.coverage.nodes)
{0x140003320: <lighthouse.coverage.NodeCoverage object at 0x000000754DD726A0>, 
 0x1400038d0: <lighthouse.coverage.NodeCoverage object at 0x000000754DD72668>, 
 0x140003960: <lighthouse.coverage.NodeCoverage object at 0x000000754DD72710>,
 ...

# retrieve a loaded coverage set (DatabaseCoverage) by name or symbol
coverage = lctx.director.get_coverage('A')

It is suggested that you review the coverage.py source files on what data can be mined through the coverage objects, specifically: DatabaseCoverage, FunctionCoverage and NodeCoverage

While this is not true headless support, it at least provides some level of access to scripts or snippets run within the disassembler. Trying to ‘drive’ or modify the internal plugin state is by no means supported, proceed at your own peril.

IDA-specific Notes

There are a number of IDA-specific notes and improvements that are worth mentioning.

Compatibility

Lighthouse has been updated to fully support IDA 7.0 to 7.4 under Python 2/3. Lighthouse has deprecated support for IDA 6.x with this release both to reduce maintenance complexity and help keep the RE ecosystem current.

Better Painting

The Lighthouse painting subsystem has undergone some major updates which help improve performance, accuracy, and stability. This is particularly true for IDA.

  • Database painting should now run upwards of 10x faster (still asynchronous)
  • Partially executed basic blocks should no longer appear fully painted in the graph
  • Hexrays / Decompilation views should refresh automatically with changes to coverage
  • It should no longer be possible to crash the painting thread when switching coverage sets

Rebasing

Lighthouse will now detect and automatically rebase its internal state if the user rebases their database. Previously, Lighthouse would get very confused in these cases but it should be better now.

You can always rebase prior to activating Lighthouse in either IDA or Binary Ninja if you want to be safe.

Faster Exit

IDA should now exit faster than it previously would after using Lighthouse.

IDA could hang a bit on exit (especially with a larger database) because the python runtime had a hard time breaking some of the reference chains in the Lighthouse subsystems. Lighthouse now explicitly breaks some of these chains on termination to ensure faster garbage collection at close.

Other Changes

There are a ton of other minor changes & bugfixes, here are some worth mentioning:

  • Batch loading no longer loads all files into memory before aggregating data
  • Updated the drcov coverage parser to support newer revisions
  • The CodeCoverage pintool code has been updated to support Pin 3.10 -> 3.13
  • Support ‘interleaved’ instruction coverage in capable disassemblers (Binary Ninja)
  • Double clicking a function in the coverage table will now jump to the ‘first’ block with coverage
  • UI: The coverage overview will more consistently snap to the right-side of the disassembler on open
  • UI: Reduced the font size of Lighthouse on macOS by 1pt, text should look a bit less comical
  • UI: Improved the coverage shell so that text selection (click+drag) actually works
  • UI: ‘Forcefully’ clearing database paint will now block with a waitbox while running
  • BUGFIX: Aggregate set symbol * was simply unusable in the coverage shell
  • BUGFIX: Coverage shell could prompt the user ‘several’ times for a coverage name when saving a composition
  • BUGFIX: Drcov parser could fail to extract module filenames when parsing a log collected on a different OS
  • BUGFIX: Deleted / undefined functions would persist in the coverage table after refresh
  • BUGFIX: Fixed bug that caused ‘renamed’ functions to lose their navigability (click to jump) in the table
  • … (and more)

For the complete changelog, please click here to see the release info on GitHub.

In the Wild

Since it has been so long since the last release, I am not going to try and enumerate the full list of publications and inidividual researchers that have cited Lighthouse in their work.

Here are a few of the blogposts and talks that Lighthouse has appeared in since the last post:


HITB AMS 2019 - Juwei Lin and Junzhi Lu - Panic On The Streets Of Amsterdam: PanicXNU 3.0

BlueHat IL 2020 - David Weston - Keeping Windows Secure

OffensiveCon20 - Netanel Ben-Simon, Yoav Alon - Bugs on the Windshield: Fuzzing the Windows Kernel

Conclusion

Lighthouse continues to empower individuals and organizations around the world. Its unique perspective is changing the way that this industry evaluates software, guiding us to new and innovative discoveries.

Our experience developing for these technologies is second to none. RET2 is happy to consult in these spaces, providing plugin development services, the addition of custom features to existing works, or other unique opportunities with regard to security tooling. If your organization has a need for this expertise, please feel free to reach out.