运行中动态添加系统调用(2)

int main(int argc, char **argv)    {        asm("cmpl $284, %eax \n\t");        return 0;    }  

编译后使用objdump得到了3d 1c 01 00 00 cmp    $0x11c,%eax这样的机器码/汇编码,于是我们可以断定,机器特征码为3d 1c 01 00 00 。类似的,sys_call_table的地址也可以这样来求得,不过记住,没有必要,既然你有root权限了,还有必要这样吗?

那么到底怎么做到的呢?请看模块dynamic_add_syscall:

#include <linux/init.h>    #include <linux/kernel.h>    #include <linux/module.h>    #include <linux/sched.h>    #include <linux/fs.h>    #include <linux/proc_fs.h>    unsigned long entry_addr, table_addr;    unsigned long nowa_num, want_num;    module_param(entry_addr, long, S_IRUSR);    MODULE_PARM_DESC(entry_addr, "system call entry");  //参数保存system_call的地址    module_param(table_addr, long, S_IRUSR);    MODULE_PARM_DESC(table_addr, "syscall table");    //参数保存sys_call_table的地址    module_param(nowa_num, long, S_IRUSR);    MODULE_PARM_DESC(nowa_num, "system calls number");  //参数保存现有的系统调用数量    module_param(want_num, long, S_IRUSR);    MODULE_PARM_DESC(want_num, "system calls number");  //参数保存希望扩充到的系统调用数量    unsigned int table_new[500] = {0x00};    //新的系统调用表    unsigned int old_table;     //保存原有的系统调用表,以备恢复    unsigned int old_num;   //��存原有系统调用数量,以备恢复    unsigned int old_table_i;  //保存系统调用表机器码命中的偏移地址    unsigned int old_num_i;  //保存系统调用数量机器码命中的偏移地址    unsigned char *entry;    unsigned char *table;    unsigned int orig_table;    unsigned char *nowa_num_addr;    unsigned int appendi;    //以下的procfs文件展示了一些地址信息,包括新的系统调用表地址以及当前到达哪个系统调用号了。    static int   read_syscall_info(char *page, char **start, off_t off, int count, int *eof, void *data)    {        int len;        len = sprintf(page, "[table_addr:%p]   [nowa number:%d]  [please inc the value at address    %p, thank you!]\n", table_new, appendi, &appendi);        len -= off;        *start = page + off;        if (len > count)            len = count;        else           *eof = 1;        if (len < 0)            len = 0;        return len;    }    int __init rm_init(void){        unsigned int new_table = table_new;        unsigned char *ntp = &new_table;               unsigned char num_test_op[5] = {0}; //定义一个数组,包含了匹配的检测系统调用号范围的机器码    :3d 1c 01 00 00。        int i, j = 0, k = 0;        entry = entry_addr;        table = table_addr;        nowa_num_addr = &nowa_num;        unsigned char *want_num_addr = &want_num;        orig_table = table;        unsigned char *otp = &orig_table;               num_test_op[0] = 0x3d;        num_test_op[1] = *(nowa_num_addr+0);  //这两行初始化匹配机器码        num_test_op[2] = *(nowa_num_addr+1);        num_test_op[3] = 0x00;        num_test_op[4] = 0x00;        for (i = 0; i < nowa_num; i ++) {            unsigned int *p = table+i*4;            table_new[i] = *p;        }        appendi = i;               j = 0;        for (i = 0; i < 256; i ++) {            if ( !j                   &&                *(entry+i+0) == num_test_op[0] &&                *(entry+i+1) == num_test_op[1] &&                *(entry+i+2) == num_test_op[2] &&                *(entry+i+3) == num_test_op[3] &&                *(entry+i+4) == num_test_op[4]            ) {                old_num_i = i;                j = 1;                *(entry+i+1) = *(want_num_addr+0); //这两行修改系统调用号的范围                *(entry+i+2) = *(want_num_addr+1);            }            if ( !k                 &&                *(entry+i+0) == *(otp+0) &&                *(entry+i+1) == *(otp+1) &&                *(entry+i+2) == *(otp+2) &&                *(entry+i+3) == *(otp+3)            ) {                old_table_i = i;                k = 1;                    *(entry+i+0) = *(ntp+0);  //这四行修改系统调用表的地址                    *(entry+i+1) = *(ntp+1);                    *(entry+i+2) = *(ntp+2);                    *(entry+i+3) = *(ntp+3);            }        }         //在procfs中导出一些信息,供实现新系统调用的模块参考        create_proc_read_entry("new_syscall", S_IFREG, NULL, read_syscall_info, NULL);        return 0;    }    void __exit rm_exit(void){        //针对init的修改进行还原        unsigned char *otp = &orig_table;        *(entry+old_table_i+0) = *(otp+0);        *(entry+old_table_i+1) = *(otp+1);        *(entry+old_table_i+2) = *(otp+2);        *(entry+old_table_i+3) = *(otp+3);               *(entry+old_num_i+1) = *(nowa_num_addr+0);        *(entry+old_num_i+2) = *(nowa_num_addr+1);        remove_proc_entry("new_syscall", NULL);    }    EXPORT_SYMBOL(appendi); //导出现在已经到哪个系统调用号了    module_init(rm_init);    module_exit(rm_exit);    MODULE_LICENSE("GPL");  

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wwfxfs.html