前言
Android 为了提高用户的用户体验,对于不同的应用程序之间的切换,基本上是无缝。举一个例子,用户打开安卓手机上的某一应用例如支付宝,进入到登陆页面,这时恶意软件检测到用户的这一动作,立即弹出一个与支付宝界面相同的 Activity,覆盖掉了合法的 Activity,用户几乎无法察觉,该用户接下来输入用户名和密码的操作其实是在恶意软件的 Activity上进行的,接下来会发生什么就可想而知了。
在日常对Android APK进行客户端安全测试过程中,有一个测试用例就是界面劫持(Activity劫持,安卓应用的界面是一层一层的,后启动的应用会在栈顶,显示在最前面),就是恶意APK可以不停枚举进程是否存在要劫持的目标进程。如果发现了目标进程,就将自己的欺骗页面启动。
本文实现的方法为直接使用一个测试的APK对目标应用进行界面覆盖,观察目标应用是否进行了报警。
检测程序
先提供下源码地址:https://github.com/aloswoya/android_app。
核心源码如下:
package com.test.uihijack;
import android.content.Context;
import android.os.Bundle;
import android.support.v7.app.ActionBarActivity;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.Toast;
public class MainActivity extends ActionBarActivity {
private Context context;
/* access modifiers changed from: protected */
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
this.context = this;
setContentView((int) R.layout.activity_main);
Toast.makeText(this.context, "界面劫持测试", 0).show();
}
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
public boolean onOptionsItemSelected(MenuItem item) {
if (item.getItemId() == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
}
AndroidManifest.xml:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" android:versionCode="1" android:versionName="1.0" package="com.test.uihijack">
<uses-sdk android:minSdkVersion="8" android:targetSdkVersion="21"/>
<application android:theme="@style/AppTheme" android:label="@string/app_name" android:icon="@drawable/ic_launcher" android:allowBackup="true">
<activity android:label="@string/app_name" android:name="com.test.uihijack.MainActivity" android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
</application>
</manifest>
测试方法
模拟器安装以上APP:
在被的测试APK(此处使用Drozer)开启的情况下,使用drozer来调用MainActivity:
run app.activity.start --component com.test.uihijack com.test.uihijack.MainActivity
效果如下:
可以看到 Drozer 应用的界面成功被劫持(覆盖)了。
修复方案
测试到缺陷后,开发方需要对程序进行修复,修复方法也很简单,就是也去判断当前应用程序是否位于栈顶 (是否显示在前面),如果在后台了,就进行一些如toast提示、震动、通知弹窗等等,告诉用于当前应用已经在后台运行了。