一个hello程序的android内核模块编译,Android内核模块编译执行

Author: GeneBlue

0X01 前言

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

0X02 编写

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

#include

#include

#include

#include

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中做如下配置:

0818b9ca8b590ca3270a3433284dd417.png

0818b9ca8b590ca3270a3433284dd417.png

如果不开启该选项就直接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

0818b9ca8b590ca3270a3433284dd417.png

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

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

# 加载内核模块

# insmod hello.ko

# 查看加载的内核模块

# lsmod

0818b9ca8b590ca3270a3433284dd417.png

0X05 参考

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值