|
// Copied from https://codeshare.frida.re/@akabe1/frida-multiple-unpinning/ at the time of writing this gist. |
|
// Copied here in case codeshare ever goes down/disapears. |
|
|
|
/* Android ssl certificate pinning bypass script for various methods |
|
by Maurizio Siddu |
|
|
|
Run with: |
|
frida -U -f [APP_ID] -l frida_multiple_unpinning.js --no-pause |
|
*/ |
|
|
|
setTimeout(function() { |
|
Java.perform(function () { |
|
console.log(''); |
|
console.log('======'); |
|
console.log('[#] Android Bypass for various Certificate Pinning methods [#]'); |
|
console.log('======'); |
|
|
|
|
|
var X509TrustManager = Java.use('javax.net.ssl.X509TrustManager'); |
|
var SSLContext = Java.use('javax.net.ssl.SSLContext'); |
|
|
|
|
|
// TrustManager (Android < 7) |
|
var TrustManager = Java.registerClass({ |
|
// Implement a custom TrustManager |
|
name: 'dev.asd.test.TrustManager', |
|
implements: [X509TrustManager], |
|
methods: { |
|
checkClientTrusted: function (chain, authType) {}, |
|
checkServerTrusted: function (chain, authType) {}, |
|
getAcceptedIssuers: function () {return []; } |
|
} |
|
}); |
|
|
|
// Prepare the TrustManager array to pass to SSLContext.init() |
|
var TrustManagers = [TrustManager.$new()]; |
|
// Get a handle on the init() on the SSLContext class |
|
var SSLContext_init = SSLContext.init.overload( |
|
'[Ljavax.net.ssl.KeyManager;', '[Ljavax.net.ssl.TrustManager;', 'java.security.SecureRandom'); |
|
try { |
|
// Override the init method, specifying the custom TrustManager |
|
SSLContext_init.implementation = function(keyManager, trustManager, secureRandom) { |
|
console.log('[+] Bypassing Trustmanager (Android < 7) request'); |
|
SSLContext_init.call(this, keyManager, TrustManagers, secureRandom); |
|
}; |
|
|
|
} catch (err) { |
|
console.log('[-] TrustManager (Android < 7) pinner not found'); |
|
//console.log(err); |
|
} |
|
|
|
|
|
|
|
// OkHTTPv3 (double bypass) |
|
try { |
|
var okhttp3_Activity = Java.use('okhttp3.CertificatePinner'); |
|
okhttp3_Activity.check.overload('java.lang.String', 'java.util.List').implementation = function (str) { |
|
console.log('[+] Bypassing OkHTTPv3 {1}: ' + str); |
|
return true; |
|
}; |
|
// This method of CertificatePinner.check could be found in some old Android app |
|
okhttp3_Activity.check.overload('java.lang.String', 'java.security.cert.Certificate').implementation = function (str) { |
|
console.log('[+] Bypassing OkHTTPv3 {2}: ' + str); |
|
return true; |
|
}; |
|
|
|
} catch (err) { |
|
console.log('[-] OkHTTPv3 pinner not found'); |
|
//console.log(err); |
|
} |
|
|
|
|
|
|
|
// Trustkit (triple bypass) |
|
try { |
|
var trustkit_Activity = Java.use('com.datatheorem.android.trustkit.pinning.OkHostnameVerifier'); |
|
trustkit_Activity.verify.overload('java.lang.String', 'javax.net.ssl.SSLSession').implementation = function (str) { |
|
console.log('[+] Bypassing Trustkit {1}: ' + str); |
|
return true; |
|
}; |
|
trustkit_Activity.verify.overload('java.lang.String', 'java.security.cert.X509Certificate').implementation = function (str) { |
|
console.log('[+] Bypassing Trustkit {2}: ' + str); |
|
return true; |
|
}; |
|
var trustkit_PinningTrustManager = Java.use('com.datatheorem.android.trustkit.pinning.PinningTrustManager'); |
|
trustkit_PinningTrustManager.checkServerTrusted.implementation = function () { |
|
console.log('[+] Bypassing Trustkit {3}'); |
|
}; |
|
|
|
} catch (err) { |
|
console.log('[-] Trustkit pinner not found'); |
|
//console.log(err); |
|
} |
|
|
|
|
|
|
|
// TrustManagerImpl (Android > 7) |
|
try { |
|
var TrustManagerImpl = Java.use('com.android.org.conscrypt.TrustManagerImpl'); |
|
TrustManagerImpl.verifyChain.implementation = function (untrustedChain, trustAnchorChain, host, clientAuth, ocspData, tlsSctData) { |
|
console.log('[+] Bypassing TrustManagerImpl (Android > 7): ' + host); |
|
return untrustedChain; |
|
}; |
|
|
|
} catch (err) { |
|
console.log('[-] TrustManagerImpl (Android > 7) pinner not found'); |
|
//console.log(err); |
|
} |
|
|
|
|
|
|
|
// Appcelerator Titanium |
|
try { |
|
var appcelerator_PinningTrustManager = Java.use('appcelerator.https.PinningTrustManager'); |
|
appcelerator_PinningTrustManager.checkServerTrusted.implementation = function () { |
|
console.log('[+] Bypassing Appcelerator PinningTrustManager'); |
|
}; |
|
|
|
} catch (err) { |
|
console.log('[-] Appcelerator PinningTrustManager pinner not found'); |
|
//console.log(err); |
|
} |
|
|
|
|
|
|
|
// OpenSSLSocketImpl Conscrypt |
|
try { |
|
var OpenSSLSocketImpl = Java.use('com.android.org.conscrypt.OpenSSLSocketImpl'); |
|
OpenSSLSocketImpl.verifyCertificateChain.implementation = function (certRefs, JavaObject, authMethod) { |
|
console.log('[+] Bypassing OpenSSLSocketImpl Conscrypt'); |
|
}; |
|
|
|
} catch (err) { |
|
console.log('[-] OpenSSLSocketImpl Conscrypt pinner not found'); |
|
//console.log(err); |
|
} |
|
|
|
|
|
// OpenSSLEngineSocketImpl Conscrypt |
|
try { |
|
var OpenSSLEngineSocketImpl_Activity = Java.use('com.android.org.conscrypt.OpenSSLEngineSocketImpl'); |
|
OpenSSLSocketImpl_Activity.verifyCertificateChain.overload('[Ljava.lang.Long;', 'java.lang.String').implementation = function (str1, str2) { |
|
console.log('[+] Bypassing OpenSSLEngineSocketImpl Conscrypt: ' + str2); |
|
}; |
|
|
|
} catch (err) { |
|
console.log('[-] OpenSSLEngineSocketImpl Conscrypt pinner not found'); |
|
//console.log(err); |
|
} |
|
|
|
|
|
|
|
// OpenSSLSocketImpl Apache Harmony |
|
try { |
|
var OpenSSLSocketImpl_Harmony = Java.use('org.apache.harmony.xnet.provider.jsse.OpenSSLSocketImpl'); |
|
OpenSSLSocketImpl_Harmony.verifyCertificateChain.implementation = function (asn1DerEncodedCertificateChain, authMethod) { |
|
console.log('[+] Bypassing OpenSSLSocketImpl Apache Harmony'); |
|
}; |
|
|
|
} catch (err) { |
|
console.log('[-] OpenSSLSocketImpl Apache Harmony pinner not found'); |
|
//console.log(err); |
|
} |
|
|
|
|
|
|
|
// PhoneGap sslCertificateChecker (https://github.com/EddyVerbruggen/SSLCertificateChecker-PhoneGap-Plugin) |
|
try { |
|
var phonegap_Activity = Java.use('nl.xservices.plugins.sslCertificateChecker'); |
|
phonegap_Activity.execute.overload('java.lang.String', 'org.json.JSONArray', 'org.apache.cordova.CallbackContext').implementation = function (str) { |
|
console.log('[+] Bypassing PhoneGap sslCertificateChecker: ' + str); |
|
return true; |
|
}; |
|
|
|
} catch (err) { |
|
console.log('[-] PhoneGap sslCertificateChecker pinner not found'); |
|
//console.log(err); |
|
} |
|
|
|
|
|
|
|
// IBM MobileFirst pinTrustedCertificatePublicKey (double bypass) |
|
try { |
|
var WLClient_Activity = Java.use('com.worklight.wlclient.api.WLClient'); |
|
WLClient_Activity.getInstance().pinTrustedCertificatePublicKey.overload('java.lang.String').implementation = function (cert) { |
|
console.log('[+] Bypassing IBM MobileFirst pinTrustedCertificatePublicKey {1}: ' + cert); |
|
return; |
|
}; |
|
WLClient_Activity.getInstance().pinTrustedCertificatePublicKey.overload('[Ljava.lang.String;').implementation = function (cert) { |
|
console.log('[+] Bypassing IBM MobileFirst pinTrustedCertificatePublicKey {2}: ' + cert); |
|
return; |
|
}; |
|
|
|
} catch (err) { |
|
console.log('[-] IBM MobileFirst pinTrustedCertificatePublicKey pinner not found'); |
|
//console.log(err); |
|
} |
|
|
|
|
|
|
|
// IBM WorkLight (ancestor of MobileFirst) HostNameVerifierWithCertificatePinning (quadruple bypass) |
|
try { |
|
var worklight_Activity = Java.use('com.worklight.wlclient.certificatepinning.HostNameVerifierWithCertificatePinning'); |
|
worklight_Activity.verify.overload('java.lang.String', 'javax.net.ssl.SSLSocket').implementation = function (str) { |
|
console.log('[+] Bypassing IBM WorkLight HostNameVerifierWithCertificatePinning {1}: ' + str); |
|
return; |
|
}; |
|
worklight_Activity.verify.overload('java.lang.String', 'java.security.cert.X509Certificate').implementation = function (str) { |
|
console.log('[+] Bypassing IBM WorkLight HostNameVerifierWithCertificatePinning {2}: ' + str); |
|
return; |
|
}; |
|
worklight_Activity.verify.overload('java.lang.String', '[Ljava.lang.String;', '[Ljava.lang.String;').implementation = function (str) { |
|
console.log('[+] Bypassing IBM WorkLight HostNameVerifierWithCertificatePinning {3}: ' + str); |
|
return; |
|
}; |
|
worklight_Activity.verify.overload('java.lang.String', 'javax.net.ssl.SSLSession').implementation = function (str) { |
|
console.log('[+] Bypassing IBM WorkLight HostNameVerifierWithCertificatePinning {4}: ' + str); |
|
return true; |
|
}; |
|
|
|
} catch (err) { |
|
console.log('[-] IBM WorkLight HostNameVerifierWithCertificatePinning pinner not found'); |
|
//console.log(err); |
|
} |
|
|
|
|
|
|
|
// Conscrypt CertPinManager |
|
try { |
|
var conscrypt_CertPinManager_Activity = Java.use('com.android.org.conscrypt.CertPinManager'); |
|
conscrypt_CertPinManager_Activity.isChainValid.overload('java.lang.String', 'java.util.List').implementation = function (str) { |
|
console.log('[+] Bypassing Conscrypt CertPinManager: ' + str); |
|
return true; |
|
}; |
|
|
|
} catch (err) { |
|
console.log('[-] Conscrypt CertPinManager pinner not found'); |
|
//console.log(err); |
|
} |
|
|
|
|
|
|
|
// CWAC-Netsecurity (unofficial back-port pinner for Android < 4.2) CertPinManager |
|
try { |
|
var cwac_CertPinManager_Activity = Java.use('com.commonsware.cwac.netsecurity.conscrypt.CertPinManager'); |
|
cwac_CertPinManager_Activity.isChainValid.overload('java.lang.String', 'java.util.List').implementation = function (str) { |
|
console.log('[+] Bypassing CWAC-Netsecurity CertPinManager: ' + str); |
|
return true; |
|
}; |
|
|
|
} catch (err) { |
|
console.log('[-] CWAC-Netsecurity CertPinManager pinner not found'); |
|
//console.log(err); |
|
} |
|
|
|
|
|
|
|
// Worklight Androidgap WLCertificatePinningPlugin |
|
try { |
|
var androidgap_WLCertificatePinningPlugin_Activity = Java.use('com.worklight.androidgap.plugin.WLCertificatePinningPlugin'); |
|
androidgap_WLCertificatePinningPlugin_Activity.execute.overload('java.lang.String', 'org.json.JSONArray', 'org.apache.cordova.CallbackContext').implementation = function (str) { |
|
console.log('[+] Bypassing Worklight Androidgap WLCertificatePinningPlugin: ' + str); |
|
return true; |
|
}; |
|
|
|
} catch (err) { |
|
console.log('[-] Worklight Androidgap WLCertificatePinningPlugin pinner not found'); |
|
//console.log(err); |
|
} |
|
|
|
|
|
|
|
// Netty FingerprintTrustManagerFactory |
|
try { |
|
var netty_FingerprintTrustManagerFactory = Java.use('io.netty.handler.ssl.util.FingerprintTrustManagerFactory'); |
|
//NOTE: sometimes this below implementation could be useful |
|
//var netty_FingerprintTrustManagerFactory = Java.use('org.jboss.netty.handler.ssl.util.FingerprintTrustManagerFactory'); |
|
netty_FingerprintTrustManagerFactory.checkTrusted.implementation = function (type, chain) { |
|
console.log('[+] Bypassing Netty FingerprintTrustManagerFactory'); |
|
}; |
|
|
|
} catch (err) { |
|
console.log('[-] Netty FingerprintTrustManagerFactory pinner not found'); |
|
//console.log(err); |
|
} |
|
|
|
|
|
|
|
// Squareup CertificatePinner [OkHTTP < v3] (double bypass) |
|
try { |
|
var Squareup_CertificatePinner_Activity = Java.use('com.squareup.okhttp.CertificatePinner'); |
|
Squareup_CertificatePinner_Activity.check.overload('java.lang.String', 'java.security.cert.Certificate').implementation = function (str1, str2) { |
|
console.log('[+] Bypassing Squareup CertificatePinner {1}: ' + str1); |
|
return; |
|
}; |
|
|
|
Squareup_CertificatePinner_Activity.check.overload('java.lang.String', 'java.util.List').implementation = function (str1, str2) { |
|
console.log('[+] Bypassing Squareup CertificatePinner {2}: ' + str1); |
|
return; |
|
}; |
|
|
|
} catch (err) { |
|
console.log('[-] Squareup CertificatePinner pinner not found'); |
|
//console.log(err); |
|
} |
|
|
|
|
|
|
|
// Squareup OkHostnameVerifier [OkHTTP v3] (double bypass) |
|
try { |
|
var Squareup_OkHostnameVerifier_Activity = Java.use('com.squareup.okhttp.internal.tls.OkHostnameVerifier'); |
|
Squareup_OkHostnameVerifier_Activity.verify.overload('java.lang.String', 'java.security.cert.X509Certificate').implementation = function (str1, str2) { |
|
console.log('[+] Bypassing Squareup OkHostnameVerifier {1}: ' + str1); |
|
return true; |
|
}; |
|
|
|
Squareup_OkHostnameVerifier_Activity.verify.overload('java.lang.String', 'javax.net.ssl.SSLSession').implementation = function (str1, str2) { |
|
console.log('[+] Bypassing Squareup OkHostnameVerifier {2}: ' + str1); |
|
return true; |
|
}; |
|
|
|
} catch (err) { |
|
console.log('[-] Squareup OkHostnameVerifier pinner not found'); |
|
//console.log(err); |
|
} |
|
|
|
|
|
|
|
// Android WebViewClient |
|
try { |
|
var AndroidWebViewClient_Activity = Java.use('android.webkit.WebViewClient'); |
|
AndroidWebViewClient_Activity.onReceivedSslError.overload('android.webkit.WebView', 'android.webkit.SslErrorHandler', 'android.net.http.SslError').implementation = function (obj1, obj2, obj3) { |
|
console.log('[+] Bypassing Android WebViewClient'); |
|
}; |
|
|
|
} catch (err) { |
|
console.log('[-] Android WebViewClient pinner not found'); |
|
//console.log(err); |
|
} |
|
|
|
|
|
|
|
// Apache Cordova WebViewClient |
|
try { |
|
var CordovaWebViewClient_Activity = Java.use('org.apache.cordova.CordovaWebViewClient'); |
|
CordovaWebViewClient_Activity.onReceivedSslError.overload('android.webkit.WebView', 'android.webkit.SslErrorHandler', 'android.net.http.SslError').implementation = function (obj1, obj2, obj3) { |
|
console.log('[+] Bypassing Apache Cordova WebViewClient'); |
|
obj3.proceed(); |
|
}; |
|
|
|
} catch (err) { |
|
console.log('[-] Apache Cordova WebViewClient pinner not found'); |
|
//console.log(err): |
|
} |
|
|
|
|
|
|
|
// Boye AbstractVerifier |
|
try { |
|
var boye_AbstractVerifier = Java.use('ch.boye.httpclientandroidlib.conn.ssl.AbstractVerifier'); |
|
boye_AbstractVerifier.verify.implementation = function (host, ssl) { |
|
console.log('[+] Bypassing Boye AbstractVerifier: ' + host); |
|
}; |
|
|
|
} catch (err) { |
|
console.log('[-] Boye AbstractVerifier pinner not found'); |
|
//console.log(err): |
|
} |
|
|
|
|
|
}); |
|
|
|
}, 0); |
very useful, by the way . google play store is till a trouble to solve