Decoding Pseudo-Darkleech (Part #2)

Published: 2016-04-21
Last Updated: 2016-04-21 12:55:14 UTC
by Daniel Wesemann (Version: 1)
1 comment(s)

Please refer to the first part that I posted earlier on some background on what "pseudo-darkleech" is, and how we decoded the first stages.

The code snippet that we were left with at the end of part #1 was this:

It sure looks like JavaScript, but is not overly readable. But adding a couple line breaks also works wonders in this case:

cat stage2.js | perl -pe 's/([;\}\{])/$1\n/g'    ... this adds a line break after every ; { and }

Now, two code blocks stand out. The first is querying the "userAgent" (browser type), and it is getting queried for the presence of "rv:11", "MSIE" and "MSIE 10".  "rv:11" can be found in both the old Firefox 11, but also in Internet Explorer 11. "MSIE" and "MSIE 10" are looking for that particular version of Internet Explorer.  This section is coded as convoluted as it is, and also includes that odd (+[window.sidebar]) section, because the bad guys are trying to fool dynamic analysis in malware sandboxes and proxy servers. On a regular browser, this code works as intended, and returns a value of "2" in the variable "ug" if the browser is IE10 or IE11. But on a "Spidermonkey" or other JavaScript interpreter that does not emulate the full range of the browser's document object model (DOM), this section will leave "ug" undefined, or set it to zero.

The second block again refers to the "evs" section, but this time, replace(/[^a-z]/g,"") strips out all the numbers and spaces, and retains only the text characters. What then follows is a loop over this resulting string, and another XOR-operation to decode it. This time, it isn't a simple XOR with "9" like in the first stage, rather

^npyu.charCodeAt(kte%npyu.length); kte++;

an XOR-operation with a password (npyu) of length 14, which means that the code block is making use of a polyalphabetic cipher ("Vigenère"). The consequence of this is that the "evs" block alone cannot really be decoded without also decoding the JavaScript that contains the password. A simple XOR with 9 is trivially broken, but a XOR with a 14-character password cannot reasonably be brute forced.

So .. lets clean up the code a bit more, so that we can actually run it in SpiderMonkey, and see the result.  

Instead of document.getElementById("evs"), we simply set the varaible zfsp directly, and assign it the content of evs:

zfsp="a9ca7 d97,b 52 3j3 db3ax4 82 d-126 gb9u6 103cc 109d 102 -126 3fef9d 1xd22 96 -p10 -ax9 b-10cd8g. 1bm07 10bw .....

Next, we strip off all that browser detection logic, and just set the result, "ug=2". And finally, instead of actually "running" the decoded block, at the very end, we want to "print" it:  print(exutkqb);. Which leaves us with:

And we are ready to rock:   daniel@debian:$ js script-cleaned.js

In the end, the "pseudo-darkleech" code block just generates an IFRAME that loads an Angler Exploit Kit.  All these stages of having a HTML and JavaScript block where one decodes the other first into a script and then into the IFRAME, and all this using of browser directives and even a polyalphabetic cipher is not malicious per se, since it does not exploit any vulnerabilities. It just serves to "hide" the malicious IFRAME from proxies and malware sandboxes, so that the AnglerEK really only loads on the user PC, and not in an emulator or filter that aims to detect its presence.


1 comment(s)


I was working on same topic today and found this solution for decoding:

Diary Archives