├── app
├── .gitignore
├── src
│ └── main
│ │ ├── assets
│ │ └── xposed_init
│ │ ├── res
│ │ ├── values
│ │ │ ├── styles.xml
│ │ │ ├── dimens.xml
│ │ │ └── strings.xml
│ │ └── values-w820dp
│ │ │ └── dimens.xml
│ │ ├── AndroidManifest.xml
│ │ └── java
│ │ └── just
│ │ └── trust
│ │ └── me
│ │ └── Main.java
├── app-release.apk
├── libs
│ └── XposedBridgeApi.jar
├── build.gradle
└── proguard-rules.pro
├── settings.gradle
├── .gitattributes
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── .gitignore
├── gradle.properties
├── LICENSE
├── Readme.md
├── gradlew.bat
└── gradlew
/app/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':app'
2 |
--------------------------------------------------------------------------------
/app/src/main/assets/xposed_init:
--------------------------------------------------------------------------------
1 | just.trust.me.Main
--------------------------------------------------------------------------------
/.gitattributes:
--------------------------------------------------------------------------------
1 | # Auto detect text files and perform LF normalization
2 | * text=auto
3 |
--------------------------------------------------------------------------------
/app/app-release.apk:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/5up3rc/JustTrustMe/HEAD/app/app-release.apk
--------------------------------------------------------------------------------
/app/libs/XposedBridgeApi.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/5up3rc/JustTrustMe/HEAD/app/libs/XposedBridgeApi.jar
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/5up3rc/JustTrustMe/HEAD/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/.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 |
--------------------------------------------------------------------------------
/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Sat Apr 08 16:14:51 PDT 2017
2 | distributionBase=GRADLE_USER_HOME
3 | distributionPath=wrapper/dists
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 | distributionUrl=https\://services.gradle.org/distributions/gradle-3.3-all.zip
7 |
--------------------------------------------------------------------------------
/app/src/main/res/values-w820dp/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 | 64dp
6 |
7 |
--------------------------------------------------------------------------------
/app/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.application'
2 |
3 | android {
4 | compileSdkVersion 22
5 | buildToolsVersion '25.0.2'
6 | defaultConfig {
7 | applicationId 'just.trust.me'
8 | minSdkVersion 16
9 | targetSdkVersion 22
10 | versionCode 3
11 | versionName '.3'
12 | }
13 |
14 | buildTypes {
15 | release {
16 | minifyEnabled false
17 | }
18 | }
19 | productFlavors {
20 | }
21 | }
22 |
23 | dependencies {
24 | provided fileTree(dir: 'libs', include: ['*.jar'])
25 | }
26 |
--------------------------------------------------------------------------------
/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
9 |
12 |
15 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2018 路伟饶
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
--------------------------------------------------------------------------------
/Readme.md:
--------------------------------------------------------------------------------
1 | JustTrustMe
2 | ===========
3 | 此版本的JustTrustMe基于[Fuzion24开发的JustTrustMe项目](https://github.com/Fuzion24/JustTrustMe)二次开发而来。
4 |
5 | ## 新增的功能
6 | 待补充
7 |
8 | ===========
9 | 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).
10 |
11 | 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.
12 |
13 | 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.
14 |
15 | ## Installation
16 |
17 | As a prequsite, your device must be rooted and the xposed framework must be installed.
18 | You can download the xposed framework [here](http://repo.xposed.info/module/de.robv.android.xposed.installer).
19 |
20 | ### Install from binary
21 |
22 | The JustTrustMe binary can be downloaded from [https://github.com/Fuzion24/JustTrustMe/releases/latest](https://github.com/Fuzion24/JustTrustMe/releases/latest)
23 |
24 | ```
25 | adb install ./JustTrustMe.apk
26 | ```
27 |
28 | or navigate here and download the APK on your phone:
29 | [https://github.com/Fuzion24/JustTrustMe/releases/latest](https://github.com/Fuzion24/JustTrustMe/releases/latest)
30 |
31 |
32 | ### Build from Source
33 | All the normal gradle build commands apply:
34 | To build a release APK:
35 | ```
36 | ./gradlew assembleRelease
37 | ```
38 | To install directly to the phone connected via ADB:
39 | ```
40 | ./gradlew installRelease
41 | ```
42 |
43 |
44 |
45 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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.util.Log;
6 | import android.webkit.SslErrorHandler;
7 | import android.webkit.WebView;
8 |
9 | import org.apache.http.conn.ClientConnectionManager;
10 | import org.apache.http.conn.scheme.HostNameResolver;
11 | import org.apache.http.conn.scheme.PlainSocketFactory;
12 | import org.apache.http.conn.scheme.Scheme;
13 | import org.apache.http.conn.scheme.SchemeRegistry;
14 | import org.apache.http.conn.ssl.SSLSocketFactory;
15 | import org.apache.http.impl.client.DefaultHttpClient;
16 | import org.apache.http.impl.conn.SingleClientConnManager;
17 | import org.apache.http.impl.conn.tsccm.ThreadSafeClientConnManager;
18 | import org.apache.http.params.HttpParams;
19 |
20 | import java.io.IOException;
21 | import java.net.Socket;
22 | import java.net.UnknownHostException;
23 | import java.security.KeyManagementException;
24 | import java.security.KeyStore;
25 | import java.security.KeyStoreException;
26 | import java.security.NoSuchAlgorithmException;
27 | import java.security.SecureRandom;
28 | import java.security.UnrecoverableKeyException;
29 | import java.security.cert.CertificateException;
30 | import java.security.cert.X509Certificate;
31 | import java.util.ArrayList;
32 | import java.util.List;
33 |
34 | import javax.net.ssl.HostnameVerifier;
35 | import javax.net.ssl.KeyManager;
36 | import javax.net.ssl.SSLContext;
37 | import javax.net.ssl.SSLSession;
38 | import javax.net.ssl.TrustManager;
39 | import javax.net.ssl.X509TrustManager;
40 |
41 | import de.robv.android.xposed.IXposedHookLoadPackage;
42 | import de.robv.android.xposed.XC_MethodHook;
43 | import de.robv.android.xposed.XC_MethodReplacement;
44 | import de.robv.android.xposed.callbacks.XC_LoadPackage.LoadPackageParam;
45 |
46 | import static de.robv.android.xposed.XposedHelpers.callMethod;
47 | import static de.robv.android.xposed.XposedHelpers.callStaticMethod;
48 | import static de.robv.android.xposed.XposedHelpers.findAndHookConstructor;
49 | import static de.robv.android.xposed.XposedHelpers.findAndHookMethod;
50 | import static de.robv.android.xposed.XposedHelpers.findClass;
51 | import static de.robv.android.xposed.XposedHelpers.getObjectField;
52 | import static de.robv.android.xposed.XposedHelpers.newInstance;
53 | import static de.robv.android.xposed.XposedHelpers.setObjectField;
54 |
55 | public class Main implements IXposedHookLoadPackage {
56 |
57 | private static final String APPNAME = "JustTrustMe:";
58 | private static String TAG = Main.APPNAME;
59 | String currentPackageName = "";
60 |
61 | public void handleLoadPackage(final LoadPackageParam lpparam) throws Throwable {
62 |
63 | currentPackageName = lpparam.packageName;
64 | TAG = new StringBuffer(Main.APPNAME).append(':').append(currentPackageName).toString();
65 |
66 | /* Apache Hooks */
67 | /* external/apache-http/src/org/apache/http/impl/client/DefaultHttpClient.java */
68 | /* public DefaultHttpClient() */
69 | Log.d(TAG, "Hooking DefaultHTTPClient for: " + currentPackageName);
70 | findAndHookConstructor(DefaultHttpClient.class, new XC_MethodHook() {
71 | @Override
72 | protected void afterHookedMethod(MethodHookParam param) throws Throwable {
73 |
74 | setObjectField(param.thisObject, "defaultParams", null);
75 | setObjectField(param.thisObject, "connManager", getSCCM());
76 | }
77 | });
78 |
79 | /* external/apache-http/src/org/apache/http/impl/client/DefaultHttpClient.java */
80 | /* public DefaultHttpClient(HttpParams params) */
81 | Log.d(TAG, "Hooking DefaultHTTPClient(HttpParams) for: " + currentPackageName);
82 | findAndHookConstructor(DefaultHttpClient.class, HttpParams.class, new XC_MethodHook() {
83 | @Override
84 | protected void afterHookedMethod(MethodHookParam param) throws Throwable {
85 |
86 | setObjectField(param.thisObject, "defaultParams", (HttpParams) param.args[0]);
87 | setObjectField(param.thisObject, "connManager", getSCCM());
88 | }
89 | });
90 |
91 | /* external/apache-http/src/org/apache/http/impl/client/DefaultHttpClient.java */
92 | /* public DefaultHttpClient(ClientConnectionManager conman, HttpParams params) */
93 | Log.d(TAG, "Hooking DefaultHTTPClient(ClientConnectionManager, HttpParams) for: " + currentPackageName);
94 | findAndHookConstructor(DefaultHttpClient.class, ClientConnectionManager.class, HttpParams.class, new XC_MethodHook() {
95 | @Override
96 | protected void afterHookedMethod(MethodHookParam param) throws Throwable {
97 |
98 | HttpParams params = (HttpParams) param.args[1];
99 |
100 | setObjectField(param.thisObject, "defaultParams", params);
101 | setObjectField(param.thisObject, "connManager", getCCM(param.args[0], params));
102 | }
103 | });
104 |
105 | /* external/apache-http/src/org/apache/http/conn/ssl/SSLSocketFactory.java */
106 | /* public SSLSocketFactory( ... ) */
107 | Log.d(TAG, "Hooking SSLSocketFactory(String, KeyStore, String, KeyStore) for: " + currentPackageName);
108 | findAndHookConstructor(SSLSocketFactory.class, String.class, KeyStore.class, String.class, KeyStore.class,
109 | SecureRandom.class, HostNameResolver.class, new XC_MethodHook() {
110 | @Override
111 | protected void afterHookedMethod(MethodHookParam param) throws Throwable {
112 |
113 | String algorithm = (String) param.args[0];
114 | KeyStore keystore = (KeyStore) param.args[1];
115 | String keystorePassword = (String) param.args[2];
116 | SecureRandom random = (SecureRandom) param.args[4];
117 |
118 | KeyManager[] keymanagers = null;
119 | TrustManager[] trustmanagers = null;
120 |
121 | if (keystore != null) {
122 | keymanagers = (KeyManager[]) callStaticMethod(SSLSocketFactory.class, "createKeyManagers", keystore, keystorePassword);
123 | }
124 |
125 | trustmanagers = new TrustManager[]{new ImSureItsLegitTrustManager()};
126 |
127 | setObjectField(param.thisObject, "sslcontext", SSLContext.getInstance(algorithm));
128 | callMethod(getObjectField(param.thisObject, "sslcontext"), "init", keymanagers, trustmanagers, random);
129 | setObjectField(param.thisObject, "socketfactory",
130 | callMethod(getObjectField(param.thisObject, "sslcontext"), "getSocketFactory"));
131 | }
132 |
133 | });
134 |
135 |
136 | /* external/apache-http/src/org/apache/http/conn/ssl/SSLSocketFactory.java */
137 | /* public static SSLSocketFactory getSocketFactory() */
138 | Log.d(TAG, "Hooking static SSLSocketFactory(String, KeyStore, String, KeyStore) for: " + currentPackageName);
139 | findAndHookMethod("org.apache.http.conn.ssl.SSLSocketFactory", lpparam.classLoader, "getSocketFactory", new XC_MethodReplacement() {
140 | @Override
141 | protected Object replaceHookedMethod(MethodHookParam param) throws Throwable {
142 | return (SSLSocketFactory) newInstance(SSLSocketFactory.class);
143 | }
144 | });
145 |
146 | /* external/apache-http/src/org/apache/http/conn/ssl/SSLSocketFactory.java */
147 | /* public boolean isSecure(Socket) */
148 | Log.d(TAG, "Hooking SSLSocketFactory(Socket) for: " + currentPackageName);
149 | findAndHookMethod("org.apache.http.conn.ssl.SSLSocketFactory", lpparam.classLoader, "isSecure", Socket.class, new XC_MethodReplacement() {
150 | @Override
151 | protected Object replaceHookedMethod(MethodHookParam param) throws Throwable {
152 | return true;
153 | }
154 | });
155 |
156 | /* JSSE Hooks */
157 | /* libcore/luni/src/main/java/javax/net/ssl/TrustManagerFactory.java */
158 | /* public final TrustManager[] getTrustManager() */
159 | Log.d(TAG, "Hooking TrustManagerFactory.getTrustManagers() for: " + currentPackageName);
160 | findAndHookMethod("javax.net.ssl.TrustManagerFactory", lpparam.classLoader, "getTrustManagers", new XC_MethodHook() {
161 | @Override
162 | protected void afterHookedMethod(MethodHookParam param) throws Throwable {
163 |
164 | if (hasTrustManagerImpl()) {
165 | Class> cls = findClass("com.android.org.conscrypt.TrustManagerImpl", lpparam.classLoader);
166 |
167 | TrustManager[] managers = (TrustManager[]) param.getResult();
168 | if (managers.length > 0 && cls.isInstance(managers[0]))
169 | return;
170 | }
171 |
172 | param.setResult(new TrustManager[]{new ImSureItsLegitTrustManager()});
173 | }
174 | });
175 |
176 | /* libcore/luni/src/main/java/javax/net/ssl/HttpsURLConnection.java */
177 | /* public void setDefaultHostnameVerifier(HostnameVerifier) */
178 | Log.d(TAG, "Hooking HttpsURLConnection.setDefaultHostnameVerifier for: " + currentPackageName);
179 | findAndHookMethod("javax.net.ssl.HttpsURLConnection", lpparam.classLoader, "setDefaultHostnameVerifier",
180 | HostnameVerifier.class, new XC_MethodReplacement() {
181 | @Override
182 | protected Object replaceHookedMethod(MethodHookParam param) throws Throwable {
183 | return null;
184 | }
185 | });
186 |
187 | /* libcore/luni/src/main/java/javax/net/ssl/HttpsURLConnection.java */
188 | /* public void setSSLSocketFactory(SSLSocketFactory) */
189 | Log.d(TAG, "Hooking HttpsURLConnection.setSSLSocketFactory for: " + currentPackageName);
190 | findAndHookMethod("javax.net.ssl.HttpsURLConnection", lpparam.classLoader, "setSSLSocketFactory", javax.net.ssl.SSLSocketFactory.class,
191 | new XC_MethodReplacement() {
192 | @Override
193 | protected Object replaceHookedMethod(MethodHookParam param) throws Throwable {
194 | return null;
195 | }
196 | });
197 |
198 | /* libcore/luni/src/main/java/javax/net/ssl/HttpsURLConnection.java */
199 | /* public void setHostnameVerifier(HostNameVerifier) */
200 | Log.d(TAG, "Hooking HttpsURLConnection.setHostnameVerifier for: " + currentPackageName);
201 | findAndHookMethod("javax.net.ssl.HttpsURLConnection", lpparam.classLoader, "setHostnameVerifier", HostnameVerifier.class,
202 | new XC_MethodReplacement() {
203 | @Override
204 | protected Object replaceHookedMethod(MethodHookParam param) throws Throwable {
205 | return null;
206 | }
207 | });
208 |
209 |
210 | /* WebView Hooks */
211 | /* frameworks/base/core/java/android/webkit/WebViewClient.java */
212 | /* public void onReceivedSslError(Webview, SslErrorHandler, SslError) */
213 | Log.d(TAG, "Hooking WebViewClient.onReceivedSslError(WebView, SslErrorHandler, SslError) for: " + currentPackageName);
214 |
215 | findAndHookMethod("android.webkit.WebViewClient", lpparam.classLoader, "onReceivedSslError",
216 | WebView.class, SslErrorHandler.class, SslError.class, new XC_MethodReplacement() {
217 | @Override
218 | protected Object replaceHookedMethod(MethodHookParam param) throws Throwable {
219 | ((android.webkit.SslErrorHandler) param.args[1]).proceed();
220 | return null;
221 | }
222 | });
223 |
224 | /* frameworks/base/core/java/android/webkit/WebViewClient.java */
225 | /* public void onReceivedError(WebView, int, String, String) */
226 | Log.d(TAG, "Hooking WebViewClient.onReceivedSslError(WebView, int, string, string) for: " + currentPackageName);
227 |
228 | findAndHookMethod("android.webkit.WebViewClient", lpparam.classLoader, "onReceivedError",
229 | WebView.class, int.class, String.class, String.class, new XC_MethodReplacement() {
230 | @Override
231 | protected Object replaceHookedMethod(MethodHookParam param) throws Throwable {
232 | return null;
233 | }
234 | });
235 |
236 | //SSLContext.init >> (null,ImSureItsLegitTrustManager,null)
237 | findAndHookMethod("javax.net.ssl.SSLContext", lpparam.classLoader, "init", KeyManager[].class, TrustManager[].class, SecureRandom.class, new XC_MethodHook() {
238 |
239 | @Override
240 | protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
241 |
242 | param.args[0] = null;
243 | param.args[1] = new TrustManager[]{new ImSureItsLegitTrustManager()};
244 | param.args[2] = null;
245 |
246 | }
247 | });
248 |
249 | // Multi-dex support: https://github.com/rovo89/XposedBridge/issues/30#issuecomment-68486449
250 | findAndHookMethod("android.app.Application",
251 | lpparam.classLoader,
252 | "attach",
253 | Context.class,
254 | new XC_MethodHook() {
255 | @Override
256 | protected void afterHookedMethod(MethodHookParam param) throws Throwable {
257 | // Hook OkHttp or third party libraries.
258 | Context context = (Context) param.args[0];
259 | processOkHttp(context.getClassLoader());
260 | processHttpClientAndroidLib(context.getClassLoader());
261 | processXutils(context.getClassLoader());
262 | }
263 | }
264 | );
265 |
266 | /* Only for newer devices should we try to hook TrustManagerImpl */
267 | if (hasTrustManagerImpl()) {
268 | /* TrustManagerImpl Hooks */
269 | /* external/conscrypt/src/platform/java/org/conscrypt/TrustManagerImpl.java */
270 | Log.d(TAG, "Hooking com.android.org.conscrypt.TrustManagerImpl for: " + currentPackageName);
271 |
272 | /* public void checkServerTrusted(X509Certificate[] chain, String authType) */
273 | findAndHookMethod("com.android.org.conscrypt.TrustManagerImpl", lpparam.classLoader,
274 | "checkServerTrusted", X509Certificate[].class, String.class,
275 | new XC_MethodReplacement() {
276 | @Override
277 | protected Object replaceHookedMethod(MethodHookParam param) throws Throwable {
278 | return 0;
279 | }
280 | });
281 |
282 | /* public List checkServerTrusted(X509Certificate[] chain,
283 | String authType, String host) throws CertificateException */
284 | findAndHookMethod("com.android.org.conscrypt.TrustManagerImpl", lpparam.classLoader,
285 | "checkServerTrusted", X509Certificate[].class, String.class,
286 | String.class, new XC_MethodReplacement() {
287 | @Override
288 | protected Object replaceHookedMethod(MethodHookParam param) throws Throwable {
289 | ArrayList list = new ArrayList();
290 | return list;
291 | }
292 | });
293 |
294 |
295 | /* public List checkServerTrusted(X509Certificate[] chain,
296 | String authType, SSLSession session) throws CertificateException */
297 | findAndHookMethod("com.android.org.conscrypt.TrustManagerImpl", lpparam.classLoader,
298 | "checkServerTrusted", X509Certificate[].class, String.class,
299 | SSLSession.class, new XC_MethodReplacement() {
300 | @Override
301 | protected Object replaceHookedMethod(MethodHookParam param) throws Throwable {
302 | ArrayList list = new ArrayList();
303 | return list;
304 | }
305 | });
306 | }
307 |
308 | } // End Hooks
309 |
310 | /* Helpers */
311 | // Check for TrustManagerImpl class
312 | public boolean hasTrustManagerImpl() {
313 |
314 | try {
315 | Class.forName("com.android.org.conscrypt.TrustManagerImpl");
316 | } catch (ClassNotFoundException e) {
317 | return false;
318 | }
319 | return true;
320 | }
321 |
322 | private javax.net.ssl.SSLSocketFactory getEmptySSLFactory() {
323 | try {
324 | SSLContext sslContext = SSLContext.getInstance("TLS");
325 | sslContext.init(null, new TrustManager[]{new ImSureItsLegitTrustManager()}, null);
326 | return sslContext.getSocketFactory();
327 | } catch (NoSuchAlgorithmException e) {
328 | return null;
329 | } catch (KeyManagementException e) {
330 | return null;
331 | }
332 | }
333 |
334 | //Create a SingleClientConnManager that trusts everyone!
335 | public ClientConnectionManager getSCCM() {
336 |
337 | KeyStore trustStore;
338 | try {
339 |
340 | trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
341 | trustStore.load(null, null);
342 |
343 | SSLSocketFactory sf = new TrustAllSSLSocketFactory(trustStore);
344 | sf.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
345 |
346 | SchemeRegistry registry = new SchemeRegistry();
347 | registry.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80));
348 | registry.register(new Scheme("https", sf, 443));
349 |
350 | ClientConnectionManager ccm = new SingleClientConnManager(null, registry);
351 |
352 | return ccm;
353 |
354 | } catch (Exception e) {
355 | return null;
356 | }
357 | }
358 |
359 | //This function creates a ThreadSafeClientConnManager that trusts everyone!
360 | public ClientConnectionManager getTSCCM(HttpParams params) {
361 |
362 | KeyStore trustStore;
363 | try {
364 |
365 | trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
366 | trustStore.load(null, null);
367 |
368 | SSLSocketFactory sf = new TrustAllSSLSocketFactory(trustStore);
369 | sf.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
370 |
371 | SchemeRegistry registry = new SchemeRegistry();
372 | registry.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80));
373 | registry.register(new Scheme("https", sf, 443));
374 |
375 | ClientConnectionManager ccm = new ThreadSafeClientConnManager(params, registry);
376 |
377 | return ccm;
378 |
379 | } catch (Exception e) {
380 | return null;
381 | }
382 | }
383 |
384 | //This function determines what object we are dealing with.
385 | public ClientConnectionManager getCCM(Object o, HttpParams params) {
386 |
387 | String className = o.getClass().getSimpleName();
388 |
389 | if (className.equals("SingleClientConnManager")) {
390 | return getSCCM();
391 | } else if (className.equals("ThreadSafeClientConnManager")) {
392 | return getTSCCM(params);
393 | }
394 |
395 | return null;
396 | }
397 |
398 | private void processXutils(ClassLoader classLoader) {
399 | Log.d(TAG, "Hooking org.xutils.http.RequestParams.setSslSocketFactory(SSLSocketFactory) (3) for: " + currentPackageName);
400 | try {
401 | classLoader.loadClass("org.xutils.http.RequestParams");
402 | findAndHookMethod("org.xutils.http.RequestParams", classLoader, "setSslSocketFactory", javax.net.ssl.SSLSocketFactory.class, new XC_MethodHook() {
403 | @Override
404 | protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
405 | super.beforeHookedMethod(param);
406 | param.args[0] = getEmptySSLFactory();
407 | }
408 | });
409 | findAndHookMethod("org.xutils.http.RequestParams", classLoader, "setHostnameVerifier", HostnameVerifier.class, new XC_MethodHook() {
410 | @Override
411 | protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
412 | super.beforeHookedMethod(param);
413 | param.args[0] = new ImSureItsLegitHostnameVerifier();
414 | }
415 | });
416 | } catch (Exception e) {
417 | Log.d(TAG, "org.xutils.http.RequestParams not found in " + currentPackageName + "-- not hooking");
418 | }
419 | }
420 |
421 | void processOkHttp(ClassLoader classLoader) {
422 | /* hooking OKHTTP by SQUAREUP */
423 | /* com/squareup/okhttp/CertificatePinner.java available online @ https://github.com/square/okhttp/blob/master/okhttp/src/main/java/com/squareup/okhttp/CertificatePinner.java */
424 | /* public void check(String hostname, List peerCertificates) throws SSLPeerUnverifiedException{}*/
425 | /* Either returns true or a exception so blanket return true */
426 | /* Tested against version 2.5 */
427 | Log.d(TAG, "Hooking com.squareup.okhttp.CertificatePinner.check(String,List) (2.5) for: " + currentPackageName);
428 |
429 | try {
430 | classLoader.loadClass("com.squareup.okhttp.CertificatePinner");
431 | findAndHookMethod("com.squareup.okhttp.CertificatePinner",
432 | classLoader,
433 | "check",
434 | String.class,
435 | List.class,
436 | new XC_MethodReplacement() {
437 | @Override
438 | protected Object replaceHookedMethod(MethodHookParam methodHookParam) throws Throwable {
439 | return true;
440 | }
441 | });
442 | } catch (ClassNotFoundException e) {
443 | // pass
444 | Log.d(TAG, "OKHTTP 2.5 not found in " + currentPackageName + "-- not hooking");
445 | }
446 |
447 | //https://github.com/square/okhttp/blob/parent-3.0.1/okhttp/src/main/java/okhttp3/CertificatePinner.java#L144
448 | Log.d(TAG, "Hooking okhttp3.CertificatePinner.check(String,List) (3.x) for: " + currentPackageName);
449 |
450 | try {
451 | classLoader.loadClass("okhttp3.CertificatePinner");
452 | findAndHookMethod("okhttp3.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 null;
461 | }
462 | });
463 | } catch (ClassNotFoundException e) {
464 | Log.d(TAG, "OKHTTP 3.x not found in " + currentPackageName + " -- not hooking");
465 | // pass
466 | }
467 |
468 | //https://github.com/square/okhttp/blob/parent-3.0.1/okhttp/src/main/java/okhttp3/internal/tls/OkHostnameVerifier.java
469 | try {
470 | classLoader.loadClass("okhttp3.internal.tls.OkHostnameVerifier");
471 | findAndHookMethod("okhttp3.internal.tls.OkHostnameVerifier",
472 | classLoader,
473 | "verify",
474 | String.class,
475 | javax.net.ssl.SSLSession.class,
476 | new XC_MethodReplacement() {
477 | @Override
478 | protected Object replaceHookedMethod(MethodHookParam methodHookParam) throws Throwable {
479 | return true;
480 | }
481 | });
482 | } catch (ClassNotFoundException e) {
483 | Log.d(TAG, "OKHTTP 3.x not found in " + currentPackageName + " -- not hooking OkHostnameVerifier.verify(String, SSLSession)");
484 | // pass
485 | }
486 |
487 | //https://github.com/square/okhttp/blob/parent-3.0.1/okhttp/src/main/java/okhttp3/internal/tls/OkHostnameVerifier.java
488 | try {
489 | classLoader.loadClass("okhttp3.internal.tls.OkHostnameVerifier");
490 | findAndHookMethod("okhttp3.internal.tls.OkHostnameVerifier",
491 | classLoader,
492 | "verify",
493 | String.class,
494 | java.security.cert.X509Certificate.class,
495 | new XC_MethodReplacement() {
496 | @Override
497 | protected Object replaceHookedMethod(MethodHookParam methodHookParam) throws Throwable {
498 | return true;
499 | }
500 | });
501 | } catch (ClassNotFoundException e) {
502 | Log.d(TAG, "OKHTTP 3.x not found in " + currentPackageName + " -- not hooking OkHostnameVerifier.verify(String, X509)(");
503 | // pass
504 | }
505 | }
506 |
507 | void processHttpClientAndroidLib(ClassLoader classLoader) {
508 | /* httpclientandroidlib Hooks */
509 | /* public final void verify(String host, String[] cns, String[] subjectAlts, boolean strictWithSubDomains) throws SSLException */
510 | Log.d(TAG, "Hooking AbstractVerifier.verify(String, String[], String[], boolean) for: " + currentPackageName);
511 |
512 | try {
513 | classLoader.loadClass("ch.boye.httpclientandroidlib.conn.ssl.AbstractVerifier");
514 | findAndHookMethod("ch.boye.httpclientandroidlib.conn.ssl.AbstractVerifier", classLoader, "verify",
515 | String.class, String[].class, String[].class, boolean.class,
516 | new XC_MethodReplacement() {
517 | @Override
518 | protected Object replaceHookedMethod(MethodHookParam methodHookParam) throws Throwable {
519 | return null;
520 | }
521 | });
522 | } catch (ClassNotFoundException e) {
523 | // pass
524 | Log.d(TAG, "httpclientandroidlib not found in " + currentPackageName + "-- not hooking");
525 | }
526 | }
527 |
528 | private class ImSureItsLegitTrustManager implements X509TrustManager {
529 | @Override
530 | public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
531 | }
532 |
533 | @Override
534 | public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
535 | }
536 |
537 | @Override
538 | public X509Certificate[] getAcceptedIssuers() {
539 | return new X509Certificate[0];
540 | }
541 | }
542 |
543 | private class ImSureItsLegitHostnameVerifier implements HostnameVerifier {
544 |
545 | @Override
546 | public boolean verify(String hostname, SSLSession session) {
547 | return true;
548 | }
549 | }
550 |
551 | /* This class creates a SSLSocket that trusts everyone. */
552 | public class TrustAllSSLSocketFactory extends SSLSocketFactory {
553 |
554 | SSLContext sslContext = SSLContext.getInstance("TLS");
555 |
556 | public TrustAllSSLSocketFactory(KeyStore truststore) throws
557 | NoSuchAlgorithmException, KeyManagementException, KeyStoreException, UnrecoverableKeyException {
558 | super(truststore);
559 |
560 | TrustManager tm = new X509TrustManager() {
561 |
562 | public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
563 | }
564 |
565 | public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
566 | }
567 |
568 | public X509Certificate[] getAcceptedIssuers() {
569 | return null;
570 | }
571 | };
572 |
573 | sslContext.init(null, new TrustManager[]{tm}, null);
574 | }
575 |
576 | @Override
577 | public Socket createSocket(Socket socket, String host, int port, boolean autoClose) throws IOException, UnknownHostException {
578 | return sslContext.getSocketFactory().createSocket(socket, host, port, autoClose);
579 | }
580 |
581 | @Override
582 | public Socket createSocket() throws IOException {
583 | return sslContext.getSocketFactory().createSocket();
584 | }
585 | }
586 | }
587 |
--------------------------------------------------------------------------------