请选择 进入手机版 | 继续访问电脑版

Android 违规获取用户隐私(获取MAC地址)整改

[复制链接]
为你演绎 发表于 2021-1-1 18:33:01 | 显示全部楼层 |阅读模式 打印 上一主题 下一主题
前几天,收到公司App违规收取用户隐私的邮件,说是存在收集设备MAC地点的行为。
这就让我很方了,上次已经整改过一次违规获取用户隐私的问题了,这次又来。。
因为上次整改的时候,已将所有的第三方库移到用户同意了隐私协议后,才去初始化的,自己的代码又不会去获取这些数据,理应不会再出现获取,所以就很希奇,不知道那边出了问题。
厥后想到,既然是去获取了MAC地点,肯定要调用系统的API,那么我只要去HOOK系统的方法,就可以知道在什么时候,去获取了MAC地点了。
由于各个系统版本获取MAC地点的方式差别,所以特意拿了个Android5.1的手机举行测试。
  1.         /**     * Android 6.0 之前(不包括6.0)获取mac地点     * 必须的权限      *     * @param context * @return     */    private String getMacDefault(Context context) {        String mac = "0";        if (context == null) {            return mac;        }        WifiManager wifi = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);        WifiInfo info = null;        try {            info = wifi.getConnectionInfo();        } catch (Exception e) {            e.printStackTrace();        }        if (info == null) {            return null;        }        mac = info.getMacAddress();        return mac;    }
复制代码
可以看到,我们在Android6.0以前是通过WifiManager.getConnectionInfo()的方式来获取相关数据的。
我们来看下这个方法。
  1.         IWifiManager mService;        public WifiInfo getConnectionInfo() {               try {                   return mService.getConnectionInfo(mContext.getOpPackageName());               } catch (RemoteException e) {                   throw e.rethrowFromSystemServer();               }           }
复制代码
可以看到,这里调用的是IWifiManager.getConnectionInfo(),IWifiManager是一个接口
  1.         interface IWifiManager{                WifiInfo getConnectionInfo(String callingPackage);                ...        }
复制代码
那么这个IWifiManager是什么时候被赋值的呢?我们回到context.getSystemService(Context.WIFI_SERVICE);
我们知道,context的实现类实在是ContextImpl.java,我们直接来看ContextImpl.getSystemService()
  1.         @Override    public Object getSystemService(String name) {        return SystemServiceRegistry.getSystemService(this, name);    }
复制代码
我们可以看到,这里调用了SystemServiceRegistry.getSystemService(this, name);
我们再来看这个类
  1.         public static Object getSystemService(ContextImpl ctx, String name) {        ServiceFetcher fetcher = SYSTEM_SERVICE_FETCHERS.get(name);        return fetcher != null ? fetcher.getService(ctx) : null;    }
复制代码

这里的SYSTEM_SERVICE_FETCHERS是一个Map iWifiManager = Class.forName("android.net.wifi.IWifiManager");            Field serviceField = WifiManager.class.getDeclaredField("mService");            serviceField.setAccessible(true);            WifiManager wifi = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);            // real mService            Object realIwm = serviceField.get(wifi);            // replace mService  with Proxy.newProxyInstance            serviceField.set(wifi, Proxy.newProxyInstance(iWifiManager.getClassLoader(),                    new Class[]{iWifiManager},                    new InvocationHandler(tag, "getConnectionInfo", realIwm)));            Log.i(tag, "wifiManager hook success");        } catch (Exception e) {            Log.e(tag, "printStackTrace:" + e.getMessage());            e.printStackTrace();        }    }    public static class InvocationHandler implements java.lang.reflect.InvocationHandler {        private final String tag;        private final String methodName;        private Object real;        public InvocationHandler(String tag, String methodName, Object real) {            this.real = real;            this.methodName = methodName;            this.tag = tag;        }        @Override        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {            Log.d(tag, "method invoke " + method.getName());            if (methodName.equals(method.getName())) {                if (cacheWifiInfo != null) {                    Log.d(tag, "cacheWifiInfo:" + cacheWifiInfo);                    return cacheWifiInfo;                }                WifiInfo wifiInfo = null;                try {                    Class cls = WifiInfo.class;                    wifiInfo = (WifiInfo) cls.newInstance();                    Field mMacAddressField = cls.getDeclaredField("mMacAddress");                    mMacAddressField.setAccessible(true);                    mMacAddressField.set(wifiInfo, "");                    cacheWifiInfo = wifiInfo;                    Log.d(tag, "wifiInfo:" + wifiInfo);                } catch (Exception e) {                    Log.e(tag, "WifiInfo error:" + e.getMessage());                }                return wifiInfo;            } else {                return method.invoke(real, args);            }        }    }}[/code] 然后举行Hook
  1.      HookUtils.hookMacAddress("Z-Application",getApplicationContext());     HookUtils.hookMacAddress("Z-Activity",MainActivity.this);     HookUtils.hookMacAddress("Z-Service",MyService.this);
复制代码
最后,运行步伐,可以看到,当获取Mac地点的时候,会打印相关日志。
  1. method invoke getConnectionInfo
复制代码
至此,我们就Hook乐成了。
然后,我们就可以在App出现这个日志的时候,定位到是哪个功能调用了Mac地点。
我们这最终定位到是点击了隐私协议,通过腾讯X5 WebView显示H5页面的时候,调用了Mac地点。
最终,通过Hook MAC地点方法,当获取MAC地点的时候,举行全局的拦截,返回一个空的MAC地点,使其无法获取到真正的MAC地点。
  参考 Hook之WifiManager

来源:https://blog.csdn.net/EthanCo/article/details/111544333
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则


专注素材教程免费分享
全国免费热线电话

18768367769

周一至周日9:00-23:00

反馈建议

27428564@qq.com 在线QQ咨询

扫描二维码关注我们

Powered by Discuz! X3.4© 2001-2013 Comsenz Inc.( 蜀ICP备2021001884号-1 )