8299254 2002-04-17 12:51 +0800  /244 rader/ Wang Jian <lark@marsec.net>
Sänt av: joel@lysator.liu.se
Importerad: 2002-04-17  08:55  av Brevbäraren
Extern mottagare: bugtraq@securityfocus.com
Extern mottagare: forensics@securityfocus.com
Mottagare: Bugtraq (import) <21886>
Ärende: An alternative method to check LKM backdoor/rootkit
------------------------------------------------------------
From: "Wang Jian" <lark@marsec.net>
To: <bugtraq@securityfocus.com>, <forensics@securityfocus.com>
Message-ID: <000601c1e5cb$7bc4ee70$8100a8c0@marsec.net>

Hello,

I can't find information about the method I find. If I am wrong, I am
sorry.


PRINCIPLE

LKM backdoor plays tricks to hide itself, including its running
processes,  loadable kernel module and arbitary files. It changes the
kernel behavior, and hide things.

Because it hides things, it creates a fake view hiding things the
installer want to hide. Thus, differences between the real view and
the fake view.

The differences are some of running processes, files are hidden, or
say, stealth.

METHODS

The discovery of LKM is important for the game. There are some ways
to do so, such as using LKM against LKM. There are two styles in all
ways:

1. Find the differences between the two views;
2. Find the LKM directly;

LKM vs. LKM game involves the 2nd style.


THE ALTERNATIVE METHOD

Our alternative method uses the first style: to find the differences
between the fake view and the real view.

And we focus on filesystem view. A LKM backdoor is stealth, or it will
be discovered by juse scan the filesystem. So we check if there are
stealth files on filesystem.

We read the raw disk and traverse the filesystem on disk, bypass the
live filesystem, and create a real view of files on disk; then
traverse the live filesystem to get the fake view. Compare the two
view, we can find the differences. We will find the stealth files.

The actual code can do comparision when traversing the filesystem,
to save resouces.


PROOF OF CONCEPT

At the end, there is proof of concept code. The code is for linux and
ext2/ext3 filesystem. It has been tested on Mandrake and
RedHat. Beware, the code needs e2fsprogs 1.26 or above. A successful
compilation on RedHat invovles upgrades e2fsprogs-devel; on Mandrake,
you need  libext2fs2-devel.

The code is used for proof of concept. It is not perfect. For example,
I don't add the check for files which points to INODE 0, I think leave
it there can give you some fun to play with debug(e2)fs, and prove it
works :-)

Thanks go to Zhang JiaJun for help me to test this out, and so I can
make it some smart when facing adore.

Thanks go to Theodore Ts'o 's good libext2fs library (and bad docs),
with which I can write simple code.

We have developed proof of concept code for solaris/ufs and 
linux/reiserfs, but we still have some technical problems. We will
release them when we resolv them.


THE GAME WILL CONTINUE

The method utilizes raw disk interface, such as /dev/rdsk/c0t0d0s2
or /dev/hda1. LKM backdoor CAN intecept the interface, of course it
is rather complex and error prone.


CODE START HERE

/* stealth_file_checker.c
 * 
 * Copyright (C) 2002   Wang Jian, Marsec System Inc.
 *
 * http://www.marsec.net/
 *
 * Concept and Programming:
 *
 *     Wang Jian  <lark@marsec.net>
 *
 * Testing and Suggestion:
 *
 *     Zhang JiaJun <jiajun.zhang@marsec.net>
 *
 *
 * No Warranty. This code is for educational use only, commercial use is
 * prohibited.
 *
 * This small program demonstrates how to detect stealth files/dirs
 * of lkm on linux ext2/ext3 filesystems.
 *
 * compile: gcc -o sfc main.c -lext2fs
 *
 * NOTE: You need e2fsprogs-1.26 or above to compile
 *
 * usage: run it without args to get hints
 *
 */

#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <dirent.h>
#include <ext2fs/ext2fs.h>


ext2_ino_t   root, cwd;
ext2_filsys  fs;

ext2_ino_t string_to_inode(ext2_filsys fs, char *str)
{
    ext2_ino_t  ino;
    int         ret;

    ret = ext2fs_namei(fs, root, cwd, str, &ino);
    if (ret) {
        return 0;
    }
    return ino;
}

int list_dir_proc(ext2_ino_t dir,
        int    entry,
        struct ext2_dir_entry *dirent,
        int    offset,
        int    blocksize,
        char   *buf,
        void   *private)
{
    char   name[EXT2_NAME_LEN];
    char   tmp[EXT2_NAME_LEN + 256];
    char   tmppath[EXT2_NAME_LEN + 256];
    int    len;
    char   *path;
    struct stat stat_buf;
    int    flag;

    char   *prefix = (char *)private;

    DIR    * dp;
    struct dirent   *dirp;
    
    len = ((dirent->name_len & 0xFF) < EXT2_NAME_LEN) ?
        (dirent->name_len & 0xFF) : EXT2_NAME_LEN;

    strncpy(name, dirent->name, len);
    name[len] = '\0';

    if(entry == DIRENT_DELETED_FILE) {
        return 0;
    }

    ext2fs_get_pathname(fs, dir, 0, &path);
    sprintf(tmp, "%s%s/%s", prefix, path, name);
    sprintf(tmppath, "%s%s", prefix, path);
	
    /* chdir() then readdir() is for adore LKM, anyway it works
     * for other LKM.
     */
    chdir(tmppath);
    if( (dp = opendir(".")) == NULL ) {
	    printf("open dir %s error\n", tmppath);
	    exit(1);
    }
    flag=1;
    while ((dirp = readdir(dp)) != NULL) {
        if (strcmp(dirp->d_name, name) == 0) { 
            flag=0;
            break;
        }
    }
    closedir(dp);
    
    if(flag) {
        printf("%s\n", tmp);
    }

    /* this will print files pointing to Inode 0 */
    if (lstat(tmp, &stat_buf)) {
        printf("%s\n", tmp);
    }
	
    free(path);

    if (!ext2fs_check_directory(fs, dirent->inode) &&
            strcmp(".", dirent->name) && strcmp("..", dirent->name)) {
        ext2fs_dir_iterate2(fs, dirent->inode, DIRENT_FLAG_INCLUDE_EMPTY,
            0, list_dir_proc, prefix);
    }
    return 0;
}

int main(int argc, char **argv)
{
    errcode_t ret;
    ext2_ino_t  ino;

    if(argc != 3) {
        printf(
"Usage: %s <device> <path>\n"
"<device>     device on which filesystem resides\n"
"<path>       the path that filesystem is mounted on\n",
        argv[0]);
        exit(0);
    }

    initialize_ext2_error_table();

    ret = ext2fs_open(argv[1], 0, 0, 0, unix_io_manager, &fs);
    if (ret) {
        com_err(argv[1], ret, "while opening filesystem");
        exit(1);
    }

    printf("The following files or directories are stealth\n");

    root = cwd = EXT2_ROOT_INO;

    ino = string_to_inode(fs, "/");

    ret = ext2fs_dir_iterate2(fs, ino, DIRENT_FLAG_INCLUDE_EMPTY,
            0, list_dir_proc, (void *) argv[2]);

    ext2fs_free(fs);

    return 0;
}
(8299254) /Wang Jian <lark@marsec.net>/---(Ombruten)
Kommentar i text 8304896 av Paul Starzetz <paul@starzetz.de>


8304896 2002-04-17 15:54 +0200  /25 rader/ Paul Starzetz <paul@starzetz.de>
Sänt av: joel@lysator.liu.se
Importerad: 2002-04-18  02:39  av Brevbäraren
Extern mottagare: Wang Jian <lark@marsec.net>
Extern mottagare: bugtraq@securityfocus.com
Mottagare: Bugtraq (import) <21906>
Kommentar till text 8299254 av Wang Jian <lark@marsec.net>
Ärende: Re: An alternative method to check LKM backdoor/rootkit
------------------------------------------------------------
From: Paul Starzetz <paul@starzetz.de>
To: Wang Jian <lark@marsec.net>, bugtraq@securityfocus.com
Message-ID: <3CBD7E92.7010600@starzetz.de>

Wang Jian wrote:

>THE ALTERNATIVE METHOD
>
>Our alternative method uses the first style: to find the differences
>between the fake view and the real view.
>
>We read the raw disk and traverse the filesystem on disk, bypass the
>live filesystem, and create a real view of files on disk; then traverse
>the live filesystem to get the fake view. Compare the two view, we can
>find the differences. We will find the stealth files.
>
Be sure that this will be fixed in the next 'generation' of LRKM's.
Patching the device methods for disk special nodes is not a big deal -
why not to incorporate even your code into one of the nice LRKM's? You
probably found a weaknes of 'current' LRKM's but in general it is a bad
idea to check your machine while running a compromised kernel.

/ih
(8304896) /Paul Starzetz <paul@starzetz.de>/--------
Kommentar i text 8304945 av Florian Weimer <Weimer@CERT.Uni-Stuttgart.DE>
8304945 2002-04-18 00:04 +0200  /29 rader/ Florian Weimer <Weimer@CERT.Uni-Stuttgart.DE>
Sänt av: joel@lysator.liu.se
Importerad: 2002-04-18  03:34  av Brevbäraren
Extern mottagare: Paul Starzetz <paul@starzetz.de>
Extern kopiemottagare: Wang Jian <lark@marsec.net>
Extern kopiemottagare: bugtraq@securityfocus.com
Mottagare: Bugtraq (import) <21914>
Kommentar till text 8304896 av Paul Starzetz <paul@starzetz.de>
Ärende: Re: An alternative method to check LKM backdoor/rootkit
------------------------------------------------------------
From: Florian Weimer <Weimer@CERT.Uni-Stuttgart.DE>
To: Paul Starzetz <paul@starzetz.de>
Cc: Wang Jian <lark@marsec.net>, bugtraq@securityfocus.com
Message-ID: <87g01ux9qg.fsf@CERT.Uni-Stuttgart.DE>

Paul Starzetz <paul@starzetz.de> writes:

> Be sure that this will be fixed in the next 'generation' of LRKM's.
> Patching the device methods for disk special nodes is not a big deal -
> why not to incorporate even your code into one of the nice LRKM's? You
> probably found a weaknes of 'current' LRKM's but in general it is a bad
> idea to check your machine while running a compromised kernel.

I agree.  You can never be sure which kernel you are running.  An
attacker could have placed a modified kernel on a swap device (which
excludes this very area from being used as swap space), and tweaked
the boot loader to load the modified kernel.

Using this approach, the modified kernel image can be made completely
invisible easily, and it still survives reboot.  Such a modification
is very hard to spot even during an offline analysis, and the
checklists I've seen so far do not address this problem at all.

-- 
Florian Weimer 	                  Weimer@CERT.Uni-Stuttgart.DE
University of Stuttgart           http://CERT.Uni-Stuttgart.DE/people/fw/
RUS-CERT                          +49-711-685-5973/fax +49-711-685-5898
(8304945) /Florian Weimer <Weimer@CERT.Uni-Stuttgart.DE>/
8310316 2002-04-18 15:16 +0200  /50 rader/ Karsten W. Rohrbach <karsten@rohrbach.de>
Sänt av: joel@lysator.liu.se
Importerad: 2002-04-18  23:23  av Brevbäraren
Extern mottagare: Florian Weimer <Weimer@CERT.Uni-Stuttgart.DE>
Extern kopiemottagare: Paul Starzetz <paul@starzetz.de>
Extern kopiemottagare: Wang Jian <lark@marsec.net>
Extern kopiemottagare: bugtraq@securityfocus.com
Mottagare: Bugtraq (import) <21927>
Kommentar till text 8304945 av Florian Weimer <Weimer@CERT.Uni-Stuttgart.DE>
Ärende: Re: An alternative method to check LKM backdoor/rootkit
------------------------------------------------------------
From: "Karsten W. Rohrbach" <karsten@rohrbach.de>
To: Florian Weimer <Weimer@CERT.Uni-Stuttgart.DE>
Cc: Paul Starzetz <paul@starzetz.de>, Wang Jian <lark@marsec.net>,
 bugtraq@securityfocus.com
Message-ID: <20020418151645.C50564@mail.webmonster.de>

Florian Weimer(Weimer@CERT.Uni-Stuttgart.DE)@2002.04.18 00:04:39 +0000:
> I agree.  You can never be sure which kernel you are running.  An
> attacker could have placed a modified kernel on a swap device (which
> excludes this very area from being used as swap space), and tweaked
> the boot loader to load the modified kernel.
> 
> Using this approach, the modified kernel image can be made completely
> invisible easily, and it still survives reboot.  Such a modification
> is very hard to spot even during an offline analysis, and the
> checklists I've seen so far do not address this problem at all.

...which implies that the kernel sitting in the swap partition has a
loader hook to be loadable, thus it has a pattern that can be found.
this pattern should be sufficiently non-ambiguous enough, to
recognize a fake kernel from swapped pages.

a different approach i know from systems with increased security
standards is clearing the swap, block by block, in the shutdown
sequence.  since linux provides swapoff(2) instrumentation this would
be very easy to implement in the init scripts. dd(1) and mkswap(8)
are your friends ;-)

a different approach would be adding signature checks to the loader
that get executed every boot time. to sign a kernel for boot
"authorization", you must sign it with an encrypted key, requiring
authentication to the signing system first (pgp style). to circumvent
this, one must have to install a new loader (lilo, grub, whatever)
which might be disallowed at run time thorugh kernel
instrumentation. imagine a kernel option "hda=allow-sec0mod" or
similar. using this setup, also the loader itself can be checked by
itself at boot time for integrity reasons.

just a few thoughts,...

regards,
/k

-- 
> Love does not make the world go around, just up and down a bit.
KR433/KR11-RIPE -- WebMonster Community Founder -- nGENn GmbH Senior Techie
http://www.webmonster.de/ -- ftp://ftp.webmonster.de/ -- http://www.ngenn.net/
GnuPG 0x2964BF46 2001-03-15 42F9 9FFF 50D4 2F38 DBEE  DF22 3340 4F4E 2964 BF46
My mail is GnuPG signed -- Unsigned ones are bogus -- http://www.gnupg.org/
Please do not remove my address from To: and Cc: fields in mailing lists. 10x
(8310316) /Karsten W. Rohrbach <karsten@rohrbach.de>/(Ombruten)
Bilaga (application/pgp-signature) i text 8310317
8310317 2002-04-18 15:16 +0200  /9 rader/ Karsten W. Rohrbach <karsten@rohrbach.de>
Importerad: 2002-04-18  23:23  av Brevbäraren
Extern mottagare: Florian Weimer <Weimer@CERT.Uni-Stuttgart.DE>
Extern kopiemottagare: Paul Starzetz <paul@starzetz.de>
Extern kopiemottagare: Wang Jian <lark@marsec.net>
Extern kopiemottagare: bugtraq@securityfocus.com
Mottagare: Bugtraq (import) <21928>
Bilaga (text/plain) till text 8310316
Ärende: Bilaga till: Re: An alternative method to check LKM backdoor/rootkit
------------------------------------------------------------
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.0.6 (FreeBSD)
Comment: For info see http://www.gnupg.org

iD8DBQE8vsc9M0BPTilkv0YRAnbaAKDD4V5sHqr7m0EkcBLE1RPX+bxDzQCfW8/v
SLe0w8xJDh9yl6LLXC200u8=
=QLpF
-----END PGP SIGNATURE-----
(8310317) /Karsten W. Rohrbach <karsten@rohrbach.de>/
8311075 2002-04-18 10:59 +0800  /58 rader/ Wang Jian <lark@marsec.net>
Sänt av: joel@lysator.liu.se
Importerad: 2002-04-19  05:03  av Brevbäraren
Extern mottagare: 'Florian Weimer' <Weimer@CERT.Uni-Stuttgart.DE>
Extern mottagare: Paul Starzetz <paul@starzetz.de>
Extern kopiemottagare: bugtraq@securityfocus.com
Mottagare: Bugtraq (import) <21949>
Kommentar till text 8304945 av Florian Weimer <Weimer@CERT.Uni-Stuttgart.DE>
Ärende: =?utf-8?B?562U5aSNOiBBbiBhbHRlcm5hdGl2ZSBtZXRob2QgdG8gY2hlY2sgTEtNIGJhYw==?= =?utf-8?B?a2Rvb3Ivcm9vdGtpdA==?=
------------------------------------------------------------
From: "Wang Jian" <lark@marsec.net>
To: "'Florian Weimer'" <Weimer@CERT.Uni-Stuttgart.DE>,
 "Paul Starzetz" <paul@starzetz.de>
Cc: <bugtraq@securityfocus.com>
Message-ID: <000101c1e685$19cabb40$8100a8c0@marsec.net>


> -----原始邮件-----
> 发件人: Florian Weimer [mailto:Weimer@CERT.Uni-Stuttgart.DE]
> 发送时间: 2002年4月18日 06:05
> 收件人: Paul Starzetz
> 抄送: Wang Jian íõ½£ [±±¾©]; bugtraq@securityfocus.com
> 主题: Re: An alternative method to check LKM backdoor/rootkit
> 
> 
> Paul Starzetz <paul@starzetz.de> writes:
> 
> > Be sure that this will be fixed in the next 'generation' of LRKM's.
> > Patching the device methods for disk special nodes is not a 
> big deal -
> > why not to incorporate even your code into one of the nice 
> LRKM's? You
> > probably found a weaknes of 'current' LRKM's but in general 
> it is a bad
> > idea to check your machine while running a compromised kernel.
> 
> I agree.  You can never be sure which kernel you are running.  An
> attacker could have placed a modified kernel on a swap device (which
> excludes this very area from being used as swap space), and tweaked
> the boot loader to load the modified kernel.

If the file integrit check reveals that the boot loader is tweaked,
the LKM loses the game in the first place, other tricks are just
futile. Rewrite boot sector to a correct one will be enough for
recovery.

If it hide the hacked boot loader, then my code can reveal it unless
it also intercept the raw disk io layer.

This specific example is very simple to check and overcome. If you
want to:

1. swapoff this device
2. dump it to a file
3. format it again
4. swapon it

The LKMs can only continue the game by intercepting raw disk io.

> Using this approach, the modified kernel image can be made completely
> invisible easily, and it still survives reboot.  Such a modification
> is very hard to spot even during an offline analysis, and the
> checklists I've seen so far do not address this problem at all.
> 
> -- 
> Florian Weimer 	                  Weimer@CERT.Uni-Stuttgart.DE
> University of Stuttgart           
http://CERT.Uni-Stuttgart.DE/people/fw/
RUS-CERT                          +49-711-685-5973/fax +49-711-685-5898
(8311075) /Wang Jian <lark@marsec.net>/---(Ombruten)