FireEye研究实验室最近发现一个新的Android恶意软件,有六个变种,并且能窃取短信、拦截电话。所有样本一致使用相同的Activity名称,所以命名为“Android.HeHe”。
这是已知变种的列表:
MD5值
VirusTotal 检测率
1caa31272daabb43180e079bca5e23c1
2/48
8265041aca378d37006799975fa471d9
1/47
2af4de1df7587fa0035dcefededaedae
2/45
2b41fbfb5087f521be193d8c1f5efb4c
2/46
aa0ed04426562df25916ff70258daf6c
1/46
9507f93d9a64d718682c0871bf354e6f
1/47
总结
该应用程序伪装成一个给用户推送系统更新的软件,名字为“android security”(图1)。它主动连接C&C服务器,并自动注册,然后就开始监视收到的短信。从C&C服务器获取定义好的一个电话号码列表。如果其中任意一个号码发信息或者打电话给一个感染后的手机,恶意软件会拦截短信或电话,关闭设备自身的通知,并删除相关痕迹或日志。并且该条短信会被记录到内部数据库,发送到C&C服务器。而来自这个列表里的任意来电都将会被拒接,并且悄无声息。
QQ图片20140123113921.jpg
图1
分析过程
程序启动时,HeHeActivity主函数就开始运行了。其构造函数调用android.os.Handle新建一个句柄,作为一个线程等待android.os.Message从而去执行不同的动作,这也是下面将要提到的。
因为HeHeActivity遵循DailogInterfaceOnClickListener标准,所以应用程序启动时会显示一个showAlterDailog消息(图2)。
QQ图片20140123113950.jpg
图2.上面的消息让用户相信程序正在检查系统更新
应用程序在后台启动了3个系统服务,如下:
沙箱逃脱策略
它通过调用isEmulator函数来判断是否为虚拟环境:
1.它会检查设备的MODEL值(谷歌ADTbundle模拟器的MODEL变量会含有字符串“SDK”)。
2.它还会检查IMSI码是否为空值(模拟器没有相关联的IMSI码)。
下面是isEmulator函数的相关代码:
String v0 =TelephonyUtils.getImsi(((Context)this));
if(v0 == null) {
return;
}
public static boolean isEmulator() {
boolean v0;
if((Build.MODEL.equalsIgnoreCase(“sdk”)) ||(Build.MODEL.equalsIgnoreCase(“google_sdk”))) {
v0 = true;
}
else {
v0 = false;
}
return v0;
}
该代码将会检查是否正在Android QEMU模拟器下运行,并且检查IMSI值是否为空。
注册服务
服务在后台运行,启动时调用setComponentEnabledSetting方法:
this.getPackageManager().setComponentEnabledSetting(newComponentName(((Context)this), HeheActivity.class), 2, 1);
从主菜单自动删除让用户以为它已经不存在了。然后通过如下检查网络状态:
public void checkNetwork() {
if(!this.isNetworkAvailable()) {
this.setMobileDataEnabled();
}
}
服务被创建后,OnStart方法被调用,它会检查intent消息中类型为START和LOGIN的消息。
START
如果消息类型为START,则调用sendReigsterRequest()方法。这个方法会首先检查模拟器的存在与否(如上面沙箱逃脱里所说)。
然后,它收集IMSI(全球用户识别号),IMEI(设备号),手机号码,地址信息和推送通道ID。将这些信息打包放在一个JSON对象中。JSON对象随后转换为一个字符串发送到C&C服务器。与C&C服务器通讯后面会提到。
LOGIN
如果消息类型为LOGIN,则调用sendLoginRequest方法收集以下信息:
1.该应用程序的版本号(硬编码为1.0.0)
2.手机型号
3.操作系统版本
4.设备关联的网络类型(GSM/CDMA)
这些信息也将打包成一个JSON对象,转换成字符串,并被发送到C&C服务器。
RegisterBroadcastReceiver服务
这个服务在启动时注册,然后反过来注册IncomeCallAndSmsReceiver(),用于对以下三个intent做出响应。
1.android.provider.Telephony.SMS_RECEIVED,设备收到短信时的通知。
2.android.intent.action.PHONE_STATE,设备的状态变化时的通知,比如RINGING或者OFF_HOOK。
3.android.intent.action.SCREEN_ON,屏幕打开或关闭时的通知。
此外,它会查看安卓的一些URI:
1.SmsObserver用于查看content://sms,这使它能够访问存在于设备上的所有短信。
2.CallObserver用于查看content://call_log/calls,这使它能够访问设备上的所有来电,去电以及未接来电的记录。
Connection服务
一开始提到的主函数HeHeActivity中,ConnectionService类的ACTION_START intent如下:
Intent v2 = new Intent(((Context)this),ConnectionService.class);
v2.setAction(ConnectionService.ACTION_START);
v2.setFlags(268435456);
this.startService(v2);
LogUtils.debug(“heheActivity”,“start connectionService service”);
然后启动一个定时器,间隔为5000秒,执行的任务如下:
1.创建android.os.Message类的实例对象
2.设置消息对象的what值为1
3.消息句柄在构造函数中初始化,然后反过来调用showFinishBar方法用于显示信息“현재 OS에서 최신 소프트웨어버전을 사용하고있습니다”,翻译过来就是“您正在使用的操作系统已经是最新版本”
接收器
来电和短信的接收
RegisterBroadcastReceiver在应用程序启动时注册为接收器。当设备收到一条短信时,IncomeCallAndSmsReceiver获取到intent。由于接收器监听三个intent之一,程序会检查接收器接收到的任意intent的类型。
如果接收到的intent类型为android.provider.telephony.SMS_RECEIVED,它将会提取短信内容和发信者号码。如果电话号码的前三个字符匹配一个名为tbl_intercept_info表中电话号码的前三个字符,则SMS intent被中止,短信被从设备的短信收件箱中删除,用户将永远看不到它。然后抑制短信通知,该应用程序捆绑短信如下:
{
“content”:“TESTING”,
“createTime”:“2014-01-10 16:21:36”,
“id”:null,“messageFrom”:“1234567890”,
“token”:null
}
然后把它发送到C&C服务器(http://108.62.240.69:9008/reportMessage)
同时把短信记录在其内部数据库中的tbl_message_info表。
如果接收到的intent是类型为android.intent.action.PHONE_STATE的,应用程序会检查本地数据库中的tbl_intercept_info表。如果来电者的号码出现在该表中,然后将手机的振铃模式设置为静音,抑制来电通知并断开来电。它从通话记录中删除相应的条目,删除该设备的所有相关痕迹。
不过没有为android.app.action.SCREEN_ON意图定义任何行为,即使IncomeCallAndSmsReceiver接收器是容器。
C&C服务器
这个程序使用了两个硬编码IP地址来定位其C&C服务器:122.10.92.117和58.64.183.12。该应用程序通过HTTP POST请求执行所有通信。在HTTP POST里的内容,使用AES与被硬编码到应用程序中的一个128位的密钥进行加密。该应用程序将其最新版本号发送到122.10.92.117,用于检查版本。IP地址58.64.183.12则用于报告收到的短信。
因为IP地址ping不通,服务器的响应就无法进行分析。可以明确的是,服务器会发送一个JSON对象的响应,其中会包含一个“token”字段。
虽然C&C服务器当前不可用,但是我们可以推断出应用程序如何通过检查处理接收到的响应。
该应用程序将不同的数据结构转换成等效的JSON对象发送到C&C服务器。此外,所有JSON对象的响应转换成其等效的内部数据结构。我们还观察到用于填充内部数据库的一个表(tbl_intercept_info),表内为需要拦截的电话号码。
该应用程序使用hxxp://122.10.92.117:9008和hxxp://58.64.183.12:9008将信息发送到C&C服务器。
这些URL在其内部类的数据结构中的映射如下所示:
GetLastVersionRequest
/getLastVersion
RegisterRequest
/register
LoginRequest
/login
ReportRequest
/report
GetTaskRequest
/getTask
ReportMessage Request
/reportMessage
其含义和结构将在下面的章节说明。
GetLastVersionRequest
当应用程序第一次安装在设备上将发送这个请求。发送设备版本号(目前设定为1.0.0)到C&C。C&C服务器应响应一个可用的有更新的URL。响应中一个“更新”字段代表一个更新的可用性。
QQ图片20140123113703.jpg
发送到C&C的检查版本请求
RegisterRequest
当应用程序发送一个类型为LOGIN的intent(上面提到过)。该请求包含IMSI,IMEI,电话号码,短信地址(电话号码),通道ID,令牌和正在使用的IP地址。这会导致受感染设备在C&C注册。
LoginRequest
这个请求被发送到C&C进行进一步验证,它包含先前接收到的令牌,恶意软件版本,手机型号,操作系统版本,网络的类型和其他活动的网络参数,诸如信号强度。回应为一个结果值。
ReportRequest
这个请求将tbl_report_info表中的信息发送到C&C。此表为其他请求已经发送但是失败的信息。
GetTaskRequest
这个请求从C&C服务器请求任务。响应包含了重试时间间隔和sendSmsActionNotify值。当LoginRequest的回应值为401而不是200时就会发送这个消息。
ReportMessageRequest
这个请求将设备上接收过的短信发送给C&C服务器。它包括短信内容,短信的时间和短信发送者。在logcat的输出可以看到:
结论
Android恶意软件变种如雨后春笋般出现。如Android.HeHe和Android.MisoSMS等恶意软件揭露攻击者对监控短信和电话呼叫记录的兴趣越来越大。它们也可以作为一个很好的提醒,从非信任的商店安装应用程序将会是多么危险。