樂安全軟件鎖實現原理分析

應廣大網友的要求,筆者近期對樂安全的軟件鎖進行了分析,下面簡單就一篇博文向大家介紹一下樂安全軟件鎖的實現原理。測試的樂安全版本爲V4.2.4

先說下結論,如果有興趣的同學可以繼續往下看分析。樂安全在本地進程得到了AMSBp,直接調用其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命令查看當前進程。我們發現了被鎖軟件:

 

 

新浪微博@安卓安全小分隊

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章