/* ============================================================================
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,需要有Linux内核开发经验,适用CentOS 6.0内核 本版本适用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 '结束清理模块'