CSC 660: Assignment #1 | |||||||
|
|||||||
The ps command is a useful tool for listing running processes. It's also one of the first targets for an attacker who wants to hide his presence on the system. In the 1990's, attackers typically hid their processes by replacing the system ps command. The modified ps was typically packaged with modified versions of other commands like ls to hide an attacker's files and netstat to hide an attacker's network connections in a package called a rootkit. However, this type of subversion could be detected by comparing the checksum of the subverted ps binary with a known good checksum and on Linux processes could be seen as directories under /proc.
As a result, attackers targeted the kernel, modifying it to hide their processes (and files and network connections) from any program on the running system. This type of software is called a kernel mode rootkit. If this type of subversion is performed in a thorough manner, it was almost impossible to detect the attacker's presence without booting the system with a known good kernel. Articles about kernel mode rootkits can be found in Phrack 61 and Phrack 63.
In this lab, we're going to learn how this type of attack works by creating a new system call cloakproc() that will remove a process from /proc. As ps on Linux uses /proc to obtain its process list, a process hidden in this manner won't be shown by ps or ls /proc. Note that there are ways to detect a process a hidden in this manner, including simply using the kill command to send it a signal. The articles on kernel mode rootkits above describe more stealthy methods of hiding processes, but you only need to hide processes from ps and ls /proc. You'll need to read quite a bit of kernel code regarding system calls, filesystems, and processes for this assignment.
The prototype for this system call is
asmlinkage long cloakproc(pid_t pid, int cloak)
where pid is the PID of the process to cloak and cloak is a boolean value, where 1 means to cloak the process and 0 means to uncloak the process. The function should verify that the process being cloaked is owned by user calling cloakproc() or that the user calling cloakproc is root. The return value indicates whether the system call succeeded or not. Use appropriate error codes from <asm-generic/errno-base.h>.
You will also need to create a user space program that will take a PID argument and invoke cloakproc() to toggle the cloaked state of the process. This will enable you to test the system call as well as to demo your code in class.
In addition to modifying arch/i386/kernel/entry.S and include/asm-i386/unistd.h to add your new system call as we've done in the past, you'll need to modify other parts of the kernel source. You'll need to add a cloaked flag to the end of the definition of task_struct in include/linux/sched.h and initialize that field in kernel/fork.c. You'll also need to modify the function that reads directories in the procfs code under fs/proc/ to hide a process or not depending on whether the cloaked flag is set. You'll find both tags (vim -t or using the Ctrl-[ option inside vim) and grep to be useful in navigating the source. You may also want to use the web-based source navigation tool at http://lxr.linux.no/source/.
As we did in lab #2, keep a clean copy of the 2.6.10 kernel source tree and do your development in a separate directory linux-2.6.10-a1. Once you've completed the assignment, make a patch
diff -ruN linux-2.6.10 linux-2.6.10-a1 >a1.patch
Make a tar archive containing both the patch and your user space test program, then submit the tar archive by e-mail to me. You'll also demo your code in class in the lab session on the due date.