前言:

调试Android程序的时候不可避免的会遇到一些恶心的反调试,为了一劳永逸的解决这些反调试问题,使用LKM模块来制作一个调试沙箱是一个很不错的想法,就像当年Windows平台上盛行一时的reload kernel一样。所以LKM是个好东西,但是默认情况,Andriod的Kernel是没有打开LKM支持的,我们需要重新配置内核选项让它支持LKM,一个比较好的办法就是使用内核源码配置内核选项,编译新内核并刷机,这篇文章记录了我的操作过程。

环境准备

  • Google Nexus 5X手机一部
  • Android 源码一份
  • Ubuntu 14.10

内核源码下载

  • 既然是5X的手机,我们需要根据官方的指导,找到适合我这个手机的源码,这里直接给出对照表:
  • 我的手机是 Nexus5X,也就是bullhead(手机插上电脑之后,adb shell之后,可以看到提示符部分显示的手机型号),于是根据表格第三列的提示,我们开始下载源码
  • 为了省去翻墙的麻烦,经过几番折腾,我把代码fork到了我的github中,在ubuntu系统中转到我的Android源码保存的目录,开始下载内核源码 git clone https://github.com/freakishfox/kernel_msm.git
  • 经过一段时间的等待,源码应该会clone完毕,进入 kernel_msm 目录,执行git branch -a | grep bullhead查看代码分支
  • 我直接选择第一个分支,然后把代码拉下来,使用如下命令操作:
  • git checkout remotes/origin/android-msm-bullhead-3.10-marshmallow-dr
  • 到这里代码就获取完毕了

编译内核

  • 经过上面一番折腾,我已经拿到了内核源码,下面准备进入编译阶段,现在我们进入内核代码目录 cd kernel_msm
  • 接着先执行一条比较重要的命令:export ARCH=arm64, 这条命令指定了我们要编译的内核的CPU架构,基于我手机的原因,我选择arm64
  • 我们的主要目的是要让内核支持LKM,所以在开始编译之前,我们来配置一下,执行命令:make menuconfig,打开图形化配置,通过空格+Tab键操作,配置结果如下:
  • 第一处是让内核支持LKM,第二处可以顺便设置一下,方便后续开发LKM的时候直接操作内核内存数据,而不用去管内存写保护,接着保存即可
  • 其实还有一个比较省事的办法就是直接 cp 目录下的 .config.old到.config
  • 接着我们设置一下编译需要的几个环境变量:
  • export PATH=PATH
  • export CROSS_COMPILE=aarch64-linux-android-
  • 这两个环境变量,一个告诉编译器交叉编译工具的路径,一个告诉编译器交叉编译工具的前缀名(这两个变量其实是编译脚本中使用的,如果不想导出,也可以直接修改编译脚本直接指定),贴一下我的环境:
  • 完毕之后,直接执行 make 进行编译;

内核刷到手机

  • 等待编译完成之后,会得到这样的结果:
  • 有了这个结果,我们就可以用编译好的结果来制作新的启动镜像了,也就是 boot.img
  • 我这里使用Android源码中的 make bootimage 命令来操作,这个命令默认会使用prebuilts中的qmenu-kernel来打包boot.img,所以在执行命令之前,先定义一下打包命令使用的内核路径,使用命令:export TARGET_PREBUILT_KERNEL=$你的内核目录/arch/arm/boot/zImage-dtb
  • 然后转到Android源码目录,执行 . build/envsetup.sh 命令,设置一下接下来编译用的环境,接着选择编译选项,lunch命令,我之前手机编译的系统是 AOSP-bullhead-userdebug, 我这里依然选择这个选项
  • 然后就是开始编译了, make bootimage
  • 经过一段时间的等待,会生成新的boot.img
  • 重启手机到 bootloader 界面,然后使用 fastboot flash boot boot.img命令刷机即可