4

I'm trying to RE a Java application that uses an obfuscated loader program to load classes from a second, obfuscated archive-like file. I'm trying to get at these loaded classes for further analysis, but thus far I haven't had any success in figuring out the format of the archive file. Since the classes are loaded into memory anyway, and I used a Java profiler to get a short list of the specific classes and objects that most likely contain what I'm looking for, is there a way to intercept these classes from memory, a core dump, as they're loaded, or through any other means, and inspect/save them? Assume I have full control of the system, and I can stop or modify the program in any way.

3 Answers 3

8

I would recommend using a Java Agent to extract classes from the running JVM instance. An agent is a tool that provides instrumentation capability for an application. Speaking of agents, there are two broad ways they can be developed:

  1. In pure java
  2. In C/C++ in the form of native agents.

A native agent has more capability than a pure Java agent, but for your purpose it is sufficient. At some point in the execution flow, the class loader has to load and decrypt the encrypted classes.

Sample code is provided below. The agent registers a callback (the transform method) to be notified whenever a new class is being loaded. Within the callback we simply dump the contents of the class to disk.

import java.io.*;
import java.lang.instrument.*;
import java.security.*;

public class dumper
{
  //A java agent must have a premain method which acts as the entry-point
  public static void premain(String agentArgs, Instrumentation inst)
  {
    System.out.println("agent loaded");

    // Register our transformer
    inst.addTransformer(new transformer());    
  }
}

class transformer implements ClassFileTransformer
{
   // The transform method is called for each non-system class as they are being loaded  
   public byte[] transform(ClassLoader loader, String className, 
                           Class<?> classBeingRedefined, ProtectionDomain protectionDomain, 
                           byte[] classfileBuffer) throws IllegalClassFormatException
   {
     if (className != null)
     {
       // Skip all system classes
       if (!className.startsWith("java") && 
           !className.startsWith("sun") && 
           !className.startsWith("javax") && 
           !className.startsWith ("com") && 
           !className.startsWith("jdk") && 
           !className.startsWith("org"))
       {
         System.out.println("Dumping: " + className);

         // Replace all separator charactors
         String newName = className.replaceAll("/", "#") + ".class";

         try
         {
           FileOutputStream fos = new FileOutputStream(newName);
           fos.write(classfileBuffer);
           fos.close();
         }
         catch (Exception ex)
         {
           System.out.println("Exception while writing: " + newName);
         } 
       }
     }
     // We are not modifying the bytecode in anyway, so return it as-is
     return classfileBuffer;
   }
 }

I have a writeup on this process here: Reversing An Obfuscated Java Malware

2
  • This was exactly what I was looking for, and Agents in general were a tremendous help for the rest of what I wanted to do. Thanks! Feb 18, 2017 at 16:28
  • What if you can't stop the JVM and hook the java agent?
    – Sajuuk
    May 5, 2019 at 9:36
5

You can dump bytecode at runtime using HotSpot tools, and use a decompiler to reverse the bytecode. I made a proof of concept, available here

It requires 3 dependencies:

  • JDK libraries (sa-jdi.jar, tools.jar) to dump bytecode
  • Fernflower to decompile bytecode into java code
  • RSyntaxTextArea to display java source code

You could also have a look at the HSDB utility

2
  • Does this work in modern versions of java. I don't think sa-jdi.jar and tools.jar exist anymore Apr 21, 2021 at 8:30
  • @RichardTingle no this was a POC targeting Java 8 Jun 15, 2022 at 12:54
0

I think the easiest way would be to dump the classes as they are loaded, assuming that you know where the obfuscated classloader is and can edit it.

The obfuscated class loader will ultimately have to call ClassLoader.defineClass at some point. If you have the classfile, you can just diassemble it, find all calls to defineClass (or reflection methods that might potentially call defineClass), and insert a logging function before the call to dump the result. You could use the Krakatau disassembler/assembler for this.

The biggest risk is if the obfuscated code is using introspection, it could mess things up. For example, the code might compute a checksum of itself, in which case modifying it at all will cause problems.

If that is the case you have two options: 1) find all the introspection checks and remove/modify/mock them out, or 2) modify the JVM itself. The later approach would be completely invisible to the obfuscated code, but is harder to do.

One other thing to try is to look into the Java Agent interface. I haven't used it myself, so I can't say much about it, but this will potentially let you access all loaded classes at runtime with no code modifications.

Your Answer

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

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