android动态脱壳教程,使用 FRIDA 为 Android 应用进行脱壳的操作指南

FortiGuard 实验室最近遇到了很多加壳 Android 恶意软件。这类恶意软件一个很有趣的点是,尽管使用的加壳工具是一样的,但生成的恶意软件却常常会发生变化。

分析加壳工具通常令人望而生畏。因为不光分析流程很难理解,并且分析过程中往往也伴随着大量的垃圾信息。

正因为如此,我们想分享我们在处理分析这类恶意软件时出现的一些问题。并且这篇文章也将演示如何使用开源免费工具解压当今最常见的 dropper 部署的恶意软件。

参考样本是:509aa4a846c6cb52e9756a282de67da3e8ec82769bceafa1265428b1289459b3

静态分析

样本概述

首先,看看我们正在处理的 APK。

图 1:APK 中包含的文件

这个样本显然就比较可疑,比如 MawmjulbcbEndsqku ^ nd.cml 文件是个什么鬼?

我们先从 bash 命令开刀,看看能不能处理这个文件,然而并没有检测到任何文件类型。接着我们再试图通过 hex editor 去打开文件(但我们实际上使用了 radare2,它是一个很好用的开源逆向工程框架),不过最后还是无法确定此文件的类型。

图 2:hex 视图下的 MawmjulbcbEndsqku ^ nd.cml

列的内容和名称看起来像是随机字符,这可能是主应用程序使用的加密文件。

也许通过 Android Manifest,我们才能获得我们想得到的信息。

Android Manifest

AndroidManifest.xml 是一个 Android 二进制 XML 文件,其中包含有关该应用程序的大量信息,包括:

·应用程序的软件包名称,可以在设备上访问

·应用程序使用的活动、服务和接收器的完整列表(如果未在此处声明,以后将无法使用它们)

·完整的权限列表

·执行期间使用的意图过滤器的完整列表

·其他通常不那么重要的东西,比如使用的图标等。

我们首先注意到的就是完全随机的字符串组成了该应用程序所有组件的名称。这是一种恶意意图的标识 , 但合法的应用开发人员也会使用它来使竞争对手更难以对其产品进行逆向工程。

接着引起我们注意的一件事是 : 除了应用类 com.asgradc.troernrn 之外,yeSACsSs 文件中没有声明 Android 组件 ( 活动、接收方和服务类 ) 。这样很奇怪 : 声明不存在的类并跳过现有的类有什么用呢 ?

现在很明显的一个事实是,这个 APK 加载了额外的外部代码。此外,考虑到请求的权限的数量和性质 ( 比如请求发送 SMS 消息 ) ,我们可以相当肯定这段代码没有任何用处。

图 3:AndroidManifest SMS 过滤器

逆向脱壳工具

有许多免费工具可将 APK 反编译成可读代码,包括:

·Apktool:获取类的 SMALI 表示

·dex2jar:将 .dex 文件转换为 jar 存档,可以使用 jd-gui 进行分析

·jadx:将 java 中的所有代码反编译成方便的 GUI

我个人最喜欢用的是 jadx,但多些选择也不错,因为在极少数情况下,只有部分工具能够反编译代码。

所以我们接下来开始分析 jadx 上的 APK。然而,事情并不如我想象中那么顺利……

图 4:脱壳工具的应用程序类

在真正的脱壳过程中,我们遇到了许多无用的垃圾信息:无意义的字符串、无意义的计算、无意义的函数。我们花了一段时间来尝试理解执行流程:如果加密文件要解密,那么它要么需要调用某个加密库,要么拥有自己的解密例程。一旦解密完成,就需要使用某种类加载器对象加载新文件。

不幸的是,APK 导入文件中没有包含这些库。APK 中包含的内容是允许文件间接调用任何已加载库的 Reflection 方法。然而,再一次,这些反射方法参数也是使用无数无法理解的函数动态创建的。

很明显静态分析不能解决这个问题。我们必须转而找寻新方法了。

动态分析

谷歌有提供所有 Android 版本中 sdk 下载,可以通过 Android Studio 创建模拟器。这是一种测试恶意软件的完美方式,不会有被感染的风险。

因此,我们首先使用 Marshmallow 6.0 模拟器获取此示例并通过 adb(Android Debug Bridge)安装了 APK。如果 APK 要加载新的可执行文件,设备的内置记录器(在我们的例子中是模拟器)应该能够获取到。

我们运行了连接到系统记录器的 adb 命令,并且只选择了包含我们的 dropper 包名的那些行:

$ adb logcat | grep "com.jgnxmcj.knreroaxvi"

然后我们启动了应用程序。在很多杂乱的输出中,我们终于找到了我们一直在寻找的东西:

10-25 17:12:11.001 24358 24358 W dex2oat : /system/bin/dex2oat --runtime-arg -classpath --runtime-arg --instruction-set=x86 --instruction-set-features=smp,ssse3,-sse4.1,-sse4.2,-avx,-avx2 --runtime-arg -Xrelocate --boot-image=/system/framework/boot.art --runtime-arg -Xms64m --runtime-arg -Xmx512m --instruction-set-variant=x86 --instruction-set-features=default --dex-file=/data/user/0/com.jgnxmcj.knreroaxvi/app_files/rzwohkt.jar --oat-file=/data/user/0/com.jgnxmcj.knreroaxvi/app_files/rzwohkt.dex

APK 确实创建了一个新的 .dex 文件。很好,我们只需要获取此文件,就不需要逆转 dropper 了。

但问题又来了,当我们尝试抓取该文件时,我们无法在 /data/user/0/com.jgnxmcj.knreroaxvi/app_files 中找到它。显然许多恶意软件编码器的创作者通常会在使用后清理了它们。所以我们面临的下一个问题是,如何阻止 dropper 删除文件?

让我向您介绍这个完美工具:FRIDA。

FRIDA 是一个非常棒的检测工具包,它允许在应用程序执行期间连接 Javascript 代码,还可以修改函数、字段等等。

在这种情况下我们想要做的是阻止应用程序删除 rzwohkt.jar 文件,以便我们可以将它拉到我们的机器上进行分析。

使用 FRIDA 的过程一般是这样的:我们的 MO 将先找到负责删除的类,然后勾住类函数并跳过它。但是,我们不想再次重复静态分析的状况,所以使用动态分析来跳过这部分。

我们只有找出哪个系统调用被用于删除执行,我们才能绕过它。不管在混乱的代码中调用是在哪里进行的,如果我们在系统中钩住了正确的本机函数,那么应该能够检索所需的有效负载。

使用 Strace

接下来的一个重要问题是,我们怎么才能找到正确的函数呢?幸运的是,有一种简单的方法可以获得执行期间发生的所有函数调用的完整列表。

Strace 是一个很棒的 Linux 实用工具,它能让用户获得进程和 Linux 内核之间所有交互的完整报告,并且 Android 支持它,所以它是我们的理想工具。

图 5:Strace 的输出结果

FRIDA 代码

最后,我们获得了所需的所有信息。现在是时候创建我们的 FRIDA 钩子了。

首先,根据所使用的架构,我们需要在移动仿真器上运行正确的 frida-server。

既然我们有了连接 FRIDA 代码的方法,现在要做的就是创建脚本,钩住 unlink ( ) 函数并跳过它。为此,我们使用了 Interceptor.replace(目标,替换)方法,它允许我们替换目标处的函数,并用了 Module.findExportByName(module,exp)获取指向函数的指针,如果模块名称未知,null 可以作为模块传递(但会影响速度)。

console.log ( " [ * ] FRIDA started" ) ; console.log ( " [ * ] skip native unlink function" ) ; // create a pointer to the function in the module var unlinkPtr = Module.findExportByName ( null, ’ unlink ’ ) ; Interceptor.replace ( unlinkPtr, new NativeCallback ( function ( ) { console.log ( " [ * ] unlink ( ) encountered, skipping it." ) ; }, ’ int ’ , [ ] ) ) ;

现在,每当调用 unlink()函数时,FRIDA 将拦截调用并运行我们的代码。在这种情况下,它只会输出一个记录器字符串,并通知我们已经跳过了调用。

最后,我们只需要将脚本附加到应用程序进程里。所运行的 dropper_startup.py 是一个快速启动应用程序的 python 脚本,我们接着将 FRIDA 脚本附加到 frida-server。

图 6:FRIDA 输出

但在前几次执行过程中,unlink ( ) 也同样会对相应文件进行删除操作。最后,在二次取消链接后,我们能够运行:

$ adb pull /data/user/0/com.jgnxmcj.knreroaxvi/app_files/rzwohkt.jar

并成功获取了文件——一个包含 classes.dex 有效负载的 jar 存档。

结论

Android 恶意软件的发展日新月异,其架构就像更成熟的 Windows 恶意软件一样,也在往复杂化的趋势前进。Droppers 只是部署有效负载的一种确实有效的方式。随机字符串和无意义函数的确很容易欺骗 AV 引擎,但是,使用以下签名可以保护 Fortinet 客户端免受这些因素的影响:

Dropper:Android / Agent.CHG!tr Payload:Android / Agent.ARL!tr

FortiGuard Labs 将对这些恶意软件活动保持持续监控。

此博客中使用的所有脚本都可以在 FortiGuard Lion github 页面上找到。

IOC:

Packer: 509aa4a846c6cb52e9756a282de67da3e8ec82769bceafa1265428b1289459b3

Payload: 4fa71942784c9f1d0d285dc44371d00da1f70f4da910da0ab2c41862b9e03c89

首先,查使用PEID或者是FI,为UPX v1.08 接下来用OD载入,提示为“压缩代码是否继续分析”,我们选择否 我在这里介绍几种方法,请看我的操作。 方法1:单步跟踪(最常见的方法) 0040E8C0 N> 60 pushad //停在这里了,我们F8单步 0040E8C1 BE 15B04000 mov esi,NOTEPAD.0040B015 0040E8C6 8DBE EB5FFFFF lea edi,dword ptr ds:[esi+FFFF> 0040E8CC 57 push edi 0040E8CD 83CD FF or ebp,FFFFFFFF 0040E8D0 EB 10 jmp short NOTEPAD.0040E8E2 //跳 。。。。。。。。。。 0040E8E2 8B1E mov ebx,dword ptr ds:[esi] //跳到这里,继续单步 0040E8E4 83EE FC sub esi,-4 0040E8E7 11DB adc ebx,ebx 0040E8E9 ^ 72 ED jb short NOTEPAD.0040E8D8 //这里要往回跳了 0040E8EB B8 01000000 mov eax,1 //F4,然后继续F8 0040E8F0 01DB add ebx,ebx 0040E8F2 75 07 jnz short NOTEPAD.0040E8FB //跳 。。。。。。。。。。。 0040E8FB 11C0 adc eax,eax //来到这里,F8继续 0040E8FD 01DB add ebx,ebx 0040E8FD 01DB add ebx,ebx 0040E8FF ^ 73 EF jnb short NOTEPAD.0040E8F0 0040E901 75 09 jnz short NOTEPAD.0040E90C //跳 。。。。。。。。。。。 0040E90C 31C9 xor ecx,ecx //跳到这里,继续F8 0040E90E 83E8 03 sub eax,3 0040E90E 83E8 03 sub eax,3 0040E911 72 0D jb short NOTEPAD.0040E920 //跳 。。。。。。。。。。。 0040E920 01DB add ebx,ebx //跳到这里,继续F8 0040E922 75 07 jnz short NOTEPAD.0040E92B //跳 。。。。。。。。。。。 0040E92B 11C9 adc ecx,ecx //跳到了这里,继续F8 0040E92D 01DB add ebx,ebx 0040E92F 75 07 jnz short NOTEPAD.0040E938 //跳 。。。。。。。。。。。 0040E938 11C9 adc ecx,ecx //跳到这里,继续F8 0040E93A 75 20 jnz short NOTEPAD.0040E95C //跳 。。。。。。。。。。。 0040E95C 81FD 00F3FFFF cmp ebp,-0D00 //来到这,继续F8 0040E962 83D1 01 adc ecx,1 0040E965 8D142F lea edx,dword ptr ds:[edi+ebp] 0040E968 83FD FC
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值