Java.perform(function() { Java.enumerateClassLoaders({ onMatch: function(loader) { Java.classFactory.loader = loader; try { console.log("==========Start hook giffgaff============="); let ReactContext = Java.use("com.facebook.react.bridge.ReactContext"); ReactContext["getSystemService"].implementation = function(str) { let result = this["getSystemService"](str); if (str == "euicc") { console.log(`ReactContext.getSystemService is called: str=${str}`); console.log(`ReactContext.getSystemService result=${result}`); } return result; }; let SimCardsManagerModule = Java.use("com.reactnativesimcardsmanager.SimCardsManagerModule"); let ReadableMapClass = Java.use("com.facebook.react.bridge.ReadableMap"); SimCardsManagerModule["setupEsim"].implementation = function(readableMap, promise) { console.log(`SimCardsManagerModule.setupEsim is called: readableMap=${readableMap}, promise=${promise}`); var confirmationCode = readableMap.getString("confirmationCode"); console.log("[*] setupEsim called with confirmationCode: ", confirmationCode); this["setupEsim"](readableMap, promise); }; console.log("Unpinning Android app..."); /// -- Generic hook to protect against SSLPeerUnverifiedException -- /// // In some cases, with unusual cert pinning approaches, or heavy obfuscation, we can't // match the real method & package names. This is a problem! Fortunately, we can still // always match built-in types, so here we spot all failures that use the built-in cert // error type (notably this includes OkHttp), and after the first failure, we dynamically // generate & inject a patch to completely disable the method that threw the error. try { const UnverifiedCertError = Java.use('javax.net.ssl.SSLPeerUnverifiedException'); UnverifiedCertError.$init.implementation = function(str) { console.log(' --> Unexpected SSL verification failure, adding dynamic patch...'); try { const stackTrace = Java.use('java.lang.Thread').currentThread().getStackTrace(); const exceptionStackIndex = stackTrace.findIndex(stack => stack.getClassName() === "javax.net.ssl.SSLPeerUnverifiedException" ); const callingFunctionStack = stackTrace[exceptionStackIndex + 1]; const className = callingFunctionStack.getClassName(); const methodName = callingFunctionStack.getMethodName(); console.log(` Thrown by ${className}->${methodName}`); const callingClass = Java.use(className); const callingMethod = callingClass[methodName]; if (callingMethod.implementation) return; // Already patched by Frida - skip it console.log(' Attempting to patch automatically...'); const returnTypeName = callingMethod.returnType.type; callingMethod.implementation = function() { console.log(` --> Bypassing ${className}->${methodName} (automatic exception patch)`); // This is not a perfect fix! Most unknown cases like this are really just // checkCert(cert) methods though, so doing nothing is perfect, and if we // do need an actual return value then this is probably the best we can do, // and at least we're logging the method name so you can patch it manually: if (returnTypeName === 'void') { return; } else { return null; } }; console.log(` [+] ${className}->${methodName} (automatic exception patch)`); } catch (e) { console.log(' [ ] Failed to automatically patch failure'); } return this.$init(str); }; console.log('[+] SSLPeerUnverifiedException auto-patcher'); } catch (err) { console.log('[ ] SSLPeerUnverifiedException auto-patcher'); } /// -- Specific targeted hooks: -- /// // HttpsURLConnection try { const HttpsURLConnection = Java.use("javax.net.ssl.HttpsURLConnection"); HttpsURLConnection.setDefaultHostnameVerifier.implementation = function(hostnameVerifier) { console.log(' --> Bypassing HttpsURLConnection (setDefaultHostnameVerifier)'); return; // Do nothing, i.e. don't change the hostname verifier }; console.log('[+] HttpsURLConnection (setDefaultHostnameVerifier)'); } catch (err) { console.log('[ ] HttpsURLConnection (setDefaultHostnameVerifier)'); } try { const HttpsURLConnection = Java.use("javax.net.ssl.HttpsURLConnection"); HttpsURLConnection.setSSLSocketFactory.implementation = function(SSLSocketFactory) { console.log(' --> Bypassing HttpsURLConnection (setSSLSocketFactory)'); return; // Do nothing, i.e. don't change the SSL socket factory }; console.log('[+] HttpsURLConnection (setSSLSocketFactory)'); } catch (err) { console.log('[ ] HttpsURLConnection (setSSLSocketFactory)'); } try { const HttpsURLConnection = Java.use("javax.net.ssl.HttpsURLConnection"); HttpsURLConnection.setHostnameVerifier.implementation = function(hostnameVerifier) { console.log(' --> Bypassing HttpsURLConnection (setHostnameVerifier)'); return; // Do nothing, i.e. don't change the hostname verifier }; console.log('[+] HttpsURLConnection (setHostnameVerifier)'); } catch (err) { console.log('[ ] HttpsURLConnection (setHostnameVerifier)'); } // SSLContext try { const X509TrustManager = Java.use('javax.net.ssl.X509TrustManager'); const SSLContext = Java.use('javax.net.ssl.SSLContext'); const 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() const TrustManagers = [TrustManager.$new()]; // Get a handle on the init() on the SSLContext class const SSLContext_init = SSLContext.init.overload( '[Ljavax.net.ssl.KeyManager;', '[Ljavax.net.ssl.TrustManager;', 'java.security.SecureRandom' ); // 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); }; console.log('[+] SSLContext'); } catch (err) { console.log('[ ] SSLContext'); } // TrustManagerImpl (Android > 7) try { const array_list = Java.use("java.util.ArrayList"); const TrustManagerImpl = Java.use('com.android.org.conscrypt.TrustManagerImpl'); // This step is notably what defeats the most common case: network security config TrustManagerImpl.checkTrustedRecursive.implementation = function(a1, a2, a3, a4, a5, a6) { console.log(' --> Bypassing TrustManagerImpl checkTrusted '); return array_list.$new(); } TrustManagerImpl.verifyChain.implementation = function(untrustedChain, trustAnchorChain, host, clientAuth, ocspData, tlsSctData) { console.log(' --> Bypassing TrustManagerImpl verifyChain: ' + host); return untrustedChain; }; console.log('[+] TrustManagerImpl'); } catch (err) { console.log('[ ] TrustManagerImpl'); } // OkHTTPv3 (quadruple bypass) try { // Bypass OkHTTPv3 {1} const okhttp3_Activity_1 = Java.use('okhttp3.CertificatePinner'); okhttp3_Activity_1.check.overload('java.lang.String', 'java.util.List').implementation = function(a, b) { console.log(' --> Bypassing OkHTTPv3 (list): ' + a); return; }; console.log('[+] OkHTTPv3 (list)'); } catch (err) { console.log('[ ] OkHTTPv3 (list)'); } try { // Bypass OkHTTPv3 {3} const okhttp3_Activity_3 = Java.use('okhttp3.CertificatePinner'); okhttp3_Activity_3.check.overload('java.lang.String', '[Ljava.security.cert.Certificate;').implementation = function(a, b) { console.log(' --> Bypassing OkHTTPv3 (cert array): ' + a); return; }; console.log('[+] OkHTTPv3 (cert array)'); } catch (err) { console.log('[ ] OkHTTPv3 (cert array)'); } try { // Bypass Squareup CertificatePinner {2} const Squareup_CertificatePinner_Activity_2 = Java.use('com.squareup.okhttp.CertificatePinner'); Squareup_CertificatePinner_Activity_2.check.overload('java.lang.String', 'java.util.List').implementation = function(a, b) { console.log(' --> Bypassing Squareup CertificatePinner (list): ' + a); return; }; console.log('[+] Squareup CertificatePinner (list)'); } catch (err) { console.log('[ ] Squareup CertificatePinner (list)'); } // Squareup OkHostnameVerifier [OkHTTP v3] (double bypass) try { // Bypass Squareup OkHostnameVerifier {1} const Squareup_OkHostnameVerifier_Activity_1 = Java.use('com.squareup.okhttp.internal.tls.OkHostnameVerifier'); Squareup_OkHostnameVerifier_Activity_1.verify.overload('java.lang.String', 'java.security.cert.X509Certificate').implementation = function(a, b) { console.log(' --> Bypassing Squareup OkHostnameVerifier (cert): ' + a); return true; }; console.log('[+] Squareup OkHostnameVerifier (cert)'); } catch (err) { console.log('[ ] Squareup OkHostnameVerifier (cert)'); } try { // Bypass Squareup OkHostnameVerifier {2} const Squareup_OkHostnameVerifier_Activity_2 = Java.use('com.squareup.okhttp.internal.tls.OkHostnameVerifier'); Squareup_OkHostnameVerifier_Activity_2.verify.overload('java.lang.String', 'javax.net.ssl.SSLSession').implementation = function(a, b) { console.log(' --> Bypassing Squareup OkHostnameVerifier (SSLSession): ' + a); return true; }; console.log('[+] Squareup OkHostnameVerifier (SSLSession)'); } catch (err) { console.log('[ ] Squareup OkHostnameVerifier (SSLSession)'); } // Android WebViewClient (double bypass) try { // Bypass WebViewClient {1} (deprecated from Android 6) const AndroidWebViewClient_Activity_1 = Java.use('android.webkit.WebViewClient'); AndroidWebViewClient_Activity_1.onReceivedSslError.overload('android.webkit.WebView', 'android.webkit.SslErrorHandler', 'android.net.http.SslError').implementation = function(obj1, obj2, obj3) { console.log(' --> Bypassing Android WebViewClient (SslErrorHandler)'); }; console.log('[+] Android WebViewClient (SslErrorHandler)'); } catch (err) { console.log('[ ] Android WebViewClient (SslErrorHandler)'); } console.log("Unpinning setup completed"); } catch (error) { if (error.message.includes("ClassNotFoundException")) { console.log("Trying next loader"); } else { console.log(error.message); } } }, onComplete: function() { } }) }) function call_enc(str_data) { //这里写函数对应的类名 var str_cls_name = "com.facebook.react.bridge.ReactContext"; //返回值 var str_ret = null; Java.perform(function() { Java.choose(str_cls_name, { onMatch: function(instance) { //调试用 console.log("onMatch "); //直接调用对象的函数 instance是找到的对象 str_ret = instance.getSystemService(str_data); }, onComplete: function() {} }); }); console.log("enc result: " + str_ret); return str_ret; } function euiccManager() { var EuiccManagerClass = Java.use('android.telephony.euicc.EuiccManager'); var ContextClass = Java.use('android.content.Context'); var EuiccInfoClass = Java.use('android.telephony.euicc.EuiccInfo'); Java.choose('android.app.ActivityThread', { onMatch: function(instance) { // 假设我们获取第一个运行的应用的上下文 var context = Java.cast(instance.currentApplication().getApplicationContext(), ContextClass); // 使用上下文获取 EuiccManager 服务的实例 var euiccManagerInstance = Java.cast(context.getSystemService('euicc'), EuiccManagerClass); console.log('[*] Result of euiccManagerInstance: ' + euiccManagerInstance); // 现在我们调用 isEnabled 方法 var result = euiccManagerInstance.isEnabled(); console.log('[*] Result of euiccManager.isEnabled(): ' + result); if (result == true) { var euiccInfo = euiccManagerInstance.getEuiccInfo() console.log('[*] Result of euiccManager.getEuiccInfo(): ' + euiccInfo); if (euiccInfo !== null) { console.log('[*] Found EuiccInfo instance. Listing methods:'); for (var method of EuiccInfoClass.class.getDeclaredMethods()) { console.log(' - ' + method); } var osVersion = euiccInfo.getOsVersion(); console.log('[*] OS Version of eSIM: ' + osVersion); } else { console.log('[*] EuiccInfo is null.'); } } }, onComplete: function() { console.log('[*] Finished searching instances.'); } }); }