0


Frida hook 双向证书秘钥

frida hook 双向证书秘钥

spawn 模式启动:

frida -U -f 包名 -l keystore.js --no-pause

加 – no-pause与不加 --no-pause的区别主要是 hook时机的早晚。 --no-pause是即时hook, 而不加 --no-pause 这个参数的话。frida会拉起进程,停在加载主界面之前,这时候 应用会出现白屏状态,就像

恢复主线程运行的话,这里要手动用 %resume关键字。

这种方法的原理是, 在手动用%resume关键字恢复主线程运行之前,frida已经拉起了进程,外壳程序已经在启动,所以这里等个几秒用%resume关键字恢复,有一定几率是可以hook到的。

/*
Android keystore hooks + utilities

All instances of keystore are captured by hooking any getInstance() calls.
You can find them in keystoreList variable.

Utilities:

KeystoreListAllAliases()
ListAliasesStatic()
* List all aliases in keystores of known hardcoded types(in keystoreTypes)

KeystoreListAllAliasesOnAllInstances()
ListAliasesRuntime()
* List all aliases in keystores of all instances obtained during app runtime.
* Instances that will be dumped are collected via hijacking
* Keystore.getInstance() -> hookKeystoreGetInstance()

ListAliasesAndroid()
* List all aliases in AndroidKeyStore.

ListAliasesType(String type)
* List all aliases in a keystore of given 'type'.
* Example: ListAliasesType('AndroidKeyStore');

ListAliasesObj(Object obj)
* List all aliases for a given keystore object.
* Example: ListAliasesObj(keystoreObj);

GetKeyStore(String name)
* Retrieve keystore instance from keystoreList.
* Example: GetKeyStore("KeyStore...@af102a");

AliasInfo(String alias)
* List keystore key properties in a JSON object.
* Example: AliasInfo('secret');

*/

Java.perform(function(){hookKeystoreGetInstance();hookKeystoreGetInstance_Provider();hookKeystoreGetInstance_Provider2();hookKeystoreConstructor();hookKeystoreLoad(false);hookKeystoreLoadStream(false);hookKeystoreGetKey();hookKeystoreSetKeyEntry();//hookKeystoreGetCertificate();hookKeystoreGetCertificateChain();hookKeystoreGetEntry();hookKeystoreSetEntry();hookKeystoreSetKeyEntry();hookKeystoreSetKeyEntry2();hookKeystoreStore();hookKeystoreStoreStream()});
console.log("KeyStore hooks loaded!");var keystoreList =[];var StringCls =null;
Java.perform(function(){
    StringCls = Java.use('java.lang.String');});functionhookKeystoreConstructor(){var keyStoreConstructor = Java.use('java.security.KeyStore').$init.overload("java.security.KeyStoreSpi","java.security.Provider","java.lang.String");
    keyStoreConstructor.implementation=function(keyStoreSpi, provider, type){//console.log("[Call] Keystore(java.security.KeyStoreSpi, java.security.Provider, java.lang.String )")
        console.log("[Keystore()]: KeyStoreSpi: "+ keyStoreSpi +", Provider: "+ provider +", type: "+ type);returnthis.$init(keyStoreSpi, provider, type);}}functionhookKeystoreGetInstance(){var keyStoreGetInstance = Java.use('java.security.KeyStore')['getInstance'].overload("java.lang.String");
    keyStoreGetInstance.implementation=function(type){//console.log("[Call] Keystore.getInstance(java.lang.String )")
        console.log("[Keystore.getInstance()]: type: "+ type);var tmp =this.getInstance(type);
        keystoreList.push(tmp);// Collect keystore objects to allow dump them later using ListAliasesRuntime()return tmp;}}functionhookKeystoreGetInstance_Provider(){var keyStoreGetInstance = Java.use('java.security.KeyStore')['getInstance'].overload("java.lang.String","java.lang.String");
    keyStoreGetInstance.implementation=function(type, provider){//console.log("[Call] Keystore.getInstance(java.lang.String, java.lang.String )")
        console.log("[Keystore.getInstance2()]: type: "+ type +", provider: "+ provider);var tmp =this.getInstance(type, proivder);
        keystoreList.push(tmp);// Collect keystore objects to allow dump them later using ListAliasesRuntime()return tmp;}}functionhookKeystoreGetInstance_Provider2(){var keyStoreGetInstance = Java.use('java.security.KeyStore')['getInstance'].overload("java.lang.String","java.security.Provider");
    keyStoreGetInstance.implementation=function(type, provider){//console.log("[Call] Keystore.getInstance(java.lang.String, java.security.Provider )")
        console.log("[Keystore.getInstance2()]: type: "+ type +", provider: "+ provider);var tmp =this.getInstance(type, proivder);
        keystoreList.push(tmp);// Collect keystore objects to allow dump them later using ListAliasesRuntime()return tmp;}}/*
* Hook Keystore.load( ... ), set dump to true if you want to perform dump of available Aliases automatically.
*/functionhookKeystoreLoad(dump){var keyStoreLoad = Java.use('java.security.KeyStore')['load'].overload('java.security.KeyStore$LoadStoreParameter');/* following function hooks to a Keystore.load(java.security.KeyStore.LoadStoreParameter) */
    keyStoreLoad.implementation=function(param){//console.log("[Call] Keystore.load(java.security.KeyStore.LoadStoreParameter)")
        console.log("[Keystore.load(LoadStoreParameter)]: keystoreType: "+this.getType()+", param: "+ param);this.load(param);if(dump) console.log(" Keystore loaded aliases: "+ListAliasesObj(this));}}/*
* Hook Keystore.load( ... ), set dump to true if you want to perform dump of available Aliases automatically.
*/functionhookKeystoreLoadStream(dump){var keyStoreLoadStream = Java.use('java.security.KeyStore')['load'].overload('java.io.InputStream','[C');/* following function hooks to a Keystore.load(InputStream stream, char[] password) */
    keyStoreLoadStream.implementation=function(stream, charArray){//console.log("[Call] Keystore.load(InputStream stream, char[] password)")//var hexString = readStreamToHex (stream);
        console.log("[Keystore.load(InputStream, char[])]: keystoreType: "+this.getType()+", password: '"+charArrayToString(charArray)+"', inputSteam: "+ stream);this.load(stream, charArray);if(dump) console.log(" Keystore loaded aliases: "+ListAliasesObj(this));}}functionhookKeystoreStore(){var keyStoreStoreStream = Java.use('java.security.KeyStore')['store'].overload('java.security.KeyStore$LoadStoreParameter');/* following function hooks to a Keystore.store(java.security.KeyStore$LoadStoreParameter) */
    keyStoreStoreStream.implementation=function(param){
        console.log("[Keystore.store()]: keystoreType: "+this.getType()+", param: '"+ param);this.store(stream, charArray);}}functionhookKeystoreStoreStream(){var keyStoreStoreStream = Java.use('java.security.KeyStore')['store'].overload('java.io.OutputStream','[C');/* following function hooks to a Keystore.store(OutputStream stream, char[] password) */
    keyStoreStoreStream.implementation=function(stream, charArray){
        console.log("[Keystore.store(OutputStream, char[])]: keystoreType: "+this.getType()+", password: '"+charArrayToString(charArray)+"', outputSteam: "+ stream);this.store(stream, charArray);}}functionhookKeystoreGetKey(){var keyStoreGetKey = Java.use('java.security.KeyStore')['getKey'].overload("java.lang.String","[C");
    keyStoreGetKey.implementation=function(alias, charArray){//console.log("[Call] Keystore.getKey(java.lang.String, [C )")
        console.log("[Keystore.getKey()]: alias: "+ alias +", password: '"+charArrayToString(charArray)+"'");returnthis.getKey(alias, charArray);}}functionhookKeystoreSetEntry(){var keyStoreSetKeyEntry = Java.use('java.security.KeyStore')['setEntry'].overload("java.lang.String","java.security.KeyStore$Entry","java.security.KeyStore$ProtectionParameter");
    keyStoreSetKeyEntry.implementation=function(alias, entry, protection){//console.log("[Call] Keystore.setEntry(java.lang.String, java.security.KeyStore$Entry, java.security.KeyStore$ProtectionParameter )")
        console.log("[Keystore.setEntry()]: alias: "+ alias +", entry: "+dumpKeyStoreEntry(entry)+"', protection: "+dumpProtectionParameter(protection));returnthis.setEntry(alias, entry, protection);}}functionhookKeystoreSetKeyEntry(){var keyStoreSetKeyEntry = Java.use('java.security.KeyStore')['setKeyEntry'].overload("java.lang.String","java.security.Key","[C","[Ljava.security.cert.Certificate;");
    keyStoreSetKeyEntry.implementation=function(alias, key, charArray, certs){//console.log("[Call] Keystore.setKeyEntry(java.lang.String, java.security.Key, [C, [Ljava.security.cert.Certificate; )
        console.log("[Keystore.setKeyEntry()]: alias: "+ alias +", key: "+ key +", password: '"+charArrayToString(charArray)+"', certs: "+ certs);returnthis.setKeyEntry(alias, key, charArray, certs);}}functionhookKeystoreSetKeyEntry2(){var keyStoreSetKeyEntry = Java.use('java.security.KeyStore')['setKeyEntry'].overload("java.lang.String","[B","[Ljava.security.cert.Certificate;");
    keyStoreSetKeyEntry.implementation=function(alias, key, certs){//console.log("[Call] Keystore.setKeyEntry(java.lang.String, [B, [Ljava.security.cert.Certificate; )")
        console.log("[Keystore.setKeyEntry2()]: alias: "+ alias +", key: "+ key +"', certs: "+ certs);returnthis.setKeyEntry(alias, key, certs);}}/*
* Usually used to load certs for cert pinning.
*/functionhookKeystoreGetCertificate(){var keyStoreGetCertificate = Java.use('java.security.KeyStore')['getCertificate'].overload("java.lang.String");
    keyStoreGetCertificate.implementation=function(alias){//console.log("[Call] Keystore.getCertificate(java.lang.String )")
        console.log("[Keystore.getCertificate()]: alias: "+ alias);returnthis.getCertificate(alias);}}/*
* Usually used to load certs for cert pinning.
*/functionhookKeystoreGetCertificateChain(){var keyStoreGetCertificate = Java.use('java.security.KeyStore')['getCertificateChain'].overload("java.lang.String");
    keyStoreGetCertificate.implementation=function(alias){//console.log("[Call] Keystore.getCertificateChain(java.lang.String )")
        console.log("[Keystore.getCertificateChain()]: alias: "+ alias);returnthis.getCertificateChain(alias);}}functionhookKeystoreGetEntry(){var keyStoreGetEntry = Java.use('java.security.KeyStore')['getEntry'].overload("java.lang.String","java.security.KeyStore$ProtectionParameter");
    keyStoreGetEntry.implementation=function(alias, protection){//console.log("[Call] Keystore.getEntry(java.lang.String, java.security.KeyStore$ProtectionParameter )")
        console.log("[Keystore.getEntry()]: alias: "+ alias +", protection: '"+dumpProtectionParameter(protection)+"'");var entry =this.getEntry(alias, protection);
        console.log("[getEntry()]: Entry: "+dumpKeyStoreEntry(entry));return entry;}}functiondumpProtectionParameter(protection){if(protection !=null){// android.security.keystore.KeyProtection, java.security.KeyStore.CallbackHandlerProtection, java.security.KeyStore.PasswordProtection, android.security.KeyStoreParametervar protectionCls = protection.$className;if(protectionCls.localeCompare("android.security.keystore.KeyProtection")==0){return""+ protectionCls +" [implement dumping if needed]";}elseif(protectionCls.localeCompare("java.security.KeyStore.CallbackHandlerProtection")==0){return""+ protectionCls +" [implement dumping if needed]";}elseif(protectionCls.localeCompare("java.security.KeyStore.PasswordProtection")==0){
            getPasswordMethod = Java.use('java.security.KeyStore.PasswordProtection')['getPassword'];
            password =getPasswordMethod.call(protection);return"password: "+charArrayToString(password);}elseif(protectionCls.localeCompare("android.security.KeyStoreParameter")==0){
            isEncryptionRequiredMethod = Java.use('android.security.KeyStoreParameter')['isEncryptionRequired'];
            result =isEncryptionRequiredMethod.call(protection);return"isEncryptionRequired: "+ result;}elsereturn"Unknown protection parameter type: "+ protectionCls;}elsereturn"null";}functiondumpKeyStoreEntry(entry){// java.security.KeyStore$PrivateKeyEntry, java.security.KeyStore$SecretKeyEntry, java.security.KeyStore$TrustedCertificateEntry, android.security.WrappedKeyEntryif(entry !=null){var entryCls = entry.$className;var castedEntry = Java.cast(entry, Java.use(entryCls));if(entryCls.localeCompare("java.security.KeyStore$PrivateKeyEntry")==0){var getPrivateKeyEntryMethod = Java.use('java.security.KeyStore$PrivateKeyEntry')['getPrivateKey'];var key =getPrivateKeyEntryMethod.call(castedEntry);return""+ entryCls +" [implement key dumping if needed] "+ key.$className;}elseif(entryCls.localeCompare("java.security.KeyStore$SecretKeyEntry")==0){var getSecretKeyMethod = Java.use('java.security.KeyStore$SecretKeyEntry')['getSecretKey'];var key =getSecretKeyMethod.call(castedEntry);var keyGetFormatMethod = Java.use(key.$className)['getFormat'];var keyGetEncodedMethod = Java.use(key.$className)['getEncoded'];//console.log(""+key.$className);if(key.$className.localeCompare("android.security.keystore.AndroidKeyStoreSecretKey")==0)return"keyClass: android.security.keystore.AndroidKeyStoreSecretKey can't dump";return"keyFormat: "+keyGetFormatMethod.call(key)+", encodedKey: '"+keyGetEncodedMethod.call(key)+"', key: "+ key;}elseif(entryCls.localeCompare("java.security.KeyStore$TrustedCertificateEntry")==0){return""+ entryCls +" [implement key dumping if needed]";}elseif(entryCls.localeCompare("android.security.WrappedKeyEntry")==0){return""+ entryCls +" [implement key dumping if needed]";}elsereturn"Unknown key entry type: "+ entryCls;}elsereturn"null";}/*
* Dump all aliasses in keystores of all types(predefined in keystoreTypes)
*/functionListAliasesStatic(){// BCPKCS12/PKCS12-DEF - exceptionsvar keystoreTypes =["AndroidKeyStore","AndroidCAStore",/*"BCPKCS12",*/"BKS","BouncyCastle","PKCS12",/*"PKCS12-DEF"*/];
    keystoreTypes.forEach(function(entry){
        console.log("[ListAliasesStatic] keystoreType: "+ entry +" \nAliases: "+ListAliasesType(entry));});return"[done]";}/*
* Dump all aliasses in keystores of all instances obtained during app runtime.
* Instances that will be dumped are collected via hijacking Keystre.getInstance() -> hookKeystoreGetInstance()
*/functionListAliasesRuntime(){
    Java.perform(function(){
        console.log("[ListAliasesRuntime] Instances: "+ keystoreList);
        keystoreList.forEach(function(entry){
            console.log("[ListAliasesRuntime] keystoreObj: "+ entry +" type: "+ entry.getType()+" \n"+ListAliasesObj(entry));});});return"[done]";}/*
* Dump all aliasses in AndroidKey keystore.
*/functionListAliasesAndroid(){returnListAliasesType("AndroidKeyStore");}/*
* Dump all aliasses in keystore of given 'type'.
* Example: ListAliasesType('AndroidKeyStore');
*/functionListAliasesType(type){var result =[];
    Java.perform(function(){var keyStoreCls = Java.use('java.security.KeyStore');var keyStoreObj = keyStoreCls.getInstance(type);
        keyStoreObj.load(null);var aliases = keyStoreObj.aliases();//console.log("aliases: " + aliases.getClass());while(aliases.hasMoreElements()){
            result.push("'"+ aliases.nextElement()+"'");}});return result;}/*
* Dump all aliasses for a given keystore object.
* Example: ListAliasesObj(keystoreObj);
*/functionListAliasesObj(obj){var result =[];
    Java.perform(function(){var aliases = obj.aliases();while(aliases.hasMoreElements()){
            result.push(aliases.nextElement()+"");}});return result;}/*
* Retrieve keystore instance from keystoreList
* Example: GetKeyStore("KeyStore...@af102a");
*/functionGetKeyStore(keystoreName){var result =null;
    Java.perform(function(){for(var i =0; i < keystoreList.length; i++){if(keystoreName.localeCompare(""+ keystoreList[i])==0)
                result = keystoreList[i];}});return result;}/*
* Dump keystore key properties in JSON object
* Example: AliasInfo('secret');
*/functionAliasInfo(keyAlias){var result ={};
    Java.perform(function(){var keyStoreCls = Java.use('java.security.KeyStore');var keyFactoryCls = Java.use('java.security.KeyFactory');var keyInfoCls = Java.use('android.security.keystore.KeyInfo');var keySecretKeyFactoryCls = Java.use('javax.crypto.SecretKeyFactory');var keyFactoryObj =null;var keyStoreObj = keyStoreCls.getInstance('AndroidKeyStore');
        keyStoreObj.load(null);var key = keyStoreObj.getKey(keyAlias,null);if(key ==null){
            console.log('key does not exist');returnnull;}try{
            keyFactoryObj = keyFactoryCls.getInstance(key.getAlgorithm(),'AndroidKeyStore');}catch(err){
            keyFactoryObj = keySecretKeyFactoryCls.getInstance(key.getAlgorithm(),'AndroidKeyStore');}var keyInfo = keyFactoryObj.getKeySpec(key, keyInfoCls.class);
        result.keyAlgorithm = key.getAlgorithm();
        result.keySize = keyInfoCls['getKeySize'].call(keyInfo);
        result.blockModes = keyInfoCls['getBlockModes'].call(keyInfo);
        result.digests = keyInfoCls['getDigests'].call(keyInfo);
        result.encryptionPaddings = keyInfoCls['getEncryptionPaddings'].call(keyInfo);
        result.keyValidityForConsumptionEnd = keyInfoCls['getKeyValidityForConsumptionEnd'].call(keyInfo);if(result.keyValidityForConsumptionEnd !=null) result.keyValidityForConsumptionEnd = result.keyValidityForConsumptionEnd.toString();
        result.keyValidityForOriginationEnd = keyInfoCls['getKeyValidityForOriginationEnd'].call(keyInfo);if(result.keyValidityForOriginationEnd !=null) result.keyValidityForOriginationEnd = result.keyValidityForOriginationEnd.toString();
        result.keyValidityStart = keyInfoCls['getKeyValidityStart'].call(keyInfo);if(result.keyValidityStart !=null) result.keyValidityStart = result.keyValidityStart.toString();
        result.keystoreAlias = keyInfoCls['getKeystoreAlias'].call(keyInfo);
        result.origin = keyInfoCls['getOrigin'].call(keyInfo);
        result.purposes = keyInfoCls['getPurposes'].call(keyInfo);
        result.signaturePaddings = keyInfoCls['getSignaturePaddings'].call(keyInfo);
        result.userAuthenticationValidityDurationSeconds = keyInfoCls['getUserAuthenticationValidityDurationSeconds'].call(keyInfo);
        result.isInsideSecureHardware = keyInfoCls['isInsideSecureHardware'].call(keyInfo);
        result.isInvalidatedByBiometricEnrollment = keyInfoCls['isInvalidatedByBiometricEnrollment'].call(keyInfo);try{ result.isTrustedUserPresenceRequired = keyInfoCls['isTrustedUserPresenceRequired'].call(keyInfo);}catch(err){}
        result.isUserAuthenticationRequired = keyInfoCls['isUserAuthenticationRequired'].call(keyInfo);
        result.isUserAuthenticationRequirementEnforcedBySecureHardware = keyInfoCls['isUserAuthenticationRequirementEnforcedBySecureHardware'].call(keyInfo);
        result.isUserAuthenticationValidWhileOnBody = keyInfoCls['isUserAuthenticationValidWhileOnBody'].call(keyInfo);try{ result.isUserConfirmationRequired = keyInfoCls['isUserConfirmationRequired'].call(keyInfo);}catch(err){}//console.log(" result: " + JSON.stringify(result));//console.log("aliases: " + aliases.getClass());});return result;}/* following function reads an InputStream and returns an ASCII char representation of it */functionreadStreamToHex(stream){var data =[];var byteRead = stream.read();while(byteRead !=-1){
        data.push(('0'+(byteRead &0xFF).toString(16)).slice(-2));/* <---------------- binary to hex ---------------> */
        byteRead = stream.read();}
    stream.close();return data.join('');}functioncharArrayToString(charArray){if(charArray ==null)return'(null)';elsereturn StringCls.$new(charArray);}
标签: java android javascript

本文转载自: https://blog.csdn.net/weixin_38927522/article/details/127093292
版权归原作者 Codeooo 所有, 如有侵权,请联系我们删除。

“Frida hook 双向证书秘钥”的评论:

还没有评论