文章详情

  • 游戏榜单
  • 软件榜单
关闭导航
热搜榜
热门下载
热门标签
php爱好者> php文档>截获系统调用之改进版

截获系统调用之改进版

时间:2007-06-11  来源:hauto

   从网上看到有介绍截获系统调用的文章,于是自己下载下来编译执行了一下。
但是发现这些例子都有缺点:像sys_execve(struct pt_regs regs)这样的系统调用,
截获后若要它仍然完成原有的功能需要调用do_execve()函数,但是这个函数是内核不导
出,很麻烦。另外,即算是截获函数实现了它的功能,错误还是难免出现。

    于是就想怎么样截获后又能不留痕迹地实现原有功能。一个好的想法是直接在截获函数中
直接调用sys_execve().然而想到信号处理时如果中断了系统调用则可以重新执行,那么
能不能通过类似的方法执行系统调用呢?一个想法:替换之前将要替换的系统调用保存在其他
中断向量中,然后在替换函数中调整内核堆栈,让系统重新以另一个调用号调用保存的系统调用。

经过近两天的编码调试,终于如愿以偿。先说明一下关键之处,然后是代码。
关键之处:  
1.将原来的系统调用函数保存在向量__NR_save=17中,这里用17有两个原因
    1) 在文件syscall_table.S中,向量17的函数是sys_ni_syscall,这是一个没有使用的
        调用号。
       .long sys_ni_syscall    /* old break syscall holder */
    2) 一开始我用 319,因为NR_syscalls=318
        #define NR_syscalls 318
        大于NR_syscalls的调用号自然没人用,然而这样做不行。因为在entry.S中
        system_call:
            ...
            cmpl $(nr_syscalls), %eax
            jae syscall_badsys  
            . ...
       若调用号大于NR_syscalls,根本不会执行调用函数
2.    信号处理中重新执行中断的调用是这样做的:
       case -ERESTARTNOINTR:
          regs->eax = regs->orig_eax;
          regs->eip -= 2;
    于是我就想这样做
          pr.eip-=2;
    然而老是出错,后来查看汇编后的代码发现,减2操作是在寄存器中实现的,内核堆栈
    根本没有改变。于是改用汇编:
     __asm__("sub $0x2,%0" : "=m" (pr.eip));
3.  将内核堆栈中regs.eax改为__NR_save,然而这一步不能通过在函数中赋值改变
    因为在entry.S中调用完函数后,内核将寄存器eax值存入regs.eax中
         system_call:
            ...
            call *sys_call_table(,%eax,4)
            movl %eax,EAX(%esp)             # store the return value     
             . ... 
    我们知道寄存器eax存的是函数返回值,于是我将替换函数返回_NR_save,让内核自动
    将其保存在regs.eax。
以下是代码:
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/sched.h>
#include <asm/unistd.h>
#include <asm/ptrace.h>

MODULE_LICENSE("GPL");
MODULE_AUTHOR("xunil@bmy and hhj");
MODULE_DESCRIPTION("Different from others, this module automatically locate the entry of sys_call_table !");
unsigned long *sys_call_table=NULL;
//asmlinkage
int (*orig_exec)(struct pt_regs);
int __NR_save=17;
struct _idt
{
unsigned short offset_low,segment_sel;
unsigned char reserved,flags;
unsigned short offset_high;
};

unsigned long *getscTable(void)
{

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__("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])
{
printk("here ok!!\n");
break;

}
p=&shell[i];
p+=3;
sct=*(unsigned long*)p;

return (unsigned long*)(sct);
}
//asmlinkage
int hacked_exec(struct pt_regs pr){
    __asm__("sub $0x2,%0" : "=m" (pr.eip));
//    pr.eax=__NR_save;
    printk("PID %d called sys_execve !\n",current->pid);
    return __NR_save;
}

static int __init find_init(void){
sys_call_table = getscTable();
printk("here 1\n");
orig_exec=(int(*)(struct pt_regs))(sys_call_table[__NR_execve]);
printk("here 2,%d\n",__NR_save);
sys_call_table[__NR_execve]=(long)hacked_exec;
sys_call_table[__NR_save]=(long)orig_exec;
return 0;
}

static void __exit find_cleanup(void){
sys_call_table[__NR_execve]=(unsigned long)orig_exec;
}

module_init(find_init);
module_exit(find_cleanup);
相关阅读 更多 +
排行榜 更多 +
几何飞行内购修改版

几何飞行内购修改版

飞行射击 下载
街头冲突帮派战斗

街头冲突帮派战斗

动作格斗 下载
componut

componut

休闲益智 下载