diff --git a/app/build.gradle b/app/build.gradle index 0149b1d..603b060 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -4,7 +4,7 @@ android { compileSdkVersion 20 buildToolsVersion '20.0.0' defaultConfig { - applicationId 'me.trust.just.justtrustme' + applicationId 'just.trust.me' minSdkVersion 16 targetSdkVersion 20 versionCode 1 @@ -14,7 +14,6 @@ android { buildTypes { release { runProguard false - proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } } productFlavors { diff --git a/app/libs/XposedBridgeApi.jar b/app/libs/XposedBridgeApi.jar index a87ddb4..fefd4ec 100644 Binary files a/app/libs/XposedBridgeApi.jar and b/app/libs/XposedBridgeApi.jar differ diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 32b1b2f..a507b3d 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -6,9 +6,14 @@ android:allowBackup="true" android:label="@string/app_name" android:theme="@style/AppTheme" > - - - + + + - diff --git a/app/src/main/java/just/trust/me/Main.java b/app/src/main/java/just/trust/me/Main.java index 2d866d9..510e733 100644 --- a/app/src/main/java/just/trust/me/Main.java +++ b/app/src/main/java/just/trust/me/Main.java @@ -1,11 +1,22 @@ package just.trust.me; -import javax.net.ssl.SSLSocketFactory; +import android.net.http.SslError; +import android.webkit.SslErrorHandler; +import android.webkit.WebView; +import java.io.IOException; import java.net.Socket; +import java.net.UnknownHostException; + import java.security.SecureRandom; +import java.security.KeyStore; +import java.security.KeyStoreException; import java.security.cert.CertificateException; import java.security.cert.X509Certificate; +import java.security.KeyManagementException; +import java.security.NoSuchAlgorithmException; +import java.security.UnrecoverableKeyException; +import java.security.cert.CertificateException; import javax.net.ssl.HostnameVerifier; import javax.net.ssl.KeyManager; @@ -13,45 +24,111 @@ import javax.net.ssl.SSLContext; import javax.net.ssl.TrustManager; import javax.net.ssl.X509TrustManager; +import org.apache.http.conn.ClientConnectionManager; +import org.apache.http.conn.scheme.HostNameResolver; +import org.apache.http.conn.scheme.PlainSocketFactory; +import org.apache.http.conn.scheme.SchemeRegistry; +import org.apache.http.conn.scheme.Scheme; +import org.apache.http.conn.ssl.SSLSocketFactory; +import org.apache.http.impl.client.DefaultHttpClient; +import org.apache.http.impl.conn.SingleClientConnManager; +import org.apache.http.impl.conn.tsccm.ThreadSafeClientConnManager; +import org.apache.http.params.HttpParams; + 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.XposedBridge; import de.robv.android.xposed.callbacks.XC_LoadPackage.LoadPackageParam; +import static de.robv.android.xposed.XposedHelpers.callMethod; +import static de.robv.android.xposed.XposedHelpers.callStaticMethod; +import static de.robv.android.xposed.XposedHelpers.findAndHookConstructor; import static de.robv.android.xposed.XposedHelpers.findAndHookMethod; +import static de.robv.android.xposed.XposedHelpers.getObjectField; +import static de.robv.android.xposed.XposedHelpers.newInstance; +import static de.robv.android.xposed.XposedHelpers.setObjectField; public class Main implements IXposedHookLoadPackage { public void handleLoadPackage(final LoadPackageParam lpparam) throws Throwable { - findAndHookMethod("javax.net.ssl.TrustManagerFactory", lpparam.classLoader, "getTrustManagers", new XC_MethodReplacement() { + /* Apache Hooks */ + /* external/apache-http/src/org/apache/http/impl/client/DefaultHttpClient.java */ + /* public DefaultHttpClient() */ + findAndHookConstructor(DefaultHttpClient.class, new XC_MethodHook() { + @Override + protected void afterHookedMethod(MethodHookParam param) throws Throwable { + + 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) */ + 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()); + } + }); + + /* external/apache-http/src/org/apache/http/impl/client/DefaultHttpClient.java */ + /* public DefaultHttpClient(ClientConnectionManager conman, HttpParams params) */ + findAndHookConstructor(DefaultHttpClient.class, ClientConnectionManager.class, HttpParams.class, new XC_MethodHook() { + @Override + protected void afterHookedMethod(MethodHookParam param) throws Throwable { + + HttpParams params = (HttpParams)param.args[1]; + + setObjectField(param.thisObject, "defaultParams", params); + setObjectField(param.thisObject, "connManager", getCCM(param.args[0], params)); + } + }); + + /* external/apache-http/src/org/apache/http/conn/ssl/SSLSocketFactory.java */ + /* public SSLSocketFactory( ... ) */ + 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]; + + KeyManager[] keymanagers = null; + TrustManager[] trustmanagers = null; + + if (keystore != null) { + keymanagers = (KeyManager[])callStaticMethod(SSLSocketFactory.class, "createKeyManagers", keystore, keystorePassword); + } + + trustmanagers = new TrustManager[]{new ImSureItsLegitTrustManager()}; + + 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() */ + findAndHookMethod("org.apache.http.conn.ssl.SSLSocketFactory", lpparam.classLoader, "getSocketFactory", new XC_MethodReplacement() { @Override protected Object replaceHookedMethod(MethodHookParam param) throws Throwable { - return new TrustManager[]{new ImSureItsLegitTrustManager()}; + return (SSLSocketFactory)newInstance(SSLSocketFactory.class); } }); - findAndHookMethod("javax.net.ssl.SSLContext", lpparam.classLoader, "init", KeyManager[].class, TrustManager[].class, SecureRandom.class, new XC_MethodHook() { - @Override - protected void beforeHookedMethod(MethodHookParam param) throws Throwable { - param.args[0] = null; - param.args[1] = new TrustManager[]{new ImSureItsLegitTrustManager()}; - param.args[2] = null; - } - }); - - - findAndHookMethod("javax.net.ssl.HttpsURLConnection", lpparam.classLoader, "setSSLSocketFactory", SSLSocketFactory.class, new XC_MethodHook() { - @Override - protected void beforeHookedMethod(MethodHookParam param) throws Throwable { - super.beforeHookedMethod(param); - SSLContext context = SSLContext.getInstance("TLS"); - context.init(null, new TrustManager[]{new ImSureItsLegitTrustManager()}, null); - param.args[0] = context.getSocketFactory(); - } - }); - - + /* external/apache-http/src/org/apache/http/conn/ssl/SSLSocketFactory.java */ + /* public boolean isSecure(Socket) */ findAndHookMethod("org.apache.http.conn.ssl.SSLSocketFactory", lpparam.classLoader, "isSecure", Socket.class, new XC_MethodReplacement() { @Override protected Object replaceHookedMethod(MethodHookParam param) throws Throwable { @@ -59,32 +136,134 @@ public class Main implements IXposedHookLoadPackage { } }); - findAndHookMethod("javax.net.ssl.HttpsURLConnection", lpparam.classLoader, "setHostnameVerifier", HostnameVerifier.class, new XC_MethodHook() { + /* JSSE Hooks */ + /* libcore/luni/src/main/java/javax/net/ssl/TrustManagerFactory.java */ + /* public final TrustManager[] getTrustManager() */ + findAndHookMethod("javax.net.ssl.TrustManagerFactory", lpparam.classLoader, "getTrustManagers", new XC_MethodReplacement() { @Override - protected void beforeHookedMethod(MethodHookParam param) throws Throwable { - param.args[0] = org.apache.http.conn.ssl.SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER; + protected Object replaceHookedMethod(MethodHookParam param) throws Throwable { + return new TrustManager[]{new ImSureItsLegitTrustManager()}; } }); - findAndHookMethod("javax.net.ssl.HttpsURLConnection", lpparam.classLoader, "setDefaultHostnameVerifier", HostnameVerifier.class, new XC_MethodHook() { + /* libcore/luni/src/main/java/javax/net/ssl/HttpsURLConnection.java */ + /* public void setDefaultHostnameVerifier(HostnameVerifier) */ + findAndHookMethod("javax.net.ssl.HttpsURLConnection", lpparam.classLoader, "setDefaultHostnameVerifier", + HostnameVerifier.class, new XC_MethodReplacement() { @Override - protected void beforeHookedMethod(MethodHookParam param) throws Throwable { - param.args[0] = org.apache.http.conn.ssl.SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER; + protected Object replaceHookedMethod(MethodHookParam param) throws Throwable { + return null; } }); - // Trick for WebViews - findAndHookMethod("android.webkit.WebViewClient", lpparam.classLoader, "onReceivedSslError", HostnameVerifier.class, new XC_MethodReplacement() { + /* libcore/luni/src/main/java/javax/net/ssl/HttpsURLConnection.java */ + /* public void setSSLSocketFactory(SSLSocketFactory) */ + findAndHookMethod("javax.net.ssl.HttpsURLConnection", lpparam.classLoader, "setSSLSocketFactory", SSLSocketFactory.class, + new XC_MethodReplacement() { + @Override + protected Object replaceHookedMethod(MethodHookParam param) throws Throwable { + return null; + } + }); + + /* libcore/luni/src/main/java/javax/net/ssl/HttpsURLConnection.java */ + /* public void setHostnameVerifier(HostNameVerifier) */ + findAndHookMethod("javax.net.ssl.HttpsURLConnection", lpparam.classLoader, "setHostnameVerifier", HostnameVerifier.class, + new XC_MethodReplacement() { + @Override + protected Object replaceHookedMethod(MethodHookParam param) throws Throwable { + return null; + } + }); + + + /* WebView Hooks */ + /* frameworks/base/core/java/android/webkit/WebViewClient.java */ + /* public void onReceivedSslError(Webview, SslErrorHandler, SslError) */ + findAndHookMethod("android.webkit.WebViewClient", lpparam.classLoader, "onReceivedSslError", + WebView.class, SslErrorHandler.class, SslError.class, new XC_MethodReplacement() { + @Override protected Object replaceHookedMethod(MethodHookParam param) throws Throwable { ((android.webkit.SslErrorHandler)param.args[1]).proceed(); return null; } }); - findAndHookMethod("android.webkit.WebViewClient", lpparam.classLoader, "onReceivedError", HostnameVerifier.class,new XC_MethodReplacement() { + + /* frameworks/base/core/java/android/webkit/WebViewClient.java */ + /* public voidonReceivedError(WebView, int, String, String) */ + findAndHookMethod("android.webkit.WebViewClient", lpparam.classLoader, "onReceivedError", + WebView.class, Integer.class, String.class, String.class, new XC_MethodReplacement() { + @Override protected Object replaceHookedMethod(MethodHookParam param) throws Throwable { return null; } }); + } // End Hooks + + /* Helpers */ + //Create a SingleClientConnManager that trusts everyone! + public ClientConnectionManager getSCCM() { + + KeyStore trustStore; + try { + + trustStore = KeyStore.getInstance(KeyStore.getDefaultType()); + trustStore.load(null, null); + + SSLSocketFactory sf = new TrustAllSSLSocketFactory(trustStore); + sf.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER); + + SchemeRegistry registry = new SchemeRegistry(); + registry.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80)); + registry.register(new Scheme("https", sf, 443)); + + ClientConnectionManager ccm = new SingleClientConnManager(null, registry); + + return ccm; + + } catch (Exception e) { + return null; + } + } + + //This function creates a ThreadSafeClientConnManager that trusts everyone! + public ClientConnectionManager getTSCCM(HttpParams params) { + + KeyStore trustStore; + try { + + trustStore = KeyStore.getInstance(KeyStore.getDefaultType()); + trustStore.load(null, null); + + SSLSocketFactory sf = new TrustAllSSLSocketFactory(trustStore); + sf.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER); + + SchemeRegistry registry = new SchemeRegistry(); + registry.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80)); + registry.register(new Scheme("https", sf, 443)); + + ClientConnectionManager ccm = new ThreadSafeClientConnManager(params, registry); + + return ccm; + + } catch (Exception e) { + return null; + } + } + + //This function determines what object we are dealing with. + public ClientConnectionManager getCCM(Object o, HttpParams params) { + + String className = o.getClass().getSimpleName(); + + if (className.equals("SingleClientConnManager")) { + return getSCCM(); + } + else if (className.equals("ThreadSafeClientConnManager")) { + return getTSCCM(params); + } + + return null; } class ImSureItsLegitTrustManager implements X509TrustManager { @@ -97,4 +276,40 @@ public class Main implements IXposedHookLoadPackage { return new X509Certificate[0]; } } + + /* This class creates a SSLSocket that trusts everyone. */ + public class TrustAllSSLSocketFactory extends SSLSocketFactory { + + SSLContext sslContext = SSLContext.getInstance("TLS"); + + public TrustAllSSLSocketFactory(KeyStore truststore) throws + NoSuchAlgorithmException, KeyManagementException, KeyStoreException, UnrecoverableKeyException { + super(truststore); + + TrustManager tm = new X509TrustManager() { + + public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException { + } + + public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException { + } + + public X509Certificate[] getAcceptedIssuers() { + return null; + } + }; + + sslContext.init(null, new TrustManager[] { tm }, null); + } + + @Override + public Socket createSocket(Socket socket, String host, int port, boolean autoClose) throws IOException, UnknownHostException { + return sslContext.getSocketFactory().createSocket(socket, host, port, autoClose); + } + + @Override + public Socket createSocket() throws IOException { + return sslContext.getSocketFactory().createSocket(); + } + } } diff --git a/bin/JustTrustMe.apk b/bin/JustTrustMe.apk deleted file mode 100644 index c08c864..0000000 Binary files a/bin/JustTrustMe.apk and /dev/null differ