mirror of
https://github.com/Fuzion24/JustTrustMe.git
synced 2026-04-03 08:15:05 +08:00
A lot of apps seem to be using the conscrypt TrustManagerImpl now, including Google Chrome. This patch detects TrustManagerImpl instances and hooks it's checkServerTrusted method.
332 lines
14 KiB
Java
332 lines
14 KiB
Java
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<X509Certificate> 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<X509Certificate> list = new ArrayList<X509Certificate>();
|
|
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();
|
|
}
|
|
}
|
|
}
|