Android内核模块编译执行
来源:互联网 发布:mac百度云客户端 编辑:程序博客网 时间:2024/05/21 00:45
Author: GeneBlue
0X01 前言
内核驱动是漏洞的高发区,了解Android驱动代码的编写是分析、利用驱动漏洞的基础。本文以一个“hello”驱动为例,简单介绍内核驱动编写、编译的基本过程,包括内核模块的内建编译和动态加载方式的编译。
0X02 编写
在 ./goldsifh/drivers 文件夹下新建hello目录,在hello目录中新建hello.c文件:
#include <linux/module.h> #include <linux/kernel.h> #include <linux/fs.h> #include <linux/miscdevice.h> MODULE_LICENSE("GPL"); MODULE_AUTHOR("GeneBlue"); MODULE_DESCRIPTION("Hello Kernel Device"); MODULE_VERSION("1.0"); #define CMD_COMMAND 0x1336 long hello_ioctl(struct file *filp, //ioctl函数 unsigned int cmd, unsigned long arg){ switch(cmd){ case CMD_COMMAND: printk("Hello Module hello_ioctl() exced"); break; default: printk("Hello Module unknown ioctl cmd"); } return 0; } struct file_operations hello_fops = { //设备的操作函数指针表 unlocked_ioctl: hello_ioctl }; static struct miscdevice hello_device = { //注册为misc设备的基本属性 minor: MISC_DYNAMIC_MINOR, name: "hello", fops: &hello_fops, mode: 777}; static int __init hello_begin(void){ int ret; ret = misc_register(&hello_device); //注册为misc设备 if(ret) printk("Failed to register misc device"); else printk("Hello Module successfully loaded"); return ret; } static void __exit hello_exit(void){ int ret = misc_deregister(&hello_device); //设备卸载 if(ret) printk("Hello module exit"); } module_init(hello_begin); //模块初始化函数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中做如下配置:
如果不开启该选项就直接 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 如下:
obj-m := hello.o KERNELDIR := /home/geneblue/Android/Source/kernel/msm/ PWD :=$(shell pwd) ARCH=arm 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- CC=$(CROSS_COMPILE)gcc LD=$(CROSS_COMPILE)ld CFLAGS_MODULE=-fno-pic modules: make -C $(KERNELDIR) ARCH=$(ARCH) CROSS_COMPILE=$(CROSS_COMPILE) M=$(PWD) modules clean: rm *.o *.ko *.mod.c *.order *.symvers
注意,Makefile中要加上 CFLAGS_MODULE=-fno-pic 选项,不然insmod加载编译好的 hello.ko relocation节 会错误:
insmod: init_module 'hello.ko' failed (Exec format error) kmsg: <3>[ 1646.589131] hello: unknown relocation: 27
最后,使用 make 命令即可编译生成正确的 hello.ko 文件。
0X04 运行
使用模拟器来加载新编好的内核,并在adb shell 中,root权限下查看新编的驱动:
# root权限下# ll /dev | grep hello# dmesg | grep Hello
这样,一个最简单的设备驱动已经可以正确运行了。
将 hello.ko 文件push 到手机中,root权限下用insmod 来加载即可。
# 加载内核模块# insmod hello.ko# 查看加载的内核模块# lsmod
0X05 参考
- 在Ubuntu上为Android系统编写Linux内核驱动程序
- Hello world kernel module for android & unknown relocation: 27 when insmod
- Android内核模块编译执行
- 编译Android内核模块
- 内核编译 & 模块编译
- 编译内核及内核模块
- 内核模块编译入门
- 内核模块编译说明
- 编译内核模块命令
- 编译内核模块
- linux内核模块编译
- Ubuntu内核模块编译
- 开始编译内核模块
- 编译内核模块
- 编译内核模块问题
- 内核模块及编译
- linux内核模块编译
- 内核模块的编译
- Linux内核模块编译
- 编译内核模块常见问题
- OpenJudge-Noi 1481 Maximum Sum
- Android NuPlayer要点详解
- java web 基础知识(一)
- 输入三个点的坐标,实现判断此三角形是不是直角三角形,并输出此三角形的周长。
- Nodejs异步编程二——Promise/A
- Android内核模块编译执行
- ML算法一:K-近邻算法
- babel总结
- Oracle中Merge into用法总结
- 最大公约数、最小公倍数
- Tomcat(二) Tomcat实现:Servlet与web.xml介绍 以及 源码分析Tomcat实现细节
- js-dom装载后异步写入的内容,无法绑定到事件
- PHP进阶
- 科锐课堂笔记:2017/2/24 代码风格规范等