diff --git a/app/build.gradle b/app/build.gradle index 86234f0..4711347 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -1,12 +1,11 @@ apply plugin: 'com.android.application' android { - compileSdkVersion 22 - buildToolsVersion '25.0.2' + compileSdkVersion 30 defaultConfig { applicationId 'just.trust.me' minSdkVersion 16 - targetSdkVersion 23 + targetSdkVersion 30 versionCode 3 versionName '.3' } @@ -18,8 +17,10 @@ android { } productFlavors { } + useLibrary 'org.apache.http.legacy' } dependencies { - provided fileTree(dir: 'libs', include: ['*.jar']) + compileOnly fileTree(dir: 'libs', include: ['*.jar']) + implementation 'org.apache.httpcomponents:httpcore:4.4.2' } diff --git a/app/src/main/java/just/trust/me/Main.java b/app/src/main/java/just/trust/me/Main.java index ac14a66..d44cd01 100644 --- a/app/src/main/java/just/trust/me/Main.java +++ b/app/src/main/java/just/trust/me/Main.java @@ -1,8 +1,12 @@ package just.trust.me; +import android.annotation.TargetApi; import android.content.Context; import android.net.http.SslError; +import android.net.http.X509TrustManagerExtensions; +import android.os.Build; import android.util.Log; +import android.util.Pair; import android.webkit.SslErrorHandler; import android.webkit.WebView; @@ -34,15 +38,20 @@ import javax.net.ssl.HostnameVerifier; import javax.net.ssl.KeyManager; import javax.net.ssl.SSLContext; +import javax.net.ssl.SSLEngine; +import javax.net.ssl.SSLParameters; import javax.net.ssl.SSLSession; import javax.net.ssl.TrustManager; +import javax.net.ssl.X509ExtendedTrustManager; import javax.net.ssl.X509TrustManager; import de.robv.android.xposed.IXposedHookLoadPackage; import de.robv.android.xposed.XC_MethodHook; import de.robv.android.xposed.XC_MethodReplacement; +import de.robv.android.xposed.XposedHelpers; import de.robv.android.xposed.callbacks.XC_LoadPackage.LoadPackageParam; +import static de.robv.android.xposed.XC_MethodReplacement.DO_NOTHING; import static de.robv.android.xposed.XposedHelpers.callMethod; import static de.robv.android.xposed.XposedHelpers.callStaticMethod; import static de.robv.android.xposed.XposedHelpers.findAndHookConstructor; @@ -66,92 +75,102 @@ public void handleLoadPackage(final LoadPackageParam lpparam) throws Throwable { /* Apache Hooks */ /* external/apache-http/src/org/apache/http/impl/client/DefaultHttpClient.java */ /* public DefaultHttpClient() */ - Log.d(TAG, "Hooking DefaultHTTPClient for: " + currentPackageName); - findAndHookConstructor(DefaultHttpClient.class, new XC_MethodHook() { - @Override - protected void afterHookedMethod(MethodHookParam param) throws Throwable { + if (hasDefaultHTTPClient()) { + Log.d(TAG, "Hooking DefaultHTTPClient for: " + currentPackageName); + findAndHookConstructor(DefaultHttpClient.class, new XC_MethodHook() { + @Override + protected void afterHookedMethod(MethodHookParam param) throws Throwable { - setObjectField(param.thisObject, "defaultParams", null); - setObjectField(param.thisObject, "connManager", getSCCM()); - } - }); + setObjectField(param.thisObject, "defaultParams", null); + setObjectField(param.thisObject, "connManager", getSCCM()); + } + }); - /* external/apache-http/src/org/apache/http/impl/client/DefaultHttpClient.java */ - /* public DefaultHttpClient(HttpParams params) */ - Log.d(TAG, "Hooking DefaultHTTPClient(HttpParams) for: " + currentPackageName); - findAndHookConstructor(DefaultHttpClient.class, HttpParams.class, new XC_MethodHook() { - @Override - protected void afterHookedMethod(MethodHookParam param) throws Throwable { + /* external/apache-http/src/org/apache/http/impl/client/DefaultHttpClient.java */ + /* public DefaultHttpClient(HttpParams params) */ + Log.d(TAG, "Hooking DefaultHTTPClient(HttpParams) for: " + currentPackageName); + findAndHookConstructor(DefaultHttpClient.class, HttpParams.class, new XC_MethodHook() { + @Override + protected void afterHookedMethod(MethodHookParam param) throws Throwable { - setObjectField(param.thisObject, "defaultParams", (HttpParams) param.args[0]); - setObjectField(param.thisObject, "connManager", getSCCM()); - } - }); + setObjectField(param.thisObject, "defaultParams", (HttpParams) param.args[0]); + setObjectField(param.thisObject, "connManager", getSCCM()); + } + }); - /* external/apache-http/src/org/apache/http/impl/client/DefaultHttpClient.java */ - /* public DefaultHttpClient(ClientConnectionManager conman, HttpParams params) */ - Log.d(TAG, "Hooking DefaultHTTPClient(ClientConnectionManager, HttpParams) for: " + currentPackageName); - findAndHookConstructor(DefaultHttpClient.class, ClientConnectionManager.class, HttpParams.class, new XC_MethodHook() { - @Override - protected void afterHookedMethod(MethodHookParam param) throws Throwable { + /* external/apache-http/src/org/apache/http/impl/client/DefaultHttpClient.java */ + /* public DefaultHttpClient(ClientConnectionManager conman, HttpParams params) */ + Log.d(TAG, "Hooking DefaultHTTPClient(ClientConnectionManager, HttpParams) for: " + currentPackageName); + findAndHookConstructor(DefaultHttpClient.class, ClientConnectionManager.class, HttpParams.class, new XC_MethodHook() { + @Override + protected void afterHookedMethod(MethodHookParam param) throws Throwable { - HttpParams params = (HttpParams) param.args[1]; + HttpParams params = (HttpParams) param.args[1]; - setObjectField(param.thisObject, "defaultParams", params); - setObjectField(param.thisObject, "connManager", getCCM(param.args[0], params)); + setObjectField(param.thisObject, "defaultParams", params); + setObjectField(param.thisObject, "connManager", getCCM(param.args[0], params)); + } + }); + } + + findAndHookMethod(X509TrustManagerExtensions.class, "checkServerTrusted", X509Certificate[].class, String.class, String.class, new XC_MethodReplacement() { + @Override + protected Object replaceHookedMethod(MethodHookParam param) throws Throwable { + return param.args[0]; } }); + findAndHookMethod("android.security.net.config.NetworkSecurityTrustManager", lpparam.classLoader, "checkPins", List.class, DO_NOTHING); + /* external/apache-http/src/org/apache/http/conn/ssl/SSLSocketFactory.java */ /* public SSLSocketFactory( ... ) */ - Log.d(TAG, "Hooking SSLSocketFactory(String, KeyStore, String, KeyStore) for: " + currentPackageName); - findAndHookConstructor(SSLSocketFactory.class, String.class, KeyStore.class, String.class, KeyStore.class, - SecureRandom.class, HostNameResolver.class, new XC_MethodHook() { - @Override - protected void afterHookedMethod(MethodHookParam param) throws Throwable { + try { + Log.d(TAG, "Hooking SSLSocketFactory(String, KeyStore, String, KeyStore) for: " + currentPackageName); + findAndHookConstructor(SSLSocketFactory.class, String.class, KeyStore.class, String.class, KeyStore.class, + SecureRandom.class, HostNameResolver.class, new XC_MethodHook() { + @Override + protected void afterHookedMethod(MethodHookParam param) throws Throwable { - String algorithm = (String) param.args[0]; - KeyStore keystore = (KeyStore) param.args[1]; - String keystorePassword = (String) param.args[2]; - SecureRandom random = (SecureRandom) param.args[4]; + String algorithm = (String) param.args[0]; + KeyStore keystore = (KeyStore) param.args[1]; + String keystorePassword = (String) param.args[2]; + SecureRandom random = (SecureRandom) param.args[4]; - KeyManager[] keymanagers = null; - TrustManager[] trustmanagers = null; + KeyManager[] keymanagers = null; + TrustManager[] trustmanagers = null; - if (keystore != null) { - keymanagers = (KeyManager[]) callStaticMethod(SSLSocketFactory.class, "createKeyManagers", keystore, keystorePassword); - } + if (keystore != null) { + keymanagers = (KeyManager[]) callStaticMethod(SSLSocketFactory.class, "createKeyManagers", keystore, keystorePassword); + } - trustmanagers = new TrustManager[]{new ImSureItsLegitTrustManager()}; + trustmanagers = new TrustManager[]{getTrustManager()}; - setObjectField(param.thisObject, "sslcontext", SSLContext.getInstance(algorithm)); - callMethod(getObjectField(param.thisObject, "sslcontext"), "init", keymanagers, trustmanagers, random); - setObjectField(param.thisObject, "socketfactory", - callMethod(getObjectField(param.thisObject, "sslcontext"), "getSocketFactory")); - } + setObjectField(param.thisObject, "sslcontext", SSLContext.getInstance(algorithm)); + callMethod(getObjectField(param.thisObject, "sslcontext"), "init", keymanagers, trustmanagers, random); + setObjectField(param.thisObject, "socketfactory", + callMethod(getObjectField(param.thisObject, "sslcontext"), "getSocketFactory")); + } - }); + }); - /* external/apache-http/src/org/apache/http/conn/ssl/SSLSocketFactory.java */ - /* public static SSLSocketFactory getSocketFactory() */ - Log.d(TAG, "Hooking static SSLSocketFactory(String, KeyStore, String, KeyStore) for: " + currentPackageName); - findAndHookMethod("org.apache.http.conn.ssl.SSLSocketFactory", lpparam.classLoader, "getSocketFactory", new XC_MethodReplacement() { - @Override - protected Object replaceHookedMethod(MethodHookParam param) throws Throwable { - return (SSLSocketFactory) newInstance(SSLSocketFactory.class); - } - }); + /* external/apache-http/src/org/apache/http/conn/ssl/SSLSocketFactory.java */ + /* public static SSLSocketFactory getSocketFactory() */ + Log.d(TAG, "Hooking static SSLSocketFactory(String, KeyStore, String, KeyStore) for: " + currentPackageName); + findAndHookMethod("org.apache.http.conn.ssl.SSLSocketFactory", lpparam.classLoader, "getSocketFactory", new XC_MethodReplacement() { + @Override + protected Object replaceHookedMethod(MethodHookParam param) throws Throwable { + return (SSLSocketFactory) newInstance(SSLSocketFactory.class); + } + }); + } catch (NoClassDefFoundError e) { + Log.d(TAG, "NoClassDefFoundError SSLSocketFactory HostNameResolver for: " + currentPackageName); + } /* external/apache-http/src/org/apache/http/conn/ssl/SSLSocketFactory.java */ /* public boolean isSecure(Socket) */ Log.d(TAG, "Hooking SSLSocketFactory(Socket) for: " + currentPackageName); - findAndHookMethod("org.apache.http.conn.ssl.SSLSocketFactory", lpparam.classLoader, "isSecure", Socket.class, new XC_MethodReplacement() { - @Override - protected Object replaceHookedMethod(MethodHookParam param) throws Throwable { - return true; - } - }); + findAndHookMethod("org.apache.http.conn.ssl.SSLSocketFactory", lpparam.classLoader, "isSecure", Socket.class, DO_NOTHING); /* JSSE Hooks */ /* libcore/luni/src/main/java/javax/net/ssl/TrustManagerFactory.java */ @@ -169,7 +188,7 @@ protected void afterHookedMethod(MethodHookParam param) throws Throwable { return; } - param.setResult(new TrustManager[]{new ImSureItsLegitTrustManager()}); + param.setResult(new TrustManager[]{getTrustManager()}); } }); @@ -177,34 +196,17 @@ protected void afterHookedMethod(MethodHookParam param) throws Throwable { /* public void setDefaultHostnameVerifier(HostnameVerifier) */ Log.d(TAG, "Hooking HttpsURLConnection.setDefaultHostnameVerifier for: " + currentPackageName); findAndHookMethod("javax.net.ssl.HttpsURLConnection", lpparam.classLoader, "setDefaultHostnameVerifier", - HostnameVerifier.class, new XC_MethodReplacement() { - @Override - protected Object replaceHookedMethod(MethodHookParam param) throws Throwable { - return null; - } - }); + HostnameVerifier.class, DO_NOTHING); /* libcore/luni/src/main/java/javax/net/ssl/HttpsURLConnection.java */ /* public void setSSLSocketFactory(SSLSocketFactory) */ Log.d(TAG, "Hooking HttpsURLConnection.setSSLSocketFactory for: " + currentPackageName); - findAndHookMethod("javax.net.ssl.HttpsURLConnection", lpparam.classLoader, "setSSLSocketFactory", javax.net.ssl.SSLSocketFactory.class, - new XC_MethodReplacement() { - @Override - protected Object replaceHookedMethod(MethodHookParam param) throws Throwable { - return null; - } - }); + findAndHookMethod("javax.net.ssl.HttpsURLConnection", lpparam.classLoader, "setSSLSocketFactory", javax.net.ssl.SSLSocketFactory.class, DO_NOTHING); /* libcore/luni/src/main/java/javax/net/ssl/HttpsURLConnection.java */ /* public void setHostnameVerifier(HostNameVerifier) */ Log.d(TAG, "Hooking HttpsURLConnection.setHostnameVerifier for: " + currentPackageName); - findAndHookMethod("javax.net.ssl.HttpsURLConnection", lpparam.classLoader, "setHostnameVerifier", HostnameVerifier.class, - new XC_MethodReplacement() { - @Override - protected Object replaceHookedMethod(MethodHookParam param) throws Throwable { - return null; - } - }); + findAndHookMethod("javax.net.ssl.HttpsURLConnection", lpparam.classLoader, "setHostnameVerifier", HostnameVerifier.class, DO_NOTHING); /* WebView Hooks */ @@ -226,12 +228,7 @@ protected Object replaceHookedMethod(MethodHookParam param) throws Throwable { Log.d(TAG, "Hooking WebViewClient.onReceivedSslError(WebView, int, string, string) for: " + currentPackageName); findAndHookMethod("android.webkit.WebViewClient", lpparam.classLoader, "onReceivedError", - WebView.class, int.class, String.class, String.class, new XC_MethodReplacement() { - @Override - protected Object replaceHookedMethod(MethodHookParam param) throws Throwable { - return null; - } - }); + WebView.class, int.class, String.class, String.class, DO_NOTHING); //SSLContext.init >> (null,ImSureItsLegitTrustManager,null) findAndHookMethod("javax.net.ssl.SSLContext", lpparam.classLoader, "init", KeyManager[].class, TrustManager[].class, SecureRandom.class, new XC_MethodHook() { @@ -240,7 +237,7 @@ protected Object replaceHookedMethod(MethodHookParam param) throws Throwable { protected void beforeHookedMethod(MethodHookParam param) throws Throwable { param.args[0] = null; - param.args[1] = new TrustManager[]{new ImSureItsLegitTrustManager()}; + param.args[1] = new TrustManager[]{getTrustManager()}; param.args[2] = null; } @@ -303,6 +300,28 @@ protected Object replaceHookedMethod(MethodHookParam param) throws Throwable { return list; } }); + + try { + findAndHookMethod("com.android.org.conscrypt.TrustManagerImpl", lpparam.classLoader, "checkTrusted", X509Certificate[].class, String.class, SSLSession.class, SSLParameters.class, boolean.class, new XC_MethodReplacement() { + @Override + protected Object replaceHookedMethod(MethodHookParam param) throws Throwable { + ArrayList list = new ArrayList(); + return list; + } + }); + + + findAndHookMethod("com.android.org.conscrypt.TrustManagerImpl", lpparam.classLoader, "checkTrusted", X509Certificate[].class, byte[].class, byte[].class, String.class, String.class, boolean.class, new XC_MethodReplacement() { + @Override + protected Object replaceHookedMethod(MethodHookParam param) throws Throwable { + ArrayList list = new ArrayList(); + return list; + } + }); + } catch (NoSuchMethodError e) { + + } + } } // End Hooks @@ -319,14 +338,21 @@ public boolean hasTrustManagerImpl() { return true; } + public boolean hasDefaultHTTPClient() { + try { + Class.forName("org.apache.http.impl.client.DefaultHttpClient"); + } catch (ClassNotFoundException e) { + return false; + } + return true; + } + private javax.net.ssl.SSLSocketFactory getEmptySSLFactory() { try { SSLContext sslContext = SSLContext.getInstance("TLS"); - sslContext.init(null, new TrustManager[]{new ImSureItsLegitTrustManager()}, null); + sslContext.init(null, new TrustManager[]{getTrustManager()}, null); return sslContext.getSocketFactory(); - } catch (NoSuchAlgorithmException e) { - return null; - } catch (KeyManagementException e) { + } catch (NoSuchAlgorithmException | KeyManagementException e) { return null; } } @@ -454,12 +480,7 @@ protected Object replaceHookedMethod(MethodHookParam methodHookParam) throws Thr "check", String.class, List.class, - new XC_MethodReplacement() { - @Override - protected Object replaceHookedMethod(MethodHookParam methodHookParam) throws Throwable { - return null; - } - }); + DO_NOTHING); } catch (ClassNotFoundException e) { Log.d(TAG, "OKHTTP 3.x not found in " + currentPackageName + " -- not hooking"); // pass @@ -502,6 +523,36 @@ protected Object replaceHookedMethod(MethodHookParam methodHookParam) throws Thr Log.d(TAG, "OKHTTP 3.x not found in " + currentPackageName + " -- not hooking OkHostnameVerifier.verify(String, X509)("); // pass } + + //https://github.com/square/okhttp/blob/okhttp_4.2.x/okhttp/src/main/java/okhttp3/CertificatePinner.kt + Log.d(TAG, "Hooking okhttp3.CertificatePinner.check(String,List) (4.2.0+) for: " + currentPackageName); + + try { + classLoader.loadClass("okhttp3.CertificatePinner"); + findAndHookMethod("okhttp3.CertificatePinner", + classLoader, + "check$okhttp", + String.class, + "kotlin.jvm.functions.Function0", + DO_NOTHING); + } catch (XposedHelpers.ClassNotFoundError | ClassNotFoundException | NoSuchMethodError e) { + Log.d(TAG, "OKHTTP 4.2.0+ (check$okhttp) not found in " + currentPackageName + " -- not hooking"); + // pass + } + + try { + classLoader.loadClass("okhttp3.CertificatePinner"); + findAndHookMethod("okhttp3.CertificatePinner", + classLoader, + "check", + String.class, + List.class, + DO_NOTHING); + } catch (XposedHelpers.ClassNotFoundError | ClassNotFoundException | NoSuchMethodError e) { + Log.d(TAG, "OKHTTP 4.2.0+ (check) not found in " + currentPackageName + " -- not hooking"); + // pass + } + } void processHttpClientAndroidLib(ClassLoader classLoader) { @@ -513,18 +564,51 @@ void processHttpClientAndroidLib(ClassLoader classLoader) { classLoader.loadClass("ch.boye.httpclientandroidlib.conn.ssl.AbstractVerifier"); findAndHookMethod("ch.boye.httpclientandroidlib.conn.ssl.AbstractVerifier", classLoader, "verify", String.class, String[].class, String[].class, boolean.class, - new XC_MethodReplacement() { - @Override - protected Object replaceHookedMethod(MethodHookParam methodHookParam) throws Throwable { - return null; - } - }); + DO_NOTHING); } catch (ClassNotFoundException e) { // pass Log.d(TAG, "httpclientandroidlib not found in " + currentPackageName + "-- not hooking"); } } + @TargetApi(Build.VERSION_CODES.N) + private class ImSureItsLegitExtendedTrustManager extends X509ExtendedTrustManager { + @Override + public void checkClientTrusted(X509Certificate[] chain, String authType, Socket socket) throws CertificateException { + + } + + @Override + public void checkServerTrusted(X509Certificate[] chain, String authType, Socket socket) throws CertificateException { + + } + + @Override + public void checkClientTrusted(X509Certificate[] chain, String authType, SSLEngine engine) throws CertificateException { + + } + + @Override + public void checkServerTrusted(X509Certificate[] chain, String authType, SSLEngine engine) throws CertificateException { + + } + + @Override + public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException { + + } + + @Override + public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException { + + } + + @Override + public X509Certificate[] getAcceptedIssuers() { + return new X509Certificate[0]; + } + } + private class ImSureItsLegitTrustManager implements X509TrustManager { @Override public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException { @@ -534,10 +618,10 @@ public void checkClientTrusted(X509Certificate[] chain, String authType) throws public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException { } - public List checkServerTrusted(X509Certificate[] chain, String authType, String host) throws CertificateException { - ArrayList list = new ArrayList(); - return list; - } + public List checkServerTrusted(X509Certificate[] chain, String authType, String host) throws CertificateException { + ArrayList list = new ArrayList(); + return list; + } @Override public X509Certificate[] getAcceptedIssuers() { @@ -545,6 +629,14 @@ public X509Certificate[] getAcceptedIssuers() { } } + private X509TrustManager getTrustManager() { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { + return new ImSureItsLegitExtendedTrustManager(); + } else { + return new ImSureItsLegitTrustManager(); + } + } + private class ImSureItsLegitHostnameVerifier implements HostnameVerifier { @Override diff --git a/build.gradle b/build.gradle index 5966013..7b51aa0 100644 --- a/build.gradle +++ b/build.gradle @@ -2,10 +2,11 @@ buildscript { repositories { - jcenter() + google() + jcenter() } dependencies { - classpath 'com.android.tools.build:gradle:2.3.3' + classpath 'com.android.tools.build:gradle:7.2.1' // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files @@ -14,6 +15,7 @@ buildscript { allprojects { repositories { - jcenter() + google() + jcenter() } } diff --git a/gradle.properties b/gradle.properties index cba9565..3bb8ecc 100644 --- a/gradle.properties +++ b/gradle.properties @@ -13,5 +13,5 @@ # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects # org.gradle.parallel=true #Mon Jun 26 14:34:35 CST 2017 -systemProp.http.proxyHost=127.0.0.1 -systemProp.http.proxyPort=1080 +#systemProp.http.proxyHost=127.0.0.1 +#systemProp.http.proxyPort=1080 diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 3710617..f338a88 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -2,4 +2,4 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-3.3-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-7.3.3-all.zip