做 者: limitemp
時 間: 2014-01-12,20:43:04 鏈 接: http://bbs.pediy.com/showthread.php?t=183692 想必不少人都知道轟動一時android木馬OBAD,該木馬利用android設備管理器的漏洞,當用戶激活設備管理器後,該程序會在setting設備管理器列表隱藏,應用程序激活成設備管理器後,能夠實現鎖屏、擦除用戶數據等功能,而且沒法使用常規的卸載方式對其卸載,本文主要和介紹漏洞原理和漏洞補丁分享我的在分析過程當中遇到的一些事情。 Android 在實現設備管理器時,須要再manifest.xml中註冊一個廣播接收者,代碼以下 <receiver android:name=".MyDeviceAdmin" android:permission="android.permission.BIND_DEVICE_ADMIN" > <meta-data android:name="android.app.device_admin" android:resource="@xml/device_admin" /> <intent-filter> <action android:name="android.app.action.DEVICE_ADMIN_ENABLED" /> </intent-filter> </receiver> OBAD如何在setting的管理器列表隱藏呢,咱們能夠經過setting的源碼找到答案。相關代碼:packages\apps\Settings\src\com\android\settings\DeviceAdminSettings.java 主要方法: void updateList() { mActiveAdmins.clear(); List<ComponentName> cur = mDPM.getActiveAdmins(); if (cur != null) { for (int i=0; i<cur.size(); i++) { mActiveAdmins.add(cur.get(i)); } } //得到已經激活設備管理器列表mActiveAdmins mAvailableAdmins.clear(); // mAvailableAdmins setting的設備管理器列表 List<ResolveInfo> avail = getActivity().getPackageManager().queryBroadcastReceivers( new Intent(DeviceAdminReceiver.ACTION_DEVICE_ADMIN_ENABLED), PackageManager.GET_META_DATA); //獲取全部註冊了DeviceAdminReceiver.ACTION_DEVICE_ADMIN_ENABLED即android.app.action.DEVICE_ADMIN_ENABLED action的廣播接收者列表avail int count = avail == null ? 0 : avail.size(); for (int i=0; i<count; i++) { ResolveInfo ri = avail.get(i); try { DeviceAdminInfo dpi = new DeviceAdminInfo(getActivity(), ri); if (dpi.isVisible() || mActiveAdmins.contains(dpi.getComponent())) { mAvailableAdmins.add(dpi); //若是應用註冊了包含該action的廣播接受者而且激活了設備管理器,就會在setting的設備管理器列表中顯示 } } catch (XmlPullParserException e) { Log.w(TAG, "Skipping " + ri.activityInfo, e); } catch (IOException e) { Log.w(TAG, "Skipping " + ri.activityInfo, e); } } getListView().setAdapter(new PolicyListAdapter()); } 可是沒有註冊android.app.action.DEVICE_ADMIN_ENABLED action的應用也能夠激活爲設備管理器。這就致使了激活後的設備管理器沒法在setting的設備管理器列表中顯示。 如何解決這種狀況呢?下面咱們一塊兒來分析一下安全管家的設備管理器補丁。該補丁是一個正常的apk,反編譯之,代碼結構以下 代碼結構.png 主要類DeviceAdminProxy代碼以下: DeviceAdminProxy.png //上面方法的主要內容就是對比直接經過DevicePolicyManager得到的已經激活的設備管理器列表a和經過遍歷註冊了android.app.action.DEVICE_ADMIN_ENABLED action的列表b進行對比,若是發現列表a中的設備管理器沒有在列表b中出現,就調用以下代碼彈出取消激活的activity,讓用戶手動取消。 取消激活.png 代碼中有一個RootMain的類,這個類在當能得到root權限的時候使用,找到利用這個漏洞的設備管理器後直接調用DevicePolicyManager的removeActiveAdmin方法取消激活,該方法須要system以上權限才能執行。 關於android.app.action.DEVICE_ADMIN_ENABLED引發的漏洞都這裏就結束了,下面說一下在分析中遇到的另一件有趣的事。 前面講到setting獲取管理器列表時,有這麼一段代碼,以下圖 DeviceAdminInfo.png 代碼中實例DeviceAdminInfo對象,DeviceAdminInfo.java在frameworks\base\core\java\android\app\admin\DeviceAdminInfo.java 關鍵代碼: di2.png 以前咱們在manifest的receiver中有以下配置: manifest.png 若是不配置meta-data,DeviceAdminInfo類就會拋出異常,DeviceAdminSettings中獲取異常,按照上面圖中的代碼能夠發現,一樣setting的設備管理器列表也沒法顯示。這樣setting雖然不顯示了,可是,若是不配置meta-data,設備管理器時沒辦法正常激活的。怎麼辦呢?用正常的設備管理器程序安裝,正常激活,而後刪除該程序的meta-data配置,生成apk,以更新安裝的形式安裝到android設備上。這個時候卸載該程序會發現,該程序已經激活爲設備管理器,可是在setting設備管理器列表中找不到。由於設備管理器註冊了android.app.action.DEVICE_ADMIN_ENABLED,因此使用上述的設備管理漏洞補丁也是找不到的。 那麼如何取消激活呢?從上面對於設備管理器漏洞補丁apk的分析能夠得出兩種取消激活的方法分析(實際上是三種): 1、 DevicePolicyManager得到的已經激活的設備管理器列表,而後使用下面的代碼 取消激活.png 啓動取消激活的activity。測試結果是行不通的,由於DeviceAdminAdd也須要解析meta-data中的信息。具體參見DeviceAdminAdd.java位於packages\apps\Settings\src\com\android\settings\ DeviceAdminAdd.java。 2、 獲取到激活的設備管理器列表後直接調用DevicePolicyManager的removeActiveAdmin方法取消激活,測試結果成功,可是須要system以上的權限。DevicePolicyManager.java位於frameworks\base\core\java\android\app\admin\DevicePolicyManager.java。 問題分析到這裏的時候可能有些童鞋已經發現了,使用正常的apk激活設備管理器,而後使用異常的apk避免設備管理器被取消。那若是android設備重啓了呢?重啓之後還能保持激活嗎?答案是否認的,重啓設備之後,沒法保持激活。緣由是什麼呢?分析以下: 主要代碼frameworks\base\services\java\com\android\server\DevicePolicyManagerService.java Android設備重啓之後,SystemServer啓動DevicePolicyManagerService服務同時調用systemReady方法從新初始化設備管理器列表。以下: systemReady.png loadSettingsLocked方法中調用findAdmin findAdmin.png 代碼到這裏就能夠看到了,在獲取meta-data的時候會捕獲異常,返回空值。 exception.png 因此第三種方法:重啓…… 若有不對的地方歡迎指正。 最後附上這次使用的apk*轉載請註明來自看雪論壇@PEdiy.com
上傳的附件
|