`
android_squad
  • 浏览: 17521 次
最近访客 更多访客>>
文章分类
社区版块
存档分类
最新评论

乐安全软件锁实现原理分析

阅读更多

应广大网友的要求,笔者近期对乐安全的软件锁进行了分析,下面简单就一篇博文向大家介绍一下乐安全软件锁的实现原理。测试的乐安全版本为V4.2.4。
先说下结论,如果有兴趣的同学可以继续往下看分析。乐安全在本地进程得到了AMS的Bp,直接调用其getTasks方法,每隔一秒检测一下当前topActivity是否是需要被锁定的,如果是的话,就弹出一个解锁界面盖住本该启动的APP。
下面进行分析
首先要爆料的是,乐安全做的实在是有点不小心,打了些对于破解有用的log出来,降低了破解的难度。比如下面的:

 

 

这是在触发软件锁的时候打出的log,给了我们启发,通过反编译APK文件后,我们很快定位到了相关的代码。

   while (AppCheck.isRun)

        try

        {

          Thread.sleep(1000L);

          List localList1 = AppCheck.a(AppCheck.this).getTasks(1, 0, null);

          if (localList1.size() > 0)

          {

            AppCheck.a(AppCheck.this, ((ActivityManager.RunningTaskInfo)localList1.get(0)).topActivity.getPackageName());

            if (!AppCheck.c(AppCheck.this).equals(AppCheck.b(AppCheck.this)))

            {

              Log.i("AppCheck", "old" + AppCheck.c(AppCheck.this) + "------------new:" + AppCheck.b(AppCheck.this));

              String[] arrayOfString3 = new String[3];

              arrayOfString3[0] = "runningTask";

              arrayOfString3[1] = AppCheck.b(AppCheck.this);

              arrayOfString3[2] = AppCheck.c(AppCheck.this);

              a(arrayOfString3);

              AppCheck.b(AppCheck.this, AppCheck.b(AppCheck.this));

            }

          }

 

可以看到,乐安全在这里做了一个循环操作,首先sleep一秒,然后直接调用getTasks()方法得到一个List。我们先看下AppCheck.a(AppCheck.this)返回的是什么。由于jd反编译的不全面,下面要po上一个smali的代码片段。

.method static synthetic a(Lcom/lenovo/safecenter/utils/AppCheck;)Landroid/app/IActivityManager;

    .locals 1

    .parameter "x0"

 

    .prologue

    .line 21

    iget-object v0, p0, Lcom/lenovo/safecenter/utils/AppCheck;->a:Landroid/app/IActivityManager;

 

    return-object v0

.end method

 

这里可以看到a(AppCheck.this)返回的是一个IActivityManager的对象。这里可能大家会有一个疑问,IActivityManagerhide的,为什么可以在这里被调用。@安卓安全小分队的大牛讲师认为乐安全很有可能自己编译了一套framework.jar使得乐安全在编译阶段顺利通过,并且在手机上也能正常运行,关于这一部分的机理,如果大家觉得有必要,我们可以在以后的时间作为一个专题来讲解。

在这里笔者对之前的猜测做下更正,乐安全并不是通过注入方式来调用AMS的一个方法,而是简单的在本地得到了AMSBp,也就是这个IActivityManager的对象。下面再po一个smali的代码段来说明这个IActivityManager是如何得到的。

.line 38

    invoke-static {}, Landroid/app/ActivityManagerNative;->getDefault()Landroid/app/IActivityManager;

 

    move-result-object v0

 

iput-object v0, p0, Lcom/lenovo/safecenter/utils/AppCheck;->a:Landroid/app/IActivityManager;

 

通过直接调用ActivityManagerNativegetDefault静态方法就获得了这个IActivityManager对象,很简单。

好,回到前面的分析阶段。我们已经知道了,乐安全通过调用AMSgetTasks方法得到了taskslist,到了第一if分支(参考前面贴出的代码)。

首先检查的是新启动的activity是否与前一个activity属于同一包。说白了就是如果用户已经在使用敏感APP了,乐安全就不要再去搞软件锁了,不然用户启动一个activity就有一锁出来不的把人烦死。

但是如果不属于同一个包,就进入了这个分支,先打了个被我们抓住尾巴的log,然后把old的包名和new的报名放进数组交给了a()方法。我们看看a()里都做了什么

    private void a(Object[] paramArrayOfObject)

    {

      if (paramArrayOfObject[0].equals("runningTask"));

      for (String str = "com.lenovo.safecenter.activityswitch"; ; str = "com.lenovo.safecenter.activityswitch2")

      {

        Log.i("AppCheck", paramArrayOfObject[0] + "------------action:" + str + " " + paramArrayOfObject[1] + " " + paramArrayOfObject[2]);

        Intent localIntent = new Intent(str);

        localIntent.putExtra("newPkg", (String)paramArrayOfObject[1]);

        localIntent.putExtra("oldPkg", (String)paramArrayOfObject[2]);

        AppCheck.g(AppCheck.this).sendBroadcast(localIntent);

        Settings.System.putString(AppCheck.g(AppCheck.this).getContentResolver(), "safe_input_method", "com.android.inputmethod.latin/.LatinIME");

        Log.i("AppCheck", paramArrayOfObject[0] + "------------end");

        return;

      }

}

 

很简单,把old packagenew package用广播给发出去了。我们到接收端看一下如何处理。

乐安全的assets包里有一个LenovoSafeBox429.apk,打开后在里面发现一个MonitorAppService的类,他在onCreate的时候注册了一个BroadcastReceiver,接收名为com.lenovo.safecenter.activityswitchaction如下。

 

 

  public void onCreate()

  {

    this.getBroadcast = false;

    this.mContext = this;

    this.pattern = Pattern.compile("(.*)(\\={1})(.*)(//*)");

    this.runtime = Runtime.getRuntime();

    this.filter = new IntentFilter();

    this.filter.addAction("android.intent.action.SCREEN_OFF");

    this.filter.addAction("android.intent.action.SCREEN_ON");

    this.filter.addAction("com.lenovo.safecenter.activityswitch");

    this.filter.addAction("com.lenovo.safebox.lockscreen");

    this.lastPkg = "";

    registerReceiver(this.receiver, this.filter);

    if (canGetPassword())

    {

      if (!this.watchAppOpen)

        watchAppStart();

      if (!this.getBroadcast)

      {

        this.mTimer = new Timer(true);

        restartTimer();

      }

}

 

receiveronReceive函数里,这个receiver做了下面的事情。我们捡主要的说

          label498: if ((MonitorAppService.this.lastPkg == null) || (MonitorAppService.this.lastPkg.equals("com.lenovo.safebox")) || (MonitorAppService.this.lastPkg.equals(str)) || (!MonitorAppService.this.checkList.contains(str)) || (MonitorAppService.isLocked))

            continue;

          Intent localIntent = new Intent(MonitorAppService.this.mContext, LockScreenActivity.class);

          localIntent.putExtra("pkg", str);

          localIntent.addFlags(268435456);

          if (MonitorAppService.DEBUG)

            Log.i("MonitorAppService", "Lock in Broadcast TopTask :" + str);

          MonitorAppService.this.mContext.startActivity(localIntent);

关键的位置就是到一个list里查看当前启动的package是不是我要锁住的,如果是锁住的,那就直接启动一个activity盖在上面,就是我们看到的效果了。

 

PS:有的网友提到乐安全阻止了程序的正常启动,相关进程不会被启动。但是通过我们的观察,进程是已经被启动了的,如下图。

 


 

需要关注的是,AMS首先启动了被锁软件。Start了它的activity以及process(最开始的两条log),然后才会执行我们之前分析的部分,然后LockScreenActivity才被启动。这个时候可以通过ps命令查看当前进程。我们发现了被锁软件:

 



 


 

  • 大小: 25.8 KB
  • 大小: 217.6 KB
  • 大小: 15.7 KB
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics