TUCoPS :: Linux :: Discontinued :: trojlnxk.txt

Yet Another Paper on Trojaning the Linux Kernel


Yet another Paper on Trojening the Linux Kernel

Typically when one thinks about kernel rootkits on linux, the subject of
system call remapping comes up. This technique is tried and true; however,
it is also quite easy to detect. Currently available are several
utilities, including lomac and my StMichael LKM to handle these attacks.

Moving beyond the simple systemcall remapping, there has been information
published about actually rewriting some functions during the kernel
runtime. Again, this can be detected easily by monitoring the values of
the functions via a checksumming mechanism. Again, an example of such
attacks on these attacks is available in StMichael_LKM-0.04.

So, where to next? One area that has not been explored is the application
of kernel threads in the production of a kernel rootkit. Although one
would not have the easy access that systemcalls provide, since the kenrel
threads are running in kernel space -- one can intercept, replace, or
alter system activity in ways that are undetectable.

But, for just a moment let me digress.

+Kernel Threads+

The concept of kernel threads is nothing new. A kernel thread is, for most
purposes, no different then a regular user-land process with three

        -- Each Kernel thread executes a single specific kernel function. This
           is in contrast to regular executable kernel functions accessible
           via events such as a system-call.

        -- Kenrel threads run only in kernel-mode, while regular processes
           run either in user-mode or kernel-mode (via systemcalls)
        -- Kernel threads are only use linear addresses greater then
           PAGE_OFFSET (defined in .h), due to the fact they run only in 
           kernel mode.

        Source: Understanding the Linux Kernel, p94. ISBN: 0-596-00002-2

As mentioned, the kernel threads are simply defined functions within
the kernel, that are passed to the kenrel_thread() call and daemonized.

Kernel threads acquire their run time via the scheduler, and have a
execution priority associated with them. One benefit of the
kernel-threads is that since they are already in kernel-space, the
latency associated with performing systemcalls is removed. This is, in
part, the justification that was used for the implementation of the kernel
httpd kernel thread.

+Kernel Threads containing Hostile Code+

So, how could a dubious individual utilize this feature of the linux
kernel to implement hostile or subversive code on a system? A couple ways
come to mind:

        -- Back-Orafice for Linux (Or some simular linux-based
           remote-administration *wink* tool.
        -- Attack-Concealment (Hiding Files, Connections, Processes, etc).
To implement these features, we will look at how the kenrel threads could
access the network overtly or covertly, modify or intercept filesystem
calls. Other items that could be done is to actually modify the memory
management to selectively load certain memory pages in depending on some
circumstance -- ie, think double books.

+Kernel Threads And Overt Network Access+

As a process, the kernel threads have a context. That permits them to
easily possess open file descriptors and network sockets. Because of this,
writing a specific kernel_therad that would accept connections, or write
data to a network socket (via the appropriate system calls) can be done
from within kernel space.

The only challenge that would have to be handled by the developer of a
kernel thread requiring overt network access is working without the
comfort of the network libraries. Sure, one could probably statically link
the libraries to the module -- but its a waste of space. Moreover, it take
the fun out of writing a kernel thread. Ever hear of roughing it?

All of the network functions that could be used, with the exception of
data manipulation functions (ie, htol), eventually perform a system call.
Guess what? The kernel thread executes in kernel context! That means that
the kernel thread could simply call the system call directly.

For example, to call, say write to a connected socket's file descriptor
(say fd 10) the buffer "Hello World", one would use:

 ret_val = (*sys_call_table[__NR_write])(10,"Hello World",12);

+Kernel Threads And Covert Network Access+

Well, that's all fine and dandy. However, if the kernel_tread is truly
hostile it probably shouldn't have open network sockets just lying around.
Perhaps they could be hidden, but why even bother?

Once again, the kernel_thread is executing in kernel context. That means
it can see the incoming and outgoing network traffic as it is stored in the
individual sk_buff lists, accessible from the skb_head_pool.

Reference: linux/net/core/skbuff.c

By monitoring established network connections for to read data, or using
established network connections to transmit data to connected, the
activities of the kernel_thread can be concealed from the system, and
specially crafted communications utilities can user innocuous services
that legitimately operate on the victim host, such as httpd or sendmail,
to manage the network connections by which commands and responses would be
transmitted from a controlling remote host and the victim host.

+Kernel Threads and File-system Access+

In UNIX, everything is represented on the fileystem. System memory,
itself, exists as a file, /dev/kmem. Without touching system call tables,
how can one control the actual filesystem activity?

In Linux, all the filesystems are abstracted under a virtual filesystem
layer. Associated with each instance of a filesystem on a device
is a operations structure, which maps the real file-system
operations to the VFS layer. 

In the case of ext2fs, the ops table is defined in linux/fs/ext2/super.c 
and is called ext2_sops.

An attacker wishing to manipulate this structure has two options:

1. Rewrite the structure with the tronned operations.

2. Seek out all superblocks, and currently open file descriptors
   replacing the ops pointer with a address of the tronned
   operations residing in the kernel_thread.

The first option is the easiest to implement, the trojaned structure
is simply copied over the original structure. No further changes
are necessary. If the structure is being monitored via a checksumming
mechanism, it will be identified as changed (as a static structure this
is definitely a sign that something is afoot). The risk of this occurring
is mitigated by the fact that the ext2_sops structure is not an exported
symbol, and is not easily monitored.

The second option is be harder to detect, but would requires
more work to implement. First, each mounted filesystem would have
to have its in-memory copy of its superblock modified to reference
the trojaned operations structure. Secondly, all currently open
files on those filesystems would have to be modified, as they copy
the ops pointer from their superblock upon creation of the file 

+Kernel Thread Concealment+

What good is a kernel thread to do all the nice and naughty things
in the world if it stands out like a sore thumb. I mean, part
of the reason for looking at this is to hide ones presence. Then
why would one be content having a kernel thread appear as:

root         9  0.0  0.1  1368   72 ?        S    Jul14   0:12 [ur0wn3d] 

OK, maybe that is a little bit over the top, but you get the point.

Again, a simple solutions:

Remember that filesystem stuff? Yep, proc file system too.
One word: proc_sops 

+Detection and Countermeasures+

So, faced with this type of mechinism that can conceal attacks
and be used as a remote administration tool for linux systems,
how do we protect ourselves?

1. Disabling the kenrel_thread call is insufficient. Even if
   the call is disabled on a system after the necessary
   kernel threads are started, then one can use their time
   during init_module to 'roll their own' kernel thread call.

2. Checksumming various common and critical filesystem,
   memory management, and scheduling data structures would
   prevent a kernel thread from using its position to subvert
   the low level memory management, filesystem, and scheduling
   This does not detect or prevent other mallicious effects that
   could be done by the kernel thread.

3. In StJude, tie kernel threads to the default (no privlage)
   rule. kernel threads can be identified by abnormalities 
   in their task_struct, so this is possible. It would limit
   the use of kernel threads as remote administration tools.

	This is just a brief summery of possible countermeasures. Others
may follow. Despite this, the kernel threads provide an elegent
and dangerous mechinism for the implementation of hostile code
within the linux kernel.

TUCoPS is optimized to look best in Firefox® on a widescreen monitor (1440x900 or better).
Site design & layout copyright © 1986-2024 AOH