设为首页 加入收藏

TOP

Linux内核hook 演示(一)
2014-11-24 03:24:54 来源: 作者: 【 】 浏览:1
Tags: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的,所以我很奇怪,

首页 上一页 1 2 下一页 尾页 1/2/2
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
分享到: 
上一篇Linux共享内存如何实现 下一篇Android 反编译APK 到java源码的..

评论

帐  号: 密码: (新用户注册)
验 证 码:
表  情:
内  容:

·常用meta整理 | 菜鸟 (2025-12-25 01:21:52)
·SQL HAVING 子句:深 (2025-12-25 01:21:47)
·SQL CREATE INDEX 语 (2025-12-25 01:21:45)
·Shell 传递参数 (2025-12-25 00:50:45)
·Linux echo 命令 - (2025-12-25 00:50:43)