linux 内核开发 hook,Linux内核hook 演示

我以前利用0x80中断程序找到system_call然后找到 sys_call_table的方法,现在试下hook系统调用sys_mkdir来阻止创建目录小试牛刀。

#include

#include

#include

#include

#include

#include

MODULE_LICENSE("Dual BSD/GPL");

#define _DEBUG

#ifdef _DEBUG

#define kprintk(fmt,args...) printk(KERN_DEBUG fmt,##args)

#define kprintf(fmt,args...) printf(fmt,##args)

#define kperror(str) perror(str)

#else

#define kprintk

#define kprintf

#define kperror

#endif

long g_old_sys_mkdir=0;

long * g_sys_call_table=NULL;

long g_oldcr0=0;

struct _idtr{

unsigned short  limit;

unsigned int    base;

} __attribute__ ( ( packed ) );

// 中断描述符表结构

struct _idt_descriptor

{

unsigned short offset_low;

unsigned short sel;

unsigned char  none, flags;

unsigned short offset_high;

} __attribute__((packed));

unsigned int close_cr(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  open_cr(unsigned int oldval)

{

asm volatile ("movl %%eax, %%cr0"

:

: "a"(oldval)

);

}

long * get_sys_call_table(void)

{

struct _idt_descriptor * idt;

struct _idtr idtr;

unsigned int sys_call_off;

int sys_call_table=0;

unsigned char* p;

int i;

asm("sidt %0":"=m"(idtr));

printk("addr of idtr: 0x%x\n", (unsigned int)&idtr);

idt=(struct _idt_descriptor *)(idtr.base+8*0x80);

sys_call_off=((unsigned int )(idt->offset_high<<16)|(unsigned int )idt->offset_low);

printk("addr of idt 0x80: 0x%x\n", sys_call_off);

p=(unsigned char *)sys_call_off;

for (i=0; i<100; i++)

{

if (p[i]==0xff && p[i+1]==0x14 && p[i+2]==0x85)

{

sys_call_table=*(int*)((int)p+i+3);

kprintk("addr of sys_call_table: 0x%x\n", sys_call_table);

return (long*)sys_call_table;

}

}

return 0;

}

//asmlinkage long my_sys_getdents64(unsigned int fd, struct linux_dirent64 __user * dirent, unsigned int count)

asmlinkage long my_sys_mkdir(const char __user *pathname, int mode)

{

kprintk("can't' mkidr ^ ^\n");

return -1;

}

void start_hook(void)

{

g_sys_call_table=get_sys_call_table();

if(!g_sys_call_table)

{

kprintk("get sys_call_table error");

return;

}

//检测获取到的地址是不是正确的

if (g_sys_call_table[__NR_close] != (unsigned long)sys_close)

{

kprintk("Incorrect sys_call_table address.\n");

return ;

}

g_old_sys_mkdir=g_sys_call_table[__NR_mkdir];

//hoot it

g_oldcr0=close_cr();

g_sys_call_table[__NR_mkdir]=my_sys_mkdir;

open_cr(g_oldcr0);

kprintk("new %08x %08x\n",(unsigned int)my_sys_mkdir,(unsigned int)g_sys_call_table[__NR_mkdir]);

}

int raider_init(void)

{

kprintk("raider init\n");

start_hook();

return  0;

}

void raider_exit(void)

{

kprintk("raider exit");

if(g_sys_call_table && g_old_sys_mkdir)

{

g_oldcr0=close_cr();

g_sys_call_table[__NR_mkdir]=g_old_sys_mkdir;

kprintk("restore %08x\n",(unsigned int)g_sys_call_table[__NR_mkdir]);

open_cr(g_oldcr0);

}

}

module_init(raider_init);

module_exit(raider_exit);

代码在2.6.28下测试通过。

可见,只要得到sys_call_table后,就能轻易的做很多手段,其实和windows下修改ssdt没有本质区别只是网上关于linux的实现大部分内核版本比较老,有的都不用改cr0的,所以我很奇怪,也许以前的内核版本可行吧.

其实通往内核的接口还有一个sysenter_entry,通过它也可以得到sys_call_table的,只是这个接口同样没有导出,要得到也得用特殊办法了.0b1331709591d260c1c78e86d0c51c18.png

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值