Linuxカーネルのハイジャック

/* ============================================================================
 Name        : hellomod.c
 Author      : Hava
 Version     : 0.0.0.0
 Copyright   : Copyright by 2011
 Description : Hello World in C, Ansi-style 
 ============================================================================
 */
 
/*hellomod.c*/
 
// hello model for Linux 2.6
 
/*
 *  some import the model include
 * */
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/moduleparam.h>
/* 
 * the function define address is over here
 * this h file is in kernel/arch/x86/include/asm/unistd.h
 * is include two file unistd_32.h & unistd_64.h
 * you can check the unistd_32.h to find the system call function entrance
 */
#include <asm/unistd.h>
#include <asm/uaccess.h>
/*
 * This include is base for the string
 */
#include <linux/string.h>
#include <linux/syscalls.h>
//#include <linux/sched.h>
//#include <linux/mm.h>
 
#define NAME_MAX 255
 
//UID
static int uid;
module_param(uid,int,0777);
 
/*
 * Set the linux kernel module infomation
 * */
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Õ½Åô");
MODULE_DESCRIPTION("Hello the model");
 
/*
 * Global Variables declaration
 * */
unsigned long * sys_call_table = NULL;
unsigned int original_cr0 = NULL;
 
asmlinkage int (* original_mkdir)(const char *,int);
asmlinkage int (* original_unlink)(const char *);
asmlinkage long (* original_unlinkat)(int, const char *,int);
asmlinkage long (* original_rename)(const char *, const char *);
asmlinkage long (* original_renameat)(int, const char *, int, const char *);
 
/*
 * The Struct of the idt the sizeof 6
 * bits  0 to 15 : limit    ->16
 * bits 16 to 47 : base     ->32
 */
struct struct_idtr {
    unsigned short limit;
    unsigned int base;
};
 
/*
 * The Struct of the idt the sizeof 8
 * bits  0 to 15 : handler offset low   ->16
 * bits 16 to 31 : segment selector ->16
 * bits 32 to 37 : reserved     ->}8
 * bits 37 to 39 : 0            ->
 * bits 40 to 47 : flags/type       ->8
 * bits 48 to 63 : handler offset high  ->16
 */
struct struct_idt
{
    unsigned short offset_low;
    unsigned short segment_selector;
    unsigned char reserved;
    unsigned char flags;
    unsigned short offset_high;
};
 
unsigned long * getSyscallTable(void)
{
    /* in x86 cpu idtr is Interrupt descriptor table register */
    unsigned char idtr [6] = {0,0,0,0,0,0};
    /*Interrupt descriptor table*/
    struct struct_idt * idt;
    /*address of system_call*/
    unsigned long system_call;
     
    unsigned char * memoryaddr;
 
    //for the while
    int i = 0;
 
    unsigned char * syscall_key = "\xff\x14\x85";
 
    unsigned char * pointer = NULL;
 
    printk("<1>Begin to Get the System call Table address");
    /* get the interrupt descriptor table register */
    asm("sidt %0" : "=m" (idtr));
    printk("<1>sidt idtr:%x %x %x %x %x %x",idtr[0],idtr[1],idtr[2],idtr[3],idtr[4],idtr[5]);
     
    idt=(struct struct_idt *)(*(unsigned long *)&idtr[2]+8*0x80);
    printk("<1>Struct idt address :%x" ,idt);
 
    /* Exchange of high and low */
    system_call = (idt->offset_high << 16) | idt->offset_low;
    printk("<1>Get the system call address :%x" ,system_call);
     
    memoryaddr=(char *)system_call;
    printk("<1>The system call address to the array:%x" ,memoryaddr);
     
    /*
     * the system_call find \xff\x14\x85 + 3 = system_call_table
     */
    for(i=0;i<(128-2);i++)
    {
        if(memoryaddr[i]==syscall_key[0]&&memoryaddr[i+1]==syscall_key[1]&&memoryaddr[i+2]==syscall_key[2])
            break;
    }
     
    printk("<1>Find the memory the key after the system call address , %d" ,i);   
    printk("<1>The memory the key address , %x" ,&memoryaddr[i]);
    pointer = &memoryaddr[i];
    pointer = pointer + 3;
 
    printk("<1>The pointer address , %x" ,pointer);
 
    printk("<1>End and return the System call Table address, is %x" ,*(unsigned long*)pointer);
    return *(unsigned long *)pointer;
}
 
asmlinkage int hacked_mkdir(const char * pathname, int mode)
{
    printk("<1>mkdir pathname :%s and the mode :%d" , pathname , mode);
    printk("<1>hijack mkdir");
    return original_mkdir(pathname,mode);
}
 
//int _unlink( const char * pathname ); 
asmlinkage int hacked_unlink(const char * pathname)
{
    printk("<1>unlink pathname :%s", pathname);
    printk("<1>hijack unlink");
 
    return original_unlink(pathname);
}
 
//kernels/2.6.32-71.el6.i686/include/linux/syscalls.h:asmlinkage long sys_unlinkat(int dfd, const char __user * pathname, int flag);
//asmlinkage long sys_unlinkat(int dfd, const char __user * pathname, int flag);
asmlinkage long hacked_unlinkat(int dfd, const char * pathname, int flag)
{
    char rmfilename[NAME_MAX];
    long rename = 0;
    long unlinkat = 0;
    printk("<1>unlinkat dfd :%d" , dfd);
    printk("<1>unlinkat pathname :%s" , pathname);
    printk("<1>unlinkat flag :%d" , flag);
    printk("<1>hijack unlinkat");
 
    printk("<1>unlinkat filename: %s by uid: %d",pathname,uid);
 
    printk("<1>Begin rename");
 
    strcpy(rmfilename,pathname);
    printk("<1>copy the filename :%s" , rmfilename);
    printk("<1>Add Exension :%s",strcat(rmfilename,".Exension"));
    printk("<1>Add Exension:%s",strcat(pathname,".Exension"));
    //rename = sys_rename(pathname,strcat(pathname,".Exension"));
    printk("<1>After add exension filename is :%s", rmfilename);
    //rename = original_rename(pathname,rmfilename);
    //printk("<1>rename %ld", rename);
    //printk("<1>show errno msg :%s" , strerror(rename));
    unlinkat = original_unlinkat(dfd,pathname,flag);
    printk("<1>unlinkat %ld",unlinkat);
    return unlinkat;
}
 
//asmlinkage long sys_renameat(int olddfd, const char __user * oldname, int newdfd, const char __user * newname);
//asmlinkage long hacked_rename(const char __user * oldname, const char __user * newname)
//{
//  printk("<1>sys_rename :%s,%s",oldname,newname);
//  original_rename(oldname,newname);
//}
/*
 * clear WP bit of CR0, and return the original value
 */
 
unsigned int clear_and_return_cr0(void)
{
    unsigned int cr0 = 0;
    unsigned int ret;
    /*get cr0*/
    asm volatile ("movl %%cr0, %%eax" : "=a"(cr0));
 
    ret = cr0;
 
    /* clear the 20 bit of CR0, a.k.a WP bit */
    cr0 &= 0xfffeffff;
    /*set cr0*/
    asm volatile ("movl %%eax, %%cr0" : : "a"(cr0));
 
    return ret;
}
 
unsigned int get_cr0(void)
{
    unsigned int cr0 = 0;
    /*get cr0*/
    asm volatile ("movl %%cr0, %%eax" : "=a"(cr0));
 
    return cr0;
}
 
/* set CR0 with new value */
void set_cr0(unsigned int cr0)
{
    /*set cr0*/
    asm volatile ("movl %%eax, %%cr0" : : "a"(cr0));
}
 
void init_cr0(void)
{
    unsigned int cr0 = NULL;
    /* clear the 20 bit of CR0, a.k.a WP bit */
    cr0 &= 0xfffeffff;
    /*set cr0*/
    asm volatile ("movl %%eax, %%cr0" : : "a"(cr0));
}
/*
 * model init and exit
 * */
static int __init mod_init(void)
{
    mm_segment_t old_fs;
 
    printk("<1><>Hello Model Init!\n");
    sys_call_table = getSyscallTable();
 
    original_cr0 = clear_and_return_cr0();
    old_fs = get_fs();
    set_fs(KERNEL_DS);
    if(sys_call_table != NULL)
    {
        //mkdir
        printk("<1>System_Call_Table address: %lx ", sys_call_table);
        printk("<1>function call number by mkdir: %d", __NR_mkdir);
        printk("<1>function call number by read: %d", __NR_read);
 
        printk("<1>function call address by mkdir: %x", sys_call_table[__NR_mkdir]);
        original_mkdir=(int(*)(const char*,int))sys_call_table[__NR_mkdir];
        printk("<1>get the Original Address : %x", original_mkdir);
        sys_call_table[__NR_mkdir]=(unsigned long)hacked_mkdir;
 
        //unlink
        printk("<1>function call number by unlink: %d", __NR_unlink);
        printk("<1>function call address by unlink: %x", sys_call_table[__NR_unlink]);
        original_unlink=(int(*)(const char*))sys_call_table[__NR_unlink];
        printk("<1>get the Original Address : %x", original_unlink);
        sys_call_table[__NR_unlink]=(unsigned long)hacked_unlink;
 
        //unlinkat
        printk("<1>function call number by unlinkat: %d", __NR_unlinkat);
        printk("<1>function call address by unlinkat: %x", sys_call_table[__NR_unlinkat]);
        original_unlinkat=(int(*)(const char*))sys_call_table[__NR_unlinkat];
        printk("<1>get the Original Address : %x", original_unlinkat);
        sys_call_table[__NR_unlinkat]=(unsigned long)hacked_unlinkat;
 
        //rename
        //printk("<1>function call number by rename: %d", __NR_rename);
        //printk("<1>function call address by rename: %x", sys_call_table[__NR_rename]);
        //original_rename=(int(*)(const char*))sys_call_table[__NR_rename];
        //printk("<1>get the Original Address : %x", original_rename);
        //sys_call_table[__NR_rename]=(unsigned long)hacked_rename;
 
        //renameat
        //printk("<1>function call number by renameat: %d", __NR_renameat);
        //printk("<1>function call address by renameat: %x", sys_call_table[__NR_renameat]);
        //original_renameat=(int(*)(const char*))sys_call_table[__NR_renameat];
        //printk("<1>get the Original Address : %x", original_renameat);
 
        printk("<1>>UID:%d",uid);
 
        printk("<1>hacked");
    }
    set_fs(old_fs);
    set_cr0(original_cr0);
    return 0;
}
 
static void __exit mod_exit(void)
{
    original_cr0 = clear_and_return_cr0();
    sys_call_table[__NR_mkdir]=(unsigned long)original_mkdir;
    sys_call_table[__NR_unlink]=(unsigned long)original_unlink;
    sys_call_table[__NR_unlinkat]=(unsigned long)original_unlinkat;
    //sys_call_table[__NR_rename]=(unsigned long)original_rename;
    set_cr0(original_cr0);
    printk("<1><>Hello Model Exit.20111217\n");
}
 
module_init(mod_init);
module_exit(mod_exit);

プラットフォームLinuxに適したLinuxカーネルハイジャックには、CentOS 6.0カーネルに適したLinuxカーネル開発の経験が必要です。このバージョンは32ビット、64ビットに適しています。レジスタビットを計算するか、ゼロを自分で埋めてください。

# Makefile2.6
# 产生hellomod 模块的目标文件
obj-m += hellomod.o
#模块所在的当前路径
CURRENT_PATH := $(shell pwd)
#Linux内核源代码的当前版本
LINUX_KERNEL := $(shell uname -r)
#Linux内核源代码的绝对路径
LINUX_KERNEL_PATH := /usr/src/kernels/$(LINUX_KERNEL) 
all:
    @echo '程序根目录:$(CURRENT_PATH)'
    @echo 'Linux内核版本:$(LINUX_KERNEL)'
    @echo 'Linux src:$(LINUX_KERNEL_PATH)'
    @echo '开始编译模块'
    make -C $(LINUX_KERNEL_PATH) M=$(CURRENT_PATH) modules
    @echo '结束编译模块'
clean:
    @echo '开始清理模块'
    make -C $(LINUX_KERNEL_PATH) M=$(CURRENT_PATH) clean
    @echo '结束清理模块'

 

 

 

 

おすすめ

転載: blog.csdn.net/qq_24436765/article/details/108355316