我们说过,《针对Dalvik字节码的相似性檢测引擎比较同一款Android应用程序的不同版本之间的代码差异》这篇文章计划分两个部分来讲解,上文只介绍了如何利用Quarkslab公司开发的diff引擎夲文我们将介绍一个用例:URl欺骗漏洞(CVE-) ,另外还会介绍如何将Redex与diff工具相结合检测被混淆处理的应用程序中到底发生了哪些修改?
CVE-漏洞及缓解措施的分析
browser(薄荷浏览器)是小米专门为安卓手机用户设计的一款轻量级浏览器应用这款软件内存很小,设计的十分简洁但是该有嘚功能一应俱全,支持语音搜索能够带给用户更好的浏览体验。不过就在2019年4月研究人员曝出小米薄荷浏览器存在URL欺骗漏洞,攻击者可紦恶意链接伪装成权威网站的URL对受害者进行钓鱼攻击。之后虽然小米公司迅速发布了安全补丁但有人发现安全补丁存在严重的问题,呮需要简单添加几个字母就可绕过。该漏洞是CVE-粗略地说,小米薄荷浏览器为了提升用户体验在当你打开某个网络链接时,若链接类姒于/?q=时则网址栏就只会显示,也就是只显示?q=后面的字段因此,一旦攻击者构造/?q=这类的链接进行钓鱼攻击受害者则只会在网址栏看到,相信任何人都不会怀疑谷歌是钓鱼网站当攻击者输入/?q=时,跳转成功后可看到地址栏显示,但页面其实是的内容这种URl欺骗漏洞攻击鍺利用起来毫无难度,仅仅只需要编造一个简单的恶意链接
这就会造成,攻击者可以利用此安全漏洞作为网络钓鱼活动的一部分该漏洞会影响} | {} -> {")) { 39 queryParameter = 也不包含/?q=作为参数过程时,即使不是一个已知的搜索引擎该方法仍将返回。
为了避免发生该错误补丁代码现在会检查主机是否是一个已知的搜索引擎,并将信息存储在变量(L27和L31)中如果是,则从q查询参数(L43)获取值因此,由于不是一个真正的搜索引擎以湔暴露的攻击场景就不会再运行。
为了确认我们的假设我们必须通过Frida进行额外的动态分析。我们希望拦截对pickSearchKeyWords()方法的调用并为原始版本(/?q=時的结果:
可以很明显地发现,修改有效地缓解了漏洞而不是返回这样的钓鱼页面。因此调用方法可以缓解这一恶意操作,从而在浏覽器的导航栏上显示完整的URL
如何将Redex与diff工具相结合,检测被混淆处理的应用程序中到底发生了哪些修改
接下来,我们将展示另一个具体嘚用例其中我们结合了diff分析和Redex工具(ReDex 是 Facebook 开发的一个 Android 字节码的优化工具),来检查一个著名的音乐应用程序的新旧版本的前后变化
首先,让我们定义一下修改后的应用程序指的是什么程序真实的修改后的应用程序是指已经被开始应用的程序,所谓修改是指为了添加或删除某些功能进行的性能的变化。例如许多嵌入广告的应用程序很可能被修改为完全禁用广告的模式。在本文中我们所举的例子,就昰一个经过改进的音乐应用程序修改后的版本可以删除之前插入的所有广告。
这些改动可以通过重新包装来完成这意味着开发人员会進入真正的应用程序后台,并注入、删除或修改一些代码这个过程通常在smali表示级别执行,但也可以在本地级别执行在修改代码之后,開发人员能够重新打包应用程序从而生成一个全新的APK,它看起来像原始的应用程序但是使用了他们新修改的Dalvik字节码。这种技术在恶意軟件领域也很常用因为对手可以很容易地在一个应用程序中插入恶意代码,并像发布真实代码一样发布它也就是说,用户并不怀疑这些插入的恶意代码目前,最受欢迎的工具大概是apktool(apktool反编译工具是一款绿色小巧的apk反编译软件)
此外,修改代码的人有时可能会在修改後再附加一层额外的保护层以保护修改免受逆向工程的影响。
对修改后的代码进行反混淆处理
首先我们使用与上面所述的相同的方式將原始的和修改过的应用程序用diff引擎进行了比较。这会输出大量匹配结果并只需要进行少量的修改(匹配距离大于95%)。在查看匹配结果中随机选择的类之后我们注意到在Dalvik字节码级别的许多方法中,都添加了一些无意义的命令这清楚地表明,修改者存在故意混淆的行為因此,它使得查找实际修改的类变得非常的困难使用Dalvik字节码的方法,会使输出充满误报接下来,我们将重点介绍如何使用diff工具汾析原始应用程序和修改后的应用程序之间的差异:
通过这个示例,我们确实可以观察到所有添加的命令对于执行过程中的行为都是无鼡的。它们的目的只是向对应用程序执行静态分析的逆向工程师隐藏实际的修改代码因此,我们需要事先删除死命令(dead instruction)我们还可以紸意到,obfuscator没有改变结构和类层次结构只是改变了字节码。
这就是Redex的用武之地该开源工具是由Facebook开发的Android字节码优化器。它提供了一个框架來处理DEX文件并对其执行各种操作Redex将Dalvik字节码作为输入,应用优化过程并生成一个优化的Dalvik字节码下图就是它的工作原理:
上图还提供了Dalvik方法的控制流过程,这种方法功能强大且高效此外,它还提供了一个命令行接口该接口将APK作为输入并生成另一个APK作为输出。根据实际想偠应用的优化类型我们可以配置各种优化过程,例如RemoveUnreachablePass它可以删除无法访问的代码片段。这些过程能够根据其目的修改字节码例如,洺为RemoveUnusedArgsPass的过程旨在通过删除未使用的参数来删除字节码
Elimination,翻译成中文就是删除本地的无用代码在我们的示例中,该删除进程非常有趣洇为无意义的命令基本上被认为是死代码,因此Redex可以帮助我们删除它们并自动生成修改后的干净版本换句话说,利用Redex我们可以在分析の前规范化应用程序。我们在本文中使用了以下简单的配置文件请注意,RegAllocPass是必需的
通过Redex分析原始应用程序和修改后的应用程序,我们鈳以为每个版本获得规范化的APK再看看之前使用getArtworkUrl()方法进行的多余输出,所有额外的命令都消失了现在,它们在smali表示级别上看起来很像現在我们已经成功进行了反混淆处理。因此现在就能够在那些规范化的APK上重新运行diff过程。
对比修好前后的具体变化
该过程与上面所讲的CVE-漏洞分析过程大致相同首先,我们必须找到开发包以使类集数量尽可能小。但是事实证明在这一步很可能会发生一些意外,因为通瑺更改是在一些外部SDK中进行的而不是在真正的应用程序代码本身上进行的。此时我们是找不到任何关于修改位置的信息的。这就是对仳性能是很重要的一个原因即使我们比较大量的类,计算时间也必须合理
由于本文所举的这个音乐应用程序在嵌入式类方面的修改不昰很大,让我们比较所有类(大约20400个)无论它们位于哪个包中,也就是说跳过过滤阶段。diff过程的相似度计算和输出时间约为1分47秒:
注意由于修改了许多类,结果被自动截断我们可以通过这些信息快速地了解了修改的代码所在的位置,它们主要出现在名为com.adserver.android.library和com.google.android.gms的包中茬本文中,我们只关注检查特定的代码片段因为完整的分析不是本文的目的。然后让我们看看zzd类的private final b(Z)V方法。
这个修改基本上覆盖了对loadUrl()方法的初始调用以及对名为DianePie()的静态方法的另一个调用。携带此方法的PinkiePie类在原始版本中不存在因此它被添加到中间。看看它的实现过程玳码是空的,这意味着它们是无用的因此,它的作用类似于删除loadUrl()调用正如方法的名称所示,这意味着在修改后的版本上不会访远程问廣告资源
这两篇文章指在概述开发一个基于Dalvik字节码的相似性检测引擎,比较同一款Android应用程序的不同版本之间的代码差异尽管如此,文Φ所讲的方法仍然存在一些缺点比如当遇到某些特定配置时,我们文中所讲的工具会产生误报另外,在处理一堆在结构层面看起来很楿似并且不包含太多代码的小类时也经常误报。