16

This is not strictly 'reverse engineering', it's mostly related to dynamic instrumentation.

So, in the same fashion as strace which allows you to see syscalls made by a process, or ftrace to see function calls, is there anything similar for Java?

What I am interested in is having a .jar file that is run in a javaVM.

Is there any way to instrument or trace all the Java API calls the application code makes ?

That is, without any static analysis of the contents of the .jar or without any editing of the contents of .jar (e.g. to add hooks). Ideally, a solution equivalent to strace or e.g. a manipulated javaVM

The same applies on Android - Is there a way to trace all Android framework API calls (or other essentially DalvikVM functions) an application makes without any editing at all of the APK file? All other editing of the environment/system is fine.

In my ideal world, the analyst would get the following output, while running an UNEDITED application (.jar or .apk):

timestamp1: java.security.SecureRandom.getSeed() called. Arguments: (Number) 
timestamp2: javax.security.cert.X509Certificate.checkValidity() called. Arguments: (null)
...
timestamp3: java.sql.Connection.prepareStatement() called. Arguments: ("SELECT * FROM X WHERE Y = W")
5
  • In this case - wouldn't it be easier to analyze behaviour of java.exe executable, when .jar file passed to it as a parameter? Commented Apr 11, 2013 at 10:22
  • I am not sure how can this be done and what kind of output it would have. Analysing the java executable would show syscalls it makes to the kernel - this is not what I'm looking for. I'm looking to trace the invocation of Java APIs. Also, it wouldn't work on Android which is the second target.
    – JavaSec
    Commented Apr 11, 2013 at 10:28
  • 1
    Regarding Android, you could use DDMS to trace the target for inspection with the profiler, but that doesn't get arguments. If you want API calls and data, you could instrument the binder_transaction function in the kernel via kprobes, although parsing the transaction buffers is problematic. Commented Apr 11, 2013 at 15:40
  • @MathewHall this is very interesting and may be the solution for Android. Will look into it! I imagine you'd instrument binder_transaction via kprobes using systemtap ?
    – JavaSec
    Commented Apr 11, 2013 at 16:32
  • SystemTap is probably easier yes, although you need to be able to "parse" the packets (args to binder_transaction). The code in the transaction data is the index in the service's aidl file and the service itself appears as a UTF-16 string in the buffer. Object arguments are trickier though; this 0xlab slide deck summarises Binder quite well. Commented Apr 12, 2013 at 10:46

3 Answers 3

14

Oracle Java Virtual Machine

Tracing the execution of a Java program can be done through the Java Platform Debugger Architecture (JPDA). This framework allow you to get a full control of an execution within the JVM (without having to modify the original code). See this tutorial for a more in depth view of this framework.

If you want to implement it by yourself, you should use the MethodEntryRequest interface and intercept any method call.

But, if you are lazy (just like me), you'd better use already existing projects such as InTrace (see also the Related Projects' page of the InTrace project).

Android Java Dalvik Virtual Machine

Tracing an Android Java program can be done through the Dalvik Debug Monitor Server (DDMS) and the full Android debug framework.

There exist already some tools to trace the execution of programs such as Traceview and dmtracedump tools. And, finally, a few tips about the Dalvik JVM.

5
  • wow, this is exactly what I was looking for, and I did not even know such things existed. Thanks for opening my eyes to this, this should be perfect for java code.
    – JavaSec
    Commented Apr 11, 2013 at 16:29
  • However, all these tools depend on the javaagents functionality, which is not supported on Dalvik, so this wouldn't work on Android. I guess I should had another question more specific to Android.
    – JavaSec
    Commented Apr 11, 2013 at 16:30
  • My fault, I didn't noticed you asked specifically for Dalvik JVM (thought the 'android' tag should have ringed a bell...). And, I don't know much about Android JVM. Sorry. :-/
    – perror
    Commented Apr 11, 2013 at 16:42
  • The closest I could come with for Dalvik JVM seems to be the Dalvik Debug Monitor Server (DDMS) and the full Android debug framework. You seems to be able to extract a trace with the Traceview and dmtracedump tools. But, I never tried it.
    – perror
    Commented Apr 11, 2013 at 16:58
  • I have tried that, but it doesn't seem to be able to give arguments for the methods, will research further. I also just found that the dalvikVM can be launched independently, using 'dalvikvm' on an adb shell, and it supports some kind of -agentlib option to launch jdwp. I wonder if that's useful somehow. [ netmite.com/android/mydroid/2.0/dalvik/docs/debugger.html ]
    – JavaSec
    Commented Apr 11, 2013 at 17:02
6

You can instrument Java by using an agent, that will manipulate the bytecode of the loaded file (using Asm is recommented for bytecode manipulation).

You might want to use Eclipse's Bytecode Outline plugin to debug execution.

This is a good tutorial on the topic.

2
  • Thank you for this, this is good. However it involves manipulating the jar file, basically inserting hooks. I am looking mostly on doing everything without ever touching the .jar file, to examine it passively. That would allow analysis of 'protected' code (e.g. code that uses integrity protection through another library, is heavily obfuscated etc). Maybe a manipulated java or dalvik VM could work, so that API calls log themselves somewhere (?).
    – JavaSec
    Commented Apr 11, 2013 at 9:54
  • Hmm I just read the article you sent again, it seems that it doesn't involve manipulation of the application.. hm, still researching!
    – JavaSec
    Commented Apr 11, 2013 at 9:56
4

AspectJ can be used to do this on the JVM, via load-time weaving. It's built on Asm but there's more abstraction (no bytecode). Tracing method calls is fairly straight-forward: first define a filter to match "pointcuts" you're interested in, then specify the actions you want to perform ("advice").

The syntax is a bit awkward though:

package aspects;

import java.util.logging.Level;
import java.util.logging.Logger;

import org.aspectj.lang.Signature;

aspect Trace{
    pointcut traceMethods() : (execution(* *(..))&& !cflow(within(Trace)));

    before(): traceMethods(){
        Signature sig = thisJoinPointStaticPart.getSignature();
        String line =""+ thisJoinPointStaticPart.getSourceLocation().getLine();
        String sourceName = thisJoinPointStaticPart.getSourceLocation().getWithinType().getCanonicalName();
        Logger.getLogger("Tracing").log(
                Level.INFO, 
                "Call from "
                    +  sourceName
                    +" line " +
                    line
                    +" to " +sig.getDeclaringTypeName() + "." + sig.getName()
        );
    }

}

Compile with: ajc -outxml -outjar aspects.jar Trace.java.

To run FooClass with the weaver, run:

java -javaagent:aspectjweaver.jar -cp aspects.jar:${target_jar_name} FooClass
1
  • 1
    Note that this won't work for obfuscated applications (or just ones compiled without debug info).
    – Antimony
    Commented Aug 28, 2013 at 13:37

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.