I am working on detecting kernel level rootkits and have chosen Adore-Ng as my first test rootkit. After having known how this rootkit hides itself and other processes in the Linux kernel (2.4, 2.6 versions), I now want to know how it gets loaded into the kernel.
Specifically, I want to know whether
1. It calls any already existing APIs in the Linux kernel OR
2. Does it have any hard-coded assembly instructions such that as soon as its compiled, it gets loaded into the kernel?
I went through the source code of Adore-Ng but couldn't find anything in this direction and could only see how it achieves its goal of hiding.
Can anyone tell/suggest how I can find its loading behaviour?
Thanks.
The core of the Adore rootkit is a malicious module, so for it to be loaded into the kernel you first need root access, then run insmod (or modinfo).
Another way to load Adore is to infect a trusted kernel module as described in Phrack volume 0x0b, issue 0x3d. It wouldn't be as stealthy as the former way because the cleaner module wouldn't be invoked. Since you went through the source code, I believe you have the aptitude to modify the source to invoke the cleaner module once the Adore module has infected a legit module. (make sure you also leave no trace of the module infection; the cleaner will not pick that up).
Any admin worth his salt would use signed modules, so don't expect these methods to work on production kernels after the 2.6 mainline.
Related
I am trying to create a character device driver that dumps /etc/shadow when read from as a non-privileged user. This is for purely academic purposes of course.
I was reading about how reading/writing files in kernel space opens a system to possible exploits. I am trying to implement this in practice.
Please spare me the "don't touch the filesystem in kernel mode" talk. I am precisely trying to exploit the nuances of doing so.
Problem is that the only way I have found so far that works to open a file in kernel mode is filp_open, which is currently producing EACCESS when I read from the device file as a non-privileged user. This was confounding at first as I assumed that I can do anything in kernel space.
For example, when I cat the device file I have created as a non-root user, filp_open produces EACCESS in kernel space???
Further investigation has led me to believe that filp_open checks the capabilities of the calling process. This would make sense as it is used internally by open(), but I am in kernel mode here! There must be a way!
I am very new to programming in kernel space. I have extensive application C experience, but I am finding it difficult to navigate the kernel documentation for precisely what I am looking for. Additionally, it seems that more and more symbols within the kernel are not exported for use in modules. As I am developing an exploit proof of concept, I would like it to work without recompiling the kernel. I am finding a lot of code (vfs and syscalls) that is deprecated as the symbols are no longer exported to kernel modules.
Is what I am trying to do a thing that is specifically engineered against? Loading a kernel module requires root to begin with, so I would see this more in the lens of a persistence focused attack rather than an access one.
Also, I got the proof of concept working by just reading from the file when the module is loaded, but this is no fun! Any pointers here are much appreciated.
After some rethinking and digging I have found two solutions to my problem. Thank you to Tsyvarev and stark for the pointers.
Solution 1
The first solution is to elevate the privileges of the calling process before making a call of filp_open. This is also basically making a rootkit, so not as interesting.
Here is a link to the guide that I found on the subject.
https://0x00sec.org/t/kernel-rootkits-getting-your-hands-dirty/1485
Solution 2
The module will have an init function that by nature must be run with elevated privs when the module is loaded. So you can open the file pointer there and just close it when the module is unloaded. Caveats are that you have the file pointer open the whole time, so all of the gotchas there are still present. Better to only read, writing is where things can get a bit tricky. This is the solution I chose in the interim, as I didn't want this thing to be a full rootkit.
Another direction is workqueue or to spawn a thread. Probably the most tricky but also the most inline with what my original vision of this demo was. I did not test this direction but it probably is the best solution.
I am looking if there is any API through which we can get OS distribution name and version from a Linux kernel module?
For example, I am using SLES 12 service pack 4. This information is present in /etc/os-release file. I want to know if there is any way to get this information from kernel code.
linux:/ # cat /etc/os-release
NAME="SLES"
VERSION="12-SP4"
VERSION_ID="12.4"
PRETTY_NAME="SUSE Linux Enterprise Server 12 SP4"
ID="sles"
ANSI_COLOR="0;32"
CPE_NAME="cpe:/o:suse:sles:12:sp4"
linux:/ #
There's no kernel API for detecting the current OS distribution, simply because it's not really needed. The Linux kernel itself is distribution-agnostic, and it couldn't care less which distribution is being run on top of it (having the kernel depend on what's being run on top of it wouldn't make much sense).
If you really want, you can open, read and parse the file yourself from kernel space. See more in this other post for an example, and in particular this answer for modern kernels. In any case, remember that filesystem interaction from kernel space is generally discouraged, and could easily lead to bugs and compromise the security of the kernel if done wrong, so be careful.
If you are developing a kernel module, I would suggest you to parse the /etc/os-release file from userspace when compiling/installing the module and use a set of #defines, or even module parameters. In any case, you should ask yourself why you need this information in kernel code in the first place, as you really shouldn't.
CLNP ( Connection Less Network protocol ) was present as a loadable kernel module in 2.6.17.3 linux version.
At that time it was not linked with Datalink layer and Application layer and so the project was not considered as complete.
The project of implementing CLNP was continued by the CLNP subteam of BPPT-SGU 2008 and the remaining work was also completed.
Here is the source code for it.
https://github.com/crazoes/clnp
INSTALL file gives the description about how we can load this particular module in 2.6.17.3 kernel as it has slight different process than other modules. https://github.com/crazoes/clnp/blob/test/INSTALL
My Question
I want to load this module on the current kernel version. Is this possible?
My ultimate goal is to anyhow get this module working on latest kernel version. But this doesn't seem to be possible without changing the code. I am assuming that I'll have to rework on the whole driver.
Because many of the header files which CLNP was using during 2.6.17.3 kernel version (example:- socket.h) has changed in lot of terms.
But still, I would like to know if there is any way possible to have this work done.
Is there a (/an efficient) way of stripping unwanted source from the linux kernel? Would it be possible for the configurators (xconfig, menuconfig) to work?
As an example, I'm planning to create a different VFS design, which might break all the VFS-dependent kernel components. Also, working with the full kernel source (currently ~400 MB) is not desirable due to space reasons (I'm only interested in booting the system & debugging my code).
Note: I've thought about removing files, but I can't find how to remove the dependencies on them.
[edit] Note 2: Ok, I'll try again deciphering the Kbuild system.
If you don't mind the files just hanging there (which unless your hard disk is 50MB, it's usually not a problem), you can disable basically every disableable feature by configuring the kernel using it's own configuration tools.
For example, simply type
$ make menuconfig # or any other available configuration option
and start by saying no to everything you don't need. There's a LOT of stuff, so this may take some time! Read the README of the kernel. There's another option (which I don't remember the name) that starts the configuration with the minimum configuration automatically detected from your running kernel. That may make things easier.
Thanks to every one,
This is the question asked in one of the interview i faced.
I have a Linux device driver which was compiled in Linux kernel version 2.6.I would like to port the same driver in a Linux PC which has kernel 3.X without compiling in new versions.
Is it possible ? If it is possible please let me know how. If it is not possible please let me know why not ?
Thanks & Regards
Siva
No you cannot port module which is compiled for one version to other version.
The reason is as follows
Modules are strongly tied to the data structures and function prototypes defined in a particular kernel version;
the interface seen by a module can change significantly from one kernel version to
the next. This is especially true of development kernels, of course
The kernel does not just assume that a given module has been built against the
proper kernel version. One of the steps in the build process is to link your module
against a file (called vermagic.o) from the current kernel tree; this object contains a
fair amount of information about the kernel the module was built for, including the
target kernel version, compiler version, and the settings of a number of important
configuration variables. When an attempt is made to load a module, this information
can be tested for compatibility with the running kernel. If things don’t match,
the module is not loaded; instead, you see something like:
# insmod hello.ko
Error inserting './hello.ko': -1 Invalid module format
A look in the system log file (/var/log/messages or whatever your system is configured
to use) will reveal the specific problem that caused the module to fail to load.
Kernel interfaces often change between releases. If you are writing a module that is
intended to work with multiple versions of the kernel (especially if it must work
across major releases), you likely have to make use of macros and #ifdef constructs
to make your code build properly.
now it's not possible:
usually, a "driver" is a binary kernel-module
porting will involve code-changes to the kernel module. if you change the code, you need to compile it, in order to get a binary.
since kernel modules run in kernel space, it is crucial that they are robust. since parts of the kernel-API change every now and then, trying to use a module compiled for kernel-X with another kernel-Y, might either not load because of missing symbols (if you are lucky) or lead to a kernel panic because semantics have changed.
btw, all this is not really related to 2.6.x vs 3.y, but holds true for any kernel version
but then: of course in theory it is possible to "write" a kernel-module as binary code in your favourite hex-editor, without resorting to compilers and such. this would allow you to "port" a driver from one kernel to another without recompilation. i guess this is not for humans though...