home | legal stuff | glossary | blog | search

 Legend:  new window    outside link    tools page  glossary link   

Spam analysis: example #5
JavaScript-encrypted message body

I should warn you here at the outset that this page gets kinda technical, so if your eyes glaze over at the mere thought of programming, you might want to give this spam dissection a pass. If, on the other hand, you want to see the lengths to which spammers will go to keep you in the dark, then by all means read on!

This is the body of a spam mail I received some time back (the headers were regrettably discarded, although I’d be willing to bet they were forged). It seems to be an HTML page, but contains all sorts of odd-looking stuff. In fact, it contains the actual text of the page in an encrypted form (all of the big numbers), and uses some fairly intensive JavaScript number crunching to decode and display the text.

If you were to try to view the source of this mail on most browsers (by using the right mouse button to display a view-source command), you’d likely be stopped by the “click()” JavaScript function near the top, which “intercepts” right-clicks and displays a naughty alert box instead of the customary pop-up menu. If you were resourceful enough to find another way to save the source, this is what you’d see (I rearranged the line breaks for readability):

<html>

<head>
<meta HTTP-EQUIV="Expires" CONTENT="HTMLcrypt">

<!--
-------------------------------------
| HTMLCrypt v1.011 Beta             |
| Cedium Software Inc               |
| http://htmlcrypt.cedium.net       |
-------------------------------------
-->
<script language="Javascript">
<!--

var message='Sorry, right-click-save is disabled on this site.'
function click(e)

{
  if (document.all)
  {
    if (event.button==2)
    {
      alert(message);
      return false;
    }
  }
  if (document.layers)
  {
    if (e.which==3)
    {
      alert(message);
      return false;
    }
  }
  if (document.layers)
  {
    document.captureEvents(Event.MOUSEDOWN);
  }
}
document.onmousedown=click

function process(ar)
{
  var Stri=''

  var y, z, sum, n, n1, number, j=0
  var x=0
  var key = new Array(7498081,25459,27507,25964)

  n1=8
  for (j=0; j<ar.length; ++j)
  {
    for (i=0; i<ar[j].length-1; ++i)
    {
      sum=4055616968
      n=n1
      y=ar[j][i]
      z=ar[j][++i]
      while(n-->0)
      {
        z-=(y<<4)+key[2]^y+sum^(y>>5)+key[3]
        y-=(z<<4)+key[0]^z+sum^(z>>5)+key[1]
        sum-=0x9E3779B9
      }

      Stri+=String.fromCharCode(y&0xFF)
        +String.fromCharCode((y>>8)&0xFF)
        +String.fromCharCode((y>>16)&0xFF)
        +String.fromCharCode((y>>24)&0xFF)
      Stri+=String.fromCharCode(z&0xFF)
        +String.fromCharCode((z>>8)&0xFF)
        +String.fromCharCode((z>>16)&0xFF)
        +String.fromCharCode((z>>24)&0xFF)
    }
    document.write(Stri)
    Stri=''
    window.status="Decrypt the HTML : "+
    Math.ceil(x++*100/0)+" % done ..."
  }
  window.status=""
}

function start() {
var ar=new Array()
ar[0]=new Array(-61916326,
269750318,
-624244224,
-1642521075,
155303938,
-1575340699,
1389513984,
-2022770407,
398686312,
917558588,
1294325367,
2047565063,
-1651519479,
1392403096,
-1141944006,
851347936,
-2017636082,
-1416993981,
-629244221,
1485019220,
-1104124370,
2027201487,
900951740,
-1498665855,
815122525,
-2133380016,
291532369,
-1519560440,
1276274993,
883002852,
1322810626,
-409952508,
1477140479,
1991295713,
1661861501,
-728615984,
-465100814,
350095974,
-594831016,
-766426687,
226203604,
-127224080,
-191088280,
79200995,
-2004106037
,577302111,
-862542391,
906502475,
-309460002,
837173820,
-1061698276,
438921122,
1378136976,
1722061135,
-1626364709,
-1840359403,
-1073498588,
-2028940101,
1354322341,
-707882174,
-1968204457,
-959445141,
571598351,
1862898409,
-2028069180,
688355534,
1303285887,
-1269096754,
187623165,
-595056702,
195470335,
1109511288,
1948871513,
-380567358,
-926333025,
2135383625,
567635414,
870652154,
1050454939,
-1303558033,
1760835270,
1400495289,
-28652002,
-1214922829,
-1606808902,
1435887229,
1809778283,
-1259462498,
-203874845,
957181024,
-296050338,
2130133740)

process(ar)
}
start()
//-->
</script>

</body>
</html>

Okay, what the Sam Scratch is going on here? Well, I’m strictly a duffer when it comes to JavaScript, but from what I can see, the following is the plan:

The first thing that happens when your browser gets the page is that the function “start()” is called; this function first defines a big array full of huge integer values, and then calls another function called “process().”

The function process() defines more secret stuff and then does a lot of weird binary computation (the “>>” is the right-bit-shift operator in JavaScript), stashing the results in a string variable called “Stri.” Then, we reach the nub of the matter with the following lines:

document.write(Stri)
Stri=''

The first statement simply prints the string Stri (presumably a long string of HTML markup) to your browser’s window, while the second cleans up the mess by setting Stri to an empty value.

Being a nosy bastard, I decided that I wanted to see exactly what Spammy was up to here, and whether it might be dangerous. The trick is to get your browser to display the contents of Stri in a “neutral” form (i.e., that will be printed as plain text rather than rendered as HTML); there are doubtless many ways to skin this cat (which might involve tedious hours bent over a JavaScript console), but I chose the straightforward expedient of displaying the string in a standard alert box by altering the two lines above as follows:

// document.write(Stri)
// Stri=''
alert(Stri.valueOf())

Here, using a text editor on the file, I commented out the two offending lines (with the “//”) so that they would not be executed, and added a new one, using the built-in alert() function of JavaScript to print the value of Stri in an alert box (where the HTML markup will be disregarded) rather than display it in a web page. Then, I saved the file and opened it in my browser. Voilá! (or walla!) The following appeared:

(I could have simply copied and pasted the text, but I wanted you to see the cool OmniWeb Mac OS X alert box!)

Now it is clear what is happening here: the HTML actually has no body at all, and all the hard work is done in the head, specifically in the META tag, which simply redirects you to the website of our old long-time penis-enlarging friends at pillsmedical.org. Our spammer, whom we’ll now call “Affiliate Jack” (his name appears at the end of the pillsmedical URL), has figured out an elegant way to point you right to the pillsmedical website (and include his affiliate code) without involving any web presence of his own. Although we could still track him down through the mail header, he’s probably already written off this distribution venue and has moved on to another open relay or proxy network.

Fortunately, there’s nothing particularly dangerous here, since Jack hasn’t passed on any personal information about me (except for my IP address at the time, which now appears in pillsmedical’s server logs along with a gold star for Jack for bringing me into the showroom).

Jack used a tool called “HTMLCrypt” to generate this wonderful code. For what it may be worth, the HTMLCrypt URL given above does not work (the server seems to be down). It’s difficult to know what the developer intended with this product, although one might guess that he (or she) simply wanted to provide a way for HTML developers to mask their markup from the curious, and not to support spammers. In any case, the developer is urinating into a high-pressure front, since the World Wide Web is by definition an information-sharing resource, and trying to mask your content while at the same time allowing everyone to see it is the very height of paradox.

Next example :: Previous example :: Back to sample analyses



 home | legal stuff | glossary | blog | search

 Legend:  new window    outside link    tools page  glossary link   

(c) 2003-2006, Richard C. Conner ( )

06610 hits since March 27 2009

Updated: Sat, 06 May 2006