Skip to content

kacpal/roothit

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

2 Commits
 
 
 
 
 
 
 
 
 
 

Repository files navigation

roothit

Anti-rootkit Loadable Kernel Module for Linux

Introduction

This LKM was made for a school project with main objective to learn about defensive security. Most of the work is based off current and outdated linux rootkits and anti-rootkits, all of which will be linked down below. The rootkit was made and tested on Linux >5.7.X.

Table of Contents

  1. Introduction
  2. Testing and Development
  3. Configuration
  4. Methodology
    1. Kprobe
    2. Modules
    3. Syscall
  5. Future possible mechanisms
  6. References

Testing and Development

The module is being tested on Ubuntu 20.04 LTS with Linux 5.13.0. Compilation is done inside the testing environment. In order to compile, simply use make, then you can load the module with sudo insmod roothit.ko and unload with sudo rmmod roothit.ko. You can also test it using Makefile with make test, that loads compiled module, runs one iteration of all checks and displays dmesg output. Please note that in order to use it, SCHEDULE_CHECKS in config must be set to 0.

The roothit was tested against Diamorphine and brokepkg rootkits, mianly because they provide a selection of common rootkit techinques and are working on newer Linux versions.

To provide better quality of code styling we use help of the clang-format.

Configuration

You can configure roothit using config.h. There you can select which checks do you want to disable or leave enabled. If SCHEDULE_CHECKS is set to 1, selected checks will be performed periodically. If set to 0, roothit will run just one iteration and exit.

Methodology

Kprobe

In order to use some of kernel functions, first we need to hook them. There are multiple way to do so, and we're using kprobe because it's effective, somewhat elegant and works for newer kernel versions. Kprobe is very mature Linux API designed for debugging and tracing but all we care for now is that after putting a kprobe on a function, we can simply get its pointer and use a function for ourselves: register_kprobe(&kp) func_ptr = (unsigned long)kp.addr; We can use this method to fetch not only very important functions but also sys_call_table! This is very handy for some of our anti-rootkit checks.

Modules

Sysfs contains data structures called kobject (kernel object), each of which is contained in kset - collection of kobjects. Kobjects contain different members, one of which might be a module that, as you probably expect, are data structures for Linux loadable kernel modules. Each module is contained in a single linked list.

Very common practice for many LKM rootkits is hiding by removing themselves from the list of modules. This can be acomplished by one simple line of code: list_del(&THIS_MODULE->list);. Modules can be referenced directly from the module list, but also from kset - and we can take advantage of that. We're iterating over the kset, and comparing each module extracted from kobject against standard module list. Whenever there is a module that is present in the kset but absent in module list - we can be pretty sure that the module is trying to hide itself from userspace.

Another addtitional approach is checking each result from kset if its list_head's were tinkered in any way. That is to see whether they point to NULL, LIST_POISON or to themselves.

When any suspected module is detected, roothit tries to unhide it by simply linking it back to the module list. While this is not the cleanest way to do this, at least it might give possibility for user to examine.

Syscall

Syscall hijacking is another very popular practice among linux rootkits. Syscalls (or system calls) are kernel functions that allow userspace to do many basic but crucial things, for example: read, write or execve. Each syscall has its own handler function and ID that are mapped in sys_call_table. The basic idea for rootkit here is to create hook that refers to the real syscall function but before calling it, do something more.

One of the most basic protections against it is copying sys_call_table at initialization of the anti-rootkit module and later on, comparing real table against the stored copy. Of course this assumes that the anti-rootkit was loaded before any rootkit.

That's why the second check is much more interesting. We're checking each entry in syscall table to see whether it points outside of its dedicated memory section - which is inside core kernel text. We can do this by using core_kernel_text function from Linux kernel.

After hijacked syscall is detected, we can restore the original one from our saved copy. Because sys_call_table resides on readonly page, we will need to disable readonly memory protection. This can be done simply by flipping bit 16 of cr0 register (only for x86 systems). This techinque is also used by most rootkits.

Future possible mechanims

  • Searching memory for assembly code that flips cr0
  • Searching memory for readable strings that are commonly associated with rootkits
  • Checking for hidden open ports
  • Checking for hidden files

References

About

Anti-rootkit for Linux

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published