你们在聚安全挑战赛正式赛第三题中,遇到android app 远程控制的题目。咱们今天带你一探究竟,如何攻破这道题目。html
购物应用pwn (6分)android
环境:web
攻击过程:chrome
目标:Chrome浏览器点击连接,致使远程触发app的购买逻辑,app界面上显示“购买成功”。shell
评分标准:经过浏览器访问网页即达到控制app远程任意代码执行得6分,其中:json
攻击流程以下:浏览器
其中题目中要求“Chrome浏览器点击连接”,Chrome的官方文档规定了如何从连接发intent启功app,官方文档连接:https://developer.chrome.com/multidevice/android/intents 。反汇编ExamPwn.apk文件发现AndroidManifest.xml中果真有接受相关intent的内容。如图:安全
类LoginActivity先接受这个intent解析出账号密码并匹配,账号密码直接以明文硬编码在类LoginActivity中,反汇编直接能够看见。匹配正确后将intent中的url丢给类MainActivity。也就是说攻击者的网页至少以下:app
反汇编类MainActivity发现,它会把url指向的文件看成特定格式的json解析。根据json内容,它会执行上传文件和下载解析显示图片的任务。不难发现上传文件的路径是攻击者提供的,app没有检查是否合法,形成任意文件上传,信息泄漏的漏洞。此时构造以下json能够泄漏app的内存地址ide
想要拿到Android app远程代码执行权限,漏洞基本只能存在于Dex动态加载逻辑、访问远程数据的native代码中。用工具androguard扫描发现,没有dex动态加载问题,漏洞只可能在native代码中。App有native代码libHt5g.so用于解析和播放gif图片。漏洞极可能就在其中,反汇编libHt5g.so发现有不少函数都有FrameSequence关键词。实际上就是Google本身的gif显示库,2016年12月和2017年1月都曝出过漏洞。
详情见:
https://source.android.com/intl/us_ALL/security/bulletin/2016-12-01.html
https://source.android.com/intl/us_ALL/security/bulletin/2017-01-01.html
但光看源代码基本不能利用。因此说出题者应该放了其余漏洞在里面。
反汇编看到private static native long nativeGetFrame(long j, int i, Bitmap bitmap, int i2);的时候能够发现,当gif一帧的大小小于等于1024字节的时候,buffer是分配在stack上而后再memcpy到原来的bitmap buffer中。不只画蛇添足并且跟源代码不一致,基本肯定出题者准备的是栈溢出。
到此为止若是尚未发现有源代码能够本身编译而后binary diff的话,能够本身构造小于1024字节的gif,而后逐个字节替换为0xff,最快几十字节改就会发现crash,分析后发现Gif格式中,一帧图片的Left变量被当成负数处理了,无符号整数被看成有符号整数处理。而知道用binary diff的同窗基本直接能够定位到出题者修改的全部地方,包括解析Left出错的地方。
光看源代码基本不能利用是由于bitmap是RGBA格式,RGB能够控制,而Alpha在源代码里直接被0xff填充,意为不透明。这样的话溢出的数据基本很难控制。因此做为出题者的咱们按照gif格式添加了tag为0x77的ExtentionBlock,里面存放的数据做为Alpha值。这样就能彻底控制溢出的数据了。
因为Left变成了负数,形成了向低地址的任意数据的栈溢出。
受影响汇编代码
能够看到此函数在栈上申请了0x480大小的字节。其中处于高地址的0x400(1024)个字节是将被溢出的buffer,处于低地址的0x80个字节是能够做为掩盖目标。到此能够任意代码执行了。
因为以前拿到/proc/self/maps,内存地址都泄露了,这里说一下咱们的rop方法。
溢出后控制memcpy的dst参数,将准备好的数据拷贝到从/proc/self/maps里找到的暂时不用的一块内存。咱们在linker64里找到两个gadget
一、修改sp地址到新地址
二、把所在内存修改成可执行
三、跳转到自定义的可执行内存