之前写了如何从kernel Image文件中静态提取符号地址,后来就有就有朋友问道image文件怎么得到。其实这个已经有很多前辈总结过了。就简单说先
获取boot.img
boot.img 一般有两种方法拿到:
- 1.从厂商提供的刷机包中提取
这种方法很直观,介绍略 2.从手机中提取
首先在手机中找到boot对应的分区1ls /dev/block/platform/<soc>/by-name |grep boot然后用dd命令将对应分区dump出来即可
可以参考从Android设备中提取内核和逆向分析
解包boot.img
在Android源码中已经给出了boot.img的结构
代码位置: /system/core/mkbootimg/bootimg.h
所以,首先解析boot header
取得page_size,从第二个page开始读取kernel_size就可以获取到kernel文件了,但是取得的kernel有可能是压缩过的。还需要进一步处理
这里大致介绍一下kernel image文件的类型,首先编译出来的kernel是vmlinux,这是一个elf文件,但是由于kernel加载进内存执行的时候系统几乎还是一片空白的状态,是不能解析elf的。所以通常都用objcopy将vmlinux转换成bin文件,后面考虑到size问题,有可能还需要进行压缩。通常Android的kernel有这几种:
- Image -> vmlinux objcopy之后的bin文件
- Image.gz -> vmlinux objcopy之后的bin文件 再进行gzip压缩 (在bootloader阶段解压)
- zImage -> vmlinux objcopy之后的bin文件 再进行gzip压缩 再在前面部署自解压代码 (bootloader调用自解压代码解压)
- XXX-dtb -> 带有dtb后缀的kernel文件,是在后面追加了device tree数据的kernel
Image.gz实际上就是一个gzip文件,以\1f\8b\08开头
zImage 以8个\00\00\a0\e1开头,前面是自解压代码,image.gz文件接在后面,可以用\1f\8b\08定位
(PS:dtb数据的magic num是 \d0\0d\fe\ed)
定位到压缩后的kernel后 提取出来解压就得到Image文件了。
code:ImgExtractor
同时把ramdisk.img也提取了,用cpio处理即可
kernel文件静态分析的部分,就暂时告一段落,后面开始写bypass技术。