Android中应用锁的实现之账号盗取

Android技术篇 尼古拉斯.赵四 8690℃ 0评论

一、前言

前几天忙着公司的活,最近又可以歇歇了,休息不能不做事呀?今天就来研究一下Android中应用锁的实现。应用锁顾名思义就是对app进行加密,在打开app的时候需要输入指定的密码才能打开应用。

现在市场中这种应用很多的,他们的实现原理很简单,网上也有人解释了。

二、市场中应用锁apk的分析

我们来随便看一下那些加密锁的应用的实现,这里我从豌豆荚上面下载了一个:应用锁.apk

安装运行,然后对360手机卫士进行加密,

我们在打开360手机卫士:


这时候就弹出了加密的页面

这时候我们查看一下系统中正在运行的程序:


这个应用果然在后台开启一个监听服务

然后我们在使用命令:

adb shell dumpsys activity >activity.txt

查看正在运行的Activity


可以发现当前的Activity就是它的解锁页面

三、原理

原理:在后台启动一个Service,然后每隔一段时间进行轮询一次,查看当前系统中topActivity,然后获取到其app的包名,从而进行过滤

四、实现

直接来看代码:

LockService.java

package com.example.applock;

import java.util.ArrayList;
import java.util.List;

import android.app.ActivityManager;
import android.app.Service;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.IBinder;
import android.util.Log;

/**
 * Created by jiangwei on 2014/12/23.
 */
public class LockService  extends Service{

    private final String TAG = "LockService";

    private Handler mHandler = null;
    private final static int LOOPHANDLER = 0;
    private HandlerThread handlerThread = null;
    
    private final List<String> lockName = new ArrayList<String>();
    
    private boolean isUnLockActivity = false;

    //每隔100ms检查一次
    private static long cycleTime = 100;

    @Override
    public void onCreate() {
        super.onCreate();
        handlerThread = new HandlerThread("count_thread");
        handlerThread.start();
        //这里只是做了一个例子:只对360手机卫士做锁机制
        lockName.add("com.qihoo360.mobilesafe");
        
        //开始循环检查
        mHandler = new Handler(handlerThread.getLooper()) {
            public void dispatchMessage(android.os.Message msg) {
                switch (msg.what) {
                    case LOOPHANDLER:
                        Log.i(TAG,"do something..."+(System.currentTimeMillis()/1000));
                        /**
                         * 这里需要注意的是:isLockName是用来判断当前的topActivity是不是我们需要加锁的应用
                         * 同时还是需要做一个判断,就是是否已经对这个app加过锁了,不然会出现一个问题
                         * 当我们打开app时,启动我们的加锁界面,解锁之后,回到了app,但是这时候又发现栈顶app是
                         * 需要加锁的app,那么这时候又启动了我们加锁界面,这样就出现死循环了。
                         * 可以自行的实验一下
                         * 所以这里用isUnLockActivity变量来做判断的
                         */
                        if(isLockName() && !isUnLockActivity){
                        	Log.i(TAG, "locking...");
                        	Intent intent = new Intent(LockService.this,UnLockActivity.class);
                        	intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                        	startActivity(intent);
                        	//调用了解锁界面之后,需要设置一下isUnLockActivity的值
                        	isUnLockActivity = true;
                        }
                        break;
                }
                mHandler.sendEmptyMessageDelayed(LOOPHANDLER, cycleTime);
            }
        };
        mHandler.sendEmptyMessage(LOOPHANDLER);
    }
    
    /**
     * 判断当前的Activity是不是我们开启解锁界面的app
     * @return
     */
    private boolean isLockName(){
    	ActivityManager mActivityManager;
    	mActivityManager = (ActivityManager) this.getSystemService(Context.ACTIVITY_SERVICE);
    	ComponentName topActivity = mActivityManager.getRunningTasks(1).get(0).topActivity;
    	String packageName = topActivity.getPackageName();
    	
    	//如果当前的Activity是桌面app,那么就需要将isUnLockActivity清空值
    	if(getHomes().contains(packageName)){
    		isUnLockActivity = false;
    	}
    	Log.v("LockService", "packageName == " + packageName);
    	if("com.qihoo360.mobilesafe".equals(packageName)){
    		return true;
    	}
    	return false;
    }
    
    /**
     * 返回所有桌面app的包名
     * @return
     */
	private List<String> getHomes() {
		List<String> names = new ArrayList<String>();
		PackageManager packageManager = this.getPackageManager();
		//属性
		Intent intent = new Intent(Intent.ACTION_MAIN);
		intent.addCategory(Intent.CATEGORY_HOME);
		List<ResolveInfo> resolveInfo = packageManager.queryIntentActivities(intent,
				PackageManager.MATCH_DEFAULT_ONLY);
		for(ResolveInfo ri : resolveInfo){
			names.add(ri.activityInfo.packageName);
			System.out.println(ri.activityInfo.packageName);
		}
		return names;
	}

    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        return Service.START_STICKY;
    }
}

这里主要就是开启一个轮询操作,然后每隔100ms去查询当前运行的Activity的包名。然后和我们需要进行加密的app进行比较。

当发现是加密的app的时候,就会弹出我们自己的解锁页面,然后我们退出(这里的退出就是简单的点击返回键,当然正常情况下是需要用户输入正确的密码才可以的,但是最后都是把这个activity给finish了)解锁页面。就进入了加密的app了

当然这里做的很简单,直接对360手机卫士进行加密的,其实我们应该会维护一个白名单,里面存储了需要加密的应用。

这里在做的过程中其实还是有一个问题需要注意的:

当我们解锁了,进入到应用之后,这时候会发现又弹出了我们的加锁页面,然后解锁了,又弹出来了。。。

这样无休止的操作,这是一个问题,其实问题很简单:

当我们解锁之后,就会进入360手机卫士,但是这时候我们还在轮询的检查,发现运行的还是360手机卫士,所以还会弹出我们的解锁页面。

这里我们可以这么处理:

就是添加一个变量,用来记录我们的解锁页面弹过一次了。当我们检测到当前的activity是桌面时,就是用户不在手机卫士的页面了,这时候我们需要将这个变量在清零,以便下次继续弹出解锁页面。

这里说的可能有点抽象,具体可以自己操作一下,就会发现问题的。

效果如下图:


好吧,上面就介绍了应用锁的实现原理。

五、如何通过应用锁来盗取账号

 

那么下面就来进入我们今天的主题吧

如何通过应用锁来进行账号的盗取?

我们现在知道一些应用在打开的时候都是需要登陆的

比如QQ:


那么我们怎么可以进行账号盗取呢?

其实很简单:

我们将我们的解锁页面布置成和QQ的登陆页面一样,然后监听文本框的输入内容,就可以轻松的记下用户名和密码了。

有人说盗取QQ没意思,那么还有我们经常用的支付宝,那个实现和这个是一样的,盗取支付宝账号就有意义了。哈哈~~

上面是说通过应用锁来进行账号的盗取。所以说自己的设备最好还是不要安装什么应用锁的app,特别是来历不明的应用。

上面说的都是通过应用锁这样的app.如果现在有一些坏人,他们会将上面的代码放到恶意的apk中,那么那就完蛋了。

六、总结

这篇文章就介绍了通过应用锁的实现原理,来进行账号的盗取。实现很简单,想法很大胆。所以我们现在能做的是,尽量少安装应用,如果真的要安装的话,那么就要安装可靠的app。关于上面的问题的解决办法:

个人感觉很难做到。不过以前看过一篇文章,说可以通过当前内存运行的大小以及应用运行时预期需要的内存大小,然后做比对,就可以判断当前应用到底是不是真实的app了。不过这种做法实现起来难度有点大。这里就详细讨论了。

项目下载地址

 

关注微信公众号,最新Android技术实时推送

转载请注明:尼古拉斯.赵四 » Android中应用锁的实现之账号盗取

喜欢 (2)or分享 (0)
发表我的评论
取消评论

表情

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址