• 从android设备中提取内核


     

    背景

    CVE-2013-2597 是高通 msm_acdb 设备驱动的一个 copy_from_user 栈溢出,利用要用到ROP。f101的漏洞利用介绍中,用到几处Gadgets,显然要根据acdb_ioctl的栈布局进行构造。

    一个.ko模块加载到内核后,如何在内核中找到其对应汇编代码,一直比较迷惑,此文解决这个问题。

    参考

    1. http://blog.csdn.net/py_panyu/article/details/45114545 少仲博客
    2. http://blog.csdn.net/hu3167343/article/details/45507999 如果找不到boot的分区,参考莫灰灰博客(后来发现,这其实在《Android安全攻防权威指南》里的。)

    操作

    以下在Nexus 5设备操作。

    1)查看boot所有分区

    root@hammerhead:/ # ls -l /dev/block/platform/msm_sdcc.1/by-name |grep boot
    lrwxrwxrwx root     root              1970-02-12 17:31 aboot -> /dev/block/mmcblk0p6
    lrwxrwxrwx root     root              1970-02-12 17:31 abootb -> /dev/block/mmcblk0p11
    lrwxrwxrwx root     root              1970-02-12 17:31 boot -> /dev/block/mmcblk0p19
    root@hammerhead:/ #
    

    2)dump出boot.img

    root@hammerhead:/ # dd if=/dev/block/mmcblk0p19 of=/data/local/tmp/boot.img
    45056+0 records in
    45056+0 records out
    23068672 bytes transferred in 0.827 secs (27894403 bytes/sec)
    root@hammerhead:/ #
    

    简单验证一下dump出的boot.img文件:

    root@hammerhead:/ # busybox hexdump -C -n 200 /data/local/tmp/boot.img
    busybox hexdump -C -n 200 /data/local/tmp/boot.img
    00000000  41 4e 44 52 4f 49 44 21  20 41 80 00 00 80 00 00  |ANDROID! A......|
    00000010  30 9d 07 00 00 00 90 02  00 00 00 00 00 00 f0 00  |0...............|
    00000020  00 00 70 02 00 08 00 00  00 00 00 00 00 00 00 00  |..p.............|
    00000030  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
    00000040  63 6f 6e 73 6f 6c 65 3d  74 74 79 48 53 4c 30 2c  |console=ttyHSL0,|
    00000050  31 31 35 32 30 30 2c 6e  38 20 61 6e 64 72 6f 69  |115200,n8 androi|
    00000060  64 62 6f 6f 74 2e 68 61  72 64 77 61 72 65 3d 68  |dboot.hardware=h|
    00000070  61 6d 6d 65 72 68 65 61  64 20 75 73 65 72 5f 64  |ammerhead user_d|
    00000080  65 62 75 67 3d 33 31 20  6d 61 78 63 70 75 73 3d  |ebug=31 maxcpus=|
    00000090  32 20 6d 73 6d 5f 77 61  74 63 68 64 6f 67 5f 76  |2 msm_watchdog_v|
    000000a0  32 2e 65 6e 61 62 6c 65  3d 31 00 00 00 00 00 00  |2.enable=1......|
    000000b0  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
    *
    000000c0
    

    由 #define BOOT_MAGIC “ANDROID!” ,就是它了。

    3)分离 boot.img-kernel 与 boot.img-ramdisk.gz

    将boot.img下载到本地,使用split_bootimg.pl这个perl脚本拆分。

    split_bootimg.pl 地址:https://gist.github.com/MAGE001/07591653c9f9378d8ffb36b10814bc9f

    zzhiyuan@ubuntu:~/zImage$ ./split_bootimg.pl boot.img
    Page size: 2048 (0x00000800)
    Kernel size: 8405280 (0x00804120)
    Ramdisk size: 498992 (0x00079d30)
    Second size: 0 (0x00000000)
    Board name: 
    Command line: console=ttyHSL0,115200,n8 androidboot.hardware=hammerhead 
            user_debug=31 maxcpus=2 msm_watchdog_v2.enable=1
    Writing boot.img-kernel ... complete.
    Writing boot.img-ramdisk.gz ... complete.
    zzhiyuan@ubuntu:~/zImage$ 
    

    完成后,Android 内核就包含在 boot.img-kernel 中,但现在还不能用IDA分析,因为这是个gzip的自解压文件(注意不是标准gzip文件,还不能使用gunzip解压),需先将里面的gzip文件提取出来。

    还有一点,手机厂商可能使用自已的压缩算法,这里不一定都是gzip,需要根据特征码或者文档,选择合适算法解压。如果下面介绍的解压方法中,没有找到gzip头(00088b1f),多半是这个原因。

    4)解压 zImage

    首先找到其中的标准gzip偏移位置:

    zzhiyuan@ubuntu:~$ arm-linux-androideabi-objdump -EL -b binary -D -m armv5t boot.img-kernel |grep 00088b1f
        48b4:       00088b1f        andeq   r8, r8, pc, lsl fp
    

    将其dump出来,注意skip=18612是上面0x48b4的十进制:

    zzhiyuan@ubuntu:~$ dd if=boot.img-kernel of=zImage.gz bs=1 skip=18612     
    8386668+0 records in
    8386668+0 records out
    8386668 bytes (8.4 MB) copied, 9.1257 s, 919 kB/s
    zzhiyuan@ubuntu:~$ 
    

    将其解压:

    zzhiyuan@ubuntu:~/zImage$ gunzip zImage.gz 
    
    gzip: zImage.gz: decompression OK, trailing garbage ignored
    zzhiyuan@ubuntu:~/zImage$ ls
    zImage
    

    用IDA打开,看到已经可以分析。但由于缺少符号表,还是较难阅读。

    另外,加载基址选择0xC0008000,就可以与 /proc/kallsyms 中看到的符号地址对应了。

    5) IDA导入内核符号表(/proc/kallsyms )

    下面的链接,讲了内核没用ELF标准符号表的原因:缩减体积。因此需要我们自己在IDA中导入。少仲文章介绍了如何搜索内核,定位符号位置。我的Nexus 5已经root就不费事了。直接 # echo 0 /proc/sys/kernel/kptr_restrict :-p http://stackoverflow.com/questions/14800515/unknown-arm-linux-kernel-image-format/14811668#14811668

    首先通过 # cat /proc/kallsyms >> kernel_synbols.txt 导出内核符号表,其格式如下:

    ...
    c0103168 t vfp_single_fmsc
    c0103194 t vfp_single_fmac
    c01031c0 t vfp_single_fadd
    c0103304 t vfp_single_fsub
    

    编写Python脚本(import_symbols.py):

    import idaapi
    import idautils
    import idc
    
    def do_rename(l):
    	splitted = l.split()
    	straddr = splitted[0]
    	strname = splitted[2].replace("
    ", "").replace("
    ", "")
    
    	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()
    

    依次通过菜单栏的 File->Script file… 导入运行即可,运行后效果如下:

     

    Have Fun!

  • 相关阅读:
    first
    JavaEE(3)
    简明Python3教程 7.运算符和表达式
    简明Python3教程 6.基础
    简明Python3教程 5.第一步
    高级程序员和低级程序员的区别
    JavaEE(2)
    Java数据结构与算法(33)
    Java数据结构与算法(32)
    Java数据结构与算法(31)
  • 原文地址:https://www.cnblogs.com/gm-201705/p/9863974.html
Copyright © 2020-2023  润新知