package just.trust.me; 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.util.ArrayList; 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 javax.net.ssl.HostnameVerifier; import javax.net.ssl.KeyManager; 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.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; import static de.robv.android.xposed.XposedHelpers.findClass; public class Main implements IXposedHookLoadPackage { public void handleLoadPackage(final LoadPackageParam lpparam) throws Throwable { /* 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 (SSLSocketFactory)newInstance(SSLSocketFactory.class); } }); /* 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 { return true; } }); /* 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_MethodHook() { @Override protected void afterHookedMethod(MethodHookParam param) throws Throwable { Class cls = findClass("com.android.org.conscrypt.TrustManagerImpl", lpparam.classLoader); TrustManager[] managers = (TrustManager[])param.getResult(); if(managers.length > 0 && cls.isInstance(managers[0])) return; param.setResult(new TrustManager[]{new ImSureItsLegitTrustManager()}); } }); /* 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 Object replaceHookedMethod(MethodHookParam param) throws Throwable { return null; } }); /* libcore/luni/src/main/java/javax/net/ssl/HttpsURLConnection.java */ /* public void setSSLSocketFactory(SSLSocketFactory) */ 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; } }); /* 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; } }); /* frameworks/base/core/java/android/webkit/WebViewClient.java */ /* public void onReceivedError(WebView, int, String, String) */ 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; } }); /* external/conscrypt/src/platform/java/org/conscrypt/TrustManagerImpl.java#217 */ /* public List checkServerTrusted(X509Certificate[] chain, String authType, String host) throws CertificateException */ findAndHookMethod("com.android.org.conscrypt.TrustManagerImpl", lpparam.classLoader, "checkServerTrusted", X509Certificate[].class, String.class, String.class, new XC_MethodReplacement() { @Override protected Object replaceHookedMethod(MethodHookParam param) throws Throwable { ArrayList list = new ArrayList(); return list; } }); } // 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 { @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]; } } /* 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(); } } }