Building

IPython Support for Binary Ninja

This blogpost is about the release of a plugin for Binary Ninja that allows you to run a Python Kernel inside the Binary Ninja GUI environment to which you can attach a Jupyer (QT) console, formerly known as IPython shell. The first section is about why this is useful, the second is about some issues I encountered and how to solve them, and the third contains everything you need to know to set it up.

The Why

Binary Ninja is a fairly new competitor on the field of disassemblers and binary analysis frameworks. But one of the features I find most interesting is that it exposes a fairly rich API and various Intermediate Languages which allows you to easily write your own scripts and plugins on top of it. You can even use it to model vulnerabilities and find heartbleed.

But personally I found the built-in Python shell that gives you access to the API fairly lacking. No tab completion, no automatic indenting for multiline code and no fancy features like inline SVG or chart rendering. Especially for exploring foreign Python APIs I have found IPython incredibly helpful so my goal was to somehow get an IPython shell running in the same environment as the built-in shell.

The How

The actual lines of code for this plugin are fairly few, yet no one had written this before. Other projects like Ryan Hileman’s bnrepl project did something similar but just emulated a simple python shell with tab completion which wasn’t enough for me. But this project, or rather the author themselves, proved incredibly helpful while developing.

Running the kernel

Running the kernel turned out to be simpler than I thought in the end. After various attempts with Binary Ninja Plugin Threads, embeding vs starting a kernel and encountering various issues like a started kernel I couldn’t attach too, the kernel refusing to start because it wasn’t being started in the main thread and thus signals didn’t work and others, the solution was basically:

self.app.init_signal = lambda *args, **kw: None
self.app.initialize()
self.app.start()

Patching the init_signal method with a no op allowed the kernel to run in a background thread and I could attach to it.

Getting the magic variables

The Binary Ninja built-in shell has various magic variables that are automatically updated according to some GUI properties, e.g. bv for the current open BinaryView, here for the cursor adress, current_function for the object corresponding the function that is currently open in the GUI (if any) and various others. They are crucial because they are the only references to those data structures we have and allow us to propagate any changes we make back into the GUI. So for example running current_function.name = 'foobar' renames the function that is currently opened in the GUI to foobar. Or we could write a script that colors any xor instructions in the currently open binary view in pink.

There were two main problems with this: Finding out where to get those values and object references from and how to inject them into the IPython/Jupyter environment.

Ryan’s bnrepl project had already solved the first so I adapted their solution.

The solution for the first problem are the magic lines:

obj = [o for o in gc.get_objects() if isinstance(o, scriptingprovider.PythonScriptingInstance.InterpreterThread)]
self._interpreter = obj[0]

This uses the garbage collector (gc) to find the object that is used internally by Binary Ninja to bridge the core (which knows about the currently opened function and the other magic variables) and the built-in shell. Most importantly it already has the proper contents for all the magic variables as attributes.

The solution to the second problem is now fairly simple. The local variables are accessible as a dict in Python and can be updated like one. So the plugin has a function that has a (cached) reference to the ScriptingProvider and updates the local variables of the Python kernel and registers this as a pre_execute hook in IPython/Jupyter.

Because I found no way to do this when starting the kernel from the plugin this is currently implemented as an IPython/Jupyterconsole extension that has to be loaded once per kernel. There might be a way to load this extension via the IPython/Jupyter API as soon as the kernel is started, but I haven’t found one yet.

Other tricks

The last trick is not about getting the kernel running but about stopping it. If you run a command that will run forever, at least until the end of the universe or just longer than you planned you can’t interrupt it without some tricks. The attached IPython shell/JupyerConsole can’t raise an KeyboardInterrupt exception in the kernel thread.

ctypes.pythonapi.PyThreadState_SetAsyncExc(ctypes.c_long(thread_obj.ident), ctypes.py_object(exception))

This is executed in the plugin context and uses ctypes to inject an exception (in our case the KeyboardInterrupt) into the IPython kernel thread. This can be triggered from the GUI. Credit again to Ryan for telling me about this.

The Plugin

Now for the most important part, installing and using it:

  1. Checkout the repo and link/move it to your binary ninja plugin folder ~/.binaryninja/plugins/
  2. Activate the virtualenv or python environment you want to use and run pip install ./binja-ipython. This installs the IPython extension
  3. Open Binary Ninja and open some binary
  4. Use the menu to run a QT console or attach with jupyter console --existing
    1. Properly installing the QT console might be more work, so test with the above command first
  5. run %load_ext binjamagic in this shell to get the variables
  6. Evaluating bv should now give you a reference to the currently opened binary view

Caveats

There are some limitations and known bugs:

  • only properly tested on Linux
    • in general it should be fairly platform agnostic
  • interrupting the kernel while nothing is executed crashes it

If you run into any other bugs, please report them as an issue on Github.

Conclusion

I hope this plugin provides useful to you or maybe even motivates you to try out Binary Ninja. For me the lack of a proper shell was what stopped me from exploring and leveraging the Binary Ninja API, so now I finally get to play around with it and can automate some reversing tasks.

Cheers

Florian Magin

Continue reading
Building

PoSh_ATTCK – ATT&CK Knowledge at your PowerShell Fingertips…

Intro

When I recently joined the Windows Security team at ERNW, Enno asked me if I wanted to write a ‘welcome’ blogpost on a topic of my choosing… Up for the challenge, and since I had been playing with BloodHound & Cypher for the last couple of months, I first thought I would do something on that topic.

However, after gathering my thoughts and some Cypher I had collected here and there, I realized that the topic of Bloodhound Cypher might actually require several blog posts… And so I changed my mind. I will keep the joys of Cypher for later, and in this post, I will talk about a tiny tool I wrote to query the Mitre ATT&CK™ knowledge base from the comfort of a PowerShell prompt.

Small, Simple and hopefully useful: should be suited for this first post…
Continue reading “PoSh_ATTCK – ATT&CK Knowledge at your PowerShell Fingertips…”

Continue reading
Building

printf(“Hello World!”)

ERNW has a new baby, so please say “hello” to the new ERNW SecTools GmbH ;-).
But why another ERNW company? Short answer: Because we want to contribute to changing the way how software is built today: insecure, focused on profit and sometimes made by people who ignore lessons from history. So how can we contribute in this space? Start changing it ;-).

Continue reading “printf(“Hello World!”)”

Continue reading
Building

Virtualized Training Environment with Ansible

As Kai and I will be holding a TROOPERS workshop on automation with ansible, we needed a setup for the attendees to use ansible against virtual machines we set up with the necessary environment. The idea was, that every attendee has their own VMs to run ansible against, ideally including one to run ansible from, as we want to avoid setup or version incompatibilities if they set up their own ansible environment on their laptop.  Also they should only be able to talk to their own machines, thus avoiding conflicts because of accidental usage of wrong IPs or host names but also simplify the setup for the users.

Continue reading “Virtualized Training Environment with Ansible”

Continue reading
Building

Why It Might Make Sense to Use IPv6 in Enterprise Infrastructure Projects

Looking at IPv6 deployment graphs like this one it becomes clear that IPv6 still is not widely deployed in enterprise space (the reason for the apparent oscillation in that curve is the difference between working days – where people use their office computers – and weekend where they preferably use their smartphones or their home equipment connected by means of broadband networks).

Continue reading “Why It Might Make Sense to Use IPv6 in Enterprise Infrastructure Projects”

Continue reading
Building

Reading the BlueCoat FileSystem

You may remember our last post regarding the SGOS system and the proprietary file system. Since then, we got access to a newer version of the system (6.6.4.2). Still not the most current one (which seems to be 6.7.1.1) nor of the 6.6.x branch (which seems to be 6.6.5.1) though. As this system version also used the same proprietary filesystem (although it initially booted from a FAT32 partition), I decided to take a deeper look into this.

Continue reading “Reading the BlueCoat FileSystem”

Continue reading
Building

A Life Without Vendors Binary Blobs

This blogpost will be about my first steps with coreboot and libreboot and a life with as few proprietary firmware blobs as possible. My main motivation were the latest headlines about fancy firmware things like Intel ME, Computrace and UEFI backdoors. This post is not intended to be about a as much as possible hardened system or about coreboot/libreboot being more secure, but rather to be able to look into every part of software running on that system if you want to.

I first got curious about coreboot and libreboot at the 33C3 (Bootstraping a slightly more secure laptop). Then I searched for some old retired hardware at ERNW which I could flash coreboot to and found an old Thinkpad X61. Finding the X60 as officially supported hardware on the libreboot homepage, I have read through the libreboot and coreboot manuals to learn about the main coreboot part and it’s several payloads. Continue reading “A Life Without Vendors Binary Blobs”

Continue reading