Thursday, 18 September 2014

Deobfuscation tips: SweetOrange EK landing page

DISCLAIMER: There isn't a single way to deal with obfuscated data/code. There are many automated and semi-automated tools available to help you with that. In this post though I'll be using none. The aim here is to walk through some code deobfuscation manually.This is not a comprehensive SweetOrange EK landing page analysis. Only bits related to data/code obfuscation are covered.

NOTE: Exploit Kit sample used in this post was captured in September 2014. Taking the ever changing nature of EKs, the described below might not be applicable to the newer variants.

Sweet and Sour

I'll be using SweetOrange EK landing page sample here. Note a huge blob of text stored in one of the list items '<li>' followed by some JavaScript code. We'll skip the general code analysis/overview and focus on the tag. It has 'id' attribute with a rather unique value - 'UHOhpWHd'. Searching for this value in the webpage code leads to the following JS function:

function uQqRecfwwf(DDDDDDDDD) {
    TLKQDEnOiE = 0;
    var ARNTO = uQqRecfwwf;
    var DnB = 0;
    UhOnd = String(Math.asin);
    if (isNaN(UhOnd.match(/aSI/ig))) {
        var k = (UhOnd.match(/In/i));
        if (k != null) {
            iuhquweh = trenoSZ(uyHMzLQ);
            XdwrQ["spl" + "ice"](Math.acos(1), 2, "UHOhpWHd");
            XdwrQ["spl" + "ice"](1, Math.acos(1), iuhquweh);
            ardddds = DDDDDDDDD;
            DnB = cXEcJlM()[qqTbFg()];
        };
    };
    return DnB;
}

At this stage it's unclear what exactly happens to the blob's data rather then being stored in 'XdwrQ' array. Before we start chasing the rabbit down the rabbit's hole and submerge into other functions, let's find out what calls 'uQqRecfwwf' function.

aCaBOUakjB = uQqRecfwwf(BFG423SDFFSDF);

Ok, it's being called during a variable initialization. Are there any operations on this variable after the function call returns?

JvUhBCJkFV = aCaBOUakjB.substring(Math.acos(1) + 70).replace(/AdgSf344_42/, "");

The value returned is passed through '.replace' where any occurrence of 'AdgSf344_42' string is removed and then '.substring' cuts off first 70 characters and what's left is stored in another variable called - 'JvUhBCJkFV'. Note the string that's being removed - 'AdgSf344_42'. This string is repeatedly present all over the data blob, so it's safe enough to assume that these 'replace' and 'substring' operations are performed on the data stored in the blob. Now let's trace 'JvUhBCJkFV' variable.

JvUhBCJkFV = JvUhBCJkFV["CmYhLBWtlcUAuPllrQzwcR".charAt((Math.acos(1) + 1) * 21).toString().toLowerCase() + "QeTyvpnauVDwgPrSyUmddePl".substr((Math.acos(1) + 1) * 21, 3).toLowerCase() + "hSReqJbsEYDVGYtSdMaKvAce".toLowerCase().substr((Math.acos(1) + 1) * 21, 3)](/__hhg7_/, "<");
JvUhBCJkFV = JvUhBCJkFV["DFhBbAbrvTfutCnsmdcFnR".charAt((Math.acos(1) + 1) * 21).toString().toLowerCase() + "pxUBkDdBwEcWypAIICsrJePl".substr((Math.acos(1) + 1) * 21, 3).toLowerCase() + "mVrJDwMWDZuUhgpMZSmVEAce".toLowerCase().substr((Math.acos(1) + 1) * 21, 3)](/__Db8__/, ">");
JvUhBCJkFV = JvUhBCJkFV["QOmUjeNOFcQYONcLQZAtOR".charAt((Math.acos(1) + 1) * 21).toString().toLowerCase() + "bWXExXVfqvcqeIuyNfJaRePl".substr((Math.acos(1) + 1) * 21, 3).toLowerCase() + "iebFbNjCVybBwfEvorJqqAce".toLowerCase().substr((Math.acos(1) + 1) * 21, 3)](/_uio0__/, "&");
JvUhBCJkFV = JvUhBCJkFV["oZBZyFhKBOkJHNmWnmNCKR".charAt((Math.acos(1) + 1) * 21).toString().toLowerCase() + "PIPoCStPfHZIWGgmYzekFePl".substr((Math.acos(1) + 1) * 21, 3).toLowerCase() + "gfAOlzFwZvghrQYqhRPhnAce".toLowerCase().substr((Math.acos(1) + 1) * 21, 3)](/__cc0__/, "%");

This is a little bit hard to read, isn't it? This is another type of code obfuscation used in this sample. Thought it's not something I want to cover in this post, let's deobfuscate it for the sake of easiness. Simply taking the code enclosed into square brackets and evaluating it using a JS sandbox yields the code below.

JvUhBCJkFV = JvUhBCJkFV.replace(/__hhg7_/, "<");
JvUhBCJkFV = JvUhBCJkFV.replace(/__Db8__/, ">");
JvUhBCJkFV = JvUhBCJkFV.replace(/_uio0__/, "&");
JvUhBCJkFV = JvUhBCJkFV.replace(/__cc0__/, "%");

More replacements!! Ok, let's do all of the above replacements and see if we get some readable code. The following simple Python script will help us do it:
 
def readFile(filename):
    fo = open(filename, "rb")
    textFile = fo.read()
    fo.close()
    return textFile

encodedString = readFile('SW_landing.txt')
encodedString = encodedString[70:]
encodedString = encodedString.replace('AdgSf344_42', '')
encodedString = encodedString.replace('__hhg7_', '<')
encodedString = encodedString.replace('__Db8__', '>')
encodedString = encodedString.replace('_uio0__', '&')
encodedString = encodedString.replace('__cc0__', '%')

print(encodedString)

Before running it, we'll need to save the data blob into 'SW_landing.txt' file and place it in the same folder with the Python script. If you ever need to deobfuscate another SweetOrange EK landing page using this script, keep in mind that the replacement strings can change, though so far I've only seen '.substring' value and the first replacement string changing.

After running the script we get the output. With the exception to some base64 encoded strings, the code is pretty readable and can be analyzed further if required. Now let's sum things up a little bit.

So, from the data/code obfuscation perspective SweetOrange EK landing page contains a relatively big blob of obfuscated data and a JavaScript to deobfuscate it into yet another JavaScript. The deobfuscation is implemented through a series of simple replacement operations. KISS.


Happy deobfuscation!


0 comments:

Post a Comment