This is a post on how to dissect the AdWind / jRAT / jBifrost Java trojan that has been around for quite a while and is still actively distributed in multiple variants. jRAT is nothing new and it has been decrypted before, but it’s still an interesting excercise.
I retreived a more or less recent AdWind variant from late 2016 (SHA256: 5b4a70e51095ca9ee19bbf81ef434d421ee5695474bc7f81e40955359d8afec8
) and decided to take a look at it. AdWind is a Java based trojan that is delivered as a jar file. Jar files are basically zip files and so you can extract them easily:
mv AdWind.jar AdWind.zip
unzip AdWind.zip
This leaves you with a bunch of files and directories:
-rw-r--r-- 1 michael michael 368 Nov 23 12:43 drop.box
-rw-r--r-- 1 michael michael 256 Nov 23 12:43 mega.download
drwxr-xr-x 2 michael michael 4,0K Jan 9 17:11 META-INF
drwxr-xr-x 3 michael michael 4,0K Jan 9 11:46 NtH
drwxr-xr-x 2 michael michael 4,0K Jan 9 11:46 operational
-rw-r--r-- 1 michael michael 1,5K Nov 23 12:43 sky.drive
drwxr-xr-x 3 michael michael 4,0K Jan 9 11:46 VRL
drwxr-xr-x 2 michael michael 16K Jan 9 11:46 w
drwxr-xr-x 3 michael michael 4,0K Jan 9 11:46 YG
There are some interesting things here: Multiple, obviously obfuscated directories NtH
, VRL
, etc. There are also some files: drop.box
, mega.download
and sky.drive
. Running the file
command to determine types results in:
root@sixtyseven:/home/michael/Disassembly/Malware/AdWind/unzip# file *
drop.box: data
mega.download: data
META-INF: directory
NtH: directory
operational: directory
sky.drive: Java serialization data, version 5
VRL: directory
w: directory
YG: directory
So we have a serialized object in sky.drive
and some unknown types of data in drop.box
and mega.download
.
Let’s have quick glance at sky.drive
:
root@sixtyseven:/home/michael/Disassembly/Malware/AdWind/unzip# hexdump -C sky.drive
00000000 ac ed 00 05 73 72 00 14 6a 61 76 61 2e 73 65 63 |....sr..java.sec|
00000010 75 72 69 74 79 2e 4b 65 79 52 65 70 bd f9 4f b3 |urity.KeyRep..O.|
00000020 88 9a a5 43 02 00 04 4c 00 09 61 6c 67 6f 72 69 |...C...L..algori|
00000030 74 68 6d 74 00 12 4c 6a 61 76 61 2f 6c 61 6e 67 |thmt..Ljava/lang|
00000040 2f 53 74 72 69 6e 67 3b 5b 00 07 65 6e 63 6f 64 |/String;[..encod|
00000050 65 64 74 00 02 5b 42 4c 00 06 66 6f 72 6d 61 74 |edt..[BL..format|
00000060 71 00 7e 00 01 4c 00 04 74 79 70 65 74 00 1b 4c |q.~..L..typet..L|
00000070 6a 61 76 61 2f 73 65 63 75 72 69 74 79 2f 4b 65 |java/security/Ke|
00000080 79 52 65 70 24 54 79 70 65 3b 78 70 74 00 03 52 |yRep$Type;xpt..R|
00000090 53 41 75 72 00 02 5b 42 ac f3 17 f8 06 08 54 e0 |SAur..[B......T.|
000000a0 02 00 00 78 70 00 00 04 c1 30 82 04 bd 02 01 00 |...xp....0......|
000000b0 30 0d 06 09 2a 86 48 86 f7 0d 01 01 01 05 00 04 |0...*.H.........|
...
The strings java.secruity.KeyRep
and RSA
stick out. Having a glance at the data files yields nothing of interested. But since there is a RSA Key in this serialized Java object, we can guess that the other files contain encrypted data. We will see if that is true later. Now let us have a look at the Java classes. Since this JAR has a META-INF
directory which contains a Manifest
file, we open the MANIFEST.MF
with a text editor and find:
Manifest-Version: 1.0
Ant-Version: Apache Ant 1.8.0
X-COMMENT: xoaJkjDXkreSrqSxraHXFVSmOyICVLsJAvAGBQgscBVBBPiZxEYcSdizcGF
WlBRdIMFgTIielKs
Class-Path:
Created-By: nnVCxJGeoqGWcmyXUYYcuGPvxTTOfZhfeagUXONAz
Main-Class: operational.JRat
The main class is operational.JRat
. We find this file in the folder operational
.
file JRat.class
JRat.class: compiled Java class data, version 50.0 (Java 1.6)
Time for some disassembly and decompilation!
For a first glance at an unknown binary I often use Radare2 since it disassembles nearly everything.
This is the main method of the JRat class:
/ (fcn) sym.operational_JRat.main 12
| sym.operational_JRat.main ();
| 0x000001b7 bb0002 new w/manintheskymanintheskymanintheskymanintheskymanintheskymanintheskymmanintheskymanintheskymanintheskymanintheskyanintheskyz
| 0x000001ba 59 dup
| 0x000001bb b70003 invokespecial w/manintheskymanintheskymanintheskymanintheskymanintheskymanintheskymmanintheskymanintheskymanintheskymanintheskyanintheskyz/<init>()V ;[1]
| 0x000001be 4c astore_1
| 0x000001bf b1 return
| 0x000001c0 57 pop
| 0x000001c1 4c astore_1
\ 0x000001c2 b1 return
It simply loads another method with a quite obfuscated and inconvinient long class name consisting of the repeating pattern maninthesky
and the letter z
.
Since this new class is part of the package w
let us have a look at the corresponding folder. Things start to get ugly:
root@sixtyseven:/home/michael/Disassembly/Malware/AdWind/unzip/w# ls
manintheskymanintheskymanintheskymanintheskymanintheskymanintheskymmanintheskymanintheskymanintheskymanintheskyanintheskyaa.class
manintheskymanintheskymanintheskymanintheskymanintheskymanintheskymmanintheskymanintheskymanintheskymanintheskyanintheskya.class
manintheskymanintheskymanintheskymanintheskymanintheskymanintheskymmanintheskymanintheskymanintheskymanintheskyanintheskyb.class
manintheskymanintheskymanintheskymanintheskymanintheskymanintheskymmanintheskymanintheskymanintheskymanintheskyanintheskyc.class
[...]
Hm. Time to get a better overview over the structure. I used bytecodeviewer to open up the original JAR. BytecodeViwer contains multiple disassemblers and decompilers that might help here.
Bytecodeviewer is pretty nice: It allows you to browse the JAR looking at different decompilations, bytecode, hexcode or whatever at the same time. Opening the maninthesky class that ends with the letter z we see a first decompilation. This is helpfull but still cumbersome to read. We can make things easier if we convert the classes and files to a more readable format.
So after opening the malicious JAR in BytecodeViewer you can do “File -> Decompile & Save All Classes”. Then chose a disassembler. I chose Krakatau, which gives good results but leaves out some classes since it couldn’t find some imports. We can add these few classes later manually.
Having decompiled (nearly) all classes, we can rename them and replace strings to produce more readable versions. Using rename and sed we can produce more readable versions of the files. E.g. in the w folder, do
rename 's/maninthesky//g' *.java
and
for i in *.java; do sed -i 's/maninthesky//g' ${i}; done;
to rename all files and replace the content. You might have to execute these commands two times to clean up everything and it might ruin some variable names in the sample but we can reconstruct this manually if needed.
After cleaning up, we can finally browse the project files in a more readable manner. The z class now basically looks like this:
package w;
public class z {
public z()
{
super();
w.y a = new w.y(new w.q(w.n.j((String)null, w.i.h_super) ).b()); //sky.drive
byte[] a0 = w.k.H(w.n.j((String)null, w.i.h_void)); //mega.download
byte[] a1 = w.k.H(w.n.j((String)null, w.i.h_this)); //drop.box
w.l a2 = new w.l(); //l contains decryption methods
a2.B(a0); //we feed mega.download
a2.O(a1); //we feed drop.box
w.s a3 = new w.s((java.io.InputStream)a2.C(a.F())); //Feed the RSAPrivateKey in sky.drive to the decryption routine in l
w.h a4 = a3.k("PRIVATE_PASSWORD");
w.h a5 = a3.k("PASSWORD_CRYPTED");
w.h a6 = a3.k("SERVER_PATH");
w.y a7 = new w.y(new w.q(w.n.j((String)null, a4)).b());
[...]
java.io.InputStream a12 = w.n.j((String)null, a5);
[...]
byte[] a16 = w.k.H(a12);
[...]
byte[] a22 = w.k.H(w.n.j((String)null, a6)); //SERVER_PATH
w.l a23 = new w.l();
a23.B(a16);
a23.O(a22);
[...]
w.sa a25 = a23.C(a7.F());
[...]
a27.E(a25);
[...]
}
}
It is much more readable. Starting from z we can dive down and see what we find. Most classes are just wrappers for some standard Java stuff, others contain more interesting pieces of code. e.g. in i you can find the filenames sky.drive, drop.box und mega.download, so that might be interesting. As we learn from examining z, these info is fed to an object of class l. Looking at class l we see a decryption routine C:
//This loads var1 as private key and decrypts the content of mega.download
public sa C(Object var1) throws GeneralSecurityException {
pa var2;
//pa.v javax.crypto.Cipher.init with key var1 und i.
(var2 = (new aa()).s("RSA")).v((RSAPrivateKey) var1, this.i_enum);
//get an instance of javax.crypto.Cipher with type AES
pa var3 = (new aa()).s("AES");
//var2.Y is a wrapper for the internal ciper.doFinal method and decrypts whatever is in this.ba_break
byte[] var5 = var2.Y(this.ba_break);
//we specify that var5 is an AES key
SecretKeySpec var6 = new SecretKeySpec(var5, "AES");
//pa.v javax.crypto.Cipher.init with key var6 und i var.
var3.v(var6, this.i_enum);
//then we decrypt ba_void
byte[] var7 = var3.Y(this.ba_void);
//and we return a java.io.ByteArrayInputStream (sa) with the decrypted content
return new sa((Object)null, var7);
}
Basically, method C
does this:
- It opens the RSAPrivateKey KeyRepository class, which is serialized in
sky.drive
- It uses the RSA key from this class to decrypt an AES key which is stored in
drop.box
- It uses the decrypted AES key to decrypt the data in
mega.download
- which will turn out to be a properties file pointing to more interesting files.
If we follow the sourcecode a little further, we will find this decryption routine in several places of the malware. Since the decryption is just a chaining of standard routines it is not too hard to write a decrypter for it.
Here is a piece of Java code that decrypts the AdWind files.
Warning: Only execute the decrypter in a seperated environment. It deserializes the object given as RSA KeyRep and might be highjacked from malicious code itself.
Using this decrypter, we can decrypt the files and get the properties file:
java -jar AdWindDecryptor.jar
-a mega.download\
-r sky.drive\
-i drop.box\
-o properties.ini
This is the decrypted properties.ini
:
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd">
<properties>
<comment>Support: https://jrat.io</comment>
<entry key="SERVER_PATH">/VRL/uW/Y.c</entry>
<entry key="PASSWORD_CRYPTED">/YG/Lab/vvv.Ttm</entry>
<entry key="PRIVATE_PASSWORD">/NtH/s/NU.xtr</entry>
</properties>
Not too interesting at first glance, just a few paths to new files we already had access to before. It also points us to a site where we could buy a jRAT version (no thanks). Since these variable names are tempting, let us try to use the decrypter once again:
- Using
PASSWORD_CRYPTED
as crypted AES key, PRIVATE_PASSWORD
as RSA Key Rep andSERVER_PATH
as something we want to decrypt.
(Looking at the decompiled code more closely we can already figure out that this will work and what we are about to decrypt here.)
After going through the decryption routine once again, we finally get to the core of the malware: The server.jar
. This is the file that contains the actual RAT code and that we can use for further analysis. And hey, we don’t have to pay for it!
Without going into too much analysis of the server.jar
, we see that its config files in server/ressources
are also encrypted. We can try to use the decryptor once again and make an educated guess of how we should provide it with the files. Checking size and type we find:
-rw-rw-r-- 1 michael michael 6,0K Nov 23 12:43 config.json
-rw-rw-r-- 1 michael michael 1,5K Nov 23 12:43 Key1.json
-rw-rw-r-- 1 michael michael 256 Nov 23 12:43 Key2.json
and
config.json: data
Key1.json: Java serialization data, version 5
Key2.json: data
So we conclude:
Key1.json
is again a serialized Java Key Rep object, so this is our RSA KeyKey2.json
is the smallest of the files with a size of 256 byte, which matches the size of the encrypted AES keys before. So it is very likely the encrypted AES key.- We can guess that
config.json
is what we want to decrypt.
Using
java -jar AdWindDecryptor.jar
-r Key1.json -a Key2.json -i config.json -o config-decrypted.json
we decrypt the encrypted config file:
{"NETWORK":[{"PORT":1663,"DNS":"***"},
{"PORT":5836,"DNS":"***"}],"INSTALL":true,
"MODULE_PATH":"nJn/rKQ/E.s","PLUGIN_FOLDER":"qhAcQBGGpDA",
"JRE_FOLDER":"X O X O X O X O","JAR_FOLDER":"Javax",
"JAR_EXTENSION":"txt, jpg",
"ENCRYPT_KEY":"WiWWIMklVZjDdqDxHIlPkCVsm",
"DELAY_INSTALL":2,"NICKNAME":"X O X O X O X O",
"VMWARE":true,"PLUGIN_EXTENSION":"txt, jpg",
"WEBSITE_PROJECT":"https://jrat.io","JAR_NAME":"Javac"
[...]
That’s it. We can retreive the malware configuration by using the same decryption routine over and over. And if you are actually a victim of AdWind / jRAT / jBifrost this might be a good starting point to figure out who is attacking you.
For comments / corrections / questions, contact me on Twitter.