星光/宝骏/缤果/长安 车机CarPlay盒子权限破解原理普及----码农版本

从 app 申请 usbdevice 权限说起,通用 app 申请 usbdevice 权限代码如下

一般通过监听 ACTION_USB_DEVICE_ATTACHED usb 设备插入广播获取 UsbDevice 设备,或者通过 UsbManager 枚举出我们感兴趣的 UsbDevice 设备

然后调用 requestPermission(UsbDevice, PendingIntent) 申请权限,这时候系统一般会弹对话框询问是否允许访问usb设备,用户点确定或取消都将

收到自定义的回调广播 ACTION_USB_PERMISSION

 private static final String ACTION_USB_PERMISSION = "com.android.example.USB_PERMISSION";public void getPermission() {HashMap<String, UsbDevice> deviceList = usbManager.getDeviceList();Iterator<UsbDevice> deviceIterator = deviceList.values().iterator();PendingIntent mPermissionIntent = PendingIntent.getBroadcast(AdbActivity.this, 0, new Intent(ACTION_USB_PERMISSION), 0);IntentFilter filter = new IntentFilter(ACTION_USB_PERMISSION);registerReceiver(mUsbReceiver, filter);while(deviceIterator.hasNext()){UsbDevice device = deviceIterator.next();Log.d("AdbActivity", "getPermission: "+device.getDeviceName());if (device.getDeviceName().contains("/dev/bus/usb/001")) {if (usbManager.hasPermission(device)){Toast.makeText(AdbActivity.this,"已授权", Toast.LENGTH_SHORT).show();usbManager.openDevice(device);}else {usbManager.requestPermission(device, mPermissionIntent);}}}}private BroadcastReceiver mUsbReceiver = new BroadcastReceiver() {public void onReceive(Context context, Intent intent) {String action = intent.getAction();if (ACTION_USB_PERMISSION.equals(action)){synchronized (this) {UsbDevice device = (UsbDevice)intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);if (intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false)) {if(device != null){usbManager.openDevice(device);hintText.setText("openDevice");}}else {Toast.makeText(context,"permission denied for device ", Toast.LENGTH_SHORT).show();Log.d("AdbActivity", "permission denied for device " + device);}}}}};

接下来分析下系统弹权限框已经授权流程

UsbManager 其实调用 UsbService 中 requestDevicePermission()

UsbService 调用 UsbUserSettingsManager 中 requestPermission()

frameworks\base\services\usb\java\com\android\server\usb\UsbService.java

    @Overridepublic void requestDevicePermission(UsbDevice device, String packageName, PendingIntent pi) {final int uid = Binder.getCallingUid();final int userId = UserHandle.getUserId(uid);final long token = Binder.clearCallingIdentity();try {getSettingsForUser(userId).requestPermission(device, packageName, pi, uid);} finally {Binder.restoreCallingIdentity(token);}}private UsbUserSettingsManager getSettingsForUser(@UserIdInt int userIdInt) {return mSettingsManager.getSettingsForUser(userIdInt);}

frameworks\base\services\usb\java\com\android\server\usb\UsbSettingsManager.java

	@NonNull UsbUserSettingsManager getSettingsForUser(@UserIdInt int userId) {synchronized (mSettingsByUser) {UsbUserSettingsManager settings = mSettingsByUser.get(userId);if (settings == null) {settings = new UsbUserSettingsManager(mContext, UserHandle.of(userId),new UsbPermissionManager(mContext, UserHandle.of(userId)));mSettingsByUser.put(userId, settings);}return settings;}}

先判断 UsbDevice 是否已经授权,若已授权,直接将 PendingIntent 扔回去

若无授权,则准备走弹出申请权限框 requestPermissionDialog()

其实最终调用 UsbPermissionManager 中 requestPermissionDialog()

frameworks\base\services\usb\java\com\android\server\usb\UsbUserSettingsManager.java

	public void requestPermission(UsbDevice device, String packageName, PendingIntent pi, int uid) {Intent intent = new Intent();// respond immediately if permission has already been grantedif (hasPermission(device, packageName, uid)) {intent.putExtra(UsbManager.EXTRA_DEVICE, device);intent.putExtra(UsbManager.EXTRA_PERMISSION_GRANTED, true);try {pi.send(mUserContext, 0, intent);} catch (PendingIntent.CanceledException e) {if (DEBUG) Slog.d(TAG, "requestPermission PendingIntent was cancelled");}return;}if (isCameraDevicePresent(device)) {if (!isCameraPermissionGranted(packageName, uid)) {intent.putExtra(UsbManager.EXTRA_DEVICE, device);intent.putExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false);try {pi.send(mUserContext, 0, intent);} catch (PendingIntent.CanceledException e) {if (DEBUG) Slog.d(TAG, "requestPermission PendingIntent was cancelled");}return;}}requestPermissionDialog(device, null, canBeDefault(device, packageName), packageName, pi,uid);}private void requestPermissionDialog(@Nullable UsbDevice device,@Nullable UsbAccessory accessory,boolean canBeDefault,String packageName,PendingIntent pi,int uid) {// compare uid with packageName to foil apps pretending to be someone elsetry {ApplicationInfo aInfo = mPackageManager.getApplicationInfo(packageName, 0);if (aInfo.uid != uid) {throw new IllegalArgumentException("package " + packageName +" does not match caller's uid " + uid);}} catch (PackageManager.NameNotFoundException e) {throw new IllegalArgumentException("package " + packageName + " not found");}mUsbPermissionManager.requestPermissionDialog(device,accessory, canBeDefault, packageName, uid, mUserContext, pi);}

可以看到直接指定了包名和类名,最终是拉起 SystemUI 中 UsbPermissionActivity

frameworks\base\services\usb\java\com\android\server\usb\UsbPermissionManager.java

 /*** Creates UI dialog to request permission for the given package to access the device* or accessory.** @param device The USB device attached* @param accessory The USB accessory attached* @param canBeDefault Whether the calling pacakge can set as default handler* of the USB device or accessory* @param packageName The package name of the calling package* @param uid The uid of the calling package* @param userContext The context to start the UI dialog* @param pi PendingIntent for returning result*/void requestPermissionDialog(@Nullable UsbDevice device,@Nullable UsbAccessory accessory,boolean canBeDefault,@NonNull String packageName,int uid,@NonNull Context userContext,@NonNull PendingIntent pi) {long identity = Binder.clearCallingIdentity();Intent intent = new Intent();if (device != null) {intent.putExtra(UsbManager.EXTRA_DEVICE, device);} else {intent.putExtra(UsbManager.EXTRA_ACCESSORY, accessory);}intent.putExtra(Intent.EXTRA_INTENT, pi);intent.putExtra(Intent.EXTRA_UID, uid);intent.putExtra(UsbManager.EXTRA_CAN_BE_DEFAULT, canBeDefault);intent.putExtra(UsbManager.EXTRA_PACKAGE, packageName);intent.setClassName("com.android.systemui","com.android.systemui.usb.UsbPermissionActivity");intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);try {userContext.startActivityAsUser(intent, mUser);} catch (ActivityNotFoundException e) {Slog.e(LOG_TAG, "unable to start UsbPermissionActivity");} finally {Binder.restoreCallingIdentity(identity);}}

UsbPermissionActivity 就一个普通 AlertActivity,通常很多系统开发人员做默认授权时都会来改这里,

将 mPermissionGranted=true,直接 finish() 这样就能达到默认授权且不弹框的目的,因为最终授权是在ondestory()中

核心方法就下面两个,一个是仅授权一次,另一个是总是授权(前提是apk没被卸载,apk卸载后授权也会情况)

service.grantDevicePermission(mDevice, mUid);

service.setDevicePackage(mDevice, mPackageName, userId);

饶了半天又得回到 UsbService 中了

frameworks\base\packages\SystemUI\src\com\android\systemui\usb\UsbPermissionActivity.java

   <activity android:name=".usb.UsbPermissionActivity"android:exported="true"android:permission="android.permission.MANAGE_USB"android:theme="@style/Theme.SystemUI.Dialog.Alert"android:finishOnCloseSystemDialogs="true"android:excludeFromRecents="true"></activity>@Overridepublic void onDestroy() {IBinder b = ServiceManager.getService(USB_SERVICE);IUsbManager service = IUsbManager.Stub.asInterface(b);// send response via pending intentIntent intent = new Intent();try {if (mDevice != null) {intent.putExtra(UsbManager.EXTRA_DEVICE, mDevice);if (mPermissionGranted) {service.grantDevicePermission(mDevice, mUid);if (mAlwaysUse != null && mAlwaysUse.isChecked()) {final int userId = UserHandle.getUserId(mUid);service.setDevicePackage(mDevice, mPackageName, userId);}}}if (mAccessory != null) {intent.putExtra(UsbManager.EXTRA_ACCESSORY, mAccessory);if (mPermissionGranted) {service.grantAccessoryPermission(mAccessory, mUid);if (mAlwaysUse != null && mAlwaysUse.isChecked()) {final int userId = UserHandle.getUserId(mUid);service.setAccessoryPackage(mAccessory, mPackageName, userId);}}}intent.putExtra(UsbManager.EXTRA_PERMISSION_GRANTED, mPermissionGranted);mPendingIntent.send(this, 0, intent);} catch (PendingIntent.CanceledException e) {Log.w(TAG, "PendingIntent was cancelled");} catch (RemoteException e) {Log.e(TAG, "IUsbService connection failed", e);}if (mDisconnectedReceiver != null) {unregisterReceiver(mDisconnectedReceiver);}super.onDestroy();}	

frameworks\base\services\usb\java\com\android\server\usb\UsbService.java
frameworks\base\services\usb\java\com\android\server\usb\UsbUserSettingsManager.java
frameworks\base\services\usb\java\com\android\server\usb\UsbPermissionManager.java

可以看到仅授权一次其实最终就是将 device 和 uid 保存到 mDevicePermissionMap 中

看注释可知这只是一个临时的权限机制

/** Temporary mapping USB device name to list of UIDs with permissions for the device*/
private final HashMap<String, SparseBooleanArray> mDevicePermissionMap = new HashMap<>();

	@Overridepublic void grantDevicePermission(UsbDevice device, int uid) {mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null);final int userId = UserHandle.getUserId(uid);final long token = Binder.clearCallingIdentity();try {getSettingsForUser(userId).grantDevicePermission(device, uid);} finally {Binder.restoreCallingIdentity(token);}}public void grantDevicePermission(UsbDevice device, int uid) {mUsbPermissionManager.grantDevicePermission(device, uid);}void grantDevicePermission(@NonNull UsbDevice device, int uid) {synchronized (mLock) {String deviceName = device.getDeviceName();SparseBooleanArray uidList = mDevicePermissionMap.get(deviceName);if (uidList == null) {uidList = new SparseBooleanArray(1);mDevicePermissionMap.put(deviceName, uidList);}uidList.put(uid, true);}}boolean hasPermission(@NonNull UsbDevice device, int uid) {synchronized (mLock) {if (uid == Process.SYSTEM_UID || mDisablePermissionDialogs) {return true;}SparseBooleanArray uidList = mDevicePermissionMap.get(device.getDeviceName());if (uidList == null) {return false;}return uidList.get(uid);}}

再看看下持久保存授权是怎么做到的,调用 UsbProfileGroupSettingsManager 中 setDevicePackage()

packageName 为空,将 device 信息从 mDevicePreferenceMap 中移除,changed 改变重新修改 mSettingsFile 内容

mSettingsFile 实际路径为 data/system/users/0/usb_device_manager.xml

因为安卓支持多用户登录,默认用户id为0,这就是参数中为什么有 userId 原因,用于区分不同用户的操作数据

packageName 不为空,将 device 信息添加到 mDevicePreferenceMap 中,changed 改变写入数据到 mSettingsFile

frameworks\base\services\usb\java\com\android\server\usb\UsbService.java
frameworks\base\services\usb\java\com\android\server\usb\UsbProfileGroupSettingsManager.java

	@Overridepublic void setDevicePackage(UsbDevice device, String packageName, int userId) {device = Preconditions.checkNotNull(device);mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null);UserHandle user = UserHandle.of(userId);final long token = Binder.clearCallingIdentity();try {mSettingsManager.getSettingsForProfileGroup(user).setDevicePackage(device, packageName,user);} finally {Binder.restoreCallingIdentity(token);}}void setDevicePackage(@NonNull UsbDevice device, @Nullable String packageName,@NonNull UserHandle user) {DeviceFilter filter = new DeviceFilter(device);boolean changed;synchronized (mLock) {if (packageName == null) {changed = (mDevicePreferenceMap.remove(filter) != null);} else {UserPackage userPackage = new UserPackage(packageName, user);changed = !userPackage.equals(mDevicePreferenceMap.get(filter));if (changed) {mDevicePreferenceMap.put(filter, userPackage);}}if (changed) {scheduleWriteSettingsLocked();}}}mSettingsFile = new AtomicFile(new File(Environment.getUserSystemDirectory(user.getIdentifier()),"usb_device_manager.xml"), "usb-state");private void scheduleWriteSettingsLocked() {if (mIsWriteSettingsScheduled) {return;} else {mIsWriteSettingsScheduled = true;}AsyncTask.execute(() -> {synchronized (mLock) {FileOutputStream fos = null;try {fos = mSettingsFile.startWrite();FastXmlSerializer serializer = new FastXmlSerializer();serializer.setOutput(fos, StandardCharsets.UTF_8.name());serializer.startDocument(null, true);serializer.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output",true);serializer.startTag(null, "settings");for (DeviceFilter filter : mDevicePreferenceMap.keySet()) {serializer.startTag(null, "preference");serializer.attribute(null, "package",mDevicePreferenceMap.get(filter).packageName);serializer.attribute(null, "user",String.valueOf(getSerial(mDevicePreferenceMap.get(filter).user)));filter.write(serializer);serializer.endTag(null, "preference");}for (AccessoryFilter filter : mAccessoryPreferenceMap.keySet()) {serializer.startTag(null, "preference");serializer.attribute(null, "package",mAccessoryPreferenceMap.get(filter).packageName);serializer.attribute(null, "user", String.valueOf(getSerial(mAccessoryPreferenceMap.get(filter).user)));filter.write(serializer);serializer.endTag(null, "preference");}serializer.endTag(null, "settings");serializer.endDocument();mSettingsFile.finishWrite(fos);} catch (IOException e) {Slog.e(TAG, "Failed to write settings", e);if (fos != null) {mSettingsFile.failWrite(fos);}}mIsWriteSettingsScheduled = false;}});}

最终 DeviceFilter write() 将 usbdevice 关键信息写入 xml 中

frameworks/base/core/java/android/hardware/usb/DeviceFilter.java

public void write(XmlSerializer serializer) throws IOException {serializer.startTag(null, "usb-device");if (mVendorId != -1) {serializer.attribute(null, "vendor-id", Integer.toString(mVendorId));}if (mProductId != -1) {serializer.attribute(null, "product-id", Integer.toString(mProductId));}if (mClass != -1) {serializer.attribute(null, "class", Integer.toString(mClass));}if (mSubclass != -1) {serializer.attribute(null, "subclass", Integer.toString(mSubclass));}if (mProtocol != -1) {serializer.attribute(null, "protocol", Integer.toString(mProtocol));}if (mManufacturerName != null) {serializer.attribute(null, "manufacturer-name", mManufacturerName);}if (mProductName != null) {serializer.attribute(null, "product-name", mProductName);}if (mSerialNumber != null) {serializer.attribute(null, "serial-number", mSerialNumber);}serializer.endTag(null, "usb-device");}

一个完整的 usb_device_manager.xml 信息内容如下

<?xml version='1.0' encoding='utf-8' standalone='yes' ?>
<settings><preference package="com.difengze.carlink" user="0"><usb-device vendor-id="6353" product-id="15616" class="0" subclass="0" protocol="0" manufacturer-name="Allwinner Technology Inc." product-name="Tina Accessory" serial-number="20080411" /></preference>
</settings>	

流程搞清楚了,针对一些定制太离谱的系统我们可以直接构造出 usb_device_manager.xml 数据,推送到 data/system/users/0/ 路径下,重启设备一次也能达到破解权限目的

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/776508.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

使用pytorch构建一个无监督的深度卷积GAN网络模型

本文为此系列的第二篇DCGAN&#xff0c;上一篇为初级的GAN。普通GAN有训练不稳定、容易陷入局部最优等问题&#xff0c;DCGAN相对于普通GAN的优点是能够生成更加逼真、清晰的图像。 因为DCGAN是在GAN的基础上的改造&#xff0c;所以本篇只针对GAN的改造点进行讲解&#xff0c;其…

Python算法100例-4.6 歌星大奖赛

完整源代码项目地址&#xff0c;关注博主私信源代码后可获取 1.问题描述2.问题分析3.算法设计4.确定程序框架5.完整的程序6.问题拓展7.知识点补充 1&#xff0e;问题描述 在歌星大奖赛中&#xff0c;有10个评委为参赛的选手打分&#xff0c;分数为1&#xff5e;100分。选手最…

Spring Cloud+Spring Alibaba笔记

Spring CloudSpring Alibaba 文章目录 Spring CloudSpring AlibabaNacos服务发现配置中心 OpenFeign超时机制开启httpclient5重试机制开启日志 SeataSentinel流量控制熔断降级热点控制规则持久化集成 OpenFeign集成 Gateway MicrometerZipKinGateway路由断言过滤器 Nacos 服务…

TikTok养号保姆级教程:学好这9招,你就是流量宠儿!

01 什么是养号&#xff1f; 在回答这个问题之前&#xff0c;我们首先要明白Tiktok智能推荐机制&#xff0c;也就是著名TikTok算法。 每个创作者发布视频时&#xff0c;TikTok都会根据视频内容、视频发布地区、标题内容进行特征识别&#xff0c;来判断视频可能会有哪些人群喜欢…

鱼哥赠书活动第14期:看完这本《数字化运维》掌握数字化运维方法,构建数字化运维体系

鱼哥赠书活动第14期&#xff1a;看完这本《数字化运维》掌握数字化运维方法&#xff0c;构建数字化运维体系 主要内容&#xff1a;读者对象&#xff1a;赠书抽奖规则:往期赠书福利&#xff1a; 数字化转型已经成为大势所趋&#xff0c;各行各业正朝着数字化方向转型&#xff0c…

SpringBoot3集成PostgreSQL

标签&#xff1a;PostgreSQL.Druid.Mybatis.Plus&#xff1b; 一、简介 PostgreSQL是一个功能强大的开源数据库系统&#xff0c;具有可靠性、稳定性、数据一致性等特点&#xff0c;且可以运行在所有主流操作系统上&#xff0c;包括Linux、Unix、Windows等。 通过官方文档可以…

MySQL数据库高级语句

文章目录 MySQL高级语句older by 排序区间判断查询或与且&#xff08;or 与and&#xff09;嵌套查询&#xff08;多条件&#xff09;查询不重复记录distinctcount 计数限制结果条目limit别名as常用通配符嵌套查询&#xff08;子查询&#xff09;同表不同表嵌套查询还能用于删除…

C语言例4-36:求Fibonacci数列的前40个数

教材优化代码如下&#xff1a; //求Fibonacci数列的前40个数 #include<stdio.h> int main(void) {long int f11,f21;int i1;for(;i<20;i){printf("%15ld%15ld",f1,f2);if(i%20)printf("\n");f1f2;f2f1;}return 0; } 结果如下&#xff1a; 我的基…

IC-随便记

1、移远通信---通信模组 物联网解决方案供应商&#xff0c;可提供完备的IoT产品和服务&#xff0c;涵盖蜂窝模组(5G/4G/3G/2G/LPWA)、车载前装模组、智能模组&#xff08;5G/4G/边缘计算&#xff09;、短距离通信模组(Wi-Fi&BT)、GNSS定位模组、卫星通信模组、天线等硬件产…

Radio Silence for mac 好用的防火墙软件

Radio Silence for Mac是一款功能强大的网络防火墙软件&#xff0c;专为Mac用户设计&#xff0c;旨在保护用户的隐私和网络安全。它具备实时网络监视和控制功能&#xff0c;可以精确显示每个网络连接的状态&#xff0c;让用户轻松掌握网络活动情况。 软件下载&#xff1a;Radio…

DNS 服务 Unbound 部署最佳实践

文章目录 安装unbound-control配置启动服务测试 参考&#xff1a; 官网地址&#xff1a;https://nlnetlabs.nl/projects/unbound/about/ 详细文档&#xff1a;https://unbound.docs.nlnetlabs.nl/en/latest/index.html DNS服务Unbound部署于使用 https://cloud.tencent.com/…

Redis项目实战

本文用用代码演示Redis实现分布式缓存、分布式锁、接口幂等性、接口防刷的功能。 课程地址&#xff1a;Redis实战系列-课程大纲_哔哩哔哩_bilibili 目录 一. 新建springBoot项目整合Redis 二. Redis实现分布式缓存 2.1 原理及好处 2.2 数据准备 2.3 Redis实现分布式缓存…

知行之桥EDI系统功能介绍——FlatFile 端口介绍

FlatFile 端口能够实现平面文件与XML文件的互相转换。 每个 Flat File 端口配置一个特定的平面文件格式&#xff0c;从而实现与 XML 格式的互相转换。Flat File 端口有两个主要的模式&#xff1a; Position DelimitedCharacter Delimited 对于 Position Delimited 平面文件&a…

【Git篇】复习git

文章目录 &#x1f354;什么是git⭐git和svn的区别 &#x1f354;搭建本地仓库&#x1f354;克隆远程仓库&#x1f6f8;git常用命令 &#x1f354;什么是git Git是一种分布式版本控制系统&#xff0c;它可以追踪文件的变化、协调多人在同一个项目上的工作、恢复文件的旧版本等…

在宝塔面板中,为自己的云服务器安装SSL证书,为所搭建的网站启用https(主要部分攻略)

前提条件 My HTTP website is running Nginx on Debian 10&#xff08;或者11&#xff09; 时间&#xff1a;2024-3-28 16:25:52 你的网站部署在Debain 10&#xff08;或者11&#xff09;的 Nginx上 安装单域名证书&#xff08;默认&#xff09;&#xff08;非泛域名&#xf…

现在做抖音小店都需要准备什么?需要什么条件?门槛很高吗?

大家好&#xff0c;我是电商花花。 自从抖音小店这个项目做的人越来越多&#xff0c;很多人都想赶上抖音小店这个红利项目&#xff0c;但是很多新手在刚开始接触这个项目时候因为不懂&#xff0c;开始频频踩雷&#xff0c;不得不关店重新再来。 我们今天汇总了一下抖音小店的…

OSCP靶场--image

OSCP靶场–image 考点(CVE-2023-34152 suid strace提权) 1.nmap扫描 ## ┌──(root㉿kali)-[~/Desktop] └─# nmap -Pn -sC -sV 192.168.178.178 --min-rate 2500 Starting Nmap 7.92 ( https://nmap.org ) at 2024-03-27 23:43 EDT Nmap scan report for 192.168.178.17…

如何在群晖NAS搭建bitwarden密码管理软件并实现无公网IP远程访问

前言 作者简介&#xff1a; 懒大王敲代码&#xff0c;计算机专业应届生 今天给大家聊聊如何在群晖NAS搭建bitwarden密码管理软件并实现无公网IP远程访问&#xff0c;希望大家能觉得实用&#xff01; 欢迎大家点赞 &#x1f44d; 收藏 ⭐ 加关注哦&#xff01;&#x1f496;&am…

降分违规?90%新手会遇到的抖音小店运营问题!解决方法快围观!

哈喽~我是电商月月 今天我们聊聊新手开抖音小店会遇到的问题以及解决方法 为了完整性我们从头到尾分析&#xff0c;根据情况不同可自行翻阅 一&#xff0c;入驻和运营时的操作问题 1.营业执照的办理&#xff0c;选择&#xff0c;填写 营业执照的办理可以去当地工商局办理&…