剖析Geost:针对俄罗斯银行的安卓木马
2020-03-18 10:20:00 Author: www.4hou.com(查看原文) 阅读量:194 收藏

概述

Android银行木马Geost是由Stratosphere实验室的Sebastian García、Maria Jose Erquiaga和Anna Shirokova首次发现。最早,他们通过监视HtBot恶意代理网络来检测到该木马。该僵尸网络以俄罗斯银行为目标,在去年发布关于该僵尸网络的研究时,受害者人数已经超过80万。

我们的研究成果揭示了Geost(Trend Micro检测为AndroidOS_Fobus.AXM)从受害者那里窃取的信息类型,并分析了僵尸网络背后恶意组织的活动,包括其运营策略以及威胁参与者与僵尸网络编码人员之间的内部通信。

基于这一有趣的发现,我们决定对恶意软件样本进行逆向工程,以更加深入地了解Geost的行为。该木马使用了混淆、加密、反射和注入非功能代码段的多种方式,使得逆向工程更加困难。为了研究代码并分析其使用的算法,我们必须首先编写Python脚本来解密字符串。

初步分析

攻击者将Geost隐藏在恶意应用程序中,并通过随机生成服务器主机名的非官方网站实现分发。如果受害者在寻找Google Play上不可用的应用程序,或者受害者无法访问应用商店时,往往就会直接到网上去搜索特定的应用。随后,受害者可能会在一些不知名的Web服务器上找到该应用程序的链接,下载应用程序并在手机上运行。随后,应用程序将向用户请求授予权限,如果受害者允许授权,则会感染恶意软件。

我们所分析的Geost样本位于一个名为“установка”(俄语)的恶意应用程序中,其名称翻译过来是“设置”。该应用程序使用了Google Play的图标,并且该图标在运行后不会出现在手机屏幕上。

恶意应用程序“установка”使用的图标:

1.png

启动应用程序时,该恶意应用请求授予设备的管理员特权。这类特权的请求是非常少见的,因为合法的应用程序通常不会要求如此之高的权限,它基本上为应用程序提供了对设备的完整权限。

用户可能在不知不觉中同意的重要权限包括“访问短信息”,这样一来,恶意应用就可以获取来自银行应用程序的确认信息。而根据这些消息,恶意软件可以收集受害者的姓名、余额和其他银行账户相关的详细信息。只需要单击几下,攻击者就可以在不知情的情况下从受害者的银行账户中转走资金。

请求设备管理员权限的截图:

2.png

请求的应用程序权限:

3.png

在确认获取到必要的权限之后,应用程序将不再可见,并且应用程序的图标将会消失,从而让受害者误认为该应用程序已经被删除。在我们分析样本所使用的设备上,起初没有显示出任何恶意活动迹象,但该恶意软件持续在后台运行,攻击者已经获得了对设备的访问权限,从而使他们可以监视已发送和已接收的消息,包括来自银行应用程序的短信确认消息。

为了保证重启设备后仍然具有持久性,恶意软件注册了BOOT_COMPLETED和QUICKBOOT_POWERON广播。

注册服务启动广播(部分代码经过混淆):

4.png

第一阶段

Geost的运行时生命周期被分为多个阶段。其中,第一阶段较为精简,随后将下载、解密并运行第二阶段,而第二阶段则更为复杂。

在Geost样本的APK中,classes.dex文件包含已编译的Java代码。APK中还包括AndroidManifest.xml和资源文件,它们是APK文件中的常规内容。除上述之外,还有一个大小为125K的“.cache”文件。

为了对提取的classes.dex文件进行反编译,我们使用了几个Java反编译器,包括dex2jar、jadx、jd-core/jd-gui和Ghidra,因为没有一个单独的反编译器能够反编译所有Smali代码。

反编译的Java源代码:

5.png

乍一看,反编译的代码似乎部分编码为一系列字符串,但根据字符使用的频率进行分析,我们发现这些字符是随机使用的。

进一步的分析表明,该恶意软件包含其他代码段,除了用于减慢其执行速度意外,这些代码段对应用程序的行为没有任何影响。由于恶意软件将有用的代码分割为多个部分,并频繁更改执行路径,因此使得我们的逆向工程更加困难。执行过程中会走到哪个分支,通常要取决于具有未知值的某个变量,而“switch”、“if”和“try/catch”命令块也同样如此。通过对有实际意义代码的功能进行分析,我们可以更为全面地了解恶意软件的行为。

带有case条件的代码段:

6.png

我们不断删除非功能代码段,从而确定了恶意软件使用的第一个解密算法。第一阶段中的所有字符串都使用RC4进行加密,并使用了一个算法,该算法被拆分为多个函数,以避免被人发现其使用了RC4算法。在得到这一信息之后,下一步就是要找到用于RC4解密的密钥。

反编译的Java源代码,作为RC4算法中的一部分:

7.png

清理后的RC4算法代码片段:

8.png

RC4密钥:

9.png

RC4是一种流密码,其内部状态随着每个解密的符号而变化。如果需要解密多个加密的字符串,通常必须要以与加密时相同的顺序来进行解密。幸运的是,我们所分析的样本并非如此。由于RC4加密算法始终复制状态数组S[],因此代码编写者简化了RC4算法,没有保留解密之间的内部状态。

RC4加密始终复制状态数组S[]:

10.png

之后,开始搜索通用代码库,找到了Android.support.v4库和ReflectASM Java Reflection库。

带有加密字符串的代码:

11.png

在解密以及符号去混淆后,包含字符串的代码:

12.png

至此,我们已经可以读懂第一阶段的代码:它使用反射代码隐藏了几个特定的类和方法。基本上,第一阶段使用相同的RC4算法和密钥解密第二阶段的文件。

反射方法调用示例:

13.png

前面提到的“.cache”文件被重命名为.localsinfotimestamp1494987116,并在解密后保存为ydxwlab.jar,从中加载并启动.dex文件。

解密并保存第二阶段:

14.png

代码作者在其中插入了一个错误的标志HttpURLConnection以及其URL,该URL似乎已经连接到命令和控制(C&C)服务器。但是,这个HTTP链接将永远不会执行。

错误标志:

15.png

第一阶段会从第二阶段的开始部分加载一个类,研究人员将其命名为“MaliciousClass”。

启动第二阶段:

16.png

第二阶段

通过查看classes.dex,我们可以看到在第二阶段中再次使用了混淆和加密的方法。但是这一次,符号名称部分被替换为长度为1-2个字符的字符串,而不再是之前使用的6-12个字符。此外,还修改了字符串加密算法,使之与上一阶段使用的算法不同。这里还使用了不同的工具。此外,针对每个类别,分别修改了解密算法的参数。

由于goto命令会跳入if块,因此所有Java反编译器在反编译解密算法时都会出现问题,只有Jeb反编译器可以很好地处理这一结构。

解密算法的Smali代码:

17.png

Java解密算法代码:

18.png

每个类的解密方法都包含不同的参数顺序和不同的常量,这使得编写Python解密脚本变得更加困难。这意味着,解密脚本必须从Smali代码中检测算法设置并进行自我调整,或者必须在解密每个类之前手动在脚本中设置参数。

加密字符串的示例:

19.png

字符串解密后,就可以检测到所使用的库,其中包括:

· AES加密引擎

· Base64编码

· 模拟环境检测器

· 文件下载服务

· IExtendedNetworkService

· USSD API库

· Zip4jUtil

初始化阶段

从第一阶段开始调用的MaliciousClass将作为实例化类的信封,研究人员将其命名为“Context”。

Context类:

20.png

Context类首先启动EmulatorDetector服务,随后启动AdminService和LPService这两个服务,然后启动主应用程序Intent。

主初始化例程:

21.png

模拟环境检测器

模拟环境检测器会检测恶意软件是否正在模拟环境中运行。该样本可以检测到Nox、Andy、Geny、Bluestacks和Qemu Android模拟器的存在。

追踪模拟环境:

22.png

AdminService

该服务负责向应用程序授予管理员权限。这是最关键的部分,因为它可以访问敏感数据并启用特权操作。

AdminService的关键部分:

23.png

LPService

该服务负责保持应用程序运行,并连接到C&C服务器。它使用WakeLock和WifiLock acquire()调用来实现。这样做的副作用是电池耗电量明显增大,但大多数受害者通常都会忽略这一点。

锁定CPU和WiFI资源:

24.png

LPService随后创建LPServiceRunnable线程,该线程每隔5秒钟唤醒一次,并监视和重新启动以下服务:

· MainService

· AdminService

· SmsKitkatService

该服务还收集有关正在运行的进程和任务的信息。它还会定期启动WebViewActivity,后者可以打开浏览器窗口以访问任意URL或启动恶意代码。在该示例中未实现WebViewActivity代码。

MainService

MainService首先挂钩到AlarmManager以设置时间计划任务,随后注册两个广播接收器MainServiceReceiver1和MainServiceReceiver2。在初始化阶段结束后,它将启动MainServiceRunnable线程。当样本执行重载的onDestroy()方法时,它将再次重新启动MainService。

重载onDestroy以重新启动MainService:

25.png

MainService中包含的一个重要方法是processApiResponse(),该方法负责处理从C&C服务器接收的命令字符串,该命令使用JSON格式。

处理C&C服务器的命令:

26.png

ClearService

该服务调用ClearServiceRunnable线程,这一线程负责锁定/解锁命令,以阻止或取消阻止用户活动,因此僵尸网络运营者可以在无需用户操作的前提下远程执行任务。如果尝试终止ClearService,它还会重新启动其自身。

ClearService类:

27.png

ClearServiceRunnable:

28.png

SmsKitkatService

该服务旨在用攻击者编写的另一种应用程序替换标准的短信息应用程序。在我们所分析的样本中,它使用默认的短消息应用程序,未进行替换。

用于替换默认短信息应用程序的代码:

29.png

命令

我们可以在下面的表和屏幕截图中看到该恶意软件可以识别的命令列表(按照代码中定义的顺序排列):

#conversations

从content://sms/conversations/、content://sms/inbox和content://sms/sent位置收集所有短信息的地址、正文、日期和类型,并将其发送到C&C服务器。

#contacts     

从content://com.android.contacts/data/phones收集所有联系人的列表,并将其发送到C&C服务器。

#calls    

从content://call_log/calls收集所有通话记录,并将其发送到C&C服务器。

#apps   

收集已安装软件包名称和标签的列表,并将其发送到C&C服务器。

#bhist   

该样本中将忽略此命令。

#interval {set:number}  

设置获取C&C服务器命令的时间段。

#intercept    

设置拦截短信的电话号码(全部“all”或号码列表)。

#send id:, to:, body:    

发送短信。

#ussd {to:address, tel:number}  

使用USSD框架拨打电话。

#send_contacts   

发送短信给电话簿中的所有联系人。

#server  

设置计划运行时间。

#check_apps {path:uri_to_server}      

将正在运行的应用程序列表发送到C&C服务器,从参数中定义为error.zip的路径下载archive.zip文件,然后将其解压缩。Zip压缩文件的密码为“encryptedz1p”。默认服务器名称为hxxp://fwg23tt23qwef.ru/。

#send_mass {messages: {to:address, body:text}, delay:ms}    

将多个短信息发送到不同的地址,两次发送之间会有延迟。

#lock    

从ClearServiceRunnable启用RLA服务,该服务将拦截按键的AKEYCODE_HOME、AKEYCODE_CAMERA和AKEYCODE_FOCUS事件。它还会拦截onBackPressed()活动方法,使铃声变为静音,清除所有短信息通知,自行停止并导致手机无响应。

#unlock  

禁用#lock命令的操作,并通过停止ClearServiceRunnable的方式来解锁手机。

#makecall {number:tel_number}       

使用标准的android.intent.action.CALL API来拨打电话。

#openurl {filesDir=j:url}      

打开网页URL。

#hooksms {number:tel_number}      

挂钩到一个特定的号码,将所有收到的短信息转发到参数中的号码上。

#selfdelete   

将任务时间设置为无法解析的字符串值,这将停止其自行调度的任务。

命令列表

C&C服务器命令列表:

30.png

ApiRequest、ApiResponse和ApiInterfaceImpl

ApiRequest、ApiResponse和ApiInterfaceImpl类负责启用与C&C服务器的通信。在连接参数初始化中,默认情况下replaceWithRandomStr变量的值设置为true,并且在代码内未进行更改。

构建C&C服务器连接字符串:

31.png

连接参数初始化:

32.png

在这里,使用了一种算法来为C&C服务器URL生成随机字符串。随后,初始化API连接,并设置为C&C服务器的主机名。

为C&C服务器URL构建随机字符串:

33.png

API连接初始化:

34.png

设置C&C服务器主机名:

35.png

下面展示了在执行C&C服务器命令“#contacts”时的API用法。最后,命令的参数以JSON格式附加,并转换为字符串。

C&C服务器API调用示例:

36.png

最佳实践与解决方案

Trend Micro在2020年安全预测中,预测了针对在线银行和支付系统的移动恶意软件家族(例如Geost)的持续增长。移动用户在目前日益危险的整体环境中,应该遵循最佳实践以保护自己的移动设备安全。其中最关键的一大注意事项,就是应避免从官方应用商店以外的地方下载应用程序。

但遗憾的是,威胁参与者也逐渐找到了通过合法应用商店传播恶意应用程序的方法。这些应用商店应加强稽查力度,下架受感染的应用程序,作为用户也应该在下载前仔细检查应用程序的评论和其他信息,以避免下载恶意应用。

应用程序的用户在点击允许之前,应该仔细检查已安装应用程序所请求的权限。在安装后,用户应当留意设备发生的变化,例如性能降低或电池寿命降低,这些都可能是感染恶意软件的特征。一旦发生上述情况,用户应该立即删除新安装的应用程序。此外,用户还应该定期进行检查,以删除无实际需要的应用程序。

为了进一步防范移动威胁,用户可以安装多层移动安全解决方案,以保护设备免受恶意应用程序和其他移动威胁的侵害。

威胁指标

SHA-256:92394e82d9cf5de5cb9c7ac072e774496bd1c7e2944683837d30b188804c1810

检测名称:AndroidOS_Fobus.AXM

本文翻译自:https://blog.trendmicro.com/trendlabs-security-intelligence/dissecting-geost-exposing-the-anatomy-of-the-android-trojan-targeting-russian-banks/若转载,请注明原文地址:


文章来源: https://www.4hou.com/posts/nNvW
如有侵权请联系:admin#unsafe.sh