Threat Level: green Handler on Duty: Johannes Ullrich

SANS ISC: InfoSec Handlers Diary Blog - Climb a small mountain... InfoSec Handlers Diary Blog

Sign Up for Free!   Forgot Password?
Log In or Sign Up for Free!

Climb a small mountain...

Published: 2006-12-07
Last Updated: 2006-12-07 20:42:10 UTC
by Tom Liston (Version: 2)
0 comment(s)
I really love malware authors who write their stuff in JavaScript.  They try so hard to be like real programmers... and they're just so gosh-darned cute.

They're at their especially "I-want-to-be-a-big-boy-programmer" best when they jump through all sorts of hoops to obfuscate their handiwork.  It's almost as if they don't realize that they're programming in toy language that's INTERPRETED...

So yesterday, I'm sitting in an airport waiting standby on a flight to get me home in time to see my daughter's choir concert, and my cell phone rings.  According to Caller ID, it's Ed Skoudis - friend, fellow Intelguardian, fellow ISC Handler, and all-around infosec stud.  I answer it anyway.

"Hey buddy!  How's it going?" I hear Ed's all-too-chipper voice through the phone.  

"Hmmm...," I think, "feigned pleasantry coupled with a fraternal 'buddy' reference.  Ed wants something."

"Hey... I have a favor to ask you..."

And so Ed, who was ISC Handler-on-duty, went on to explain that he'd received an email from a reader who had come across what appeared to be some sort of encoded JavaScript.  According to the reader, the script was found on a webpage that had been spammed to several blogs, and he was concerned that there might be something evil going on.

"Generally if you're on the up-and-up, you don't feel the need to obfuscate what you're doing," was Ed's conclusion.

Can't argue with that.

"So, what do you need me for?" I asked.

"Well... I'm really kind of swamped, both with HOD stuff and real work stuff, and I know how much you like this kind of thing..."


"Ok... send it to me."

After shooting the breeze with Ed for a few more minutes, I hang up and flip open my laptop, planning to hop onto the local public WiFi and ssh my way into the mailserver? only to find that there IS no public WiFi available.

Sigh... #2

"Ok," I decide, adopting my best those-grapes-are-probably-sour-anyway attitude, "my laptop is too dang big to use on a plane comfortably anyway.  I'll just work on it tonight when I get home."  But as the minutes to my flight tick away, I find myself looking at my shiny new "Windows Mobile" cell phone, and an evil plan begins to take shape.

"Nah...," I think, "it would never work... but it would sure be cool to try..."

So, as the clerks begin calling different groups for boarding, I furiously kick off the mail client on my phone, grab Ed's message from the server and save it as a text file.

A few minutes later, I'm seated on the plane, looking at the text of the email message in Pocket Word.  I work down through the message, deleting everything but the actual text of the script:

var arr =

 ... many, MANY rows of numbers deleted ...


var table = new Array();
table['0'] = 0;table['1'] = 1;
table['2'] = 2;table['3'] = 3;
table['4'] = 4;table['5'] = 5;
table['6'] = 6;table['7'] = 7;
table['8'] = 8;table['9'] = 9;
table['a'] = 10;table['b'] = 11;
table['c'] = 12;table['d'] = 13;
table['e'] = 14;table['f'] = 15;
function markCounter(a) {
  var txt = ""; var c = 0;
  while (c < a.length) {
    txt += String.fromCharCode(table[a[c]] * 16 + table[a[c + 1]]);
    c += 2;
demo = ""+false;details = "false";
if (demo == details) {

I slap an <html><head></head><body>...</body></html> framework around the script, and I'm ready to delve into the code itself.

The first thing that strikes me is the "eval(txt)" call.  That's where the actual rubber meets the road in this script.  I'll need to take care of that.

I replace "eval(txt)" with the following:

document.write("<textarea rows=50 cols=50>");

I also get rid of all the "demo" crud at the bottom, replacing it with a simple call:


Having done that, I change the name of the file from "edsmail.txt" to "edsmail.htm," and fire it off in Pocket IE.

It displays my TEXTAREA, but... well... nothing else.  Perhaps I'm not as clever as I think I am.


Turns out, it was the JavaScript jockey who wasn't so clever.  Dude... if you're out there and reading this, take some notes, ok? You can't access a string using array notation: "a[c]" doesn't work.  Here's how you fix it:  you need to replace "a[c]" with "a.substr(c, 1)"

I correct Mr. LeetHaxor's code, and it promptly dumps the following into my TEXTAREA:

var ref = document.referrer;
var loc = document.location.href;
if (ref.indexOf("google") == -1 && ref.indexOf("yahoo") == -1 &&
ref.indexOf("msn") == -1) {
document.location.href = "" + loc;
} else {
if (ref.indexOf("site:") >= 0 || ref.indexOf("site%3A") >= 0) {
 document.location.href = "" + loc;
} else {
 var re = new RegExp("http:\/\/([a-z0-9\-A-Z\.]*)\/");
 var domain = re.exec(loc);
 if (domain == null) {
  document.location.href = "" + loc;
 } else {
  re = new RegExp("\\.([a-z0-9\-A-Z\.]*)");
  topdomain = re.exec(domain[1]);
  if (ref.indexOf(domain[1]) != -1 || ref.indexOf(topdomain[1]) != -1) {
   document.location.href = "" + loc;
  } else {
   re = new RegExp("q=[^&]*");
   var m = re.exec(ref);
   if (m == null) {
    re = new RegExp("p=[^&]*");
    m = re.exec(ref);
    if (m == null) {
     document.location.href =
"" + loc;
    } else {
     var q = m[0].substring(2);
     q = q.replace(/\+/, "_");
     q = q.replace(/\s/, "_");
     document.location.href = "" + q + ".html";
   } else {
    var q = m[0].substring(2);
    q = q.replace(/\+/, "_");
    q = q.replace(/\s/, "_");
    document.location.href = "" + q + ".html";

Looks like someone is VERY interested in referrer info, but doesn't want anyone to know it.

So... all of you JavaScript geniuses out there, please take note:  I "cracked" this obfuscation while munching on in-flight pretzels and working ON MY CELLPHONE.  If you seriously don't want someone to know what you're up to, then I think your encoding techniques should require cracking on something that doesn't ring...

UPDATE: Bojan has done some checking, and it appears that you can access characters within a string in JavaScript using array notation... but only under FireFox.  I still stand by my "fix", 'cause it's cross-platform.

Tom Liston - Senior Security Consultant - Intelguardians
0 comment(s)
Diary Archives