一、前言
前段时间,国外知名的安全公司fireeye发表了一篇病毒分析文章,讲述的主角是一个专门针对手机银行的android手机病毒。文章链接如下:https://www.fireeye.com/blog/threat-research/2015/12/slembunk_an_evolvin.html。这个手机病毒变种甚多,影响广泛,也不乏一些高端技术的应用。其中有一个很有意思的特性,就是它可以劫持手机银行的登录界面,从而盗取受害者的银行账号、密码。
看完fireeye这篇精彩的分析文章之后,我对这个病毒使用的一些技术很感兴趣,无奈没有找到样本,不能自己动手分析,因此也只能作罢。
事情过了大概一两个月,有一次和朋友出去吃饭聊起这个病毒的一些特性。友人说,你说的这个技术梆梆就有啊,而且他们还出了一个防御界面劫持的SDK呢。听完我甚是欣喜,于是就有了接下来对梆梆SDK的分析。下面分析的SDK均可以在梆梆的SDK主页上下载到。http://www.bangcle.com/solution/sdk-center/。
二、梆梆防界面劫持SDK
界面劫持概述
界面劫持通俗来说就是病毒或木马在后台实时监控某个窗口的产生,例如QQ、支付宝、手机银行等软件的登录界面。一旦发现目标窗口出现,病毒就马上创建一个跟目标窗口一毛一样的窗体来覆盖在它之上。
当发生界面劫持时,用户在无察觉的情况下将自己的账号、密码信息输入到仿冒界面中,恶意程序再把这些数据上报到其自身服务器,这个过程便是钓鱼攻击。
界面劫持具有病毒制作成本低(技术含量低)、用户难察觉、杀毒软件不易查杀等特点而被广泛使用。早在PC时代该技术就已经很成熟了,当时比较出名的是“QQ粘虫病毒”,此病毒看名字就已经通俗易懂了,主要是被用来盗取受害者的QQ账号密码。
SDK预览
梆梆的防界面劫持SDK里面提供了两个APK,一个是防界面劫持demo,我们可以称它为demo1,界面如图1。从图中可以看出,梆梆的SDK提供了基类和接口两种方式来防御界面劫持。
图1
另一个就是界面劫持demo,我们可以称它为demo2,界面如图2所示。它的功能比较简单,就是启动和关闭界面劫持。
图2
梆梆想的还是蛮周到的,提供了攻、防两个程序。Demo2开启功能后可以劫持demo1产生的窗口。Demo1检测到界面劫持之后会给用户一个提示,“疑似非本应用界面,请注意!!!”。如图3。
图3
逆向分析
看完了梆梆SDK的功能演示,我觉得他们这技术很是新奇,于是准备逆向分析之。反编译界面劫持demo的时候发现该APK加了梆梆的壳,无奈手工脱壳,接着分析。
在理解梆梆防界面劫持SDK原理之前,我们先来了解下android程序中onPause方法的一些知识。
onPause方法用于由一个Activity转到另一个Activity、设备进入休眠状态(屏幕锁住了)、或者有dialog弹出时由系统通知程序的一个方法。此时,我们的android程序知道自己的窗体发生切换了。在这个方法里面,开发者可以保存一些必要的窗体状态信息。
当界面劫持发生时,正常APP的登录界面会被病毒程序的仿冒界面覆盖,即上述所说的一个Activity转到另一个Activity,此时正常APP的onPause方法会被调用。因此,梆梆的界面劫持SDK在onPause阶段检查顶层窗口即可判断是否被劫持了。
梆梆防界面劫持SDK的代码非常简单,逆向出来的源码不足百行,已经自测功能正常,大致如下:
代码:
public class MyBaseActivity extends Activity {
private static Set set = new HashSet();
private boolean b = true;
@Override
protected void onCreate(Bundle savedInstanceState) {
if (set.size() == 0) {
try {
InputStream is = getAssets().open("white.txt");
BufferedReader br = new BufferedReader(new InputStreamReader(is, "UTF-8"));
while (true) {
String write = br.readLine();
if (write == null) {
break;
}
set.add(write);
}
is.close();
br.close();
}
catch (IOException exp) {
exp.printStackTrace();
}
}
set.add(getPackageName());
super.onCreate(savedInstanceState);
}
protected void onPause() {
if(b) {
String packagename = ((ActivityManager)getSystemService(Context.ACTIVITY_SERVICE)).
getRunningTasks(1).get(0).topActivity.getPackageName();
if(!set.contains(packagename)) {
String msg = "疑似界面劫持攻击,请小心使用,并查杀病毒!";
Toast toast = Toast.makeText(getApplicationContext(), msg, Toast.LENGTH_LONG);
toast.setGravity(17, 0, 0);
toast.show();
b = false;
}
}
b = true;
super.onPause();
}
}
SDK的不足之处
逆完了梆梆的防界面劫持SDK之后,我觉得他们的这个检测方法并不是很好,主要有以下几点不足之处:
1. 误报多。
因为梆梆是在onPause的时候检测顶层窗口是不是自己的,如果不是,就开始报警。所以说,只要是窗口发生切换,不论是不是界面劫持它都会报警。为了证明我的猜测,我用Android Studio生成了一个完全没有功能的Hello World测试程序,之后点击“Run”按钮来启动程序。如图4。
图4
稍等片刻之后,Android Studio会启动我们的测试程序。与此同时,窗体会发生切换,由梆梆的防界面劫持demo切到了我们的测试程序界面。此时,梆梆的防界面劫持demo就发出报警了,说有界面劫持发生。这是一个典型的误报。如图5所示。而且类似这样的界面切换操作,在android机器上是很容易发生的,因此多误报在所难免。
图5
显然,梆梆也意识到了误报多这个问题了。于是,他们在SDK中加入了一些白名单,主要根据包名来过滤,如果是白名单中的程序就不报警了。白名单如图6所示。
图6
2. 容易被绕过。
既然有了白名单,那么无疑是增加了被绕过的几率。例如图6中的com.sonyericsson.*,这些程序只有在索尼的机器上才会有。那么病毒木马只要把自己命名成com.sonyericsson.home,就可以在诸如小米、华为、三星这样的手机上绕过梆梆防界面劫持SDK的检测了。
3. 仅支持android 5.0以下机型。
由上面我逆向出来的代码中可以看出,梆梆防界面劫持SDK主要是通过getRunningTasks这个函数来获取顶层窗口对应的包名的。然而这个函数存在泄露用户个人信息的风险,因此在android 5.0以后google就不让第三方程序使用该API了。Google的文档中也写的很清楚了,如图7所示。
图7
三、总结
通过逆向梆梆的防界面劫持SDK,我对android上的界面劫持技术有了一个更深入的了解。另外,梆梆在android安全方面有很多的技术储备,如果能很好的解决上述三个不足之处,那应该能造福不少的android用户。