当前位置:   article > 正文

Android内核模块编译执行_安卓驱动内核ko编译

安卓驱动内核ko编译

Author: GeneBlue

0X01 前言

内核驱动是漏洞的高发区,了解Android驱动代码的编写是分析、利用驱动漏洞的基础。本文以一个“hello”驱动为例,简单介绍内核驱动编写、编译的基本过程,包括内核模块的内建编译动态加载方式的编译

0X02 编写

在 ./goldsifh/drivers 文件夹下新建hello目录,在hello目录中新建hello.c文件:

  1. #include <linux/module.h>
  2. #include <linux/kernel.h>
  3. #include <linux/fs.h>
  4. #include <linux/miscdevice.h>
  5. MODULE_LICENSE("GPL");
  6. MODULE_AUTHOR("GeneBlue");
  7. MODULE_DESCRIPTION("Hello Kernel Device");
  8. MODULE_VERSION("1.0");
  9. #define CMD_COMMAND 0x1336
  10. long hello_ioctl(struct file *filp, //ioctl函数
  11. unsigned int cmd,
  12. unsigned long arg){
  13. switch(cmd){
  14. case CMD_COMMAND:
  15. printk("Hello Module hello_ioctl() exced");
  16. break;
  17. default:
  18. printk("Hello Module unknown ioctl cmd");
  19. }
  20. return 0;
  21. }
  22. struct file_operations hello_fops = { //设备的操作函数指针表
  23. unlocked_ioctl: hello_ioctl
  24. };
  25. static struct miscdevice hello_device = { //注册为misc设备的基本属性
  26. minor: MISC_DYNAMIC_MINOR,
  27. name: "hello",
  28. fops: &hello_fops,
  29. mode: 777
  30. };
  31. static int __init hello_begin(void){
  32. int ret;
  33. ret = misc_register(&hello_device); //注册为misc设备
  34. if(ret)
  35. printk("Failed to register misc device");
  36. else
  37. printk("Hello Module successfully loaded");
  38. return ret;
  39. }
  40. static void __exit hello_exit(void){
  41. int ret = misc_deregister(&hello_device); //设备卸载
  42. if(ret)
  43. printk("Hello module exit");
  44. }
  45. module_init(hello_begin); //模块初始化函数
  46. module_exit(hello_exit); //模块卸载函数

写驱动模块时都要包含 module.h 头文件,该头文件定义了一些编写模块时常用宏或函数  kernel.h 提供常用的内核函数,如printk(); fs.h  提供文件表和文件结构,如file_operations; miscdevice.h 提供注册为misc设备的常用函数

0X03 编译

在编译之前,要确保下载下来的内核代码已经可以顺利地编译运行,具体可以参考这里

在hello目录中,要增加Makefile配置文件用于编译。在Makefile中添加:

obj-y +=  hello.o

表示内建编译,即直接编译到内核文件zImage中。然后在 goldfish/drivers/Makefile包含新建的驱动设备

obj-y += hello/

这样,再次编译内核后驱动设备即可包含在内核中


有的时候,我们需要在手机中编写可动态加载的驱动模块可动态加载模块非常便于调试,在 kmsg可直接看到调试信息,这个时候需要重新编译手机内核开启内核的动态加载属性。在编译的内核的时候,使用

make menuconfig

命令,并在menuconfig中做如下配置:


menuconfig

menuconfig

如果不开启该选项就直接 insmod 加载hello.ko,一般情况下都会报如下错误:

insmod: init_module 'hello.ko' failed (Function not implemented)


[内建编译的情况]--编译完内核之后,还需要将内核拷贝到aosp的源码中替换掉默认的内核文件,在我的Android源码中默认的内核文件存放在如下路径中:

/android-4.4.4_r1/device/lge/hammerhead-kernel/zImage-dtb

编译Android源码生成新boot.img文件,然后只要将boot.img刷入到手机即可。


完成内核的准备工作之后,下面就要编译动态加载模块hello.ko,依然是上述的  hello.c  文件,在任意位置建一个目录,拷贝hello.c并编写  Makefile  如下:

  1. obj-m := hello.o
  2. KERNELDIR := /home/geneblue/Android/Source/kernel/msm/
  3. PWD :=$(shell pwd)
  4. ARCH=arm
  5. CROSS_COMPILE=/home/geneblue/Android/Source/tsinghua_aosp/android-4.4.4_r1/prebuilts/gcc/linux-x86/arm/arm-linux-androideabi-4.6/bin/arm-linux-androideabi-
  6. CC=$(CROSS_COMPILE)gcc
  7. LD=$(CROSS_COMPILE)ld
  8. CFLAGS_MODULE=-fno-pic
  9. modules:
  10. make -C $(KERNELDIR) ARCH=$(ARCH) CROSS_COMPILE=$(CROSS_COMPILE) M=$(PWD) modules
  11. clean:
  12. rm *.o *.ko *.mod.c *.order *.symvers

注意,Makefile中要加上  CFLAGS_MODULE=-fno-pic  选项,不然insmod加载编译好的  hello.ko relocation节  会错误:

  1. insmod: init_module 'hello.ko' failed (Exec format error)
  2. kmsg:
  3. <3>[ 1646.589131] hello: unknown relocation: 27

最后,使用  make  命令即可编译生成正确的   hello.ko   文件。

0X04 运行

使用模拟器来加载新编好的内核,并在 adb shell  中,root权限下查看新编的驱动:

  1. # root权限下
  2. # ll /dev | grep hello
  3. # dmesg | grep Hello

内建编译

这样,一个最简单的设备驱动已经可以正确运行了。


将 hello.ko 文件 push  到手机中,root权限下用 insmod 来加载即可。

  1. # 加载内核模块
  2. # insmod hello.ko
  3. # 查看加载的内核模块
  4. # lsmod

模块编译

0X05 参考


声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/Monodyee/article/detail/327215
推荐阅读
相关标签
  

闽ICP备14008679号