就把某鱼叫X鱼吧,懂的都懂
某(X)鱼app整个get/post请求中,基本必须在请求头中携带Cookie,这个Cookie的相关操作并不是在 mtopsdk这个包中
,并且

  • anetwork.channel.entity.RequestImpl
  • mtopsdk.network.domain.Request
  • mtopsdk.network.domain.Request.Builder

这几个类中的成员变量Map<String, String> headers中也没有cookie,
它是在android.taobao.windvane.connect.HttpConnector类中setConnectProp方法时添加的

private void setConnectProp(HttpURLConnection paramHttpURLConnection, HttpRequest paramHttpRequest) {
    int i = paramHttpRequest.getRetryTime();
    paramHttpURLConnection.setConnectTimeout(paramHttpRequest.getConnectTimeout() * (i + 1));
    paramHttpURLConnection.setReadTimeout(paramHttpRequest.getReadTimeout() * (i + 1));
    paramHttpURLConnection.setInstanceFollowRedirects(false);
    paramHttpURLConnection.setRequestProperty("Host", paramHttpRequest.getUri().getHost());
    paramHttpURLConnection.setRequestProperty("Connection", "close");
    paramHttpURLConnection.setRequestProperty("Accept-Encoding", "gzip");
    String str = WVCookieManager.getCookie(paramHttpURLConnection.getURL().toString());
    if (str != null)
      paramHttpURLConnection.setRequestProperty("Cookie", str); 
    Map<String, String> map = paramHttpRequest.getHeaders();
    if (map != null)
      for (Map.Entry<String, String> entry : map.entrySet())
        paramHttpURLConnection.setRequestProperty((String)entry.getKey(), (String)entry.getValue());  
    paramHttpURLConnection.setUseCaches(false);
  }

这里的静态方法
WVCookieManager.getCookie();只是个代理类,放一下内容吧

package android.taobao.windvane;

import android.content.Context;
import android.text.TextUtils;
import android.webkit.CookieManager;
import android.webkit.CookieSyncManager;
import com.taobao.codetrack.sdk.util.ReportUtil;

public class WVCookieManager {
  private static final String TAG = "WVCookieManager";
  
  static {
    ReportUtil.dj(-953400378);
  }
  
  public static String getCookie(String paramString) {
    return TextUtils.isEmpty(paramString) ? null : CookieManager.getInstance().getCookie(paramString);
  }
  
  public static void onCreate(Context paramContext) {
    CookieSyncManager.createInstance(paramContext);
  }
  
  public static void setCookie(String paramString1, String paramString2) {
    if (!TextUtils.isEmpty(paramString1) && paramString2 != null) {
      if (!CookieManager.getInstance().acceptCookie())
        CookieManager.getInstance().setAcceptCookie(true); 
      CookieManager.getInstance().setCookie(paramString1, paramString2);
    } 
  }
}

所以真是的还是来看看,此时你以为事情就清晰了不,当在jd_gui中想转跳到CookieManager.getInstance()内部实现时,发现进不去,而且发现这里引用的是import android.webkit.CookieManager类,而hook起到作用的是anetwork.channel.cookie.CookieManager这个类的public static String getCookie(String paramString){…}才被调用,所以这个是骗人的

但是再次搜索在

  • anetwork.channel.unified.DegradeTask
  • anetwork.channel.unified.NetworkTask
    放下代码
package anetwork.channel.unified;

import android.text.TextUtils;
import anet.channel.RequestCb;
import anet.channel.bytes.ByteArray;
import anet.channel.request.Cancelable;
import anet.channel.request.Request;
import anet.channel.session.HttpConnector;
import anet.channel.statist.RequestStatistic;
import anet.channel.util.ALog;
import anet.channel.util.HttpHelper;
import anet.channel.util.StringUtils;
import anetwork.channel.aidl.DefaultFinishEvent;
import anetwork.channel.cookie.CookieManager;
import com.taobao.codetrack.sdk.util.ReportUtil;
import java.util.List;
import java.util.Map;

public class DegradeTask implements IUnifiedTask {
  private static final String TAG = "anet.DegradeTask";
  volatile Cancelable a;
  private RequestContext a = null;
  private int bc = 0;
  private int contentLength = 0;
  private volatile boolean isCanceled = false;
  private Request request;
  static {
    ReportUtil.dj(655715856);
    ReportUtil.dj(471853369);
  }
  
  public DegradeTask(RequestContext paramRequestContext) {
    this.a = paramRequestContext;
    this.request = paramRequestContext.config.b();
  }
  
  public void cancel() {
    this.isCanceled = true;
    if (this.a != null)
      this.a.cancel(); 
  }
  
  public void run() {
    if (!this.isCanceled) {
      if (this.a.config.aW()) {//这里注意待会看看这个判断aw是什么,有意义
        String str = CookieManager.getCookie(this.a.config.getUrlString());
        if (!TextUtils.isEmpty(str)) {
          Request.Builder builder = this.request.a();
          String str1 = (String)this.request.getHeaders().get("Cookie");//这里注意1
          String str2 = str;
          if (!TextUtils.isEmpty(str1))
            str2 = StringUtils.b(str1, "; ", str); 
          builder.a("Cookie", str2);//这里在看看builder.a方法是不是添加头键值对
          this.request = builder.a();
        } 
      } 
      this.request.rs.degraded = 2;
      this.request.rs.sendBeforeTime = System.currentTimeMillis() - this.request.rs.reqStart;
      HttpConnector.a(this.request, new RequestCb(this) {
            public void onDataReceive(ByteArray param1ByteArray, boolean param1Boolean) {
              if (!(DegradeTask.a(this.a)).isDone.get()) {
                DegradeTask.a(this.a);
                if ((DegradeTask.a(this.a)).a != null)
                  (DegradeTask.a(this.a)).a.onDataReceiveSize(DegradeTask.b(this.a), DegradeTask.c(this.a), param1ByteArray); 
              } 
            }
            
            public void onFinish(int param1Int, String param1String, RequestStatistic param1RequestStatistic) {....}
            
            public void onResponseCode(int param1Int, Map<String, List<String>> param1Map) {....} 
  }
}

下面放一下另一个基本差不多

package anetwork.channel.unified;

import android.text.TextUtils;
import anet.channel.Config;
import anet.channel.GlobalAppRuntimeInfo;
import anet.channel.NoAvailStrategyException;
import anet.channel.RequestCb;
import anet.channel.Session;
import anet.channel.SessionCenter;
import anet.channel.SessionGetCallback;
import anet.channel.appmonitor.AppMonitor;
import anet.channel.bytes.ByteArray;
import anet.channel.entity.ConnInfo;
import anet.channel.entity.ENV;
import anet.channel.entity.SessionType;
import anet.channel.request.Cancelable;
import anet.channel.request.Request;
import anet.channel.session.HttpSession;
import anet.channel.statist.ExceptionStatistic;
import anet.channel.statist.RequestStatistic;
import anet.channel.statist.StatObject;
import anet.channel.status.NetworkStatusHelper;
import anet.channel.thread.ThreadPoolExecutorFactory;
import anet.channel.util.ALog;
import anet.channel.util.AppLifecycle;
import anet.channel.util.ErrorConstant;
import anet.channel.util.HttpHelper;
import anet.channel.util.HttpUrl;
import anet.channel.util.StringUtils;
import anetwork.channel.aidl.DefaultFinishEvent;
import anetwork.channel.cache.Cache;
import anetwork.channel.cache.CacheHelper;
import anetwork.channel.config.NetworkConfigCenter;
import anetwork.channel.cookie.CookieManager;
import anetwork.channel.http.NetworkSdkSetting;
import anetwork.channel.interceptor.Callback;
import com.taobao.codetrack.sdk.util.ReportUtil;
import java.io.ByteArrayOutputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;

class NetworkTask implements IUnifiedTask {
  public static final int MAX_RSP_BUFFER_LENGTH = 131072;
  public static final String TAG = "anet.NetworkTask";
  volatile Cancelable a;
  Cache.Entry a;
  Cache a;
  ResponseBuffer a;
  RequestContext a = null;
  int bc;
  boolean br;
  boolean bs;
  ByteArrayOutputStream c;
  int contentLength;
  String f_refer;
  volatile boolean isCanceled;
  volatile AtomicBoolean isDone;
  static {
    ReportUtil.dj(-2085384120);
    ReportUtil.dj(471853369);
  }
  
  NetworkTask(RequestContext paramRequestContext, Cache paramCache, Cache.Entry paramEntry) {.....}
  
  private Session a() {
  ......
    return a(null, sessionCenter, httpUrl, bool);
  }
  
  private Session a(Session paramSession, SessionCenter paramSessionCenter, HttpUrl paramHttpUrl, boolean paramBoolean) {
    return (Session)httpSession;
  }
  
  private SessionCenter a() {
    String str1 = this.a.config.getRequestProperty("APPKEY");
    if (TextUtils.isEmpty(str1))
      return SessionCenter.getInstance(); 
    ENV eNV = ENV.ONLINE;//这里很熟悉,在抓包的头里面出现过这个
    String str2 = this.a.config.getRequestProperty("ENVIRONMENT");
    if ("pre".equalsIgnoreCase(str2)) {
      eNV = ENV.PREPARE;
    } else if ("test".equalsIgnoreCase(str2)) {
      eNV = ENV.TEST;
    } 
    if (eNV != NetworkSdkSetting.CURRENT_ENV) {
      NetworkSdkSetting.CURRENT_ENV = eNV;
      SessionCenter.switchEnvironment(eNV);
    } 
    Config config2 = Config.a(str1, eNV);
    Config config1 = config2;
    if (config2 == null)
      config1 = (new Config.Builder()).b(str1).a(eNV).c(this.a.config.getRequestProperty("AuthCode")).a(); 
    return SessionCenter.getInstance(config1);
  }
  

  private Request a(Request paramRequest) {
    Request.Builder builder1 = null;
    Request.Builder builder2 = builder1;
    if (this.a.config.aW()) {//差不多一样先判断
      String str = CookieManager.getCookie(this.a.config.getUrlString());
      builder2 = builder1;
      if (!TextUtils.isEmpty(str)) {
        builder1 = paramRequest.a();
        String str2 = (String)paramRequest.getHeaders().get("Cookie");
        String str1 = str;
        if (!TextUtils.isEmpty(str2))
          str1 = StringUtils.b(str2, "; ", str); 
        builder1.a("Cookie", str1);
        builder2 = builder1;
      } 
    } 
    Request.Builder builder3 = builder2;
    if (this.a != null) {
      builder1 = builder2;
      if (builder2 == null)
        builder1 = paramRequest.a(); 
      if (((Cache.Entry)this.a).etag != null)
        builder1.a("If-None-Match", ((Cache.Entry)this.a).etag); 
      builder3 = builder1;
      if (((Cache.Entry)this.a).lastModified > 0L) {
        builder1.a("If-Modified-Since", CacheHelper.e(((Cache.Entry)this.a).lastModified));
        builder3 = builder1;
      } 
    } 
    builder2 = builder3;
    if (this.a.config.bb == 0) {
      builder2 = builder3;
      if ("weex".equalsIgnoreCase(this.f_refer)) {
        builder2 = builder3;
        if (builder3 == null)
          builder2 = paramRequest.a(); 
        builder2.b(3000);
      } 
    } 
    if (builder2 != null)
      paramRequest = builder2.a(); 
    return paramRequest;
  }
 
  




  private static class ResponseBuffer {
    int code;
    Map<String, List<String>> header;
    List<ByteArray> v = new ArrayList<ByteArray>();
    static {
      ReportUtil.dj(229651421);
    }
    ResponseBuffer(int param1Int, Map<String, List<String>> param1Map) {
      this.code = param1Int;
      this.header = param1Map;
      }
    int a(Callback param1Callback, int param1Int) {....}
    void release() {...}
}

hook结果是NetworkTask在中操作的,接着看看if (this.a.config.aW()) {…}

  • anetwork.channel.entity. RequestConfig
public boolean aW() {
    return !"false".equalsIgnoreCase(this.a.getExtProperty("EnableCookie"));
  }

我只能说用的属性名叫"EnableCookie"却用等于false取反,水太深了

  • anetwork.channel.entity.RequestImpl
    明显有相关方法
  @Deprecated
  public void setCookieEnabled(boolean paramBoolean) {
    String str;
    if (paramBoolean) {
      str = "true";
    } else {
      str = "false";
    } 
    setExtProperty("EnableCookie", str);
  }
  
  public void setExtProperty(String paramString1, String paramString2) {
    if (!TextUtils.isEmpty(paramString1)) {
      if (this.extProperties == null)
        this.extProperties = new HashMap<String, String>(); 
      this.extProperties.put(paramString1, paramString2);
    } 
  }

hook这个方法发现确实有调用

(String)paramRequest.getHeaders().get(“Cookie”);
这个paramRequest是anet.channel.request.Request类应该很有操作性但是到现在已经够清楚了,这个是不是就不太重要了,之接放

 public Map<String, String> getHeaders() {
    return Collections.unmodifiableMap(this.headers);
  }

来看看这个 builder1.a(“Cookie”, str1);是不是调用了 hook监听下

 if (!TextUtils.isEmpty(str)) {
        builder1 = paramRequest.a();
        String str2 = (String)paramRequest.getHeaders().get("Cookie");
        String str1 = str;
        if (!TextUtils.isEmpty(str2))
          str1 = StringUtils.b(str2, "; ", str); 
        builder1.a("Cookie", str1);//看看这个实现
        builder2 = builder1;
      } 

顺便直接跳到Request类下面的Builder类a的实现

 public Builder a(String param1String1, String param1String2) {
      this.headers.put(param1String1, param1String2);
      return this;
    }

结果就是完全hook住了说明确实调用了

10019 10284 I EdXposed-Bridge: anet.channel.request.Request$Builder中public Builder a(String param1String1, String param1String2)
08-15 19:14:29.857 10019 10284 I EdXposed-Bridge: 参数1Content-Type 参数2application/x-www-form-urlencoded;charset=UTF-8
08-15 19:14:29.948 10019 10342 I EdXposed-Bridge: setCookieEnabled:false
08-15 19:14:29.948 10019 10342 I EdXposed-Bridge: setExtProperty方法 键:EnableCookie 值:false
08-15 19:14:29.948 10019 10342 I EdXposed-Bridge: addHeader方法 键:f-refer 值:picture
08-15 19:14:29.948 10019 10342 I EdXposed-Bridge: addHeader方法 键:User-Agent 值:TBAndroid/Native
08-15 19:14:29.949 10019 10342 I EdXposed-Bridge: setExtProperty方法 键:f-netReqStart 值:1629026069949
08-15 19:14:29.949 10019 10342 I EdXposed-Bridge: setExtProperty方法 键:f-traceId 值:null
08-15 19:14:29.949 10019 10342 I EdXposed-Bridge: setExtProperty方法 键:f-reqProcess 值:com.taobao.idlefish
08-15 19:14:29.971 10019 10319 I EdXposed-Bridge: setCookieEnabled:false
08-15 19:14:29.971 10019 10319 I EdXposed-Bridge: setExtProperty方法 键:EnableCookie 值:false
08-15 19:14:29.971 10019 10319 I EdXposed-Bridge: addHeader方法 键:f-refer 值:picture
08-15 19:14:29.971 10019 10319 I EdXposed-Bridge: addHeader方法 键:User-Agent 值:TBAndroid/Native
08-15 19:14:29.972 10019 10319 I EdXposed-Bridge: setExtProperty方法 键:f-netReqStart 值:1629026069972
08-15 19:14:29.972 10019 10319 I EdXposed-Bridge: setExtProperty方法 键:f-traceId 值:null
08-15 19:14:29.972 10019 10319 I EdXposed-Bridge: setExtProperty方法 键:f-reqProcess 值:com.taobao.idlefish
08-15 19:14:29.973 10019 10341 I EdXposed-Bridge: setCookieEnabled:false
08-15 19:14:29.973 10019 10341 I EdXposed-Bridge: setExtProperty方法 键:EnableCookie 值:false
08-15 19:14:29.973 10019 10341 I EdXposed-Bridge: addHeader方法 键:f-refer 值:picture
08-15 19:14:29.973 10019 10341 I EdXposed-Bridge: addHeader方法 键:User-Agent 值:TBAndroid/Native
08-15 19:14:29.973 10019 10341 I EdXposed-Bridge: setExtProperty方法 键:f-netReqStart 值:1629026069973
08-15 19:14:29.973 10019 10341 I EdXposed-Bridge: setExtProperty方法 键:f-traceId 值:null
08-15 19:14:29.973 10019 10341 I EdXposed-Bridge: setExtProperty方法 键:f-reqProcess 值:com.taobao.idlefish
08-15 19:14:30.034 10019 10284 I EdXposed-Bridge: NetworkTask:private Request a(Request paramRequest)中String str = CookieManager.getCookie(this.a.config.getUrlString());
08-15 19:14:30.034 10019 10272 I EdXposed-Bridge: NetworkTask:private Request a(Request paramRequest)中String str = CookieManager.getCookie(this.a.config.getUrlString());
08-15 19:14:30.035 10019 10272 I EdXposed-Bridge: NetworkTask:private Request a(Request paramRequest)中String str = CookieManager.getCookie(this.a.config.getUrlString());
08-15 19:14:30.272 10019 10309 I EdXposed-Bridge: setExtProperty方法 键:f-pTraceId 值:null

由此某鱼的Cookie就整的明明白白,但是虽然getCookie虽然要传入一个String参数 观察发现其实就是所请求的api,本以为请求的api得到的cookie字符串里面会有部分不同结果发现,不管用什么参数都返回相同cookie,本来想进去看一下这个方法但是…

 public static String getCookie(String paramString) {
    // Byte code:
    //   0: aconst_null
    //   1: astore_1
    //   2: ldc anetwork/channel/cookie/CookieManager
    //   4: monitorenter
    //   5: aload_1
    //   6: astore_2
    //   7: invokestatic checkSetup : ()Z
    //   10: ifeq -> 23
    //   13: getstatic anetwork/channel/cookie/CookieManager.bn : Z
    //   16: istore_3
    //   17: iload_3
    //   18: ifne -> 28
    //   21: aload_1
    //   22: astore_2
    //   23: ldc anetwork/channel/cookie/CookieManager
    //   25: monitorexit
    //   26: aload_2
    //   27: areturn
    //   28: aconst_null
    //   29: astore_2
    //   30: getstatic anetwork/channel/cookie/CookieManager.webkitCookMgr : Landroid/webkit/CookieManager;
    //   33: aload_0
    //   34: invokevirtual getCookie : (Ljava/lang/String;)Ljava/lang/String;
    //   37: astore_1
    //   38: aload_1
    //   39: astore_2
    //   40: aload_0
    //   41: aload_2
    //   42: invokestatic g : (Ljava/lang/String;Ljava/lang/String;)V
    //   45: goto -> 23
    //   48: astore_0
    //   49: ldc anetwork/channel/cookie/CookieManager
    //   51: monitorexit
    //   52: aload_0
    //   53: athrow
    //   54: astore #4
    //   56: new java/lang/StringBuilder
    //   59: astore_1
    //   60: aload_1
    //   61: invokespecial <init> : ()V
    //   64: ldc 'anet.CookieManager'
    //   66: aload_1
    //   67: ldc 'get cookie failed. url='
    //   69: invokevirtual append : (Ljava/lang/String;)Ljava/lang/StringBuilder;
    //   72: aload_0
    //   73: invokevirtual append : (Ljava/lang/String;)Ljava/lang/StringBuilder;
    //   76: invokevirtual toString : ()Ljava/lang/String;
    //   79: aconst_null
    //   80: aload #4
    //   82: iconst_0
    //   83: anewarray java/lang/Object
    //   86: invokestatic b : (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Throwable;[Ljava/lang/Object;)V
    //   89: goto -> 40
    // Exception table:
    //   from	to	target	type
    //   7	17	48	finally
    //   30	38	54	java/lang/Throwable
    //   30	38	48	finally
    //   40	45	48	finally
    //   56	89	48	finally
  }
  

那就这样吧

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐