content: package mobi.acpm.inspeckage.hooks;
  
  import android.os.Build;
  
  import java.io.DataOutputStream;
  import java.net.HttpURLConnection;
  import java.net.URI;
  import java.net.URL;
  import java.security.SecureRandom;
  import java.security.cert.X509Certificate;
  import java.util.List;
  import java.util.Map;
  
  import javax.net.ssl.KeyManager;
  import javax.net.ssl.SSLContext;
  import javax.net.ssl.TrustManager;
  import javax.net.ssl.X509TrustManager;
  
  import de.robv.android.xposed.XC_MethodHook;
  import de.robv.android.xposed.XposedBridge;
  import de.robv.android.xposed.callbacks.XC_LoadPackage;
  import mobi.acpm.inspeckage.Module;
  
  import static de.robv.android.xposed.XposedBridge.hookAllConstructors;
  import static de.robv.android.xposed.XposedHelpers.findAndHookMethod;
  import static de.robv.android.xposed.XposedHelpers.findClass;
  import static de.robv.android.xposed.XposedHelpers.getObjectField;
  
  /**
   * Created by acpm on 14/02/16.
   */
  public class HttpHook extends XC_MethodHook {
  
      public static final String TAG = "Inspeckage_Http:";
  
      public static void initAllHooks(final XC_LoadPackage.LoadPackageParam loadPackageParam) {
  
          try {
              final Class<?> httpUrlConnection = findClass("java.net.HttpURLConnection", loadPackageParam.classLoader);
              hookAllConstructors(httpUrlConnection, new XC_MethodHook() {
  
                  protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
  
                      if (param.args.length != 1 || param.args[0].getClass() != URL.class) {
                          return;
                      }
  
                      XposedBridge.log(TAG + "HttpURLConnection: " + param.args[0] + "");
                  }
              });
          } catch (Error e) {
              Module.logError(e);
          }
  
          XC_MethodHook RequestHook = new XC_MethodHook() {
  
              protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
  
                  HttpURLConnection urlConn = (HttpURLConnection) param.thisObject;
  
                  if (urlConn != null) {
                      StringBuilder sb = new StringBuilder();
                      boolean connected = (boolean)getObjectField(param.thisObject, "connected");
  
                      if(!connected){
  
  
                          Map<String, List<String>> properties = urlConn.getRequestProperties();
                          if (properties != null && properties.size() > 0) {
  
  
                              for (Map.Entry<String, List<String>> entry : properties.entrySet()){
                                  sb.append(entry.getKey()+": "+entry.getValue()+", ");
                              }
  
  /**
   Collection<List<String>> coll = properties.values();
   if (coll != null && coll.size() > 0) {
   for (List<String> ls : coll) {
   for (String s : ls) {
   sb.append(s+", ");
   }
   }
   }
   **/
                          }
  
                          DataOutputStream dos = (DataOutputStream) param.getResult();
  
  
                          XposedBridge.log(TAG + "REQUEST: method=" + urlConn.getRequestMethod() + " " +
                                  "URL=" + urlConn.getURL().toString() + " " +
                                  "Params=" + sb.toString());
                      }
                  }
  
              }
          };
  
  
          XC_MethodHook ResponseHook = new XC_MethodHook() {
  
              protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
  
                  HttpURLConnection urlConn = (HttpURLConnection) param.thisObject;
  
                  if (urlConn != null) {
                      StringBuilder sb = new StringBuilder();
                      int code = urlConn.getResponseCode();
                      if(code==200){
  
                          Map<String, List<String>> properties = urlConn.getHeaderFields();
                          if (properties != null && properties.size() > 0) {
  
                              for (Map.Entry<String, List<String>> entry : properties.entrySet()) {
                                  sb.append(entry.getKey() + ": " + entry.getValue() + ", ");
                              }
                          }
                      }
  
                      XposedBridge.log(TAG + "RESPONSE: method=" + urlConn.getRequestMethod() + " " +
                              "URL=" + urlConn.getURL().toString() + " " +
                              "Params=" + sb.toString());
                  }
  
              }
          };
  
          try {
              final Class<?> okHttpClient = findClass("com.android.okhttp.OkHttpClient", loadPackageParam.classLoader);
              if(okHttpClient != null) {
                  findAndHookMethod(okHttpClient, "open", URI.class, new XC_MethodHook() {
                      @Override
                      protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
                          URI uri = null;
                          if (param.args[0] != null)
                              uri = (URI) param.args[0];
                          XposedBridge.log(TAG + "OkHttpClient: " + uri.toString() + "");
                      }
                  });
              }
          } catch (Error e) {
              Module.logError(e);
          }
  
  
          try {
              if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.KITKAT) {
                  findAndHookMethod("libcore.net.http.HttpURLConnectionImpl", loadPackageParam.classLoader, "getOutputStream", RequestHook);
              } else {
                  //com.squareup.okhttp.internal.http.HttpURLConnectionImpl
                  final Class<?> httpURLConnectionImpl = findClass("com.android.okhttp.internal.http.HttpURLConnectionImpl", loadPackageParam.classLoader);
                  if(httpURLConnectionImpl != null) {
                      findAndHookMethod("com.android.okhttp.internal.http.HttpURLConnectionImpl", loadPackageParam.classLoader, "getOutputStream", RequestHook);
                      findAndHookMethod("com.android.okhttp.internal.http.HttpURLConnectionImpl", loadPackageParam.classLoader, "getInputStream", ResponseHook);
                  }
              }
          } catch (Error e) {
              Module.logError(e);
          }
  
          findAndHookMethod(SSLContext.class, "init",
                  KeyManager[].class, TrustManager[].class, SecureRandom.class, new XC_MethodHook() {
  
                      protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
                          KeyManager[] km = (KeyManager[]) param.args[0];
                          TrustManager[] tm_ = (TrustManager[]) param.args[1];
  
                          if (tm_ != null && tm_[0] != null) {
                              X509TrustManager tm = (X509TrustManager) tm_[0];
                              X509Certificate[] chain = new X509Certificate[]{};
  
                              XposedBridge.log(TAG + "Possible pinning.");
                              boolean check = false;
                              /**
                               try {
                               tm.checkClientTrusted(chain, "");
                               tm.checkServerTrusted(chain, "");
  
                               }catch (CertificateException ex){
                               check = true;
                               }
  
                               if(check){
                               XposedBridge.log(TAG + " Custom TrustManager - Possible pinning.");
                               }else {
                               XposedBridge.log(TAG + " App not verify SSL.");
                               }**/
                          }
                      }
                  });
      }
  }
  