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
Events

Diversity, Community, Blackhoodie

Gender equality in the Infosec world as a topic of discussion comes with a lot of heated arguments and differences in opinion.
So let me start with some disclaimers on the target audience for this post. If you are in the category who believes everything about gender is perfect in the infosec world, this post is not for you. If you are in the category who believes gender and bringing diversity is not your area of interest, then this post is not for you either. There are so many interesting problems that the world offers you. Climate change, poverty, diseases, unemployment, addiction, science problems and what not. Everybody has the freedom to choose their area of interest and contribute towards it. If you are in the category who thinks gender equality in infosec needs some attention and would like to explore more on the topic without prejudices, then this post may  be interesting to you. Continue reading “Diversity, Community, Blackhoodie”

Continue reading
Misc

A little KeePass Mea Culpa…

Some weeks ago, I tweeted about grabbing clipboard content from KeePass with some PowerShell. From some reactions to this tweet, and after reading it a couple of times again, I realize it was sending the wrong message, and I would like to take a bit more than 280 chars to clarify what I meant when I posted that tweet…

TLDR: Password managers are a must, not using one exposes you to far more risks than using one. Do it.  Continue reading “A little KeePass Mea Culpa…”

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
Events

The building IoT 2018 in Cologne

In Mai 2018, Tobias and me were in Cologne at the Building IoT conference. The topics of the talks covered a broad spectrum of the Internet of Things field. There were three tracks covering different topics ranging from the jungle of IoT protocols, secure Linux hypervisors specially developed for IoT modules to machine learning and blockchain.

Continue reading “The building IoT 2018 in Cologne”

Continue reading
Events

Modern Application Stacks & Security

I had the pleasure to give a presentation at the Security Interest Group Switzerland Technology Conference about modern application stacks and how they can be used to improve infrastructure and application security posture – the slides can be found here. Besides seeing a lot of old friends, I particularly enjoyed a round table discussion on security integration into CI/CD pipelines. Continue reading “Modern Application Stacks & Security”

Continue reading
Breaking

Security of Busch-Jaeger IP Gateway

IoT is everywhere right now and there are a lot of products out there. I have been looking at an IP Gateway lately and found some serious issues. The Busch-Welcome IP-Gateway from Busch-Jaeger is one of the devices that bridges the gap between sensors and actors in your smart home and the network/Internet. It enables the communication to a door control system that implements various smart home functions. The device itself is offering an HTTP service to configure it, which is protected by a username and password. Some folks even actually expose the device and its login to the Internet. I tried to configure one of these lately and stumbled upon some security issues that I would like to discuss in this blog post.
Continue reading “Security of Busch-Jaeger IP Gateway”

Continue reading