A few months ago, I came across a piece of Java malware. This was a nice change of pace for me, since most of what I see is written in C/C++. The malware was heavily obfuscated using a common tool, Allatori v5.3. After working my way manually through decoding, I came to a point where a config.ini was being parsed and each class was loaded directly into memory prior to being executed. This intrigued me because up until this point I had .class files that I could use CFR to decompile. Not having worked with Java malware before, I was unsure of a good way to convert these in-memory classes back to the *.class file format. After some research, I came across a reference to Oracle’s ClassFileTransformer and VirtualMachine.attach(PID). Using these classes, I was able to dump to the memory resident classes to files. The following is a description of the process I took to accomplish this task.
Let start off with an explanation of the VirtualMachine.attach( Agent ) and the Agent Jar (Inherited from ClassFileTransformer in this case). The VirtualMachine.attach( Agent ) function allows us to attach to a Java Virtual Machine(JVM) running another application by its process ID. This feature is only available in the Oracle JVM and is similar to using gdb to attach to another running process. Unlike gdb, this is done programmatically, and a function is provided to process the values in the target JVM. Figure 1 shows the source for the Attacher program using the VirtualMachine attach and loadAgent methods. The loadAgent method is used to instruct the VirtualMachine which Agent Jar file to load into memory and execute.
The Agent Jar has two (2) components. The first is the manifest.mf file (see Figure 2). The manifest.mf file contains the name to two entry points into the Agent class. Premain-Class is the entry point for the Agent when the target is not already started. The Agent-Class is the entry point for when the target has already been is launched, as in this case.
The manifest.mf file contains two (2) other important lines. The Can-Redefine-Classes, which allows the Agent to change the definitions of existing or already loaded classes. The Can-Retransform-Classes is used prior to classes being loaded and can change the byte code prior to the class being initialized. In this case, I used the latter with a ClassFileTransformer. This allows the agent to transform the classes in memory to the *.class files. The Agent can be a simple program that has a single class containing a single method.
Detailed Code Walk-Through:
I used this transform to loop through all loaded classes in the JVM and write these classes to disk in the traditional <filename>.class format. To best use this feature, I modified the malware to loop after loading the values from the config.ini. I then executed the Attacher program and did a little happy dance, as I had the hidden class files. Convert to *.java files and have a nice easy time understanding the rest of the malware. J
This process contains three (3) components:
- Attacher Program (shown in Figure 1)
- Agent Jar file
- mf (shown in Figure 2)
- ClassDumperAgent (My term)
- Malware or VM to attach too
In this section we will discuss the components of the Agent and how to create the Jar file. Click here for access to the full Agent code.
I created a class, ClassDumperAgent, which inherits from the ClassFileTransformer Agent class. (Figure 3). This agent provides us with the ability to be launched from the Attacher and to convert the individual classes into files. In this case I dumped all the classes that were loaded into memory to <classname>.class files. While I could have dumped only specific files, as a test, I dumped just the class names, then dumped all the classes to compare against the *.class files that I already had.
There are three (3) major parts to the Agent class. Two (2) of which have been mentioned in the manifest.mf, the Premain-Class and the Agent-Class. I named these methods premain and agentmain, as seen in Figure 4. In this case, the premain is not used and was coded to call the agentmain. This was never tested.
The agent main is called by the Attacher with a set of arguments and the Instrumentation object. The arguments are used to determine the directory to store the class files after the transformation and the pattern used to filter the class files. The Instrumentation object is used to obtain the classes from memory and to call the registered transform method which is used to write the file to disk. The final result of the transformation is shown in Figure 5. The left column shows the original *.class files while the right column contains all the *.class files written from memory. As an interesting note, the ClassDumperAgent.class was dumped too.
Compile and Create Jar File:
jar cfm ClassDumperAgent.jar manifest.mf ClassDumperAgent.class
Compile and Execute Attacher:
java Attacher <pid> <Agent.jar> <Agent Options>