android签名检测和绕过
PackageManagerService获取签名
正常APP中获取PackageInfo中的签名信息是通过Binder通讯向PackageManagerService发送TRANSACTION_getPackageInfo请求,同时设置请求的参数的flag为GET_SIGNATURES。当PackageManagerService判断是TRANSACTION_getPackageInfo请求后会去调用PackageManagerService.getPackageInfo。

PackageManagerService.getPackageInfo 会进一步调用PackageManagerService.getPackageInfoInternal

PackageManagerService.getPackageInfoInternal会进行一些权限校验和匹配,最后调用PackageManagerService.generatePackageInfo

PackageManagerService.generatePackageInfo获取到包名对应的PackageParser.Package,然后调用PackageParser.generatePackageInfo

PackageParser.generatePackageInfo就是取出PackageParser.Package对象中的成员mSigningDetails.pastsigningcertificates[0] / mSigningDetails.signatures的值,此值就是apk对应的签名信息。

而每个apk包对应的PackageParser.Package保存在PackageManagerService的mPackages成员中。这是一个map表,键是包名,值就是PackageParser.Package,而apk的签名信息就保存在PackageParser.Package对象中的成员mSigningDetails.pastsigningcertificates[0] / mSigningDetails.signatures中。在apk安装的时候,会将解析的apk签名保存(put)在mPackages中。

总结:APK进程中获取自身签名实际就是获取PackageManagerService的mPackages成员中包名对应的PackageParser.Package.mSigningDetails.pastsigningcertificates[0] / mSigningDetails.signatures。
PackageManagerService获取签名绕过
- APP进程直接通过
getApplicationContext().getPackageManager().getPackageInfo(packagename, PackageManager.GET_SIGNATURES)获取签名信息 - APP进程利用
Binder通讯直接向PackageManagerService发送TRANSACTION_getPackageInfo请求获取签名信息 - 将1和2java层的操作拿到native层利用反射执行同样的操作。
以上获取签名的方式本质上都是获取PackageManagerService的mPackages成员中包名对应的PackageParser.Package.mSigningDetails.pastsigningcertificates[0] / mSigningDetails.signatures,只要在整个通讯的中间的任意一个位置进行hook就可以将签名信息进行替换,获取直接修改PackageManagerService的mPackages成员中包名对应的PackageParser.Package.mSigningDetails.pastsigningcertificates[0] / mSigningDetails.signatures值为指定签名就可以绕过上面的签名检测。

浙公网安备 33010602011771号