动态调用kernel任意函数(anycall)

来源:互联网 发布:网络兼职被骗怎么报警 编辑:程序博客网 时间:2024/05/21 02:54

有的时候只需要简单调用下别的kernel函数

或者别的模块函数没有export,而你又不想单独编译kernel重新下载的时候

或者动态去修改某个驱动的寄存器值。

首先看下效果及使用步骤:

加入kernel ,更多时候是驱动中有以下函数:

 ssize_t justfortest0(){    printk(KERN_ERR"[anycall] successful....justfortest  000\r\n");    return 0;} ssize_t justfortest1(int i){    printk(KERN_ERR"[anycall] successful....justfortest  111 value is %d \r\n",i);    return 0;} ssize_t justfortest2(int i, int j){    printk(KERN_ERR"[anycall] successful....justfortest  222 value is %d ,%d \r\n",i,j);    return 0;}

我只需要在shell 中输入:

echo "^justfortest2:1,7788,#"  >  /sys/kernel/debug/anycall

log 输入如下:

内核即会去执行函数:justfortest2 (参数是1 及7788)

输入字符串的协议如下:

         ^address:1,2,3,4,#           (objdump -S vmlinux 可以通过函数名得到函数地址,注意这里输入函数地址必须是: 0X......格式)

或     ^func_name:1,2,3,4,#     (func_name是你执行的函数名)

看下此内核模块:

#include <linux/kernel.h>#include <linux/module.h>#include <linux/kprobes.h>#include <linux/slab.h>#include <linux/init.h>#include <linux/module.h>#include <linux/delay.h>#include <linux/errno.h>#include <linux/sched.h>#include <linux/types.h>#include <linux/wait.h>#include <linux/spinlock.h>#include <linux/interrupt.h>#include <linux/mtd/mtd.h>#include <linux/mtd/nand.h>#include <linux/mtd/partitions.h>#include <linux/mtd/nand_ecc.h>#include <linux/dma-mapping.h>#include <linux/jiffies.h>#include <linux/platform_device.h>#include <linux/proc_fs.h>#include <linux/time.h>#include <linux/debugfs.h>#include <linux/module.h>#include <asm/uaccess.h>#include <asm/pgtable.h>#include <linux/kallsyms.h>#if 0protocol:echo "^justfortest1:1,#"  >  /sys/kernel/debug/anycallecho "^justfortest1:1#"  >  /sys/kernel/debug/anycallecho "^justfortest2:1,7788,#"  >  /sys/kernel/debug/anycallstep:make TARGET_PRODUCT=jrdhz75_gb2  SUBDIRS=./samples/ifs  modules insmod ifs.ko rmmod ifs lsmod#endiftypedef char (*my_f_0)();typedef char (*my_f_1)(int);typedef char (*my_f_2)(int,int);typedef char (*my_f_3)(int,int,int);typedef char (*my_f_4)(int,int,int,int);#define PRINT_ADDR(index)  printk(KERN_ERR"func: %s address is :%p\r\n","hello"#index,hello_##index) #define define_func(index)   my_f_##index pfun_##index#define select_func(index)   pfun_##index#define select_func_define(index)  my_f_##indexdefine_func(0);define_func(1);define_func(2);define_func(3);define_func(4);int atoi(const char *s);static int runAny( char * buf){    int i=1;    unsigned char * tempBuf;    unsigned char * addr;        unsigned char  addrLen;    unsigned long sum=0;    unsigned int temp=0;    unsigned char * para;    unsigned char * myPara[4]={0x00,0x00,0x00,0x00};    unsigned int  myPara_i[4];    unsigned char paraCount;    // the input format like this :  ^address:1,2,3,4,#    //     tempBuf=buf;    if(*tempBuf!='^')    {        printk(KERN_ERR"[anycall]bad begin char is %02x and should be %02x \r\n",*tempBuf,'^');        return -1;    }    printk(KERN_ERR"[anycall]  begin with ^ is right \r\n");    addr=++tempBuf;    printk(KERN_ERR"[anycall]addr is  %02x %02x %02x\r\n",addr[0],addr[1],addr[2]);    char  name[256]={0x00};     for(i=0;*tempBuf!=':';i++)    {                     name[i]=*tempBuf;       addrLen++;       tempBuf++;    }    //  判断输入的是函数名或者直接是函数的绝对地址         if(addr[0]=='0' && (addr[1]=='x' || addr[1]=='X') )    {         //get func addr   addr=addr+2;     //added for 0xaddress  printk(KERN_ERR"[anycall]addrLen is  %d \r\n",addrLen);  for(i=0;i<addrLen;i++)  {      unsigned int ii=addr[addrLen-1-i];   // this is key!!      if(ii>='0' && ii <='9')      {         ii=ii-'0';      }      else if(ii>='a' && ii <='f')      {         ii=ii-'a'+10;      }      ii=ii<<(4*i);      sum=ii+sum;   }    }    else    {        // get func name        printk(KERN_ERR"[anycall]get func name  and name is %s\r\n",name);        // 通过函数名,得到函数的地址sum=(unsigned long)kallsyms_lookup_name(name);    }       printk(KERN_ERR"[anycall] finaly func addr is :%08x\r\n",sum);    //////////////////////////////////////////////////////////////////////////////////    //get the func parameters    //unsigned char * myPara[4];    // 获取函数的参数    para=++tempBuf;    for(paraCount=0;*tempBuf!='#' && paraCount<4 ;)    {       if(*tempBuf==',')       {          *tempBuf=0X00;          tempBuf++;          myPara[paraCount]=para;          para=tempBuf;          paraCount++;          continue;       }       tempBuf++;    }    // debug parameters    for(i=0;i<(sizeof(myPara)/sizeof(myPara[0]));i++)    {       if(!myPara[i])       {          break;       }        printk(KERN_ERR"[anycall]para %d is %s \r\n",i,myPara[i]);       myPara_i[i]=atoi(myPara[i]);        printk(KERN_ERR"[anycall]para %d int is %d \r\n",i,myPara_i[i]);    }    ////////////////////////////////////////////////////       // 调用不同参数个数,目前最多只支持4个参数,且都是INT类型    switch(paraCount)    {        case 0:       printk(KERN_ERR"[anycall]pfun_0.....\r\n");       pfun_0=(my_f_0)sum;             pfun_0();              break;case 1:      printk(KERN_ERR"[anycall]pfun_1.....\r\n");             pfun_1=(my_f_1)sum;             pfun_1(myPara_i[0]);                      break;        case 2:      printk(KERN_ERR"[anycall]pfun_2.....\r\n");             pfun_2=(my_f_2)sum;             pfun_2(myPara_i[0],myPara_i[1]);                   break;        case 3:       printk(KERN_ERR"[anycall]pfun_3.....\r\n");             pfun_3=(my_f_2)sum;             pfun_3(myPara_i[0],myPara_i[1],myPara_i[2]);                break;        case 4:      printk(KERN_ERR"[anycall]pfun_4.....\r\n");             pfun_4=(my_f_4)sum;             pfun_4(myPara_i[0],myPara_i[1],myPara_i[2],myPara_i[3]);             break;    }        return 0;}// copy from preloader int atoi(const char *s){    unsigned val=0;         /* value we're accumulating */    int neg=0;                 /* set to true if we see a minus sign */    while (*s==' ' || *s=='\t') {        s++;    }    if (*s=='-') {        neg=1;        s++;    } else if (*s=='+') {        s++;    }    while (*s) {        unsigned digit;        digit = (*s - '0');        val = val*10 + digit;        s++;    }    if (neg) {        return -val;    }    return val;}static ssize_t anycall_write(struct file *file, const char __user *user_buf,      size_t size, loff_t *ppos){char buf[64];int buf_size;int ret=0;buf_size = min(size, (sizeof(buf) - 1));        //user拷贝数据到kernelif (strncpy_from_user(buf, user_buf, buf_size) < 0)return -EFAULT;buf[buf_size] = 0;if (ret < 0)return ret;// 逻辑处理        runAny(buf);        return size;}static const struct file_operations anycall_fops = {.owner= THIS_MODULE,.write= anycall_write,};static int __init anycall_init(void){     struct dentry *dentry;        //创建debugfs文件节点        //你可以在 /sys/kernel/debug/cancall 找到它dentry = debugfs_create_file("anycall", S_IRUGO, NULL, NULL,     &anycall_fops);printk(KERN_ERR "[anycall]install  anycall  !!!!\n");;return 0;}static void __exit anycall_exit(void){ printk(KERN_ERR "[anycall]remove anycall  !!!!\n");}module_init(anycall_init)module_exit(anycall_exit)MODULE_LICENSE("GPL");


在简单介绍下使用步骤:

1  编译上述模块

                加入上述模块名字为 : anycall.c

                放在  kernel/drivers/char/anycall

                          kernel/drivers/char/anycall/下的makefile   中添加   : obj-m +=anycall.c

2     kernel/drivers/char/ 下makefile 中添加 : obj-m += anycall/    (注意反斜杠的意思代表目录的意思,千万不能少)

3     insmod anycall.ko

 good luck !

 需要完整模块代码,可以给我留邮箱地址:) 

 


 

原创粉丝点击