查看原文
其他

内核篇加载内核模块(Android10)

哆啦安全 2022-08-17

The following article is from 卓码星球 Author QDroid88888

一、 开发前期准备

本文中使用的是linageOs源码中下载的oneplus3 安卓10内核源码进行研究测试。交叉编译链使用的是linageOs源码中的交叉编译链。

lineageOs源码中oneplus3内核源码位置路径:

/home/qiang/lineageOs/kernel/oneplus/msm8996

lineageOs源码中交叉编译目录位置路径:

/home/qiang/lineageOs/prebuilts/gcc/linux-x86

为了方便研究测试,不破坏lineageOs中的内核源码结构。我新建一个目录专门存放内核源码、内核模块源码。并将内核源码拷贝到该目录。

本文后续测试的内核源码目录路径:

 home/qiang/myproject/kernel/oneplus3/msm8996

本文后续内核模块编写存放目录路径:

/home/qiang/myproject/kernel/oneplus3/modules

二、编译内核源码

  1. 找到oneplus3设备的内核源码配置

安卓源码中device/厂商/手机型号/BoardConfig.mk文件中配置了内核源码路径和编译配置文件。因此在device/oneplus/oneplus3/BoardConfig.mk中存放了相关的内核配置信息,如下所示:

BOARD_KERNEL_BASE := 0x80000000
BOARD_KERNEL_PAGESIZE := 4096
BOARD_KERNEL_TAGS_OFFSET := 0x02000000
BOARD_RAMDISK_OFFSET     := 0x02200000
BOARD_KERNEL_IMAGE_NAME := Image.gz-dtb
TARGET_KERNEL_SOURCE := kernel/oneplus/msm8996
TARGET_KERNEL_CONFIG := lineageos_oneplus3_defconfig

以上TARGET_KERNEL_CONFIG变量指定了oneplus3内核的编译配置文件名为:lineageos_oneplus3_defconfig

在内核源码中编译配置文件一般存放在路径arch/处理器平台/configs下面。由于一加3手机为arm64,所以在路径arch/arm64/configs下找到配置文件lineageos_oneplus3_defconfig。如下所示:

qiang@ubuntu:~/myproject/kernel/oneplus3/msm8996/arch/arm64/configs$ pwd
/home/qiang/myproject/kernel/oneplus3/msm8996/arch/arm64/configs

qiang@ubuntu:~/myproject/kernel/oneplus3/msm8996/arch/arm64/configs$ ls -la lineageos_oneplus3_defconfig
-rw-rw-r-- 1 qiang qiang 15001 1月   3 23:00 lineageos_oneplus3_defconfig
  1. 为编译配置添加内核可加载、卸载选项

由于编译内核模块的时候需要依赖于已经编译过的内核输出,并且内核需要配置为可加载才能正常编译内核模块。所以需要修改一下arch/arm64/configs/lineageos_oneplus3_defconfig,添加如下配置项。

# 开启内核模块可加载
CONFIG_MODULES=y
# 开启内核模块可卸载
CONFIG_MODULE_UNLOAD=y
  1. 配置编译内核源码脚本

脚本如下

# 设置编译平台为64位arm
export ARCH=arm64
export SUBARCH=arm64
# 配置arm64的交叉编译路径
export PATH=/home/qiang/lineageOs/prebuilts/gcc/linux-x86/aarch64/aarch64-linux-android-4.9/bin:$PATH
# 配置32位arm的交叉编译路径
# 测试过程中32位的不设置居然编译不过
export PATH=/home/qiang/lineageOs/prebuilts/gcc/linux-x86/arm/arm-linux-androideabi-4.9/bin:$PATH

# 设置64位交叉编译工具前缀
# 这个前缀其实就是交叉编译链路径/home/qiang/lineageOs/prebuilts/gcc/linux-x86/aarch64/aarch64-linux-android-4.9/bin 下面的工具的公共前缀
export CROSS_COMPILE=aarch64-linux-android-

# 设置32位交叉编译工具前缀
# 这个前缀其实就是交叉编译链路径/home/qiang/lineageOs/prebuilts/gcc/linux-x86/arm/arm-linux-androideabi-4.9/bin 下面的工具的公共前缀
export CROSS_COMPILE_ARM32=arm-linux-androideabi-

# 通过make命令生成编译配置文件.config
# O=out指定输出目录  lineageos_oneplus3_defconfig:这个是oneplus3的内核编译配置
make  O=out lineageos_oneplus3_defconfig

#  执行内核编译
make -j2 O=out ARCH=arm64

以上脚本在终端难的一个一个的输入,我将上面的弄成一个make.sh文件,到时候直接执行。make.sh内容如下:

#!/bin/bash

# 切换到内核源码根目录去 
cd ./msm8996
make mrproper
make clean
export ARCH=arm64
export SUBARCH=arm64
export PATH=/home/qiang/lineageOs/prebuilts/gcc/linux-x86/aarch64/aarch64-linux-android-4.9/bin:$PATH
export PATH=/home/qiang/lineageOs/prebuilts/gcc/linux-x86/arm/arm-linux-androideabi-4.9/bin:$PATH
export CROSS_COMPILE=aarch64-linux-android-
export CROSS_COMPILE_ARM32=arm-linux-androideabi-
make -j2 O=out lineageos_oneplus3_defconfig
make -j2  O=out ARCH=arm64

在终端执行make.sh之后就可以看到编译内核了,如下所示:

qiang@ubuntu:~/myproject/kernel/oneplus3$ ./make.sh 
make[1]: Entering directory '/home/qiang/myproject/kernel/oneplus3/msm8996/out'
  GEN     ./Makefile
  HOSTCC  scripts/basic/fixdep
  HOSTCC  scripts/kconfig/conf.o
  HOSTCC  scripts/kconfig/zconf.tab.o
  HOSTLD  scripts/kconfig/conf

编译完成之后,可以在目录/home/qiang/myproject/kernel/oneplus3/msm8996/out下面找到编译产生的文件和内核镜像。

三、编写helloworld模块

此处编写一个简单的HelloWorld模块进行研究测试。

  1. 创建helloworld.c模块源文件

文件代码如下:

#include <linux/init.h>
#include <linux/module.h>
#include <linux/sched.h>
static int __init hello_init(void){
   printk(KERN_ALERT "Hello World!\n");
   return 0;
}
static void __exit hello_exit(void){
   printk(KERN_ALERT "See You,Hello World!\n");
}
module_init(hello_init);
module_exit(hello_exit);
  1. 创建模块编译配置文件Makefile

Makefile如下:

# 设置内核源码编译的输出目录
KERNEL_OUT=/home/qiang/myproject/kernel/oneplus3/msm8996/out
# 设置arm64交叉编译链工具路径
TOOLCHAIN=/home/qiang/lineageOs/prebuilts/gcc/linux-x86/aarch64/aarch64-linux-android-4.9/bin/aarch64-linux-android-
# 设置arm32交叉编译链工具路径
TOOLCHAIN32=/home/qiang/lineageOs/prebuilts/gcc/linux-x86/arm/arm-linux-androideabi-4.9/bin/arm-linux-androideabi-
# 设置模块
obj-m := helloworld.o
# 编译命令配置 
all:
 make ARCH=arm64 CROSS_COMPILE_ARM32=$(TOOLCHAIN32)  CROSS_COMPILE=$(TOOLCHAIN) -C $(KERNEL_OUT) M=$(shell pwd)  modules
# 清理编译命令
clean:
 make -C $(KERNEL_OUT) M=$(shell pwd) clean
  1. 在helloworld模块目录执行make命令进行编译

编译如下:

qiang@ubuntu:~/myproject/kernel/oneplus3/modules/helloworldmodule$ pwd
/home/qiang/myproject/kernel/oneplus3/modules/helloworldmodule

qiang@ubuntu:~/myproject/kernel/oneplus3/modules/helloworldmodule$ ls -la
total 16
drwxrwxr-x 2 qiang qiang 4096 1月   5 21:18 .
drwxrwxr-x 6 qiang qiang 4096 1月   5 21:17 ..
-rw-rw-r-- 1 qiang qiang  310 1月   5 21:06 helloworld.c
-rw-rw-r-- 1 qiang qiang  498 1月   5 21:08 Makefile

qiang@ubuntu:~/myproject/kernel/oneplus3/modules/helloworldmodule$ make
make ARCH=arm64 CROSS_COMPILE_ARM32=/home/qiang/lineageOs/prebuilts/gcc/linux-x86/arm/arm-linux-androideabi-4.9/bin/arm-linux-androideabi-  CROSS_COMPILE=/home/qiang/lineageOs/prebuilts/gcc/linux-x86/aarch64/aarch64-linux-android-4.9/bin/aarch64-linux-android- -C /home/qiang/myproject/kernel/oneplus3/msm8996/out M=/home/qiang/myproject/kernel/oneplus3/modules/helloworldmodule  modules
make[1]: Entering directory '/home/qiang/myproject/kernel/oneplus3/msm8996/out'
  CC [M]  /home/qiang/myproject/kernel/oneplus3/modules/helloworldmodule/helloworld.o
  Building modules, stage 2.
  MODPOST 1 modules
  CC      /home/qiang/myproject/kernel/oneplus3/modules/helloworldmodule/helloworld.mod.o
  LD [M]  /home/qiang/myproject/kernel/oneplus3/modules/helloworldmodule/helloworld.ko
make[1]: Leaving directory '/home/qiang/myproject/kernel/oneplus3/msm8996/out'

模块编译好之后就可以 adb push到手机,使用insmod加载模块进行测试验证了。以后就可以通过写内核系统hook模块进行系统调用内核层拦截、写netfileter hook模块进行网络管控等等操作。


您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存