在重构某个apk的时候,偶然发现了友盟在使用一个叫utdid的库,感觉是生成UUID用的,刚好对UUID的生成逻辑比较感兴趣,就有了下文。

一、utdid实现过程分析

   publicstatic String getUtdid(Context arg2)是utdid库对外调用的接口, 在com.ta.utdid2.device.UTDevice类里

   具体代码如下图:

主要功能在com.ta.utdid2.device.UTUtdid.getValue()里面

utdid主要获取和生成流程如下:

1.从Setting.System读取"mqBRboGZkQPcAkyk",如果有值,则直接作为utid使用,如果获取失败,继续读"dxCRMxhQkdGePGnp",这里面的值是utid使用aes加密后,再进行base64编译的结果,对其进行解密,即可得到utid,并将"mqBRboGZkQPcAkyk"的值,修改正确。失败则进行下一步

2.从name为"Alvin2"的SharedPreferences读取UTDID做为utdid,对其进行读取校验,失败就从name为"ContextData"的SharedPreferences里读取K_1171477665,对读取值进行解密,如果解密后的结果正确,则将其作为utdid返回

3.上面的缓存都失败了,那就只有生成了。

生成函数为:com.ta.utdid2.device.UTUtdid. _generateUtdid()

阿里系UTDID库生成唯一性ID分析_第1张图片
生成的时候会引入两个随机值,一个是时间,一个是Random,然后跟IMEI串联起来,IMEI如果获取不成功就再用一个Random.这里的生成因子其实就是两个随机值外加IMEI。

IMEI的获取是相当不稳定的。部分安全软件会拦截此值的获取,小米手机很早就可以设置让此值返回为空。6.0系统以后,在targetSDKVersion为23的条件下,IMEI默认也是获取不到的。

所以这里来源因子比较弱,很大可能最终结果就是一个随机值。

二、utdid可能存在的风险

个人认为这种唯一性ID生成方式是有安全问题的

1.从Setting.System读取到的"mqBRboGZkQPcAkyk"值即是utdid,而Setting.System无任何权限的情况下也可以读取,这样第三方app都可以去读取。这样会导致utdid外泄。

2.第三方app甚至可以让用户手机上的阿里utdid设置成他想要的值,只要添加<uses-permissionandroid:name="android.permission.WRITE_SETTINGS"/>即可。

   大概撸了几个阿里的apk看了一下,使用的有友盟、虾米音乐、阿里小智、老版本的支付宝、淘宝等

   public static String getUtdid(Context arg2)

  下面的两幅图是随便找了两个app,用jeb分析getUtdid接口的交叉引用,可以看到哪些模块再调用这个接口

阿里系UTDID库生成唯一性ID分析_第2张图片
阿里系UTDID库生成唯一性ID分析_第3张图片

   比较了支付宝的不同的版本,一个是去年的8.4.0.120608,一个是今年的9.3.1.120312,发现8.4时候,支付宝的唯一性id使用的还是这个库,9.3版本已经不再使用这个库了,而是从libsecuritysdk-x.x.x.so这个so库来生成一个加密的uuid。支付宝可能也是意识到这样的安全问题,所以做了更改。后面有时间再分析一下libsecuritysdk.so里utdid的生成逻辑。