市面上的大部分的合规检测工具是使用Frida或Xposed等Hook框架进行Hook注入代码,通常会带来额外的性能开销,包括更高的延迟和资源消耗,Hook过程中的错误或与应用的不兼容可能导致应用崩溃或不稳定。直接修改AOSP源码能够实现对操作系统所有层级(包括内核、系统服务、框架等)的深度控制和集成,实现从底层到应用层的全面隐私合规检测,系统的稳定性和可靠性相对较高,不会因运行时的动态代码注入带来不确定性的问题。
基于Android-10.0.0_r2版本源码进行的修改,并编译了适配Pixel 2 XL和Pixel 3机型的镜像,具体改动位置和检测点如下表所示:
| 序号 | 文件所在路径 | 监测内容 | 目标函数 |
|---|---|---|---|
| 1 | frameworks/base/core/java/android/app/ApplicationPackageManager.java | 权限申请 | int checkPermission(String permName, String pkgName) |
| 2 | frameworks/base/core/java/android/app/ApplicationPackageManager.java | 获取APP安装列表 | List getInstalledPackages(int flags) |
| 3 | frameworks/base/core/java/android/app/ApplicationPackageManager.java | 获取APP安装列表 | List getInstalledApplications(int flags) |
| 4 | frameworks/base/core/java/android/app/ActivityManager.java | 正在运行的进程 | List getRunningAppProcesses() |
| 5 | frameworks/base/core/java/android/app/ActivityManager.java | 正在运行的服务 | PendingIntent getRunningServiceControlPanel(ComponentName service) |
| 6 | frameworks/base/core/java/android/app/admin/DevicePolicyManager.java | 获取Mac地址 | String getWifiMacAddress(ComponentName admin) |
| 7 | frameworks/base/core/java/android/bluetooth/BluetoothAdapter.java | 获取蓝牙名称 | String getName() |
| 8 | frameworks/base/core/java/android/bluetooth/BluetoothDevice.java | 获取蓝牙Mac地址 | String getAddress() |
| 9 | frameworks/base/core/java/android/bluetooth/BluetoothDevice.java | 获取蓝牙名称 | String getName() |
| 10 | frameworks/base/core/java/android/content/ClipboardManager.java | 获取剪切板信息 | void setPrimaryClip(ClipData clip) |
| 11 | frameworks/base/core/java/android/content/ClipboardManager.java | 监测剪切板信息 | boolean hasPrimaryClip() |
| 12 | frameworks/base/core/java/android/content/ClipboardManager.java | 设置剪切板信息 | void setPrimaryClip(ClipData clip) |
| 13 | frameworks/base/core/java/android/content/Camera.java | 打开摄像头 | Camera open(int cameraId) |
| 14 | frameworks/base/core/java/android/hardware/camera2/CameraManager.java | 打开摄像头 | openCameraDeviceUserAsync |
| 15 | frameworks/base/core/java/android/hardware/SensorManager.java | 获取传感器信息 | List getSensorList(int type) |
| 16 | frameworks/base/core/java/android/os/Build.java | 获取设备序列号 | String getSerial() |
| 17 | frameworks/base/core/java/android/provider/Settings.java | 获取Android_id | String getString(ContentResolver resolver, String name) |
| 18 | frameworks/base/core/java/android/telephony/TelephonyManager.java | 获取IMEI | String getDeviceId() |
| 19 | frameworks/base/core/java/android/telephony/TelephonyManager.java | 获取IMEI | String getImei(int slotIndex) |
| 20 | frameworks/base/core/java/android/telephony/TelephonyManager.java | 获取MEID | String getMeid(int slotIndex) |
| 21 | frameworks/base/core/java/android/telephony/TelephonyManager.java | 获取MCC/MNC | String getNetworkOperatorName(int subId) |
| 22 | frameworks/base/core/java/android/telephony/TelephonyManager.java | 获取当前位置信息 | CellLocation getCellLocation() |
| 23 | frameworks/base/location/java/android/location/Location.java | 获取纬度信息 | double getLatitude() |
| 24 | frameworks/base/location/java/android/location/Location.java | 获取经度信息 | double getLongitude() |
| 25 | frameworks/base/location/java/android/location/LocationManager.java | 获取最后已知位置 | Location getLastKnownLocation(@NonNull String provider) |
| 26 | frameworks/base/location/java/android/location/LocationManager.java | 获取最后已知位置 | Location getLastLocation() |
| 27 | frameworks/base/telephony/java/android/telephony/gsm/GsmCellLocation.java | 获取基站cid信息 | int getCid() |
| 28 | frameworks/base/telephony/java/android/telephony/gsm/GsmCellLocation.java | 获取基站lac信息 | int getLac() |
| 29 | frameworks/base/core/java/android/telephony/TelephonyManager.java | 获取SIM卡国际代码 | String getSimCountryIsoForPhone(int phoneId) |
| 30 | frameworks/base/core/java/android/telephony/TelephonyManager.java | 获取IMSI/ICCID | String getSimSerialNumber(int subId) |
| 31 | frameworks/base/core/java/android/telephony/TelephonyManager.java | 获取IMSI | String getSubscriberId(int subId) |
| 32 | frameworks/base/core/java/android/telephony/TelephonyManager.java | 获取电话号码 | String getLine1Number(int subId) |
| 33 | frameworks/base/core/java/android/telephony/TelephonyManager.java | 获取IMSI | int getSubscriptionId() |
| 34 | frameworks/base/core/java/android/telephony/TelephonyManager.java | 检测sim卡是否可用 | ServiceState getServiceStateForSubscriber(int subId) |
| 35 | frameworks/base/core/java/android/os/SystemProperties.java | 获取系统属性 | String get(@NonNull String key) |
| 36 | frameworks/base/core/java/android/os/SystemProperties.java | 设置系统属性 | void set(@NonNull String key, @Nullable String val) |
| 37 | frameworks/base/wifi/java/android/net/wifi/WifiInfo.java | 获取附近Wifi列表 | List getScanResults() |
| 38 | frameworks/base/wifi/java/android/net/wifi/WifiInfo.java | 获取Mac地址 | String[] getFactoryMacAddresses() |
准备一台谷歌Pixel 2 XL或Pixel 3型号的手机,下载提供的镜像进行刷机即可,具体步骤如下:
# 进入到bootloader模式
adb reboot bootloader
# 设置环境变量,下载的镜像存储路径
export ANDROID_PRODUCT_OUT='/Users/xxxx/xxx/taimen_rom'
# 刷机
fastboot flashall -w
# 如果刷机过程中,提示存储空间不够,可以指定刷机文件系统分区大小
fastboot flashall -S 50M -w
- 直接打开系统中集成的”合规检测APP“ ,按着下图中的流程进行操作即可开始检测

- 保证电脑和手机处于同一局域网下,即手机和电脑连接同一个wifi
- 在电脑的浏览器中输入APP中展示的地址:
http://192.168.xxx.xxx:8080/,即可看到检测结果
- 点击详情,即可查看具体的调用堆栈

- 检测信息展示内容细分,更加便于快速捕捉违规信息。
- 修改检测逻辑,进一步增加对敏感信息获取的检测。
- 增加采集数据统计,便于后续分析。
- 计划会增加第三方SDK的识别和检测,同时增加更多底层信息采集的监控和新检测点,比如:模拟OAID的获取。