4 comments

[ 4.3 ms ] story [ 12.9 ms ] thread
Very cool project: I've done this a number of times where I just need a simple bug fix in a jar without source.

Question for the author: why is this a ruby script wrapping a python library rather than a full-Java app?

jarsurgeon is a simple wrapper script that builds upon several pre-existing tools:

- Krakatau (Python)

- GNU make (C)

- git (C)

- javac, jar (ELF binaries that invoke Java)

- javap (alternative to Krakatau's disassemble.py; another ELF binary that invokes Java)

After repeating this workflow by hand for numerous JAR files, I figured it was worth automating.

Arguably the "disassemble" step could have been integrated a little better using e.g. jython or "import Krakatau", but I didn't feel that it was worth the trouble. Also, structuring it this way makes it easy to substitute jasper/jasmin or another bytecode (dis)assembler if desired.

The "reassemble" (make) step would have to be completely redesigned to use pure Java tools. Changing to Ant/Maven/Gradle/... might be helpful if the instrumentation has more complicated dependencies. For my purposes, GNU make was the most expedient solution.

Shelling out to run the binaries has the added advantage of making it easy to switch between different JDK versions.

I can see the appeal if you only want to do a transformation once, but if you've found you're doing it many times why not do it with ASM or some of the other available infrastructure? You could even do the work within a class loader to instrument methods on the fly as the classes are loaded.
My use case is the equivalent of adding printf's to various obfuscated methods, for purposes like:

- Determining if/when/how the method is called, i.e. understanding how specific operator actions affect the program flow

- Dumping out arguments or intermediate values, to see if I recognize the data or have properly identified the purpose of the obfuscated method

- Extracting secrets buried in the program, without having to reverse engineer the storage format

- Printing out strings or byte arrays after the de-obfuscator code has run (FWIW I have also used ASM for this when I had a bunch of similarly-obfuscated .class files to process)

This tends to be a manual, iterative process - not necessarily something well-suited to applying the same "formula" to every method. So I'll find an interesting method (often identified using strings or magic numbers), instrument it, and rerun the program. That result will determine what gets instrumented next. Being able to run "make ; java -jar new.jar", and only reassemble the files that have changed, is a huge time saver.

I'd actually prefer to use a debugger, but the best solution I found was Dr. Garbage[1] and it doesn't allow inspection of objects on the operand stack, or breakpoints on specific opcodes. Also, attaching a debugger to a more complex multithreaded system, such as a J2EE application server, may be tricky.

[1] http://www.drgarbage.com/bytecode-visualizer/