编译安卓Kernel内核

1.前言

1、好一段时间没有写安卓逆向相关的文章了,最近朋友发我一个apk说是让我研究一下怎么过掉apk的反调试,于是我就想起了之前看过的一篇关于如何编译Android Kernel内核过掉apk的的文章,我就参考教程实战一次,这里做下记录,分享给大家,也为自己以后需要的时候也好有个不时之需。

2、关于如何过掉apk反调试的解决方案度娘给的答案也是相对比较多的,目前主要是两种方式,一种就是基于boot.img 解包获取kernel二进制文件,然后用IDA修改相关检测逻辑。二就是编译Android 系统 Kernel源码然后替换boot.img 中的kernel文件来实现的,相比之下,前者对系统的环境要求不是很高,只需要解包boot.img然后用 IDA Pro工具修改就行了,而后者则需要系统安装arm交叉编译器,可能还需要搭梯子才能获取到Android Kernel源码而且编译过程中可能会遇到各种奇葩无数的坑,但优点是基于源码修改,逻辑比较清晰,修改也比较简单,而且还可以在源码的基础上添加自己额外的逻辑或者需求,最重要的是可以深入理解反调试的原理和实现。这里我主要是采用后者编译源码的形式来操作的。

2.编译环境

1.Nexus 6 Android 7.1.2
2.Kernel Version Linux version 3.10.73-gcbf66a6
3.Un

3.编译kernel内核

1.查看系统兼容版本。
sh-3.2# adb shell
angler:/ $ cat /proc/version                                                                                           
Linux version 3.10.73-gcbf66a6 ([email protected]) (gcc version 4.9.x-google 20140827 (prerelease) (GCC) ) #1 SMP PREEMPT Thu Nov 17 18:18:57 UTC 2016

这里gcbf66a6的 cbf66a6实际上就是对应的 git 仓库的branch(分支)short commit id,即commit提交版本id,下边会用到。

2.下载Android Kernel源码。

下载源码之前首先安装一些基本环境,其中包括Git、unzip、gcc相关等工具,如果你安装过可忽略此步操作。

$ sudo apt-get update
$ sudo apt-get install git-core gnupg flex bison gperf build-essential zip curl zlib1g-dev gcc-multilib g++-multilib libc6-dev-i386 lib32ncurses5-dev x11proto-core-dev libx11-dev lib32z-dev libgl1-mesa-dev libxml2-utils xsltproc unzip

然后说明一下,不同的系统内核下载的源码地址是不一样的,这里如何查看自己的手机内核类型,可以重启手机进入fastboot模式(adb reboot bootloader 获按电源键+音量减 开机即可,也可在手机设置关于中查看基本内核版本,不同品牌型号手机可能会略有差异这里仅供参考)如图

我这里是Nexus 6 angler,另外Android官方提供了不同开发板的内核地址,以下都是Android官方提供的代码git地址,没有梯子的同学可以尝试将https://android.googlesource.com/全部替换成https://aosp.tuna.tsinghua.edu.cn/即可。
1.exynos 项目包含适用于 Nexus 10 的内核源代码,可用作在 Samsung Exynos 芯片组上开展相关工作的着手点。

git clone https://android.googlesource.com/kernel/exynos

2.goldfish 项目包含适用于模拟平台的内核源代码。

git clone https://android.googlesource.com/kernel/goldfish

3.hikey-linaro 项目用于 HiKey 参考开发板内核源代码。

git clone https://android.googlesource.com/kernel/hikey-linaro

4.msm 项目包含适用于 ADP1、ADP2、Nexus One、Nexus 4、Nexus 5、Nexus 6、Nexus 5X、Nexus 6P、Nexus 7 (2013)、Pixel 和 Pixel XL 的源代码

git clone https://android.googlesource.com/kernel/msm

5.omap 项目用于 PandaBoard 和 Galaxy Nexus参考开发板内核源代码。

git clone https://android.googlesource.com/kernel/omap

6.samsung 项目用于 Nexus S参考开发板内核源代码。

git clone https://android.googlesource.com/kernel/samsung

7.tegra 项目适用于 Xoom、Nexus 7 (2012) 和 Nexus 9参考开发板内核源代码。

git clone https://android.googlesource.com/kernel/tegra

8.x86_64 项目包含 Nexus Player 的内核源代码。

git clone https://android.googlesource.com/kernel/x86_64

由于我这里手机是Nexus 6所有我下载msm库源码,这里不同的版本要下载不同的仓库源码。

下载完成之后,我们会惊奇的发现目录内没有任何文件,这是因为有些仓库地址master分支是没有任何代码的,需要我们切换到指定的分支才可以继续编译。我可以执行git branch -a 看下所有分支列表如图。
这里的分支名貌似有很规律的命名规则,即
andorid-项目名-内核类型-内核版本-系统版本别名(例 安卓7、8等)-系统版本(例.1、.2)
然后我们用之前获取到的cbf66a6(short commit id(显示的是实际的commit id的前7位)) 直接检出我们需要的代码的分支,执行如下命令。

git branch -r --contains 

这里由于我是Android7.2 所有我这里检出分支 origin/android-msm-angler-3.10-nougat-mr2 执行。

# git chekout -b 本地分支名 远程分支名
git checkout -b android-msm-angler-3.10-nougat-mr2 origin/android-msm-angler-3.10-nougat-mr2

到此Android Kernel源码就算是成功拉取下来了,接下来就是要准备编译源码了。

3.安装arm交叉编译器

这里唠叨几句,期初我按照百度上的文章拉取源码进行编译的时候,大部分文章编译的都是arm32位的kernel,而我编译的Kernel 是arm64位的,所以按照百度上的例子下载arm32位交叉编译器编译结果不想而知...就是各种奇葩错误。由于没有经验所以走了不少弯路,期初以为是源码有问题,还傻乎乎的去修改源码,折腾了许久,才发现是编译器搞错了,至于我为什么是arm64位的而不是百度上说的arm32位编译这里后边说。


如果你先编译Android系统的话你会惊奇的发现在Android Source里就已经包含了Linux系统Mac系统的交叉编译器,在 https://android.googlesource.com/platform/prebuilts/gcc/ 这里可以看的到。

这里由于我的编译环境是Ubuntu64为所以我选择 aarch64-linux-android-4.9(这里的aarch64即arm64,darwin即mac系统 ),这里有必要提醒一下,我期初为了方便直接选择的是 aarch64-linux-android-4.8,结果编译的时候会出现这种类似错误

Makefile:660: Cannot use CONFIG_CC_STACKPROTECTOR_STRONG: -fstack-protector-strong not supported by compiler
  CHK     include/config/kernel.release
  CHK     include/generated/uapi/linux/version.h
  CHK     include/generated/utsrelease.h
make[1]: `include/generated/mach-types.h' is up to date.
  CC      kernel/bounds.s
arm-linux-gnueabihf-gcc: error: unrecognized command line option ‘-fstack-protector-strong’
make[1]: *** [kernel/bounds.s] Error 1
make: *** [prepare0] Error 2

然后Google了一番发现是-fstack-protector-strong命令是在 gcc4.9之后加入的,所以选择了4.8自然就不行啦。
下载arm64编译器

#arm64编译器下载
$ mkdir gcc
$ cd gcc
$ git clone https://android.googlesource.com/platform/prebuilts/gcc/linux-x86/aarch64/aarch64-linux-android-4.9
#如果你是arm编译器则下载
$ git clone https://android.googlesource.com/platform/prebuilts/gcc/linux-x86/arm/arm-eabi-4.8
#或
$ git clone https://android.googlesource.com/platform/prebuilts/gcc/linux-x86/arm/arm-eabi-4.7

这里没有梯子的同学,也可按照上边的方法替换成https://aosp.tuna.tsinghua.edu.cn/清华镜像源。
下载之后配置系统环境变量

#export PATH=<你clone的gcc编译根目录>/bin:$PATH
export PATH=~/gcc/aarch64-linux-android-4.9/bin:$PATH

也可在将此环境变量配置到bash脚本中,这里就不多说了。到此arm交叉编译器就算是配置好了,这里说明一下Kernel编译所用的是 Python2.7 版本,如果你用的是Python3以上的话则还需要安装2.7版本且设置为默认版本(不同的版本的Kernel可能有所不同)。参考https://blog.csdn.net/qq_42693848/article/details/88900553这篇文章。
这里还需要注意下,Clone下载后编译器后默认是master分支,这里还需要切换到对应的分支,否则后边make编译的时候可能会有些 gcc编译指令找不到。

这里我切换到nougat-mr2-release分支执行

$ git checkout nougat-mr2-release origin/nougat-mr2-release

这里不同内核对应不同的分支,这里的分支命名规则是
系统别名(安卓7/8等)-版本-release release代表正式版,其他的可能是测试分支。由于我kernel源码选择的分支是 nougat-mr2 所以这里自然也要相对应。

4.编译Kernel源码

环境源码准备ok了,接下来就是编译了,可以安卓官网文档一次执行如下命令。

cd msm
#设置环境遍历arch编译器类型  这里 可能是 arm、arm64、x86 等
export ARCH=arm64
#指定编译器
export CROSS_COMPILE=aarch64-linux-android-
#初始化配置
make angler_defconfig
#编译源码
make

执行最后一步make之后我们等待编译完成就可以了。



这里解释下上文说的为什么编译器ARCH选择了arm64而不是arm,起初我设置的ARCH编译器是arm结果 执行 make angler_defconfig 的时候提示 angler_defconfig 找不到之类的错误,结果进入/msm/arch/arm/configs 发现确实没有angler_defconfig配置,但是在 /msm/arch/arm64/configs确实存在的,所以只能选择arm64了。
这里不同的内核版本可能会不同,这里仅供参考,避免少走弯路。

4.构建boot.img镜像

make编译之后生成 Image、Image.gz、Image.gz.dtb 三个文件(如果是arm编译,会生成 zImage、zImage.gz、zImage.gz.dtb文件,我这里是arm64所以是Image文件),接下来我们就可以用生成的 .dtb去构建 boot.img镜像,然后刷机了。这里的.dtb文件就是打包boot.img用的kernel文件

1.提取原boot.img
angler:/ # su
angler:/ # cd /dev/block/bootdevice/by-name
angler:/dev/block/bootdevice/by-name # ls -la
#导出boot.img
angler:/dev/block/bootdevice/by-name # dd if=/dev/block/mmcblk0p34 of=/data/local/boot.img

导出boot.img之后我们下载到电脑,然后解包,在替换我们之前事先编译好的kernel文件,在打包成boot.img就可以了。

angler:/dev/block/bootdevice/by-name # cp /data/local/boot.img /sdcard
$ adb pull /sdcard/boot.img

这里建议将导出的boot.img备份一下,如果刷机失败,我们在将备份的boot.img在刷回去就好了。

2.解包boot.img文件
$ unmkbootimg -i boot.img 
#我们获得了rebuild需要输入的指令, 之后要rebuild的时候要修改一下才能用。
#这里用自己的
 mkbootimg --base 0 --pagesize 4096 --kernel_offset 0x00008000 --ramdisk_offset 0x02000000 --second_offset 0x00f00000 --tags_offset 0x01e00000 --cmdline 'androidboot.hardware=angler androidboot.console=ttyHSL0 msm_rtb.filter=0x37 ehci-hcd.park=3 lpm_levels.sleep_disabled=1 boot_cpus=0-3 no_console_suspend buildvariant=user' --kernel kernel --ramdisk ramdisk.cpio.gz -o boot.img


然后我们将之前编译好的Image.gz.dtb移动到当前目录,并更名为kernel,覆盖解包生成的kernel文件。然后执行获取到的rebuild指令即可(切记备份好原boot.img文件)

 mkbootimg --base 0 --pagesize 4096 --kernel_offset 0x00008000 --ramdisk_offset 0x02000000 --second_offset 0x00f00000 --tags_offset 0x01e00000 --cmdline 'androidboot.hardware=angler androidboot.console=ttyHSL0 msm_rtb.filter=0x37 ehci-hcd.park=3 lpm_levels.sleep_disabled=1 boot_cpus=0-3 no_console_suspend buildvariant=user' --kernel kernel --ramdisk ramdisk.cpio.gz -o boot-new.img

这里生成的boot-new.img文件就是我们编译之后的镜像文件,然后刷入手机就可以了。

5.刷入boot镜像

#重启手机进入fastboot模式
$ adb reboot bootloader
#刷入boot镜像
$ fastboot flash boot boot-new.img
#重启手机
$ fastboot reboot

6.参考文章

1.https://source.android.com/setup/build/building-kernels-deprecated
2.https://se8s0n.github.io/2019/04/19/%E5%B0%9D%E8%AF%95%E7%BB%95%E8%BF%87TracePID%E5%8F%8D%E8%B0%83%E8%AF%95%E4%BA%8C%E2%80%94%E2%80%94%E4%BB%8E%E6%BA%90%E7%A0%81%E5%85%A5%E6%89%8B/
3.https://www.52pojie.cn/thread-917096-1-1.html
4.https://blog.csdn.net/qq_42693848/article/details/88900553

你可能感兴趣的:(编译安卓Kernel内核)