Linux rootkit implementation
Sunday, December 4, 2011
This is a rootkit i developed some time ago for educational purposes. It has the ability to hide itself from lsmod, hide processes, tcp connections, logged in users and to give uid 0 to any running process. The rootkit does not work on linux kernel >= 3.0; I′ve successfully tested it on kernels >= 2.6.26 && <= 2.6.38.
The hiding is performed through file system function hooking. On Linux, every fs driver provides functions to open, read, write and perform operations with files and directories. This functions are stored in a struct file_operations, stored inside every inode. Therefore, every file_operations contains a pointer to the open, read, write(and many other) functions which will be called whenever a user tries to execute those actions on a filesystem object.
So what i did was to retrieve a certain inode and modify the pointer to its read function, replacing it with my own function. In this new function, filtering on the input was performed, in order to remove the entries i wanted to hide.
Let's take for example the connection hiding mechanism. netstat takes tcp connections information from a virtual file named /proc/net/tcp. This file contains one entry per line, each one indicating source and destination port, source and destination address and more information about each open connection. In order to hide a certain connection, i replaced the default read function with my own, in which i read entries on that file and skipped those containing the port i needed to hide.
In order to give orders to the rootkit, i used the same mechanism. I added a write function pointer to the file /proc/buddyinfo, which by default has no write permissions. So after hooking that function, whenever any user writes something to that virtual file, the rootkit will read what was wrote and execute actions based on the input. The commands it supports are the next ones:
- hide/show. This commands hide/show the rootkit from lsmod(actually from /proc/modules).
- hsport PORT/ssport PORT. Hides(hsport) connection which have PORT as their source port, or "unhides it"(ssport) if it was previously hidden.
- hdport PORT/sdport PORT. Same as above but using destination port instead of source.
- hpid PID/spid PID. Hides or "unhides" a process that has PID as its pid. This is done by hooking the /proc readdir pointer.
- huser USER/suser USER. This commands hide or "unhide" a logged in user, so that who or other similar commands won't indicate USER is logged in the system. This is done by hooking /var/run/utmp.
- root PID. This makes the process identified by PID to contain uid 0 and gid 0. This is kind of dirty but works well; the credentials struct from the init process is copied to the process identified by PID.
This is a screenshot showing how the rootkit works, hiding a user, a process, the ssh socket and making the bash process gain root privileges:
You can get the source code https://github.com/mfontanini/Programs-Scripts/tree/master/rootkit. In order to compile it, you require your kernel's headers(on debian-based distributions, this can be found on the package linux-headers-2.6.X.X, where X depend on your kernel version). Download both the Makefile and the source file, and then just execute:
That's all. Hope you find it useful!
Posted by Matias Fontanini at 16:49