因研究逆向工程需要编译多个Android源码和内核在Nexus5真机上运行。通过简书记录编译过程,所以不会针对单个功能做详细介绍,初次接触的同学可以按照下面流程一步一步来进行环境搭建,资源准备,真机编译。
源码编译
目标
- 编译Android4.4.4-r1源码及内核
- 编译Android6.0.1-r1源码及内核
硬件环境
- Ubuntu 14.0.4LTS
- LG Nexus5 手机
环境JDK搭建
关于不同版本安卓源码对JDK版本的要求,如下是官方的文字描述:
....
C. AOSP 中 Android 的 master 分支:Ubuntu - OpenJDK 8;Mac OS - jdk 8u45 或更高版本
D. Android 5.x (Lollipop) - Android 6.0 (Marshmallow):Ubuntu - OpenJDK 7;Mac OS - jdk-7u71-macosx-x64.dmg
E. Android 2.3.x (Gingerbread) - Android 4.4.x (KitKat):Ubuntu - Java JDK 6;Mac OS - Java JDK 6
F. Android 1.5 (Cupcake) - Android 2.2.x (Froyo):Ubuntu - Java JDK 5
...
所以编译Android 4.4.4需要 Java JDK 6, 编译Android6.0.1需要openJDK7
Java JDK 6已经无法通过apt-get install方式安装, oracle官方下载地址
Java JDK 6安装过程:
1 把下载的文件放到自己定义的地方.
2 修改权限
$chmod 777 jdk-6u45-linux-x64.bin
3 执行
$./jdk-6u45-linux-x64.bin
4 配置环境变量
$sudo gedit /etc/profile
##添加到profile中保存
JAVA_HOME=$jdk1.6自定目录/jdk1.6.0_45
JRE_HOME=$JAVA_HOME/jre
CLASSPATH=$CLASSPATH:$JAVA_HOME/lib:$JRE_HOME/lib
PATH=$PATH:$JAVA_HOME/bin:$JRE_HOME/bin:$JAVA_HOME/lib:$JAVA_HOME
5 使/etc/profile生效
$source /etc/profile
6 查看是否生效
$java –version
openJDK7 安装过程
终端上执行下面命令
$sudo apt-get install openjdk-7-jdk
正常情况下会安装到/usr/lib/jvm/java-7-openjdk-adm64/目录下
安装基础软件
$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 ccache
libgl1-mesa-dev libxml2-utils xsltproc unzip
安装Repo
1 创建目录
$ mkdir ~/bin
$ PATH=~/bin:$PATH
2 下载 Repo 工具
//使用了清华大学的镜像文件
$curl https://mirrors.tuna.tsinghua.edu.cn/git/git-repo > ~/bin/repo
$chmod a+x ~/bin/repo
同步源码
1 建立工作目录
$mkdir WORKING_DIRECTORY
$cd WORKING_DIRECTORY
2 初始化仓库
//WORKING_DIRECTORY 源码要放的目录
$mkdir WORKING_DIRECTORY
$cd WORKING_DIRECTORY
初始化特定的 Android 版本列表文件,本文选择了两个支持Nexus 5的版本
,此处使用清华大学的镜像文件。
//android-4.4.4_r1使用
$repo init -u https://aosp.tuna.tsinghua.edu.cn/platform/manifest -b android-4.4.4_r1
//android-6.0.1_r1使用
$repo init -u https://aosp.tuna.tsinghua.edu.cn/platform/manifest -b android-6.0.1_r1
如果提示无法连接到 gerrit.googlesource.com,参考链接
3 同步源码
$repo sync –j4
同步时间看大家自己网络情况,我的网络比较好,大约花了2个小时同步一个版本
4 下载驱动文件
首先查看源码分支列表,确定源码分支代号
5 下载驱动
访问https://developers.google.com/android/nexus/drivers#hikey(暂时没发现国内有镜像,如果有需要的话加我QQ3231549366)中找到对应设备与源码分支的硬件驱动。
下载对应版本的渠道文件,依次解压三个文件,得到的三个shell脚本文件,将其置于源码根目录中再依次执行三个脚本,执行操作前,它会让你阅读相关协议,协议比较多有8项,最后输入I ACCEPT即可。执行完成以后会在源码的主目录生成一个vendor目录。注意执行shell的顺序,我第一次编译的时候没按照顺序执行,刷完机发现屏幕显示有问题,具体原因就没去研究,解决方法:删除了vendor目录,按照顺序又执行了一遍,重新编译后一切正常。
初始化编译环境
1 执行配置
//终端执行
$source build/envsetup.sh
//输出信息
including device/asus/deb/vendorsetup.sh
including device/asus/flo/vendorsetup.sh
including device/asus/fugu/vendorsetup.sh
including device/generic/mini-emulator-arm64/vendorsetup.sh
including device/generic/mini-emulator-armv7-a-neon/vendorsetup.sh
including device/generic/mini-emulator-mips/vendorsetup.sh
including device/generic/mini-emulator-x86_64/vendorsetup.sh
including device/generic/mini-emulator-x86/vendorsetup.sh
including device/htc/flounder/vendorsetup.sh
including device/huawei/angler/vendorsetup.sh
including device/lge/bullhead/vendorsetup.sh
including device/lge/hammerhead/vendorsetup.sh
including device/moto/shamu/vendorsetup.sh
including sdk/bash_completion/adb.bash
2 选择编译类型
//终端执行
$lunch
//输出信息
You're building on Linux
Lunch menu... pick a combo:
1. aosp_arm-eng
2. aosp_x86-eng
3. aosp_mips-eng
4. vbox_x86-eng
5. aosp_hammerhead-userdebug
6. aosp_mako-userdebug
7. aosp_deb-userdebug
8. aosp_tilapia-userdebug
9. aosp_grouper-userdebug
10. aosp_flo-userdebug
11. mini_armv7a_neon-userdebug
12. mini_mips-userdebug
13. mini_x86-userdebug
14. aosp_manta-userdebug
Which would you like? [aosp_arm-eng]
//选择5, 因为Nexus5设备代号就是hammerhead,会出现下面的输出信息
#### make completed successfully ####
============================================
PLATFORM_VERSION_CODENAME=REL
PLATFORM_VERSION=4.4.4
TARGET_PRODUCT=aosp_hammerhead
TARGET_BUILD_VARIANT=userdebug
TARGET_BUILD_TYPE=release
TARGET_BUILD_APPS=
TARGET_ARCH=arm
TARGET_ARCH_VARIANT=armv7-a-neon
TARGET_CPU_VARIANT=krait
HOST_ARCH=x86
HOST_OS=linux
HOST_OS_EXTRA=Linux-4.2.0-27-generic-x86_64-with-Ubuntu-14.04-trusty
HOST_BUILD_TYPE=release
BUILD_ID=KTU84P
OUT_DIR=out
============================================
3 检查Java环境
//终端执行
$java –version
//Android 4.4.4 需要 Java JDK 6
//Android 6.0.1需要open JDK7
//有的时候大家通过update-alternatives命令切换当前JAVA环境。
//sudo update-alternatives --config java
//sudo update-alternatives --config javac
//sudo update-alternatives --config javaws
//envsetup.sh中会使用当前环境变量中JAVA_HOME指定的JDK,虽然Android 4.4.4有指定使用java6,最好还是通过修改/etc/profile中JAVA_HOME 指定jdk的版本,
编译
$make –j16
//j后面的参数取决于你电脑处理器的核心数,j=核心数*2
大约2-3个小时。
刷机
1 进入recovery模式
将Nexus5设备连接到电脑上,打开usb调试,输入$sudo adb reboot bootloader
手机就会进入recovery模式。
2 刷机
$fastboot flashall –w
//或者fastboot -w flashall 刷机的过程大概在一至两分钟左右,刷机结束后会自动开机。
内核编译
下载内核
当前工程目录下新建kernel目录,同步远程kernel代码仓库到本地
$git clone https://aosp.tuna.tsinghua.edu.cn/kernel/msm.git
//仓库文件大概有1.2G的大小,同步完成以后本地有文件夹msm
确认分支
$cd msm
$git branch -a
//终端会输出如下信息
.
.
.
remotes/origin/android-msm-hammerhead-3.4-kitkat-mr1
remotes/origin/android-msm-hammerhead-3.4-kitkat-mr2
remotes/origin/android-msm-hammerhead-3.4-kk-fr1
remotes/origin/android-msm-hammerhead-3.4-kk-fr2
remotes/origin/android-msm-hammerhead-3.4-kk-r1
remotes/origin/android-msm-hammerhead-3.4-l-preview
remotes/origin/android-msm-hammerhead-3.4-lollipop-mr1
remotes/origin/android-msm-hammerhead-3.4-lollipop-mr1.1
remotes/origin/android-msm-hammerhead-3.4-lollipop-release
remotes/origin/android-msm-hammerhead-3.4-m-preview
remotes/origin/android-msm-hammerhead-3.4-marshmallow
remotes/origin/android-msm-hammerhead-3.4-marshmallow-mr1
remotes/origin/android-msm-hammerhead-3.4-marshmallow-mr2
remotes/origin/android-msm-hammerhead-3.4-marshmallow-mr3
.
.
.
1 Android4.4.4_r1分支
remotes/origin/android-msm-hammerhead-3.4-kitkat-mr2
2 Android6.0.1_r1分支
按照设备代号,源码中的内核版本号,Android版本代号描述,有3个分支
remotes/origin/android-msm-hammerhead-3.4-marshmallow-mr1
remotes/origin/android-msm-hammerhead-3.4-marshmallow-mr2
remotes/origin/android-msm-hammerhead-3.4-marshmallow-mr3
理论上面这3个分支都可以使用,mr是"maintenance release"简写。因工作需要本文还是需要和源码中的kernel一致
3 通过官方提供的命令行获取
非 Nexus 5 (hammerhead)运行以下命令
$ dd if=kernel bs=1 skip=$(LC_ALL=C grep -a -b -o $'\x1f\x8b\x08\x00\x00\x00\x00\x00' kernel | cut -d ':' -f 1) | zgrep -a 'Linux version'
//Kernel在源码out/target/product/hammerhead/目录下
对于 Nexus 5 (hammerhead),请运行以下命令:
$ dd if=zImage-dtb bs=1 skip=$(LC_ALL=C od -Ad -x -w2 zImage-dtb | grep 8b1f | cut -d ' ' -f1 | head -1) | zgrep -a 'Linux version'
//zImage-dtb在源码/device/lge/hammerhead-kernel目录下
//Android4.4.4-r1输出信息
Linux version 3.4.0-gd59db4e (android-build@vpbs1.mtv.corp.google.com) (gcc version 4.7 (GCC) ) #1 SMP PREEMPT Mon Mar 17 15:16:36 PDT 2014
Linux version CIFS VFS Client for Linux<7>%s: sess setup type %
//Android6.0.1-r1输出信息
Linux version 3.4.0-g7717f76 (android-build@kpfi6.cbf.corp.google.com) (gcc version 4.8 (GCC) ) #1 SMP PREEMPT Wed Nov 4 21:42:24 UTC 2015
Linux version CIFS VFS Client for Linux<7>%s: sess setup type %d
Linux version 3.4.0-gd59db4e 文本中d59db4e是git commit版本号信息
Linux version 3.4.0-g7717f76 文本中7717f76是git commit版本号信息
4 在关于手机内核版本信息查看
5 在代码中或者adb中通过cat /proc/version信息查看
内核源码下载
//输入终端命令获取到对应的内核源码:
//Android4.4.4-r
$ git checkout d59db4e
或者
$ git checkout -b remotes/origin/android-msm-hammerhead-3.4-kitkat-mr2
//Android6.0.1-r
$ git checkout 7717f76
内核源码编译
设置环境变量
//需要设置环境变量可以在kernel源码根目录下build.config文件中查看
//Android6.0.1-r1
$export ANDROID_SRC_PATH=源码根目录
$export PATH=$ANDROID_SRC_PATH/prebuilts/gcc/linux-x86/arm/arm-eabi-4.8/bin:$PATH
$export ARCH=arm
$export SUBARCH=arm
$export CROSS_COMPILE=arm-eabi-
//Android4.4.4-r1
$export ANDROID_SRC_PATH=源码根目录
$export PATH=$ANDROID_SRC_PATH/prebuilts/gcc/linux-x86/arm/arm-eabi-4.6/bin:$PATH
$export ARCH=arm
$export SUBARCH=arm
$export CROSS_COMPILE=arm-eabi-
配置
$make hammerhead_defconfig
编译
$make
终端输出:Kernel: arch/arm/boot/zImage-dtb is ready 编译完成
使用zImage-dtb替换/device/lge/hammerhead-kernel/zImage-dtb文件重新编译源码,编译后boot.img的内核就是我们编译的内核,可以在手机的关于界面内核信息可以看到。
也可以通过如下文bootimg-tools针对当前编译后的boot.img重打包,毕竟重编译的时间太长了。
Boot.img重打包
bootimg-tools工具是一款基于mkbootimg开发的boot.img 解包重打包C语言工具,github地址:https://github.com/pbatard/bootimg-tools
1 下载编译bootimg-tools
//kernel/msm根目录终端命令行下执行
$mkdir bootimg-tools
$cd bootimg-tools
$git clone https://github.com/pbatard/bootimg-tools.git
$make
编译完成以后,在 makebootimg目录下生成了相应的二进制执行文件,将该二进制文件所在路径添加到 PATH路径中。
2 终端上执行解包:
$cd 源码目录/out/target/product/hammerhead/
$unmkbootimg –i boot.img
//执行完毕输出信息
/*
kernel written to 'kernel' (8451496 bytes)
ramdisk written to 'ramdisk.cpio.gz' (923769 bytes)
To rebuild this boot image, you can use the command:
mkbootimg --base 0 --pagesize 2048 --kernel_offset 0x00008000 --ramdisk_offset 0x02900000 --second_offset 0x00f00000 --tags_offset 0x02700000 --cmdline 'console=ttyHSL0,115200,n8 androidboot.hardware=hammerhead user_debug=31 maxcpus=2 msm_watchdog_v2.enable=1' --kernel kernel --ramdisk ramdisk.cpio.gz -o boot.img
*/
3 覆盖原来的kernel
把内核源码目录下生成的arch/arm/boot目录下的zImage-dtb拷贝到Android源码目录out/target/product/hammerhead下。
并改名为kernel(注意备份原始的kernel文件)
4 重打包
使用步骤2中输出的mkbootimg 命令
//ramdisk.cpio.gz boot.img 可以在命令上指定目录,例子是在当前目录下执行,所以不需要全路径
$cd 安卓源码目录/out/target/product/hammerhead/
$mkbootimg --base 0 --pagesize 2048 --kernel_offset 0x00008000 --ramdisk_offset 0x02900000 --second_offset 0x00f00000 --tags_offset 0x02700000 --cmdline 'console=ttyHSL0,115200,n8 androidboot.hardware=hammerhead user_debug=31 maxcpus=2 msm_watchdog_v2.enable=1' --kernel kernel --ramdisk ramdisk.cpio.gz -o boot.img
生成boot.img后,连接手机执行烧写
5 烧写
$ adb reboot bootloader
$ fastboot flash boot boot.img
总结
本文介绍了2个版本源码和内核编译,其它版本源码和内核版本类似,主要是如何确认细节部分文中也做了说明。
后续会写些逆向工程方面的学习资料,主要包含基础知识,相关工具介绍,逆向思维,主要是Android方面了。
参考文档:
1 https://source.android.com/source/requirements
2 http://blog.csdn.net/liu1075538266/article/details/51272398
3 https://mirrors.tuna.tsinghua.edu.cn/help/AOSP/