├── .gitignore ├── License.md ├── Readme.md ├── app ├── .gitignore ├── build.gradle ├── libs │ └── XposedBridgeApi.jar ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── me │ │ └── trust │ │ └── just │ │ └── justtrustme │ │ └── ApplicationTest.java │ └── main │ ├── AndroidManifest.xml │ ├── assets │ └── xposed_init │ ├── java │ └── just │ │ └── trust │ │ └── me │ │ └── Main.java │ └── res │ ├── values-w820dp │ └── dimens.xml │ └── values │ ├── dimens.xml │ ├── strings.xml │ └── styles.xml ├── build.gradle ├── build.sh ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat └── settings.gradle /.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | /bin/ 3 | app/build/ 4 | app/src/main/bin/ 5 | app/src/main/gen/ 6 | build/ 7 | .idea/ 8 | .gradle 9 | /local.properties 10 | /.idea/workspace.xml 11 | .DS_Store 12 | -------------------------------------------------------------------------------- /License.md: -------------------------------------------------------------------------------- 1 | Copyright [ 2019 ] [ Ryan Welton ] 2 | 3 | Licensed under the Apache License, Version 2.0 (the "License"); 4 | you may not use this file except in compliance with the License. 5 | You may obtain a copy of the License at 6 | 7 | http://www.apache.org/licenses/LICENSE-2.0 8 | 9 | Unless required by applicable law or agreed to in writing, software 10 | distributed under the License is distributed on an "AS IS" BASIS, 11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | See the License for the specific language governing permissions and 13 | limitations under the License. 14 | -------------------------------------------------------------------------------- /Readme.md: -------------------------------------------------------------------------------- 1 | JustTrustMe 2 | =========== 3 | 4 | An xposed module that disables SSL certificate checking. This is useful for auditing an application which does certificate pinning. There also exists a nice framework built by @moxie to aid in pinning certs in your app: [certificate pinning](https://github.com/moxie0/AndroidPinning). 5 | 6 | An example of an application that does cert pinning is [Twitter](https://play.google.com/store/apps/details?id=com.twitter.android). If you would like to view the network traffic for this application, you must disable the certificate pinning. 7 | 8 | I built this for xposed rather than cydia substrate because xposed seems to support newer devices better. Marc Blanchou wrote the [original tool](https://github.com/iSECPartners/Android-SSL-TrustKiller) for cydia substrate. If you find that you are not able to MITM an application please file an issue. 9 | 10 | ## Installation 11 | 12 | As a prequsite, your device must be rooted and the xposed framework must be installed. 13 | You can download the xposed framework [here](http://repo.xposed.info/module/de.robv.android.xposed.installer). 14 | 15 | ### Install from binary 16 | 17 | The JustTrustMe binary can be downloaded from [https://github.com/Fuzion24/JustTrustMe/releases/latest](https://github.com/Fuzion24/JustTrustMe/releases/latest) 18 | 19 | ``` 20 | adb install ./JustTrustMe.apk 21 | ``` 22 | 23 | or navigate here and download the APK on your phone: 24 | [https://github.com/Fuzion24/JustTrustMe/releases/latest](https://github.com/Fuzion24/JustTrustMe/releases/latest) 25 | 26 | 27 | ### Build from Source 28 | All the normal gradle build commands apply: 29 | To build a release APK: 30 | ``` 31 | ./gradlew assembleRelease 32 | ``` 33 | To install directly to the phone connected via ADB: 34 | ``` 35 | ./gradlew installRelease 36 | ``` 37 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | android { 4 | compileSdkVersion 30 5 | defaultConfig { 6 | applicationId 'just.trust.me' 7 | minSdkVersion 16 8 | targetSdkVersion 30 9 | versionCode 3 10 | versionName '.3' 11 | } 12 | 13 | buildTypes { 14 | release { 15 | minifyEnabled false 16 | } 17 | } 18 | productFlavors { 19 | } 20 | useLibrary 'org.apache.http.legacy' 21 | } 22 | 23 | dependencies { 24 | compileOnly fileTree(dir: 'libs', include: ['*.jar']) 25 | implementation 'org.apache.httpcomponents:httpcore:4.4.2' 26 | } 27 | -------------------------------------------------------------------------------- /app/libs/XposedBridgeApi.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TrackerControl/JustTrustMe/78a4fd50842fca908e63cf34a1e9565ceea25ba3/app/libs/XposedBridgeApi.jar -------------------------------------------------------------------------------- /app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # By default, the flags in this file are appended to flags specified 3 | # in /home/fuzion24/bin/android_sdk_home/tools/proguard/proguard-android.txt 4 | # You can edit the include path and order by changing the proguardFiles 5 | # directive in build.gradle. 6 | # 7 | # For more details, see 8 | # http://developer.android.com/guide/developing/tools/proguard.html 9 | 10 | # Add any project specific keep options here: 11 | 12 | # If your project uses WebView with JS, uncomment the following 13 | # and specify the fully qualified class name to the JavaScript interface 14 | # class: 15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 16 | # public *; 17 | #} 18 | -------------------------------------------------------------------------------- /app/src/androidTest/java/me/trust/just/justtrustme/ApplicationTest.java: -------------------------------------------------------------------------------- 1 | package me.trust.just.justtrustme; 2 | 3 | import android.app.Application; 4 | import android.test.ApplicationTestCase; 5 | 6 | /** 7 | * Testing Fundamentals 8 | */ 9 | public class ApplicationTest extends ApplicationTestCase { 10 | public ApplicationTest() { 11 | super(Application.class); 12 | } 13 | } -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 9 | 12 | 15 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /app/src/main/assets/xposed_init: -------------------------------------------------------------------------------- 1 | just.trust.me.Main -------------------------------------------------------------------------------- /app/src/main/java/just/trust/me/Main.java: -------------------------------------------------------------------------------- 1 | package just.trust.me; 2 | 3 | import android.content.Context; 4 | import android.net.http.SslError; 5 | import android.net.http.X509TrustManagerExtensions; 6 | import android.util.Log; 7 | import android.webkit.SslErrorHandler; 8 | import android.webkit.WebView; 9 | 10 | import org.apache.http.conn.ClientConnectionManager; 11 | import org.apache.http.conn.scheme.HostNameResolver; 12 | import org.apache.http.conn.scheme.PlainSocketFactory; 13 | import org.apache.http.conn.scheme.Scheme; 14 | import org.apache.http.conn.scheme.SchemeRegistry; 15 | import org.apache.http.conn.ssl.SSLSocketFactory; 16 | import org.apache.http.impl.client.DefaultHttpClient; 17 | import org.apache.http.impl.conn.SingleClientConnManager; 18 | import org.apache.http.impl.conn.tsccm.ThreadSafeClientConnManager; 19 | import org.apache.http.params.HttpParams; 20 | 21 | import java.io.IOException; 22 | import java.net.Socket; 23 | import java.net.UnknownHostException; 24 | import java.security.KeyManagementException; 25 | import java.security.KeyStore; 26 | import java.security.KeyStoreException; 27 | import java.security.NoSuchAlgorithmException; 28 | import java.security.SecureRandom; 29 | import java.security.UnrecoverableKeyException; 30 | import java.security.cert.CertificateException; 31 | import java.security.cert.X509Certificate; 32 | import java.util.ArrayList; 33 | import java.util.List; 34 | 35 | import javax.net.ssl.HostnameVerifier; 36 | import javax.net.ssl.KeyManager; 37 | import javax.net.ssl.SSLContext; 38 | import javax.net.ssl.SSLParameters; 39 | import javax.net.ssl.SSLSession; 40 | import javax.net.ssl.TrustManager; 41 | import javax.net.ssl.X509TrustManager; 42 | 43 | import de.robv.android.xposed.IXposedHookLoadPackage; 44 | import de.robv.android.xposed.XC_MethodHook; 45 | import de.robv.android.xposed.XC_MethodReplacement; 46 | import de.robv.android.xposed.XposedHelpers; 47 | import de.robv.android.xposed.callbacks.XC_LoadPackage.LoadPackageParam; 48 | 49 | import static de.robv.android.xposed.XC_MethodReplacement.DO_NOTHING; 50 | import static de.robv.android.xposed.XposedHelpers.callMethod; 51 | import static de.robv.android.xposed.XposedHelpers.callStaticMethod; 52 | import static de.robv.android.xposed.XposedHelpers.findAndHookConstructor; 53 | import static de.robv.android.xposed.XposedHelpers.findAndHookMethod; 54 | import static de.robv.android.xposed.XposedHelpers.findClass; 55 | import static de.robv.android.xposed.XposedHelpers.getObjectField; 56 | import static de.robv.android.xposed.XposedHelpers.newInstance; 57 | import static de.robv.android.xposed.XposedHelpers.setObjectField; 58 | 59 | public class Main implements IXposedHookLoadPackage { 60 | 61 | private static final String TAG = "JustTrustMe"; 62 | String currentPackageName = ""; 63 | 64 | public void handleLoadPackage(final LoadPackageParam lpparam) throws Throwable { 65 | 66 | currentPackageName = lpparam.packageName; 67 | 68 | 69 | 70 | /* Apache Hooks */ 71 | /* external/apache-http/src/org/apache/http/impl/client/DefaultHttpClient.java */ 72 | /* public DefaultHttpClient() */ 73 | if (hasDefaultHTTPClient()) { 74 | Log.d(TAG, "Hooking DefaultHTTPClient for: " + currentPackageName); 75 | findAndHookConstructor(DefaultHttpClient.class, new XC_MethodHook() { 76 | @Override 77 | protected void afterHookedMethod(MethodHookParam param) throws Throwable { 78 | 79 | setObjectField(param.thisObject, "defaultParams", null); 80 | setObjectField(param.thisObject, "connManager", getSCCM()); 81 | } 82 | }); 83 | 84 | /* external/apache-http/src/org/apache/http/impl/client/DefaultHttpClient.java */ 85 | /* public DefaultHttpClient(HttpParams params) */ 86 | Log.d(TAG, "Hooking DefaultHTTPClient(HttpParams) for: " + currentPackageName); 87 | findAndHookConstructor(DefaultHttpClient.class, HttpParams.class, new XC_MethodHook() { 88 | @Override 89 | protected void afterHookedMethod(MethodHookParam param) throws Throwable { 90 | 91 | setObjectField(param.thisObject, "defaultParams", (HttpParams) param.args[0]); 92 | setObjectField(param.thisObject, "connManager", getSCCM()); 93 | } 94 | }); 95 | 96 | /* external/apache-http/src/org/apache/http/impl/client/DefaultHttpClient.java */ 97 | /* public DefaultHttpClient(ClientConnectionManager conman, HttpParams params) */ 98 | Log.d(TAG, "Hooking DefaultHTTPClient(ClientConnectionManager, HttpParams) for: " + currentPackageName); 99 | findAndHookConstructor(DefaultHttpClient.class, ClientConnectionManager.class, HttpParams.class, new XC_MethodHook() { 100 | @Override 101 | protected void afterHookedMethod(MethodHookParam param) throws Throwable { 102 | 103 | HttpParams params = (HttpParams) param.args[1]; 104 | 105 | setObjectField(param.thisObject, "defaultParams", params); 106 | setObjectField(param.thisObject, "connManager", getCCM(param.args[0], params)); 107 | } 108 | }); 109 | } 110 | 111 | findAndHookMethod(X509TrustManagerExtensions.class, "checkServerTrusted", X509Certificate[].class, String.class, String.class, new XC_MethodReplacement() { 112 | @Override 113 | protected Object replaceHookedMethod(MethodHookParam param) throws Throwable { 114 | return param.args[0]; 115 | } 116 | }); 117 | 118 | findAndHookMethod("android.security.net.config.NetworkSecurityTrustManager", lpparam.classLoader, "checkPins", List.class, DO_NOTHING); 119 | 120 | /* external/apache-http/src/org/apache/http/conn/ssl/SSLSocketFactory.java */ 121 | /* public SSLSocketFactory( ... ) */ 122 | try { 123 | Log.d(TAG, "Hooking SSLSocketFactory(String, KeyStore, String, KeyStore) for: " + currentPackageName); 124 | findAndHookConstructor(SSLSocketFactory.class, String.class, KeyStore.class, String.class, KeyStore.class, 125 | SecureRandom.class, HostNameResolver.class, new XC_MethodHook() { 126 | @Override 127 | protected void afterHookedMethod(MethodHookParam param) throws Throwable { 128 | 129 | String algorithm = (String) param.args[0]; 130 | KeyStore keystore = (KeyStore) param.args[1]; 131 | String keystorePassword = (String) param.args[2]; 132 | SecureRandom random = (SecureRandom) param.args[4]; 133 | 134 | KeyManager[] keymanagers = null; 135 | TrustManager[] trustmanagers = null; 136 | 137 | if (keystore != null) { 138 | keymanagers = (KeyManager[]) callStaticMethod(SSLSocketFactory.class, "createKeyManagers", keystore, keystorePassword); 139 | } 140 | 141 | trustmanagers = new TrustManager[]{new ImSureItsLegitTrustManager()}; 142 | 143 | setObjectField(param.thisObject, "sslcontext", SSLContext.getInstance(algorithm)); 144 | callMethod(getObjectField(param.thisObject, "sslcontext"), "init", keymanagers, trustmanagers, random); 145 | setObjectField(param.thisObject, "socketfactory", 146 | callMethod(getObjectField(param.thisObject, "sslcontext"), "getSocketFactory")); 147 | } 148 | 149 | }); 150 | 151 | 152 | /* external/apache-http/src/org/apache/http/conn/ssl/SSLSocketFactory.java */ 153 | /* public static SSLSocketFactory getSocketFactory() */ 154 | Log.d(TAG, "Hooking static SSLSocketFactory(String, KeyStore, String, KeyStore) for: " + currentPackageName); 155 | findAndHookMethod("org.apache.http.conn.ssl.SSLSocketFactory", lpparam.classLoader, "getSocketFactory", new XC_MethodReplacement() { 156 | @Override 157 | protected Object replaceHookedMethod(MethodHookParam param) throws Throwable { 158 | return (SSLSocketFactory) newInstance(SSLSocketFactory.class); 159 | } 160 | }); 161 | } catch (NoClassDefFoundError e) { 162 | Log.d(TAG, "NoClassDefFoundError SSLSocketFactory HostNameResolver for: " + currentPackageName); 163 | } 164 | 165 | /* external/apache-http/src/org/apache/http/conn/ssl/SSLSocketFactory.java */ 166 | /* public boolean isSecure(Socket) */ 167 | Log.d(TAG, "Hooking SSLSocketFactory(Socket) for: " + currentPackageName); 168 | findAndHookMethod("org.apache.http.conn.ssl.SSLSocketFactory", lpparam.classLoader, "isSecure", Socket.class, DO_NOTHING); 169 | 170 | /* JSSE Hooks */ 171 | /* libcore/luni/src/main/java/javax/net/ssl/TrustManagerFactory.java */ 172 | /* public final TrustManager[] getTrustManager() */ 173 | Log.d(TAG, "Hooking TrustManagerFactory.getTrustManagers() for: " + currentPackageName); 174 | findAndHookMethod("javax.net.ssl.TrustManagerFactory", lpparam.classLoader, "getTrustManagers", new XC_MethodHook() { 175 | @Override 176 | protected void afterHookedMethod(MethodHookParam param) throws Throwable { 177 | 178 | if (hasTrustManagerImpl()) { 179 | Class cls = findClass("com.android.org.conscrypt.TrustManagerImpl", lpparam.classLoader); 180 | 181 | TrustManager[] managers = (TrustManager[]) param.getResult(); 182 | if (managers.length > 0 && cls.isInstance(managers[0])) 183 | return; 184 | } 185 | 186 | param.setResult(new TrustManager[]{new ImSureItsLegitTrustManager()}); 187 | } 188 | }); 189 | 190 | /* libcore/luni/src/main/java/javax/net/ssl/HttpsURLConnection.java */ 191 | /* public void setDefaultHostnameVerifier(HostnameVerifier) */ 192 | Log.d(TAG, "Hooking HttpsURLConnection.setDefaultHostnameVerifier for: " + currentPackageName); 193 | findAndHookMethod("javax.net.ssl.HttpsURLConnection", lpparam.classLoader, "setDefaultHostnameVerifier", 194 | HostnameVerifier.class, DO_NOTHING); 195 | 196 | /* libcore/luni/src/main/java/javax/net/ssl/HttpsURLConnection.java */ 197 | /* public void setSSLSocketFactory(SSLSocketFactory) */ 198 | Log.d(TAG, "Hooking HttpsURLConnection.setSSLSocketFactory for: " + currentPackageName); 199 | findAndHookMethod("javax.net.ssl.HttpsURLConnection", lpparam.classLoader, "setSSLSocketFactory", javax.net.ssl.SSLSocketFactory.class, DO_NOTHING); 200 | 201 | /* libcore/luni/src/main/java/javax/net/ssl/HttpsURLConnection.java */ 202 | /* public void setHostnameVerifier(HostNameVerifier) */ 203 | Log.d(TAG, "Hooking HttpsURLConnection.setHostnameVerifier for: " + currentPackageName); 204 | findAndHookMethod("javax.net.ssl.HttpsURLConnection", lpparam.classLoader, "setHostnameVerifier", HostnameVerifier.class, DO_NOTHING); 205 | 206 | 207 | /* WebView Hooks */ 208 | /* frameworks/base/core/java/android/webkit/WebViewClient.java */ 209 | /* public void onReceivedSslError(Webview, SslErrorHandler, SslError) */ 210 | Log.d(TAG, "Hooking WebViewClient.onReceivedSslError(WebView, SslErrorHandler, SslError) for: " + currentPackageName); 211 | 212 | findAndHookMethod("android.webkit.WebViewClient", lpparam.classLoader, "onReceivedSslError", 213 | WebView.class, SslErrorHandler.class, SslError.class, new XC_MethodReplacement() { 214 | @Override 215 | protected Object replaceHookedMethod(MethodHookParam param) throws Throwable { 216 | ((android.webkit.SslErrorHandler) param.args[1]).proceed(); 217 | return null; 218 | } 219 | }); 220 | 221 | /* frameworks/base/core/java/android/webkit/WebViewClient.java */ 222 | /* public void onReceivedError(WebView, int, String, String) */ 223 | Log.d(TAG, "Hooking WebViewClient.onReceivedSslError(WebView, int, string, string) for: " + currentPackageName); 224 | 225 | findAndHookMethod("android.webkit.WebViewClient", lpparam.classLoader, "onReceivedError", 226 | WebView.class, int.class, String.class, String.class, DO_NOTHING); 227 | 228 | //SSLContext.init >> (null,ImSureItsLegitTrustManager,null) 229 | findAndHookMethod("javax.net.ssl.SSLContext", lpparam.classLoader, "init", KeyManager[].class, TrustManager[].class, SecureRandom.class, new XC_MethodHook() { 230 | 231 | @Override 232 | protected void beforeHookedMethod(MethodHookParam param) throws Throwable { 233 | 234 | param.args[0] = null; 235 | param.args[1] = new TrustManager[]{new ImSureItsLegitTrustManager()}; 236 | param.args[2] = null; 237 | 238 | } 239 | }); 240 | 241 | // Multi-dex support: https://github.com/rovo89/XposedBridge/issues/30#issuecomment-68486449 242 | findAndHookMethod("android.app.Application", 243 | lpparam.classLoader, 244 | "attach", 245 | Context.class, 246 | new XC_MethodHook() { 247 | @Override 248 | protected void afterHookedMethod(MethodHookParam param) throws Throwable { 249 | // Hook OkHttp or third party libraries. 250 | Context context = (Context) param.args[0]; 251 | processOkHttp(context.getClassLoader()); 252 | processHttpClientAndroidLib(context.getClassLoader()); 253 | processXutils(context.getClassLoader()); 254 | } 255 | } 256 | ); 257 | 258 | /* Only for newer devices should we try to hook TrustManagerImpl */ 259 | if (hasTrustManagerImpl()) { 260 | /* TrustManagerImpl Hooks */ 261 | /* external/conscrypt/src/platform/java/org/conscrypt/TrustManagerImpl.java */ 262 | Log.d(TAG, "Hooking com.android.org.conscrypt.TrustManagerImpl for: " + currentPackageName); 263 | 264 | /* public void checkServerTrusted(X509Certificate[] chain, String authType) */ 265 | findAndHookMethod("com.android.org.conscrypt.TrustManagerImpl", lpparam.classLoader, 266 | "checkServerTrusted", X509Certificate[].class, String.class, 267 | new XC_MethodReplacement() { 268 | @Override 269 | protected Object replaceHookedMethod(MethodHookParam param) throws Throwable { 270 | return 0; 271 | } 272 | }); 273 | 274 | /* public List checkServerTrusted(X509Certificate[] chain, 275 | String authType, String host) throws CertificateException */ 276 | findAndHookMethod("com.android.org.conscrypt.TrustManagerImpl", lpparam.classLoader, 277 | "checkServerTrusted", X509Certificate[].class, String.class, 278 | String.class, new XC_MethodReplacement() { 279 | @Override 280 | protected Object replaceHookedMethod(MethodHookParam param) throws Throwable { 281 | ArrayList list = new ArrayList(); 282 | return list; 283 | } 284 | }); 285 | 286 | 287 | /* public List checkServerTrusted(X509Certificate[] chain, 288 | String authType, SSLSession session) throws CertificateException */ 289 | findAndHookMethod("com.android.org.conscrypt.TrustManagerImpl", lpparam.classLoader, 290 | "checkServerTrusted", X509Certificate[].class, String.class, 291 | SSLSession.class, new XC_MethodReplacement() { 292 | @Override 293 | protected Object replaceHookedMethod(MethodHookParam param) throws Throwable { 294 | ArrayList list = new ArrayList(); 295 | return list; 296 | } 297 | }); 298 | 299 | try { 300 | findAndHookMethod("com.android.org.conscrypt.TrustManagerImpl", lpparam.classLoader, "checkTrusted", X509Certificate[].class, String.class, SSLSession.class, SSLParameters.class, boolean.class, new XC_MethodReplacement() { 301 | @Override 302 | protected Object replaceHookedMethod(MethodHookParam param) throws Throwable { 303 | ArrayList list = new ArrayList(); 304 | return list; 305 | } 306 | }); 307 | 308 | 309 | findAndHookMethod("com.android.org.conscrypt.TrustManagerImpl", lpparam.classLoader, "checkTrusted", X509Certificate[].class, byte[].class, byte[].class, String.class, String.class, boolean.class, new XC_MethodReplacement() { 310 | @Override 311 | protected Object replaceHookedMethod(MethodHookParam param) throws Throwable { 312 | ArrayList list = new ArrayList(); 313 | return list; 314 | } 315 | }); 316 | } catch (NoSuchMethodError e) { 317 | 318 | } 319 | 320 | } 321 | 322 | } // End Hooks 323 | 324 | /* Helpers */ 325 | // Check for TrustManagerImpl class 326 | public boolean hasTrustManagerImpl() { 327 | 328 | try { 329 | Class.forName("com.android.org.conscrypt.TrustManagerImpl"); 330 | } catch (ClassNotFoundException e) { 331 | return false; 332 | } 333 | return true; 334 | } 335 | 336 | public boolean hasDefaultHTTPClient() { 337 | try { 338 | Class.forName("org.apache.http.impl.client.DefaultHttpClient"); 339 | } catch (ClassNotFoundException e) { 340 | return false; 341 | } 342 | return true; 343 | } 344 | 345 | private javax.net.ssl.SSLSocketFactory getEmptySSLFactory() { 346 | try { 347 | SSLContext sslContext = SSLContext.getInstance("TLS"); 348 | sslContext.init(null, new TrustManager[]{new ImSureItsLegitTrustManager()}, null); 349 | return sslContext.getSocketFactory(); 350 | } catch (NoSuchAlgorithmException | KeyManagementException e) { 351 | return null; 352 | } 353 | } 354 | 355 | //Create a SingleClientConnManager that trusts everyone! 356 | public ClientConnectionManager getSCCM() { 357 | 358 | KeyStore trustStore; 359 | try { 360 | 361 | trustStore = KeyStore.getInstance(KeyStore.getDefaultType()); 362 | trustStore.load(null, null); 363 | 364 | SSLSocketFactory sf = new TrustAllSSLSocketFactory(trustStore); 365 | sf.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER); 366 | 367 | SchemeRegistry registry = new SchemeRegistry(); 368 | registry.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80)); 369 | registry.register(new Scheme("https", sf, 443)); 370 | 371 | ClientConnectionManager ccm = new SingleClientConnManager(null, registry); 372 | 373 | return ccm; 374 | 375 | } catch (Exception e) { 376 | return null; 377 | } 378 | } 379 | 380 | //This function creates a ThreadSafeClientConnManager that trusts everyone! 381 | public ClientConnectionManager getTSCCM(HttpParams params) { 382 | 383 | KeyStore trustStore; 384 | try { 385 | 386 | trustStore = KeyStore.getInstance(KeyStore.getDefaultType()); 387 | trustStore.load(null, null); 388 | 389 | SSLSocketFactory sf = new TrustAllSSLSocketFactory(trustStore); 390 | sf.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER); 391 | 392 | SchemeRegistry registry = new SchemeRegistry(); 393 | registry.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80)); 394 | registry.register(new Scheme("https", sf, 443)); 395 | 396 | ClientConnectionManager ccm = new ThreadSafeClientConnManager(params, registry); 397 | 398 | return ccm; 399 | 400 | } catch (Exception e) { 401 | return null; 402 | } 403 | } 404 | 405 | //This function determines what object we are dealing with. 406 | public ClientConnectionManager getCCM(Object o, HttpParams params) { 407 | 408 | String className = o.getClass().getSimpleName(); 409 | 410 | if (className.equals("SingleClientConnManager")) { 411 | return getSCCM(); 412 | } else if (className.equals("ThreadSafeClientConnManager")) { 413 | return getTSCCM(params); 414 | } 415 | 416 | return null; 417 | } 418 | 419 | private void processXutils(ClassLoader classLoader) { 420 | Log.d(TAG, "Hooking org.xutils.http.RequestParams.setSslSocketFactory(SSLSocketFactory) (3) for: " + currentPackageName); 421 | try { 422 | classLoader.loadClass("org.xutils.http.RequestParams"); 423 | findAndHookMethod("org.xutils.http.RequestParams", classLoader, "setSslSocketFactory", javax.net.ssl.SSLSocketFactory.class, new XC_MethodHook() { 424 | @Override 425 | protected void beforeHookedMethod(MethodHookParam param) throws Throwable { 426 | super.beforeHookedMethod(param); 427 | param.args[0] = getEmptySSLFactory(); 428 | } 429 | }); 430 | findAndHookMethod("org.xutils.http.RequestParams", classLoader, "setHostnameVerifier", HostnameVerifier.class, new XC_MethodHook() { 431 | @Override 432 | protected void beforeHookedMethod(MethodHookParam param) throws Throwable { 433 | super.beforeHookedMethod(param); 434 | param.args[0] = new ImSureItsLegitHostnameVerifier(); 435 | } 436 | }); 437 | } catch (Exception e) { 438 | Log.d(TAG, "org.xutils.http.RequestParams not found in " + currentPackageName + "-- not hooking"); 439 | } 440 | } 441 | 442 | void processOkHttp(ClassLoader classLoader) { 443 | /* hooking OKHTTP by SQUAREUP */ 444 | /* com/squareup/okhttp/CertificatePinner.java available online @ https://github.com/square/okhttp/blob/master/okhttp/src/main/java/com/squareup/okhttp/CertificatePinner.java */ 445 | /* public void check(String hostname, List peerCertificates) throws SSLPeerUnverifiedException{}*/ 446 | /* Either returns true or a exception so blanket return true */ 447 | /* Tested against version 2.5 */ 448 | Log.d(TAG, "Hooking com.squareup.okhttp.CertificatePinner.check(String,List) (2.5) for: " + currentPackageName); 449 | 450 | try { 451 | classLoader.loadClass("com.squareup.okhttp.CertificatePinner"); 452 | findAndHookMethod("com.squareup.okhttp.CertificatePinner", 453 | classLoader, 454 | "check", 455 | String.class, 456 | List.class, 457 | new XC_MethodReplacement() { 458 | @Override 459 | protected Object replaceHookedMethod(MethodHookParam methodHookParam) throws Throwable { 460 | return true; 461 | } 462 | }); 463 | } catch (ClassNotFoundException e) { 464 | // pass 465 | Log.d(TAG, "OKHTTP 2.5 not found in " + currentPackageName + "-- not hooking"); 466 | } 467 | 468 | //https://github.com/square/okhttp/blob/parent-3.0.1/okhttp/src/main/java/okhttp3/CertificatePinner.java#L144 469 | Log.d(TAG, "Hooking okhttp3.CertificatePinner.check(String,List) (3.x) for: " + currentPackageName); 470 | 471 | try { 472 | classLoader.loadClass("okhttp3.CertificatePinner"); 473 | findAndHookMethod("okhttp3.CertificatePinner", 474 | classLoader, 475 | "check", 476 | String.class, 477 | List.class, 478 | DO_NOTHING); 479 | } catch (ClassNotFoundException e) { 480 | Log.d(TAG, "OKHTTP 3.x not found in " + currentPackageName + " -- not hooking"); 481 | // pass 482 | } 483 | 484 | //https://github.com/square/okhttp/blob/parent-3.0.1/okhttp/src/main/java/okhttp3/internal/tls/OkHostnameVerifier.java 485 | try { 486 | classLoader.loadClass("okhttp3.internal.tls.OkHostnameVerifier"); 487 | findAndHookMethod("okhttp3.internal.tls.OkHostnameVerifier", 488 | classLoader, 489 | "verify", 490 | String.class, 491 | javax.net.ssl.SSLSession.class, 492 | new XC_MethodReplacement() { 493 | @Override 494 | protected Object replaceHookedMethod(MethodHookParam methodHookParam) throws Throwable { 495 | return true; 496 | } 497 | }); 498 | } catch (ClassNotFoundException e) { 499 | Log.d(TAG, "OKHTTP 3.x not found in " + currentPackageName + " -- not hooking OkHostnameVerifier.verify(String, SSLSession)"); 500 | // pass 501 | } 502 | 503 | //https://github.com/square/okhttp/blob/parent-3.0.1/okhttp/src/main/java/okhttp3/internal/tls/OkHostnameVerifier.java 504 | try { 505 | classLoader.loadClass("okhttp3.internal.tls.OkHostnameVerifier"); 506 | findAndHookMethod("okhttp3.internal.tls.OkHostnameVerifier", 507 | classLoader, 508 | "verify", 509 | String.class, 510 | java.security.cert.X509Certificate.class, 511 | new XC_MethodReplacement() { 512 | @Override 513 | protected Object replaceHookedMethod(MethodHookParam methodHookParam) throws Throwable { 514 | return true; 515 | } 516 | }); 517 | } catch (ClassNotFoundException e) { 518 | Log.d(TAG, "OKHTTP 3.x not found in " + currentPackageName + " -- not hooking OkHostnameVerifier.verify(String, X509)("); 519 | // pass 520 | } 521 | 522 | //https://github.com/square/okhttp/blob/okhttp_4.2.x/okhttp/src/main/java/okhttp3/CertificatePinner.kt 523 | Log.d(TAG, "Hooking okhttp3.CertificatePinner.check(String,List) (4.2.0+) for: " + currentPackageName); 524 | 525 | try { 526 | classLoader.loadClass("okhttp3.CertificatePinner"); 527 | findAndHookMethod("okhttp3.CertificatePinner", 528 | classLoader, 529 | "check$okhttp", 530 | String.class, 531 | "kotlin.jvm.functions.Function0", 532 | DO_NOTHING); 533 | } catch (XposedHelpers.ClassNotFoundError | ClassNotFoundException | NoSuchMethodError e) { 534 | Log.d(TAG, "OKHTTP 4.2.0+ (check$okhttp) not found in " + currentPackageName + " -- not hooking"); 535 | // pass 536 | } 537 | 538 | try { 539 | classLoader.loadClass("okhttp3.CertificatePinner"); 540 | findAndHookMethod("okhttp3.CertificatePinner", 541 | classLoader, 542 | "check", 543 | String.class, 544 | List.class, 545 | DO_NOTHING); 546 | } catch (XposedHelpers.ClassNotFoundError | ClassNotFoundException | NoSuchMethodError e) { 547 | Log.d(TAG, "OKHTTP 4.2.0+ (check) not found in " + currentPackageName + " -- not hooking"); 548 | // pass 549 | } 550 | 551 | } 552 | 553 | void processHttpClientAndroidLib(ClassLoader classLoader) { 554 | /* httpclientandroidlib Hooks */ 555 | /* public final void verify(String host, String[] cns, String[] subjectAlts, boolean strictWithSubDomains) throws SSLException */ 556 | Log.d(TAG, "Hooking AbstractVerifier.verify(String, String[], String[], boolean) for: " + currentPackageName); 557 | 558 | try { 559 | classLoader.loadClass("ch.boye.httpclientandroidlib.conn.ssl.AbstractVerifier"); 560 | findAndHookMethod("ch.boye.httpclientandroidlib.conn.ssl.AbstractVerifier", classLoader, "verify", 561 | String.class, String[].class, String[].class, boolean.class, 562 | DO_NOTHING); 563 | } catch (ClassNotFoundException e) { 564 | // pass 565 | Log.d(TAG, "httpclientandroidlib not found in " + currentPackageName + "-- not hooking"); 566 | } 567 | } 568 | 569 | private class ImSureItsLegitTrustManager implements X509TrustManager { 570 | @Override 571 | public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException { 572 | } 573 | 574 | @Override 575 | public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException { 576 | } 577 | 578 | public List checkServerTrusted(X509Certificate[] chain, String authType, String host) throws CertificateException { 579 | ArrayList list = new ArrayList(); 580 | return list; 581 | } 582 | 583 | @Override 584 | public X509Certificate[] getAcceptedIssuers() { 585 | return new X509Certificate[0]; 586 | } 587 | } 588 | 589 | private class ImSureItsLegitHostnameVerifier implements HostnameVerifier { 590 | 591 | @Override 592 | public boolean verify(String hostname, SSLSession session) { 593 | return true; 594 | } 595 | } 596 | 597 | /* This class creates a SSLSocket that trusts everyone. */ 598 | public class TrustAllSSLSocketFactory extends SSLSocketFactory { 599 | 600 | SSLContext sslContext = SSLContext.getInstance("TLS"); 601 | 602 | public TrustAllSSLSocketFactory(KeyStore truststore) throws 603 | NoSuchAlgorithmException, KeyManagementException, KeyStoreException, UnrecoverableKeyException { 604 | super(truststore); 605 | 606 | TrustManager tm = new X509TrustManager() { 607 | 608 | public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException { 609 | } 610 | 611 | public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException { 612 | } 613 | 614 | public X509Certificate[] getAcceptedIssuers() { 615 | return null; 616 | } 617 | }; 618 | 619 | sslContext.init(null, new TrustManager[]{tm}, null); 620 | } 621 | 622 | @Override 623 | public Socket createSocket(Socket socket, String host, int port, boolean autoClose) throws IOException, UnknownHostException { 624 | return sslContext.getSocketFactory().createSocket(socket, host, port, autoClose); 625 | } 626 | 627 | @Override 628 | public Socket createSocket() throws IOException { 629 | return sslContext.getSocketFactory().createSocket(); 630 | } 631 | } 632 | } 633 | -------------------------------------------------------------------------------- /app/src/main/res/values-w820dp/dimens.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 64dp 6 | 7 | -------------------------------------------------------------------------------- /app/src/main/res/values/dimens.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 16dp 4 | 16dp 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | JustTrustMe 5 | Hello world! 6 | Settings 7 | 8 | 9 | -------------------------------------------------------------------------------- /app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /build.gradle: -------------------------------------------------------------------------------- 1 | // Top-level build file where you can add configuration options common to all sub-projects/modules. 2 | 3 | buildscript { 4 | repositories { 5 | google() 6 | jcenter() 7 | } 8 | dependencies { 9 | classpath 'com.android.tools.build:gradle:7.2.1' 10 | 11 | // NOTE: Do not place your application dependencies here; they belong 12 | // in the individual module build.gradle files 13 | } 14 | } 15 | 16 | allprojects { 17 | repositories { 18 | google() 19 | jcenter() 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /build.sh: -------------------------------------------------------------------------------- 1 | APK_PATH="bin/JustTrustMe.apk" 2 | mkdir bin 3 | ./gradlew assembleRelease && cp app/build/outputs/apk/app-release-unsigned.apk $APK_PATH && signapk $APK_PATH 4 | 5 | #adb install -r bin/AndroidVTS.apk 6 | -------------------------------------------------------------------------------- /gradle.properties: -------------------------------------------------------------------------------- 1 | ## Project-wide Gradle settings. 2 | # 3 | # For more details on how to configure your build environment visit 4 | # http://www.gradle.org/docs/current/userguide/build_environment.html 5 | # 6 | # Specifies the JVM arguments used for the daemon process. 7 | # The setting is particularly useful for tweaking memory settings. 8 | # Default value: -Xmx1024m -XX:MaxPermSize=256m 9 | # org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8 10 | # 11 | # When configured, Gradle will run in incubating parallel mode. 12 | # This option should only be used with decoupled projects. More details, visit 13 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects 14 | # org.gradle.parallel=true 15 | #Mon Jun 26 14:34:35 CST 2017 16 | systemProp.http.proxyHost=127.0.0.1 17 | systemProp.http.proxyPort=1080 18 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TrackerControl/JustTrustMe/78a4fd50842fca908e63cf34a1e9565ceea25ba3/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | zipStoreBase=GRADLE_USER_HOME 4 | zipStorePath=wrapper/dists 5 | distributionUrl=https\://services.gradle.org/distributions/gradle-7.3.3-all.zip 6 | -------------------------------------------------------------------------------- /gradlew: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | ############################################################################## 4 | ## 5 | ## Gradle start up script for UN*X 6 | ## 7 | ############################################################################## 8 | 9 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 10 | DEFAULT_JVM_OPTS="" 11 | 12 | APP_NAME="Gradle" 13 | APP_BASE_NAME=`basename "$0"` 14 | 15 | # Use the maximum available, or set MAX_FD != -1 to use that value. 16 | MAX_FD="maximum" 17 | 18 | warn ( ) { 19 | echo "$*" 20 | } 21 | 22 | die ( ) { 23 | echo 24 | echo "$*" 25 | echo 26 | exit 1 27 | } 28 | 29 | # OS specific support (must be 'true' or 'false'). 30 | cygwin=false 31 | msys=false 32 | darwin=false 33 | case "`uname`" in 34 | CYGWIN* ) 35 | cygwin=true 36 | ;; 37 | Darwin* ) 38 | darwin=true 39 | ;; 40 | MINGW* ) 41 | msys=true 42 | ;; 43 | esac 44 | 45 | # For Cygwin, ensure paths are in UNIX format before anything is touched. 46 | if $cygwin ; then 47 | [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"` 48 | fi 49 | 50 | # Attempt to set APP_HOME 51 | # Resolve links: $0 may be a link 52 | PRG="$0" 53 | # Need this for relative symlinks. 54 | while [ -h "$PRG" ] ; do 55 | ls=`ls -ld "$PRG"` 56 | link=`expr "$ls" : '.*-> \(.*\)$'` 57 | if expr "$link" : '/.*' > /dev/null; then 58 | PRG="$link" 59 | else 60 | PRG=`dirname "$PRG"`"/$link" 61 | fi 62 | done 63 | SAVED="`pwd`" 64 | cd "`dirname \"$PRG\"`/" >&- 65 | APP_HOME="`pwd -P`" 66 | cd "$SAVED" >&- 67 | 68 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 69 | 70 | # Determine the Java command to use to start the JVM. 71 | if [ -n "$JAVA_HOME" ] ; then 72 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 73 | # IBM's JDK on AIX uses strange locations for the executables 74 | JAVACMD="$JAVA_HOME/jre/sh/java" 75 | else 76 | JAVACMD="$JAVA_HOME/bin/java" 77 | fi 78 | if [ ! -x "$JAVACMD" ] ; then 79 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 80 | 81 | Please set the JAVA_HOME variable in your environment to match the 82 | location of your Java installation." 83 | fi 84 | else 85 | JAVACMD="java" 86 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 87 | 88 | Please set the JAVA_HOME variable in your environment to match the 89 | location of your Java installation." 90 | fi 91 | 92 | # Increase the maximum file descriptors if we can. 93 | if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then 94 | MAX_FD_LIMIT=`ulimit -H -n` 95 | if [ $? -eq 0 ] ; then 96 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 97 | MAX_FD="$MAX_FD_LIMIT" 98 | fi 99 | ulimit -n $MAX_FD 100 | if [ $? -ne 0 ] ; then 101 | warn "Could not set maximum file descriptor limit: $MAX_FD" 102 | fi 103 | else 104 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 105 | fi 106 | fi 107 | 108 | # For Darwin, add options to specify how the application appears in the dock 109 | if $darwin; then 110 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 111 | fi 112 | 113 | # For Cygwin, switch paths to Windows format before running java 114 | if $cygwin ; then 115 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 116 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 117 | 118 | # We build the pattern for arguments to be converted via cygpath 119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 120 | SEP="" 121 | for dir in $ROOTDIRSRAW ; do 122 | ROOTDIRS="$ROOTDIRS$SEP$dir" 123 | SEP="|" 124 | done 125 | OURCYGPATTERN="(^($ROOTDIRS))" 126 | # Add a user-defined pattern to the cygpath arguments 127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 129 | fi 130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 131 | i=0 132 | for arg in "$@" ; do 133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 135 | 136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 138 | else 139 | eval `echo args$i`="\"$arg\"" 140 | fi 141 | i=$((i+1)) 142 | done 143 | case $i in 144 | (0) set -- ;; 145 | (1) set -- "$args0" ;; 146 | (2) set -- "$args0" "$args1" ;; 147 | (3) set -- "$args0" "$args1" "$args2" ;; 148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;; 149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 154 | esac 155 | fi 156 | 157 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules 158 | function splitJvmOpts() { 159 | JVM_OPTS=("$@") 160 | } 161 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS 162 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" 163 | 164 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" 165 | -------------------------------------------------------------------------------- /gradlew.bat: -------------------------------------------------------------------------------- 1 | @if "%DEBUG%" == "" @echo off 2 | @rem ########################################################################## 3 | @rem 4 | @rem Gradle startup script for Windows 5 | @rem 6 | @rem ########################################################################## 7 | 8 | @rem Set local scope for the variables with windows NT shell 9 | if "%OS%"=="Windows_NT" setlocal 10 | 11 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 12 | set DEFAULT_JVM_OPTS= 13 | 14 | set DIRNAME=%~dp0 15 | if "%DIRNAME%" == "" set DIRNAME=. 16 | set APP_BASE_NAME=%~n0 17 | set APP_HOME=%DIRNAME% 18 | 19 | @rem Find java.exe 20 | if defined JAVA_HOME goto findJavaFromJavaHome 21 | 22 | set JAVA_EXE=java.exe 23 | %JAVA_EXE% -version >NUL 2>&1 24 | if "%ERRORLEVEL%" == "0" goto init 25 | 26 | echo. 27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 28 | echo. 29 | echo Please set the JAVA_HOME variable in your environment to match the 30 | echo location of your Java installation. 31 | 32 | goto fail 33 | 34 | :findJavaFromJavaHome 35 | set JAVA_HOME=%JAVA_HOME:"=% 36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 37 | 38 | if exist "%JAVA_EXE%" goto init 39 | 40 | echo. 41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 42 | echo. 43 | echo Please set the JAVA_HOME variable in your environment to match the 44 | echo location of your Java installation. 45 | 46 | goto fail 47 | 48 | :init 49 | @rem Get command-line arguments, handling Windowz variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | if "%@eval[2+2]" == "4" goto 4NT_args 53 | 54 | :win9xME_args 55 | @rem Slurp the command line arguments. 56 | set CMD_LINE_ARGS= 57 | set _SKIP=2 58 | 59 | :win9xME_args_slurp 60 | if "x%~1" == "x" goto execute 61 | 62 | set CMD_LINE_ARGS=%* 63 | goto execute 64 | 65 | :4NT_args 66 | @rem Get arguments from the 4NT Shell from JP Software 67 | set CMD_LINE_ARGS=%$ 68 | 69 | :execute 70 | @rem Setup the command line 71 | 72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 73 | 74 | @rem Execute Gradle 75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 76 | 77 | :end 78 | @rem End local scope for the variables with windows NT shell 79 | if "%ERRORLEVEL%"=="0" goto mainEnd 80 | 81 | :fail 82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 83 | rem the _cmd.exe /c_ return code! 84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 85 | exit /b 1 86 | 87 | :mainEnd 88 | if "%OS%"=="Windows_NT" endlocal 89 | 90 | :omega 91 | -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | include ':app' 2 | --------------------------------------------------------------------------------