android隐私违规获取问题处理 及 Hook拦截处理记录 (VirtualXposted/epic等)
Posted iOSTianNan
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了android隐私违规获取问题处理 及 Hook拦截处理记录 (VirtualXposted/epic等)相关的知识,希望对你有一定的参考价值。
最近公司启动了隐私合规检测,报告告知我们在用户未同意隐私协议前,我们APP提前获取了WIIF/SSID/Mac地址等信息,不合规需要处理 (就是在同意前以及拒绝后, 不进行某些SDK的初始化…)
APP启动时,在用户授权同意隐私政策前,APP及SDK不可以提前收集和使用IMEI、OAID、IMSI、MAC、应用列表等信息
为了处理上面问题,或者说, 为了自己能够检测改版后的APP 是否符合要求, 我们就需要自己进行对APP进行检测和验证, 确保修改后达到效果
(第三方检测机构出的报告, 我们也要能自己给自己出 ╭(╯^╰)╮)
一通了解折腾以后, 我遇到了这么些框架/工具/demo, 这里逐个介绍一下
Xposed -> Dexposed -> Epic -> VirtualXposed ->HookLoginDemo
Xposed框架不用多说 rovo90 - Xposed , Xpose中文站 但是直接使用这个,需要走root,搞机等操作,较为麻烦
Dexposed 是阿里开源的 alibaba/dexposed,能在非root情况下掌控自己进程空间内的任意Java方法调用, 主要的就是用框架进行hook, 来抓取系统函数调用, 追踪三方SDK的启动情况/函数调用等
Epic - github 是weishu大神基于ART重新实现的一套 Dexposed( ART取代Dalvik成为android的运行时,Dexposed无法支持更高版本的安卓系统) 这边一篇大神的Epic介绍
Epic可以在你自己的android工程中添加依赖,
dependencies
compile 'com.github.tiann:epic:0.11.2'
然后可以通过
class ThreadMethodHook extends XC_MethodHook
@Override
protected void beforeHookedMethod(MethodHookParam param) throws Throwable
super.beforeHookedMethod(param);
Thread t = (Thread) param.thisObject;
Log.i(TAG, "thread:" + t + ", started..");
@Override
protected void afterHookedMethod(MethodHookParam param) throws Throwable
super.afterHookedMethod(param);
Thread t = (Thread) param.thisObject;
Log.i(TAG, "thread:" + t + ", exit..");
DexposedBridge.hookAllConstructors(Thread.class, new XC_MethodHook()
@Override
protected void afterHookedMethod(MethodHookParam param) throws Throwable
super.afterHookedMethod(param);
Thread thread = (Thread) param.thisObject;
Class<?> clazz = thread.getClass();
if (clazz != Thread.class)
Log.d(TAG, "found class extend Thread:" + clazz);
DexposedBridge.findAndHookMethod(clazz, "run", new ThreadMethodHook());
Log.d(TAG, "Thread: " + thread.getName() + " class:" + thread.getClass() + " is created.");
);
DexposedBridge.findAndHookMethod(Thread.class, "run", new ThreadMethodHook());
提供的函数进行 hook操作, 但是只支持 inhook,就是你自己有android工程, 自己在项目里面添加epic依赖后, 自己写代码自己抓日志,
其实, 如果仅仅是为了验证用户隐私确认前合规的改版后APP
. Epic其实足够使用了. 借助Epic,我们可以通过移除SDK来比对监听偷跑的WIFI/MAC地址等行为是否还存在
贴一下我项目里面的一些调用
在MainActivity中, oncreat() 中调用就可以
implementation 'com.github.tiann:epic:0.11.2'
private String TAG ="ddddd";
private void startHook()
XC_MethodHook hook = new XC_MethodHook()
@Override
protected void beforeHookedMethod(MethodHookParam param) throws Throwable
super.beforeHookedMethod(param);
Object hookObj = param.thisObject;
String clsName = "unknownClass";
if (hookObj != null)
clsName = hookObj.getClass().getName();
String mdName = "unknownMethod";
if (param.method != null)
mdName = param.method.getName();
Log.d(TAG, "beforeHookedMethod: " + clsName + "-" + mdName);
@Override
protected void afterHookedMethod(MethodHookParam param) throws Throwable
super.beforeHookedMethod(param);
Object hookObj = param.thisObject;
String clsName = "unknownClass";
if (hookObj != null)
clsName = hookObj.getClass().getName();
String mdName = "unknownMethod";
if (param.method != null)
mdName = param.method.getName();
Log.d(TAG, "afterHookedMethod: " + clsName + "-" + mdName);
;
try
// hook系统方法
// hook系统方法
// DexposedBridge.hookAllMethods(Thread.class, "run", hook);
// hook构造方法
// DexposedBridge.hookAllConstructors(Thread.class, hook);
DexposedBridge.hookAllMethods(BluetoothLeScanner.class, "startScan", hook);
// deviceID
DexposedBridge.hookAllMethods(TelephonyManager.class,"getDeviceId", hook);
// wifi
DexposedBridge.hookAllMethods(WifiManager.class,"", hook);
// wifi - 构造hook
DexposedBridge.hookAllConstructors(WifiManager.class, hook);
// MAC
DexposedBridge.hookAllMethods(WifiManager.class,"getMacAddress", hook);
catch (Throwable t)
t.printStackTrace();
踩坑1: Epic依赖的
minSdkVersion
是21
, 记得把项目的minSdkVersion改为一样否则跑不了程序
但是,检测机构是如何检测我们的APP?
猜测也是借助于 VirtualXposed 等工具,自行编写hook插件 , 来扫描 提交审核的 APP
VirtualXposed - 官方介绍及使用视频 是一个apk应用程序, 目的就是
过简单的 APP 使用 Xposed,无需 root、解锁引导加载程序或刷写系统映像。
具体使用开官网/或者视频,
VirtualXposed 是基于VirtualApp 和 epic 在非ROOT环境下运行Xposed模块的实现(支持5.0~10.0)。
我最后使用的是 0.20.3 版本, 其他版本都没成功, 要么唤起不了自己的APP, 要么安装不了 Xposed install 失败
这是目前我测试确认可以使用的环境:
设备: 小米 Mix2s
Androdi版本:10
VirtualXposed版本: 0.20.3
踩坑1: VirtualXposed 仅支持到 Android 5~10 , 在2022的今天, 也好在我的Mix2s还能使用, 一开始我用公司测试机 都是Android11, 不支持…
踩坑2: 确定自己项目的APP 是 32位 还是 64位 , 32位的仅仅能使用 0.18版本
HookLoginDemo 是一个插件(也是APP) , 基于这个插件 , 可以让我们方便的对我们的APP进行hook, 通过查看日志来方便的检测
在用户同意隐私前
我们的APP或第三方SDK, 有没有偷跑一些系统API, (就像检测机构对我们APP做的检测一样
)
当然, 也可以在
HookLoginDemo
中添加跟多的检测 比如SSID / WIFI列表. 只要稍微修改代码编译成apk 安装到手机, 接着就是 VirtualXposed 的时间了
贴一下 HookLoginDemo 中
HookLogin
代码的修改 (有错误的代码… 后面再完善)
package com.example.hooklogin;
import android.app.Activity;
import android.content.ContentResolver;
import android.content.Context;
import android.location.LocationManager;
import android.util.Log;
import android.widget.AutoCompleteTextView;
import android.widget.EditText;
import android.widget.Toast;
import java.lang.reflect.Field;
import de.robv.android.xposed.IXposedHookLoadPackage;
import de.robv.android.xposed.XC_MethodHook;
import de.robv.android.xposed.XposedBridge;
import de.robv.android.xposed.XposedHelpers;
import de.robv.android.xposed.callbacks.XC_LoadPackage;
import static de.robv.android.xposed.XposedHelpers.findField;
public class HookLogin implements IXposedHookLoadPackage
private static final String TAG = "HookLogin";
public void handleLoadPackage(XC_LoadPackage.LoadPackageParam lpparam)
if (lpparam == null)
return;
Log.e(TAG, "Load app packageName:" + lpparam.packageName);
/*判断hook的包名*/
// if (!MyApplication.pageName.equals(lpparam.packageName) && !"com.enhance.kaomanfen.yasilisteningapp".equals(lpparam.packageName)
// && !"com.tal.tiku".equals(lpparam.packageName))
// return;
//
// //固定格式
// XposedHelpers.findAndHookMethod(
// "com.", // 需要hook的方法所在类的完整类名
// lpparam.classLoader, // 类加载器,固定这么写就行了
// "attachBaseContext", // 需要hook的方法名
// Context.class,
// new XC_MethodHook()
// @Override
// protected void beforeHookedMethod(MethodHookParam param)
// XposedBridge.log("调用getDeviceId()获取了imei");
//
//
// @Override
// protected void afterHookedMethod(MethodHookParam param) throws Throwable
// XposedBridge.log(getMethodStack());
// super.afterHookedMethod(param);
//
//
// );
//固定格式
XposedHelpers.findAndHookMethod(
android.telephony.TelephonyManager.class.getName(), // 需要hook的方法所在类的完整类名
lpparam.classLoader, // 类加载器,固定这么写就行了
"getDeviceId", // 需要hook的方法名
new XC_MethodHook()
@Override
protected void beforeHookedMethod(MethodHookParam param)
XposedBridge.log("调用getDeviceId()获取了imei");
@Override
protected void afterHookedMethod(MethodHookParam param) throws Throwable
XposedBridge.log(getMethodStack());
super.afterHookedMethod(param);
);
XposedHelpers.findAndHookMethod(
android.telephony.TelephonyManager.class.getName(),
lpparam.classLoader,
"getDeviceId",
int.class,
new XC_MethodHook()
@Override
protected void beforeHookedMethod(MethodHookParam param)
XposedBridge.log("调用getDeviceId(int)获取了imei");
@Override
protected void afterHookedMethod(MethodHookParam param) throws Throwable
XposedBridge.log(getMethodStack());
super.afterHookedMethod(param);
);
// XposedHelpers.findAndHookMethod(
// "com.android.internal.telephony.PhoneSubInfo",
// lpparam.classLoader,
// "getDeviceId",
// new XC_MethodHook()
// @Override
// protected void beforeHookedMethod(MethodHookParam param)
// XposedBridge.log("调用PhoneSubInfo的getDeviceId()获取了imei");
//
//
// );
XposedHelpers.findAndHookMethod(
android.telephony.TelephonyManager.class.getName(),
lpparam.classLoader,
"getSubscriberId",
int.class,
new XC_MethodHook()
@Override
protected void beforeHookedMethod(MethodHookParam param)
XposedBridge.log("调用getSubscriberId获取了imsi");
@Override
protected void afterHookedMethod(MethodHookParam param) throws Throwable
XposedBridge.log(getMethodStack());
super.afterHookedMethod(param);
);
XposedHelpers.findAndHookMethod(
android.net.wifi.WifiInfo.class.getName(),
lpparam.classLoader,
"getMacAddress",
new XC_MethodHook()
@Override
protected void beforeHookedMethod(MethodHookParam param)
XposedBridge.log("调用getMacAddress()获取了mac地址");
@Override
protected void afterHookedMethod(MethodHookParam param) throws Throwable
XposedBridge.log(getMethodStack());
super.afterHookedMethod(param);
);
// wifiName
XposedHelpers.findAndHookMethod(
android.net.wifi.WifiInfo.class.getName(),
lpparam.classLoader,
"getWifiName",
new XC_MethodHook()
protected void beforeHookedMethod(MethodHookParam param)
XposedBridge.log("调用getWifiName()获取了wifi地址");
@Override
protected void afterHookedMethod(MethodHookParam param) throws Throwable
XposedBridge.log(getMethodStack());
super.afterHookedMethod(param);
);
//SSID
XposedHelpers.findAndHookMethod(
android.net.wifi.WifiInfo.class.getName(),
lpparam.classLoader,
"getSSID",
new XC_MethodHook()
protected void beforeHookedMethod(MethodHookParam param)
XposedBridge.log("调用getSSID()获取了wifi地址");
@Override
protected void afterHookedMethod(MethodHookParam param) throws Throwable
XposedBridge.log(getMethodStack());
super.afterHookedMethod(param);
);
//BSSID
XposedHelpers.findAndHookMethod(
android.net.wifi.WifiInfo.class.getName(),
lpparam.classLoader,
"getBSSID",
new XC_MethodHook()
protected void beforeHookedMethod(MethodHookParam param)
XposedBridge.log("调用getBSSID()获取了wifi地址");
@Override
protected void afterHookedMethod(MethodHookParam param) throws Throwable
XposedBridge.log(getMethodStack());
super.afterHookedMethod(param);
);
XposedHelpers.findAndHookMethod(
java.net.NetworkInterface.class.getName(),
lpparam.classLoader,
"getHardwareAddress",
new XC_MethodHook()
@Override
protected void beforeHookedMethod(MethodHookParam param)
XposedBridge.log("调用getHardwareAddress()获取了mac地址");
@Override
protected void afterHookedMethod(MethodHookParam param) throws Throwable
XposedBridge.log(getMethodStack());
super.afterHookedMethod(param);
);
XposedHelpers.findAndHookMethod(
android.provider.Settings.Secure.class.getName(),
lpparam.classLoader,
"getString",
ContentResolver.class,
以上是关于android隐私违规获取问题处理 及 Hook拦截处理记录 (VirtualXposted/epic等)的主要内容,如果未能解决你的问题,请参考以下文章
隐私保护!27%的Android手机APP越界获取用户隐私权限
在 ZipOutputStream.write() 方法中强化隐私违规