So a couple of months ago, I wanted to poke at my android phone to see how soft and squishy it was. I thought I’d take Mercury, a security assessment framework for android that we developed, for a spin. So I grabbed the shiniest copy of mercury I could and tried to write a toy plugin to list the secretcodes from android applications.
After lots of experimenting with the stock version of mercury, the quickest client-side plugin I could come up with was one which copied each application’s apk to the client and unzipped it to read the manifest. It was slow. Really, mind numbingly, excruciatingly slow. So slow, it needed the charger plugged in to complete. Not good.
Looking in the Mercury server code, I figured I could add a custom command to pull out the data I needed, but then the server would soon bloat if everybody did that. There had to be a way of writing a little bit of code in the server that would let me write whatever I wanted in the client and get it to run…
I agreed with a colleague of mine, Nils, on an interface for performing reflection (fitting, given the program it’s for), which is a method for examining objects dynamically at runtime. Using reflection, we can instantiate new java objects, access their fields and call methods on them. Dynamic reflection means we can get the client to tell the server what objects to make and what to do with them. Goodbye server-side changes…
The interface we decided upon was quite simple, only seven methods:
Nils coded up the server side, and I coded up the python side, and amazingly it worked, after a fashion, first time. Unfortunately it was still quite slow, and debugging indicated this was due to the round-trips being taken for each communication.
We managed to reduce these by changing the send and receive code to reuse existing connection rather than repeatedly closing and opening a new connection. Nils also implemented a custom BufferedBracketReader to efficiently parse incoming data, rather than reading it a byte at a time.
The framework was pretty smooth, the python side constructs objects that proxy through attributes and methods, so any java object you get, you can interact with as you’d expect. For example, object.method(args) should all work fine, and you can manually construct primitives if python can’t autoconvert them for you appropriately.
Sadly, the secret code generator was still a little slow. Round-trips for every single call were time consuming. We needed some way of pushing new java code to the server and having it run it and just send back the answer. A quick trip to the virtual library that is the internets, and I discovered the joys of classloading which meant we could write java code elsewhere and make it a part of mercury on the fly. Awesome! The solution only required a couple more functions for the interface:
Now to put it all together in the example plugin :
f = open(os.path.join(os.path.dirname(__file__), "secretcodes.apk"), "rb") classdata = f.read() f.close() r = Reflect(session, debug = False) classloader = r.classload(base64.b64encode(classdata)) cls = classloader.loadClass("ManifestReader") obj = r.construct(cls) ctx = r.getctx() pml = ctx.getPackageManager().getInstalledPackages(0) for i in range(pml.size().native): package = pml.get(i).packageName print "Package:", package codelist = obj.main(ctx, package) for i in codelist: print " ", i
So this basically reads in an apk file (produced by compiling a class and running dx --dex --output file.apk file.class), and then transmits it to the server. A helper method then creates a classloader object from the apk file, and from that point on the object can be used almost transparently on the python side, so we can call the loadclass method, asking for the class we defined.
We then use reflection again to construct an object dynamically from the ManifestReader class we just loaded. We get an application context, call (reflected) methods on it to get a PackageManager instance, and get the list of installed packages. It traverses this using an index and calls our ManifestReader object’s main method on each package to search for secret codes natively on the device. The result is a string array, which we can pass through pythonicly as an iterator and print out the results.
What this means is we can add new functionality to mercury without having to change/recompile the java application at all. Now we can convert over existing plugins, or turn them into classloader plugins if there is too great an overhead incurred using pure reflection, and slim the main server down to a minimum. All of these are available now in the master branch, and will be part of the new Mercury 1.1 which will be released in the coming days! So go add some new functionality today…