Threat Research

Analysis of a JAR Obfuscated Malware Packer

By Ruhai Zhang | December 01, 2014

Normal Java JAR or class format samples can be easily analyzed with Java decompiler tools, such as JAD and JD-GUI. Not so with those obfuscated ones, where decompiling results may be empty or not clear. When this happens, we need to then analyze the JVM (Java Virtual Machine) p-code.

Nowadays, more and more Java malware use anti-decompiling techniques to increase the difficulty of analysis. In this blog post, we will analyze a new JAR obfuscated packer that is being used by Java malware, using a sample that we detect as Java/Obfus.CI!tr as an example.

Decompiling the JAR Malware Sample

This JAR sample has the following layout: Title

Figure 1. JAR sample layout

The main class defined in MANIFEST.MF is stub.EcryptedWrapper; the file stub.dll contains encrypted or compressed data. Using JD-GUI to decompile this sample, we can only see empty classes. Using JAD, we can get the result, but most of the classes are in JVM p-code.

In the decompiled results from JAD, there are a large number of System.out.println() junk codes. After removing all of them, the flow is a little bit clearer. Many strings are still encrypted, but we can then locate and analyze the decrypting methods.

  • EncryptedLoader.ALLATORIxDEMOxpalksksdqwdqbgnhmtyter("")
  • EncryptedLoaderOld.ALLATORIxDEMOxpalksksdqwdqbgnhmtyter("")

These two methods have the same algorithm (shown in Figure 2) but just use different parameters. Title

Figure 2. String decoder loop.

Decrypting the String

Based on the algorithm in Figure 2, we can use the following Python function to decrypt the strings:

def decoder(enc_str, key_str, key1, key2):
    klen = len(key_str)
    kidx = klen - 1
    elen = len(enc_str)
    eidx = elen - 1
    olist = [''] * elen

    while eidx >= 0: 
        olist[eidx] = chr(ord(key_str[kidx]) ^ ord(enc_str[eidx]) ^ key1)
        eidx -= 1
        if eidx >= 0:
            olist[eidx] = chr(ord(key_str[kidx]) ^ ord(enc_str[eidx]) ^ key2)
        eidx -= 1
        kidx -= 1
        if kidx < 0:
            kidx = klen - 1
    return ''.join(olist)

The three parameters key_str, key1, and key2 are as follows:

    EncryptedLoader: <class_name>+<method_name>, 0x52, 0x5A
    EncryptedLoaderOld: <method_name>+<class_name>, 0x2F, 0x55

After replacing all the encrypted strings, the flow is quite clear. The following is a simplified flow of the main class EcryptedWrapper.

public class EcryptedWrapper implements Runnable
    private EncryptedLoaderOld loader_old;
    public void run()
        Class cls = loader_old.loadClass('Start');

    public EcryptedWrapper()
        EncryptedLoader loader = new EncryptedLoader();
        loader.load();    //load and decrypt stub.dll
        loader_old = new EncryptedLoaderOld(loader.getClasses(), loader.getResources());              

    public static void main(String args[])
EcryptedWrapper wrapper = new EcryptedWrapper(); (new Thread(wrapper)).start(); } }

Decrypting stub.dll

Based on the decompiling result of EncryptedLoader.class, the file stub.dll can be decrypted with the following Python function:

from Crypto.Cipher import AES

def decrypt_jar(fname):
    fp_in = open(fname, 'rb')
    fp_out = open(fname+'_', 'wb')
    key = '0B4wCrd5N2OxG93h'
    cipher =

The decrypted result is a friendly JAR file which can be decompiled by JD-GUI. Its main class in MANIFEST.MF is Start, as shown in the run() method of EcryptedWrapper. Our initial analysis shows that it is a multiplatform RAT.


As we have seen, Java malware have continued to evolve in order to make analysis more difficult by adding an obfuscation packer. We have already added detection for several Java malware that use this kind packer and will continue to keep our eyes open for new techniques that may emerge in the days ahead.

Join the Discussion