MITM(Man In the Middle Attack) Android 7(API 24) 이전, Proxy(Burp) 인증서를 단말기에 설치만 하면 인증서 신뢰하였다. 하지만 Android 7 이후, OS 정책 변경으로 사용자가 설치한 루트 인증서는 신뢰하지 않음
이를 해결하기 위해
루팅된 기기에서 시스템 인증서 경로로 버프 인증서 강제로 밀어넣기
openssl설치
https://slproweb.com/products/Win32OpenSSL.html
Win32/Win64 OpenSSL Installer for Windows - Shining Light Productions
Minimum system requirements: Windows XP or later 32MB RAM 200MHz CPU 30MB hard drive space Recommended system requirements: Windows XP or later 128MB RAM 500MHz CPU 300MB hard drive space March 14, 2023 - OpenSSL 3.1 is available. Also, Happy Pi Day. Users
slproweb.com
Burp > Proxy > Options > Import/export CA certificate
Certificate in DER format > Next > 인증서 저장
OpenSSL 이용하여 pem 파일로 변환
openssl x509 -inform DER -in cacert.der -out cacert.pem
openssl x509 -inform PEM -subject_hash_old -in cacert.pem
mv cacert.pem 9a5ba575.0
mount -o rw,remount /system
chmod 644 9a5ba575.0
adb push 9a5ba575.0 /system/etc/security/cacerts/
Reboot
복사
버프 인증서 만료 날짜 360로 설정 변경
//Win64 OpenSSL v1.1.1u 설치할 것
openssl req -x509 -days 360 -nodes -newkey rsa:2048 -outform der -keyout server.key -out ca.der
openssl rsa -in server.key -inform pem -out server.key.der -outform der
openssl pkcs8 -topk8 -in server.key.der -inform der -out server.key.pkcs8.der -outform der -nocrypt
openssl x509 -inform DER -in cacert.der -out cacert.pem
openssl x509 -inform PEM -subject_hash_old -in cacert.pem
adb push 9a5ba575.0 /sdcard/
adb remount
mount -o rw,remount /system
chmod 644 9a5ba575.0
mv 9a5ba575.0 /system/etc/security/cacerts/
복사
방법 2. APP 리패키징하여 사용자 인증서를 신뢰하도록 하는 옵션 추가 하여 설치
방법 3. SSL-Pinning(with. frida) (앱에서 인증서 검증을 하는 경우)
https://codeshare.frida.re/
Frida CodeShare
Unleash the power of Frida. "If I have seen further, it is by standing on the shoulders of giants." -Sir Issac Newton The Frida CodeShare project is comprised of developers from around the world working together with one goal - push Frida to its l
codeshare.frida.re
들어가면 ssl pinning 관련 코드가 존재한다. 그 중에서 frida-mutiple-unpinning이 범용성이 좋다.
Project: Universal Android SSL Pinning Bypass with Frida 사용시 아래 과정으로 사용
adb push cacert.der /data/local/tmp/cert-der.crt
chmod 777 cert-der.crt
frida -U -l ssl_bypass.js [pid]
복사
setTimeout(function(){
Java.perform(function (){
console.log("" );
console.log("[.] Cert Pinning Bypass/Re-Pinning" );
var CertificateFactory = Java.use("java.security.cert.CertificateFactory" );
var FileInputStream = Java.use("java.io.FileInputStream" );
var BufferedInputStream = Java.use("java.io.BufferedInputStream" );
var X509Certificate = Java.use("java.security.cert.X509Certificate" );
var KeyStore = Java.use("java.security.KeyStore" );
var TrustManagerFactory = Java.use("javax.net.ssl.TrustManagerFactory" );
var SSLContext = Java.use("javax.net.ssl.SSLContext" );
console.log("[+] Loading our CA..." )
var cf = CertificateFactory.getInstance("X.509" );
try {
var fileInputStream = FileInputStream.$new ("/data/local/tmp/cert-der.crt" );
}
catch (err) {
console.log("[o] " + err);
}
var bufferedInputStream = BufferedInputStream.$new (fileInputStream);
var ca = cf.generateCertificate(bufferedInputStream);
bufferedInputStream.close();
var certInfo = Java.cast(ca, X509Certificate);
console.log("[o] Our CA Info: " + certInfo.getSubjectDN());
console.log("[+] Creating a KeyStore for our CA..." );
var keyStoreType = KeyStore.getDefaultType();
var keyStore = KeyStore.getInstance(keyStoreType);
keyStore.load(null , null );
keyStore.setCertificateEntry("ca" , ca);
console.log("[+] Creating a TrustManager that trusts the CA in our KeyStore..." );
var tmfAlgorithm = TrustManagerFactory.getDefaultAlgorithm();
var tmf = TrustManagerFactory.getInstance(tmfAlgorithm);
tmf.init(keyStore);
console.log("[+] Our TrustManager is ready..." );
console.log("[+] Hijacking SSLContext methods now..." )
console.log("[-] Waiting for the app to invoke SSLContext.init()..." )
SSLContext.init.overload("[Ljavax.net.ssl.KeyManager;" , "[Ljavax.net.ssl.TrustManager;" , "java.security.SecureRandom" ).implementation = function(a,b,c) {
console.log("[o] App invoked javax.net.ssl.SSLContext.init..." );
SSLContext.init.overload("[Ljavax.net.ssl.KeyManager;" , "[Ljavax.net.ssl.TrustManager;" , "java.security.SecureRandom" ).call(this , a, tmf.getTrustManagers(), c);
console.log("[+] SSLContext initialized with our custom TrustManager!" );
}
});
},0 );
복사
Project: frida-multiple-unpinning code
frida ssl_pinning.js -U -f [app package 명]
복사
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' );
var TrustManager = Java.registerClass ({
name: 'dev.asd.test.TrustManager' ,
implements: [X509TrustManager],
methods: {
checkClientTrusted: function (chain, authType) {},
checkServerTrusted: function (chain, authType) {},
getAcceptedIssuers: function () {return []; }
}
});
var TrustManagers = [TrustManager.$new ()];
var SSLContext_init = SSLContext.init.overload (
'[Ljavax.net.ssl.KeyManager;' , '[Ljavax.net.ssl.TrustManager;' , 'java.security.SecureRandom' );
try {
SSLContext_init.implementation = function (keyManager, trustManager, secureRandom) {
console.log ('[+] Bypassing Trustmanager (Android < 7) pinner' );
SSLContext_init.call (this , keyManager, TrustManagers, secureRandom);
};
} catch (err) {
console.log ('[-] TrustManager (Android < 7) pinner not found' );
}
try {
var 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 {1}: ' + a);
return ;
};
} catch (err) {
console.log ('[-] OkHTTPv3 {1} pinner not found' );
}
try {
var okhttp3_Activity_2 = Java.use ('okhttp3.CertificatePinner' );
okhttp3_Activity_2.check.overload ('java.lang.String' , 'java.security.cert.Certificate' ).implementation = function (a, b) {
console.log ('[+] Bypassing OkHTTPv3 {2}: ' + a);
return ;
};
} catch (err) {
console.log ('[-] OkHTTPv3 {2} pinner not found' );
}
try {
var 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 {3}: ' + a);
return ;
};
} catch (err) {
console.log ('[-] OkHTTPv3 {3} pinner not found' );
}
try {
var okhttp3_Activity_4 = Java.use ('okhttp3.CertificatePinner' );
okhttp3_Activity_4.check$okhttp.overload ('java.lang.String' , 'kotlin.jvm.functions.Function0' ).implementation = function (a, b) {
console.log ('[+] Bypassing OkHTTPv3 {4}: ' + a);
return ;
};
} catch (err) {
console.log ('[-] OkHTTPv3 {4} pinner not found' );
}
try {
var trustkit_Activity_1 = Java.use ('com.datatheorem.android.trustkit.pinning.OkHostnameVerifier' );
trustkit_Activity_1.verify.overload ('java.lang.String' , 'javax.net.ssl.SSLSession' ).implementation = function (a, b) {
console.log ('[+] Bypassing Trustkit {1}: ' + a);
return true ;
};
} catch (err) {
console.log ('[-] Trustkit {1} pinner not found' );
}
try {
var trustkit_Activity_2 = Java.use ('com.datatheorem.android.trustkit.pinning.OkHostnameVerifier' );
trustkit_Activity_2.verify.overload ('java.lang.String' , 'java.security.cert.X509Certificate' ).implementation = function (a, b) {
console.log ('[+] Bypassing Trustkit {2}: ' + a);
return true ;
};
} catch (err) {
console.log ('[-] Trustkit {2} pinner not found' );
}
try {
var trustkit_PinningTrustManager = Java.use ('com.datatheorem.android.trustkit.pinning.PinningTrustManager' );
trustkit_PinningTrustManager.checkServerTrusted.overload ('[Ljava.security.cert.X509Certificate;' , 'java.lang.String' ).implementation = function (chain, authType) {
console.log ('[+] Bypassing Trustkit {3}' );
};
} catch (err) {
console.log ('[-] Trustkit {3} pinner not found' );
}
try {
var array_list = Java.use ("java.util.ArrayList" );
var TrustManagerImpl_Activity_1 = Java.use ('com.android.org.conscrypt.TrustManagerImpl' );
TrustManagerImpl_Activity_1.checkTrustedRecursive.implementation = function (certs, ocspData, tlsSctData, host, clientAuth, untrustedChain, trustAnchorChain, used) {
console.log ('[+] Bypassing TrustManagerImpl (Android > 7) checkTrustedRecursive check: ' + host);
return array_list.$new ();
};
} catch (err) {
console.log ('[-] TrustManagerImpl (Android > 7) checkTrustedRecursive check not found' );
}
try {
var TrustManagerImpl_Activity_2 = Java.use ('com.android.org.conscrypt.TrustManagerImpl' );
TrustManagerImpl_Activity_2.verifyChain.implementation = function (untrustedChain, trustAnchorChain, host, clientAuth, ocspData, tlsSctData) {
console.log ('[+] Bypassing TrustManagerImpl (Android > 7) verifyChain check: ' + host);
return untrustedChain;
};
} catch (err) {
console.log ('[-] TrustManagerImpl (Android > 7) verifyChain check not found' );
}
try {
var appcelerator_PinningTrustManager = Java.use ('appcelerator.https.PinningTrustManager' );
appcelerator_PinningTrustManager.checkServerTrusted.implementation = function (chain, authType) {
console.log ('[+] Bypassing Appcelerator PinningTrustManager' );
return ;
};
} catch (err) {
console.log ('[-] Appcelerator PinningTrustManager pinner not found' );
}
try {
var fabric_PinningTrustManager = Java.use ('io.fabric.sdk.android.services.network.PinningTrustManager' );
fabric_PinningTrustManager.checkServerTrusted.implementation = function (chain, authType) {
console.log ('[+] Bypassing Fabric PinningTrustManager' );
return ;
};
} catch (err) {
console.log ('[-] Fabric PinningTrustManager pinner not found' );
}
try {
var OpenSSLSocketImpl = Java.use ('com.android.org.conscrypt.OpenSSLSocketImpl' );
OpenSSLSocketImpl.verifyCertificateChain.implementation = function (certRefs, JavaObject, authMethod) {
console.log ('[+] Bypassing OpenSSLSocketImpl Conscrypt {1}' );
};
} catch (err) {
console.log ('[-] OpenSSLSocketImpl Conscrypt {1} pinner not found' );
}
try {
var OpenSSLSocketImpl = Java.use ('com.android.org.conscrypt.OpenSSLSocketImpl' );
OpenSSLSocketImpl.verifyCertificateChain.implementation = function (certChain, authMethod) {
console.log ('[+] Bypassing OpenSSLSocketImpl Conscrypt {2}' );
};
} catch (err) {
console.log ('[-] OpenSSLSocketImpl Conscrypt {2} pinner not found' );
}
try {
var OpenSSLEngineSocketImpl_Activity = Java.use ('com.android.org.conscrypt.OpenSSLEngineSocketImpl' );
OpenSSLEngineSocketImpl_Activity.verifyCertificateChain.overload ('[Ljava.lang.Long;' , 'java.lang.String' ).implementation = function (a, b) {
console.log ('[+] Bypassing OpenSSLEngineSocketImpl Conscrypt: ' + b);
};
} catch (err) {
console.log ('[-] OpenSSLEngineSocketImpl Conscrypt pinner not found' );
}
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' );
}
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 (a, b, c) {
console.log ('[+] Bypassing PhoneGap sslCertificateChecker: ' + a);
return true ;
};
} catch (err) {
console.log ('[-] PhoneGap sslCertificateChecker pinner not found' );
}
try {
var WLClient_Activity_1 = Java.use ('com.worklight.wlclient.api.WLClient' );
WLClient_Activity_1.getInstance ().pinTrustedCertificatePublicKey.overload ('java.lang.String' ).implementation = function (cert) {
console.log ('[+] Bypassing IBM MobileFirst pinTrustedCertificatePublicKey {1}: ' + cert);
return ;
};
} catch (err) {
console.log ('[-] IBM MobileFirst pinTrustedCertificatePublicKey {1} pinner not found' );
}
try {
var WLClient_Activity_2 = Java.use ('com.worklight.wlclient.api.WLClient' );
WLClient_Activity_2.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 {2} pinner not found' );
}
try {
var worklight_Activity_1 = Java.use ('com.worklight.wlclient.certificatepinning.HostNameVerifierWithCertificatePinning' );
worklight_Activity_1.verify.overload ('java.lang.String' , 'javax.net.ssl.SSLSocket' ).implementation = function (a, b) {
console.log ('[+] Bypassing IBM WorkLight HostNameVerifierWithCertificatePinning {1}: ' + a);
return ;
};
} catch (err) {
console.log ('[-] IBM WorkLight HostNameVerifierWithCertificatePinning {1} pinner not found' );
}
try {
var worklight_Activity_2 = Java.use ('com.worklight.wlclient.certificatepinning.HostNameVerifierWithCertificatePinning' );
worklight_Activity_2.verify.overload ('java.lang.String' , 'java.security.cert.X509Certificate' ).implementation = function (a, b) {
console.log ('[+] Bypassing IBM WorkLight HostNameVerifierWithCertificatePinning {2}: ' + a);
return ;
};
} catch (err) {
console.log ('[-] IBM WorkLight HostNameVerifierWithCertificatePinning {2} pinner not found' );
}
try {
var worklight_Activity_3 = Java.use ('com.worklight.wlclient.certificatepinning.HostNameVerifierWithCertificatePinning' );
worklight_Activity_3.verify.overload ('java.lang.String' , '[Ljava.lang.String;' , '[Ljava.lang.String;' ).implementation = function (a, b) {
console.log ('[+] Bypassing IBM WorkLight HostNameVerifierWithCertificatePinning {3}: ' + a);
return ;
};
} catch (err) {
console.log ('[-] IBM WorkLight HostNameVerifierWithCertificatePinning {3} pinner not found' );
}
try {
var worklight_Activity_4 = Java.use ('com.worklight.wlclient.certificatepinning.HostNameVerifierWithCertificatePinning' );
worklight_Activity_4.verify.overload ('java.lang.String' , 'javax.net.ssl.SSLSession' ).implementation = function (a, b) {
console.log ('[+] Bypassing IBM WorkLight HostNameVerifierWithCertificatePinning {4}: ' + a);
return true ;
};
} catch (err) {
console.log ('[-] IBM WorkLight HostNameVerifierWithCertificatePinning {4} pinner not found' );
}
try {
var conscrypt_CertPinManager_Activity = Java.use ('com.android.org.conscrypt.CertPinManager' );
conscrypt_CertPinManager_Activity.checkChainPinning.overload ('java.lang.String' , 'java.util.List' ).implementation = function (a, b) {
console.log ('[+] Bypassing Conscrypt CertPinManager: ' + a);
return true ;
};
} catch (err) {
console.log ('[-] Conscrypt CertPinManager pinner not found' );
}
try {
var legacy_conscrypt_CertPinManager_Activity = Java.use ('com.android.org.conscrypt.CertPinManager' );
legacy_conscrypt_CertPinManager_Activity.isChainValid.overload ('java.lang.String' , 'java.util.List' ).implementation = function (a, b) {
console.log ('[+] Bypassing Conscrypt CertPinManager (Legacy): ' + a);
return true ;
};
} catch (err) {
console.log ('[-] Conscrypt CertPinManager (Legacy) pinner not found' );
}
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 (a, b) {
console.log ('[+] Bypassing CWAC-Netsecurity CertPinManager: ' + a);
return true ;
};
} catch (err) {
console.log ('[-] CWAC-Netsecurity CertPinManager pinner not found' );
}
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 (a, b, c) {
console.log ('[+] Bypassing Worklight Androidgap WLCertificatePinningPlugin: ' + a);
return true ;
};
} catch (err) {
console.log ('[-] Worklight Androidgap WLCertificatePinningPlugin pinner not found' );
}
try {
var netty_FingerprintTrustManagerFactory = Java.use ('io.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' );
}
try {
var Squareup_CertificatePinner_Activity_1 = Java.use ('com.squareup.okhttp.CertificatePinner' );
Squareup_CertificatePinner_Activity_1.check.overload ('java.lang.String' , 'java.security.cert.Certificate' ).implementation = function (a, b) {
console.log ('[+] Bypassing Squareup CertificatePinner {1}: ' + a);
return ;
};
} catch (err) {
console.log ('[-] Squareup CertificatePinner {1} pinner not found' );
}
try {
var 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 {2}: ' + a);
return ;
};
} catch (err) {
console.log ('[-] Squareup CertificatePinner {2} pinner not found' );
}
try {
var 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 {1}: ' + a);
return true ;
};
} catch (err) {
console.log ('[-] Squareup OkHostnameVerifier check not found' );
}
try {
var 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 {2}: ' + a);
return true ;
};
} catch (err) {
console.log ('[-] Squareup OkHostnameVerifier check not found' );
}
try {
var 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 check {1}' );
};
} catch (err) {
console.log ('[-] Android WebViewClient {1} check not found' );
}
try {
var AndroidWebViewClient_Activity_2 = Java.use ('android.webkit.WebViewClient' );
AndroidWebViewClient_Activity_2.onReceivedSslError.overload ('android.webkit.WebView' , 'android.webkit.WebResourceRequest' , 'android.webkit.WebResourceError' ).implementation = function (obj1, obj2, obj3) {
console.log ('[+] Bypassing Android WebViewClient check {2}' );
};
} catch (err) {
console.log ('[-] Android WebViewClient {2} check not found' );
}
try {
var AndroidWebViewClient_Activity_3 = Java.use ('android.webkit.WebViewClient' );
AndroidWebViewClient_Activity_3.onReceivedError.overload ('android.webkit.WebView' , 'int' , 'java.lang.String' , 'java.lang.String' ).implementation = function (obj1, obj2, obj3, obj4) {
console.log ('[+] Bypassing Android WebViewClient check {3}' );
};
} catch (err) {
console.log ('[-] Android WebViewClient {3} check not found' );
}
try {
var AndroidWebViewClient_Activity_4 = Java.use ('android.webkit.WebViewClient' );
AndroidWebViewClient_Activity_4.onReceivedError.overload ('android.webkit.WebView' , 'android.webkit.WebResourceRequest' , 'android.webkit.WebResourceError' ).implementation = function (obj1, obj2, obj3) {
console.log ('[+] Bypassing Android WebViewClient check {4}' );
};
} catch (err) {
console.log ('[-] Android WebViewClient {4} check not found' );
}
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 check' );
obj3.proceed ();
};
} catch (err) {
console.log ('[-] Apache Cordova WebViewClient check not found' );
}
try {
var boye_AbstractVerifier = Java.use ('ch.boye.httpclientandroidlib.conn.ssl.AbstractVerifier' );
boye_AbstractVerifier.verify.implementation = function (host, ssl) {
console.log ('[+] Bypassing Boye AbstractVerifier check: ' + host);
};
} catch (err) {
console.log ('[-] Boye AbstractVerifier check not found' );
}
try {
var apache_AbstractVerifier = Java.use ('org.apache.http.conn.ssl.AbstractVerifier' );
apache_AbstractVerifier.verify.implementation = function (a, b, c, d) {
console.log ('[+] Bypassing Apache AbstractVerifier check: ' + a);
return ;
};
} catch (err) {
console.log ('[-] Apache AbstractVerifier check not found' );
}
try {
var CronetEngineBuilderImpl_Activity = Java.use ("org.chromium.net.impl.CronetEngineBuilderImpl" );
CronetEngine_Activity.enablePublicKeyPinningBypassForLocalTrustAnchors.overload ('boolean' ).implementation = function (a) {
console.log ("[+] Disabling Public Key pinning for local trust anchors in Chromium Cronet" );
var cronet_obj_1 = CronetEngine_Activity.enablePublicKeyPinningBypassForLocalTrustAnchors.call (this , true );
return cronet_obj_1;
};
CronetEngine_Activity.addPublicKeyPins.overload ('java.lang.String' , 'java.util.Set' , 'boolean' , 'java.util.Date' ).implementation = function (hostName, pinsSha256, includeSubdomains, expirationDate) {
console.log ("[+] Bypassing Chromium Cronet pinner: " + hostName);
var cronet_obj_2 = CronetEngine_Activity.addPublicKeyPins.call (this , hostName, pinsSha256, includeSubdomains, expirationDate);
return cronet_obj_2;
};
} catch (err) {
console.log ('[-] Chromium Cronet pinner not found' )
}
try {
var HttpCertificatePinning_Activity = Java.use ('diefferson.http_certificate_pinning.HttpCertificatePinning' );
HttpCertificatePinning_Activity.checkConnexion.overload ("java.lang.String" , "java.util.List" , "java.util.Map" , "int" , "java.lang.String" ).implementation = function (a, b, c ,d, e) {
console.log ('[+] Bypassing Flutter HttpCertificatePinning : ' + a);
return true ;
};
} catch (err) {
console.log ('[-] Flutter HttpCertificatePinning pinner not found' );
}
try {
var SslPinningPlugin_Activity = Java.use ('com.macif.plugin.sslpinningplugin.SslPinningPlugin' );
SslPinningPlugin_Activity.checkConnexion.overload ("java.lang.String" , "java.util.List" , "java.util.Map" , "int" , "java.lang.String" ).implementation = function (a, b, c ,d, e) {
console.log ('[+] Bypassing Flutter SslPinningPlugin: ' + a);
return true ;
};
} catch (err) {
console.log ('[-] Flutter SslPinningPlugin pinner not found' );
}
function rudimentaryFix (typeName) {
if (typeName === undefined){
return ;
} else if (typeName === 'boolean' ) {
return true ;
} else {
return null;
}
}
try {
var UnverifiedCertError = Java.use ('javax.net.ssl.SSLPeerUnverifiedException' );
UnverifiedCertError.$init.implementation = function (str) {
console.log ('\x1b[36m[!] Unexpected SSLPeerUnverifiedException occurred, trying to patch it dynamically...\x1b[0m' );
try {
var stackTrace = Java.use ('java.lang.Thread' ).currentThread ().getStackTrace ();
var exceptionStackIndex = stackTrace.findIndex (stack =>
stack.getClassName () === "javax.net.ssl.SSLPeerUnverifiedException"
);
var callingFunctionStack = stackTrace[exceptionStackIndex + 1 ];
var className = callingFunctionStack.getClassName ();
var methodName = callingFunctionStack.getMethodName ();
var callingClass = Java.use (className);
var callingMethod = callingClass[methodName];
console.log ('\x1b[36m[!] Attempting to bypass uncommon SSL Pinning method on: ' +className+'.' +methodName+'\x1b[0m' );
if (callingMethod.implementation) {
return ;
}
var returnTypeName = callingMethod.returnType.type;
callingMethod.implementation = function () {
rudimentaryFix (returnTypeName);
};
} catch (e) {
if (String (e).includes (".overload" )) {
var splittedList = String (e).split (".overload" );
for (let i=2 ; i<splittedList.length; i++) {
var extractedOverload = splittedList[i].trim ().split ("(" )[1 ].slice (0 ,-1 ).replaceAll ("'" ,"" );
if (extractedOverload.includes ("," )) {
var argList = extractedOverload.split (", " );
console.log ('\x1b[36m[!] Attempting overload of ' +className+'.' +methodName+' with arguments: ' +extractedOverload+'\x1b[0m' );
if (argList.length == 2 ) {
callingMethod.overload (argList[0 ], argList[1 ]).implementation = function (a,b) {
rudimentaryFix (returnTypeName);
}
} else if (argNum == 3 ) {
callingMethod.overload (argList[0 ], argList[1 ], argList[2 ]).implementation = function (a,b,c) {
rudimentaryFix (returnTypeName);
}
} else if (argNum == 4 ) {
callingMethod.overload (argList[0 ], argList[1 ], argList[2 ], argList[3 ]).implementation = function (a,b,c,d) {
rudimentaryFix (returnTypeName);
}
} else if (argNum == 5 ) {
callingMethod.overload (argList[0 ], argList[1 ], argList[2 ], argList[3 ], argList[4 ]).implementation = function (a,b,c,d,e) {
rudimentaryFix (returnTypeName);
}
} else if (argNum == 6 ) {
callingMethod.overload (argList[0 ], argList[1 ], argList[2 ], argList[3 ], argList[4 ], argList[5 ]).implementation = function (a,b,c,d,e,f) {
rudimentaryFix (returnTypeName);
}
}
} else {
callingMethod.overload (extractedOverload).implementation = function (a) {
rudimentaryFix (returnTypeName);
}
}
}
} else {
console.log ('\x1b[36m[-] Failed to dynamically patch SSLPeerUnverifiedException ' +e+'\x1b[0m' );
}
}
return this .$init (str);
};
} catch (err) {
}
});
}, 0 );
복사