Android系统内核提取及逆向
2021-04-05 18:58:00 Author: mp.weixin.qq.com(查看原文) 阅读量:131 收藏


本文为看雪论坛优秀文章

看雪论坛作者ID:These-us

前言

该部分主要是涉及到Android设备的内核提取与逆向分析相关的知识点,通常是用于对内核对底层文件的分析。原本计划是从提取到逆向分析再到POC编写一条龙服务,能力有限,漏洞分析和POC编写就留到以后再分享。

一、 boot.img的结构

在介绍boot文件之前,简单阐述一下android系统的分区。
 

比较重要的几个分区如下:

(1) /boot分区:该分区主要包含android kernel镜像和ramdisk(一种将RAM模拟为硬盘的技术,提高访问速度)。
 
(2) /system分区:该分区主要存放Android框架及其相关配置,包含系统预装的app。
 
(3)/recovery分区:该分区主要是备份的分区。
 
(4) /data 用户数据的存储区域。
/data/app/com.xxxx/ 以包名存放应用安装文件,包括base.apk /lib/data/data/com.xxxx/ 存放应用数据,包括sp、db等/data/dalvik-cache 以包名存放优化过的应用dex文件
(5) /cache分区:Android系统缓存区域,保存系统最常访问的数据和应用程序。
 
(6) /misc分区:此分区包含一些系统功能设置开关和数据,比如USB设置。
 
(7) sdcard分区:外置存储分区。
 
(8) /vendor分区:厂商定制的分区,厂商的某些系统升级可以通过这个分区来实现。

1. boot文件

boot.img就是android系统的Linux内核主要的镜像文件,在该文件中大致包含boot header,kernel,ramdisk。
 
boot.img文件跳过2K的文件头之后,包含两个gz压缩包,一个是boot.img-kernel.gz Linux内核,一个是boot.img-ramdisk.cpio.gz,然后加上ramdisk文件。
 
大致的结构图如下:
值得注意的是我们的boot.img文件在针对kernel是有不同压缩算法来进行压缩的,在后面的实战环节中是有相关的案例。

二、 提取内核及分离

1. 提取

提取内核可以从升级包中提取,也可以选择从Android手机中提取内核,android手机中提取内核的方法百度一大堆,这里就不展开。

2. 分离

分离内核通常会使用到binwalk、imgtool、或者其他集成工具,建议分离在Linux环境中进行。
 
使用binwalk查看相关的结构:
一个boot.img文件在前面的章节中介绍过,会大致有三个结构。而我们的内核文件则会使用压缩算法进行压缩,我们需要分离出这三个部分的文件,我们可以使用imgtool或者perl脚本进行分离。

3. 我们先来看perl脚本集合工具

如下图:
可以查看到镜像文件的大小还有其他的一些基础信息。
 
split_boot 脚本
 
该脚本的功能就是分解boot.img或者recovery.img文件。
 
解压后的文件目录如下:
boot/ramdiskboot.img-kernelboot.img-ramdisk.cpio.gz
其中unpack_ramdisk和repack_ramdisk是对ramdisk进行解包和打包的工具脚本。
 
在我们对boot.img文件提取后还需要查看生成的boot.img-kernel文件的内容,大部分提取出来的都会存在压缩算法,gzip、lz4等等压缩,我们再进行解压才能够得到我们用于内核分析。
lz4 -d filename

4. imgtool工具解包

该工具需要自己编译一下。
 
工具链接:https://github.com/kerastinell/imgtool
 
编译之后就可以使用工具进行解包。
 
解包之后的文件:
与上一个工具的解包后的文件是相似的,我们依然需要查看相应内核文件的压缩算法,依然需要使用解压工具进行解压即可。

5. 解包实例分析

实例1:固件 nexus6p手机中脱的内核镜像 

在拿到一个img文件我们可以使用file命令去查看一个基础信息。
基础信息对我们提取内核并没有多大帮助,如果后期设计到修改内核文件,重新打包boot.img这些信息对我们来讲就是有用。
 
接下来我们可以使用binwalk工具查看一下文件类型。
 
可以看出boot中含有两个使用gzip压缩的文件,在前面介绍boot.img文件结构的时我们就讲过含有三个压缩包文件。
 
我们可以尝试使用暴力提取的方法,直接使用binwalk提取我们的内核文件。
会生成四个文件(实际上是三个),我们依次查看文件类型。
第一个文件就是我们的内核文件,第二个是我们的。
 
第二种办法使用比较官方的解法,也是比较正式的解法来剥离我们的内核。
 
该方法会使用到上面提供工具进行解包。
解出来的三个文件实际上是很官方的三个文件,在这里验证了我们前面的理论知识。
 
我们识别一下我们的kernel文件。
 这就是一个使用gzip压缩的文件,那我们直接解压我们的文件就可以拿到我们的内核文件。这样的形式直接使用binwalk当然可以暴力拉出kernel文件,但是后面的例子就不一定可以暴力拉出kernel文件。
解压后可以拿到同样的文件。

实例2:固件 pixel-kernel

 
第二个固件我们查看信息会发现采用了LZ4压缩。
这个时候你binwalk暴力提取并不会有什么好的发现,没有办法分离干净。
得到的两个文件,第一个并不是kernel包含的地方,第二个文件中使用binwalk查看是有内核信息,我们继续使用binwalk暴力提取,会发现生成如下文件:
然后你再去binwalk,一样的结果。
 
这样我们提取内核文件就没办法使用暴力破解的方式。
 
我们来看官方一点的提取方法,除了上面使用的imgtool外,还可以依然使用实例1中的方法。
可以看出有LZ4压缩算法管理者我们的内核文件,我们只能先解LZ4算法再进行提取。
 
那我们就使用lz4工具解压。
解压之后的问价那我们查看就成功提取到我们的kernel文件啦。

实例3:固件 某嵌入式设备内核

查看基础文件类型,我们可以看到另外一个新的压缩算法LZO。
 
同样我们可以使用binwalk暴力破解。
这个76C5文件就是我们想要的文件。
 
当时使用比较正式的方法也是可以进行提取的,这里就不过多讲解。

三、 逆向分析

在逆向分析过程中,我们加载上面分离出来的内核文件。
 
工具使用:
 
IDA pro 7.5
 
droiding(https://github.com/nforest/droidimg)
 
通常的做法是使用IDA加载二进制文件,根据我们系统架构来选择相应的分析。
选择处理器类型,然后在设置内核起始地址为:
0xC0008000(0xFFFFFFC0008000)
这样就将二进制文件加载到IDA中,但是我们的IDA并不会自动给我们进行反编译分析,需要我们手动进行转换成代码文件,或者我们也可以使用脚本进行。
 
同时,这样加载的二进制内核文件并没有符号表,我们还需要去提取符号表。
 
我们现在已经root过的手机中查询我们的符号表。
cat /proc/kallsyms >> kernel_synbols.txt
然后使用python脚本导入IDA中。
import idaapiimport idautilsimport idc
def do_rename(l): splitted = l.split() straddr = splitted[0] strname = splitted[2].replace("\r", "").replace("\n", "")
eaaddr = int(straddr, 16) idc.MakeCode(eaaddr) idc.MakeFunction(eaaddr) idc.MakeNameEx(int(straddr, 16), strname, idc.SN_NOWARN)
if __name__ == "__main__": Message("Hello IDC") f = open( "D:\\TOP1_201601\\android\\exploits\\kernel_symbols.txt", "r") for l in f: do_rename(l) f.close()
就可以完成我们的加载,但是这样的分析方式比较的复杂,我们在载入二进制内核文件是会出现IDA不分析的提示,需要我们手动去选择分析点。
 
使用IDA插件droiding
 
该插件的功能可以自动的解析我们的内核文件,并对符号进行重命名,使用的效果非常不错,根据官方文档我们将vmlinux.py文件放在IDAxxx\loaders\文件下就可以在加载二进制内核是多一个选项。
这样就只需要等待加载完毕就可以直接进行内核分析。
我们的内核文件就已经被完全反编译出来了,可以进行漏洞分析的逆向分析。

四、实战内核提权

实战环节我们就使用相关的未打补丁的内核文件进行实战分析并简单的验证我们的漏洞。

案例1:固件 某嵌入式设备内核

Linux-kernel版本:3.0.35-g4113e5c-dirty
 
在我们使用上面的技术手段拿到我们的kernel文件,直接载入含有vmlinux查看的IDA中进行逆向分析。
 
我是在线去搜寻一下该版本的内核存在哪些历史CVE。
 
https://www.cvedetails.com/vulnerability-list/vendor_id-33/product_id-47/version_id-135854/opov-1/Linux-Linux-Kernel-3.0.35.html
每一个已经修复的CVE都存在补丁,我们检测漏洞的存在与否首先是去确认kernel文件是否打补丁,然后构造poc去验证漏洞的存在性,如果我们是做漏洞安全研究的,还会去梳理漏洞触发的原理,检查补丁是否准确有效,是否可以绕过补丁达到发掘新漏洞的目的。
 
我们以CVE-2014-3153为例来进行分析。

补丁分析

首先该漏洞年代比较久远,算是比较经典的漏洞类型,原理我们在后面进行剖析,现在我们先确认我们的版本中是否存在该漏洞。
 
从打补丁的位置进行分析。
总共有三个地方进行了修改,我们在IDA中去分析这三个函数。
 
我们在我们待分析的固件中查看到并没有对该地方进行修复。
在我们修复的kernel文件中是这样存在的。
除此之外,我们查看一下第二个补丁点,进一步确认漏洞的修复性。
 
而我们的第二个补丁位置如下:
 
未打补丁:
而我们来看看打过补丁的位置:
经过一步一步的去逆向补丁位置,我们可以初步认定该kernel是未打补丁。
 
接下来就是构造该漏洞的POC进行漏洞验证。
 
原则上,想要写出POC是要在理清楚漏洞触发的原理才能够poc的编写。当然,我们同样可以使用公开的poc来进行漏洞的验证。

POC构造:

http://blog.topsec.com.cn/cve2014-3153/
 

五、参考

https://bbs.pediy.com/thread-209387.htm

https://www.cnblogs.com/kevingrace/p/10271581.html

https://juejin.cn/post/6844903993924141069

https://www.cnblogs.com/0xJDchen/p/6007938.html

- End -

看雪ID:These-us

https://bbs.pediy.com/user-home-849527.htm

  *本文由看雪论坛These-us 原创,转载请注明来自看雪社区。

# 往期推荐

公众号ID:ikanxue
官方微博:看雪安全
商务合作:[email protected]

球分享

球点赞

球在看

点击“阅读原文”,了解更多!


文章来源: http://mp.weixin.qq.com/s?__biz=MjM5NTc2MDYxMw==&mid=2458383274&idx=1&sn=da5e0f7c3ae844be72fe7d866ddc8e93&chksm=b180c32086f74a362f32d3b9fd62cfded50ec9f26474c2dbb8f939fca3262ea5dc1152b43069#rd
如有侵权请联系:admin#unsafe.sh