最终由 IIntegrityService 做为服务端处理来自客户端的请求,至此我们正式进入 Google Play 源码分析。
由于篇幅的关系,我这里不展开 c 以及一系列子函数的调用。我只大概讲一下它的流程:
在收集的所有信息中,最为人津津乐道的便是 Tee 签名的证书链。这是由绝对安全的硬件空间生成的设备描述信息,按理说是绝对可信的。因为,一旦你更改了返回的证书链,你没办法重签。不重签后端就不认这个证书链,直接判定为伪造。你想要重签,就必须拿到私钥,可是私钥放到 Tee 中,不可导出不可读取。因此,形成了完美闭环。
这套完美的防御体系,看似无懈可击。但是当 Tee 私钥泄漏了之后呢?这条防御链条中最重要的一环,将土崩瓦解。
Google Play 版本均保持一致(过 AttestationApplicationId 签名校验)
我们使用如下 Frida 脚本启动 Pixel 的 Google Play:
如下脚本启动 Y700 的 Google Play:
然后惊奇的发现:
设备
是否具有Root 权限
是否通过 Google Integrity 验证
Y700
是
是
Pixel 6
是
否
import com.google.android.gms.tasks.Task; ...
// Receive the nonce from the secure server.Stringnonce= ...
// Create an instance of a manager.IntegrityManagerintegrityManager=
IntegrityManagerFactory.create(getApplicationContext());
// Request the integrity token by providing a nonce.
Task<IntegrityTokenResponse> integrityTokenResponse =
integrityManager
.requestIntegrityToken(
IntegrityTokenRequest.builder().setNonce(nonce).build());
import com.google.android.gms.tasks.Task;
// Create an instance of a manager.
StandardIntegrityManager standardIntegrityManager =
IntegrityManagerFactory.createStandard(applicationContext);
StandardIntegrityTokenProvider integrityTokenProvider;
long cloudProjectNumber = ...;
// Prepare integrity token. Can be called once in a while to keep internal
// state fresh.
standardIntegrityManager.prepareIntegrityToken(
PrepareIntegrityTokenRequest.builder()
.setCloudProjectNumber(cloudProjectNumber)
.build())
.addOnSuccessListener(tokenProvider -> {
integrityTokenProvider = tokenProvider;
})
.addOnFailureListener(exception -> handleError(exception));