折腾:
【已解决】为何Python中32字节的md值和小花生中getMD5Str计算出的md5值不同
期间,
现在确认之前Python计算出md5值不对的原因是:
StringBuilder localStringBuilder = new StringBuilder(); localStringBuilder.append(MainActivity.userId); localStringBuilder.append(l); localStringBuilder.append((String)localObject); localStringBuilder.append(paramString); localStringBuilder.append(“AyGt7ohMR!xxx#N"); paramString = StringUtil.md5(localStringBuilder.toString());
中的paramString参数搞错了
-》此处的paramString实际上已经是被赋值为
paramString = getToken(MainActivity.userId);
-》要去搞清楚此处的getToken的逻辑
-》才能拿到正确的paramString
-》才能继续计算出正确的md5
-》才能继续正常请求api,获取到期望返回的json数据
结果此处的
com/huili/readingclub/model/ModelSecurity.java
/* Error */
private static String getToken(String paramString)
{
// Byte code:
// 0: aload_0
// 1: invokestatic 81 com/huili/readingclub/utils/StringUtil:isNullOrEmpty (Ljava/lang/String;)Z
// 4: ifeq +5 -> 9
// 7: aconst_null
// 8: areturn
// 9: aload_0
// 10: invokestatic 87 java/lang/Integer:parseInt (Ljava/lang/String;)I
// 13: iconst_1
// 14: if_icmpge +5 -> 19
// 17: aconst_null
// 18: areturn
// 19: getstatic 22 com/huili/readingclub/model/ModelSecurity:userTokens Ljava/util/HashMap;
// 22: aload_0
// 23: invokevirtual 135 java/util/HashMap:containsKey (Ljava/lang/Object;)Z
// 26: ifeq +14 -> 40
// 29: getstatic 22 com/huili/readingclub/model/ModelSecurity:userTokens Ljava/util/HashMap;
// 32: aload_0
// 33: invokevirtual 139 java/util/HashMap:get (Ljava/lang/Object;)Ljava/lang/Object;
// 36: checkcast 56 java/lang/String
// 39: areturn
// 40: invokestatic 145 com/huili/readingclub/MyApplication:getApplication ()Lcom/huili/readingclub/MyApplication;
// 43: invokestatic 151 com/huili/readingclub/network/XutilsHttpClient:isNetWorkAvaiable (Landroid/content/Context;)Z
// 46: ifne +5 -> 51
// 49: aconst_null
// 50: areturn
// 51: invokestatic 99 com/huili/readingclub/utils/DateUtils:get1970ToNowSeconds ()J
// 54: lstore_1
// 55: new 101 java/lang/StringBuilder
// 58: dup
// 59: invokespecial 102 java/lang/StringBuilder:<init> ()V
// 62: astore_3
// 63: aload_3
// 64: aload_0
// 65: invokevirtual 109 java/lang/StringBuilder:append (Ljava/lang/String;)Ljava/lang/StringBuilder;
// 68: pop
// 69: aload_3
// 70: lload_1
// 71: invokevirtual 106 java/lang/StringBuilder:append (J)Ljava/lang/StringBuilder;
// 74: pop
// 75: aload_3
// 76: ldc 111
// 78: invokevirtual 109 java/lang/StringBuilder:append (Ljava/lang/String;)Ljava/lang/StringBuilder;
// 81: pop
// 82: aload_3
// 83: invokevirtual 115 java/lang/StringBuilder:toString ()Ljava/lang/String;
// 86: invokestatic 118 com/huili/readingclub/utils/StringUtil:md5 (Ljava/lang/String;)Ljava/lang/String;
// 89: astore_3
// 90: getstatic 27 com/huili/readingclub/model/ModelSecurity:lock Ljava/util/concurrent/locks/Lock;
// 93: invokeinterface 153 1 0
// 98: new 155 java/lang/Thread
// 101: astore 4
// 103: new 6 com/huili/readingclub/model/ModelSecurity$1
// 106: astore 5
// 108: aload 5
// 110: aload_0
// 111: lload_1
// 112: aload_3
// 113: invokespecial 158 com/huili/readingclub/model/ModelSecurity$1:<init> (Ljava/lang/String;JLjava/lang/String;)V
// 116: aload 4
// 118: aload 5
// 120: invokespecial 161 java/lang/Thread:<init> (Ljava/lang/Runnable;)V
// 123: aload 4
// 125: invokevirtual 164 java/lang/Thread:start ()V
// 128: getstatic 35 com/huili/readingclub/model/ModelSecurity:condition Ljava/util/concurrent/locks/Condition;
// 131: invokeinterface 169 1 0
// 136: getstatic 22 com/huili/readingclub/model/ModelSecurity:userTokens Ljava/util/HashMap;
// 139: aload_0
// 140: invokevirtual 135 java/util/HashMap:containsKey (Ljava/lang/Object;)Z
// 143: ifeq +24 -> 167
// 146: getstatic 22 com/huili/readingclub/model/ModelSecurity:userTokens Ljava/util/HashMap;
// 149: aload_0
// 150: invokevirtual 139 java/util/HashMap:get (Ljava/lang/Object;)Ljava/lang/Object;
// 153: checkcast 56 java/lang/String
// 156: astore_0
// 157: getstatic 27 com/huili/readingclub/model/ModelSecurity:lock Ljava/util/concurrent/locks/Lock;
// 160: invokeinterface 172 1 0
// 165: aload_0
// 166: areturn
// 167: getstatic 27 com/huili/readingclub/model/ModelSecurity:lock Ljava/util/concurrent/locks/Lock;
// 170: invokeinterface 172 1 0
// 175: aconst_null
// 176: areturn
// 177: astore_0
// 178: goto +18 -> 196
// 181: astore_0
// 182: aload_0
// 183: invokevirtual 175 java/lang/Exception:printStackTrace ()V
// 186: getstatic 27 com/huili/readingclub/model/ModelSecurity:lock Ljava/util/concurrent/locks/Lock;
// 189: invokeinterface 172 1 0
// 194: aconst_null
// 195: areturn
// 196: getstatic 27 com/huili/readingclub/model/ModelSecurity:lock Ljava/util/concurrent/locks/Lock;
// 199: invokeinterface 172 1 0
// 204: aload_0
// 205: athrow
// Local variable table:
// start length slot name signature
// 0 206 0 paramString String
// 54 58 1 l long
// 62 51 3 localObject Object
// 101 23 4 localThread Thread
// 106 13 5 local1 1
// Exception table:
// from to target type
// 98 157 177 finally
// 182 186 177 finally
// 98 157 181 java/lang/Exception
}-》竟然是代码error出错,无法得到源码的。。。
尝试分析看看这段代码,看看是否能找到可能的逻辑。
好像是内部用到了userTokens这个HashMap
但是却找不到哪里得到的数据
好像是从网络中获取到的?
后续好像又用md5,timestamp等处理了?
那想办法去试试:
- 用其他工具导出jar包得到源码
- 看看代码是否正常显示
- 找找其他版本的apk,再去试试
- 或许dump出来的dex,dex转jar,jar导出的java就正常显示源码了?
然后换用Luyten,还真可以看到正常原始java代码了:

然后去整理:
【整理】把jar包转换为java源代码的java反编译器的整理和对比
另外,也去试试别人提到的,貌似效果不错的CFR:
【已解决】用java反编译器CFR从jar包导出java源代码
然后拷贝出代码:
private static String getToken(String s) {
if (StringUtil.isNullOrEmpty(s)) {
return null;
}
if (Integer.parseInt(s) < 1) {
return null;
}
if (ModelSecurity.userTokens.containsKey(s)) {
return ModelSecurity.userTokens.get(s);
}
if (!XutilsHttpClient.isNetWorkAvaiable((Context)MyApplication.getApplication())) {
return null;
}
final long get1970ToNowSeconds = DateUtils.get1970ToNowSeconds();
final StringBuilder sb = new StringBuilder();
sb.append(s);
sb.append(get1970ToNowSeconds);
sb.append(“AyGt7ohMR!xx#N");
final String md5 = StringUtil.md5(sb.toString());
ModelSecurity.lock.lock();
try {
try {
new Thread(new Runnable() {
@Override
public void run() {
ModelSecurity.lock.lock();
try {
try {
final StringBuilder sb = new StringBuilder();
sb.append("http://www.xiaohuasheng.cn:83/UserService.svc/getToken/");
sb.append(s);
sb.append("/");
sb.append(get1970ToNowSeconds);
sb.append("/");
sb.append(md5);
final HttpURLConnection httpURLConnection = (HttpURLConnection)new URL(sb.toString()).openConnection();
httpURLConnection.setRequestMethod("GET");
httpURLConnection.setRequestProperty("Content-Type", "application/json");
httpURLConnection.setRequestProperty("Authorization", "NSTp9~)NwSfrXp@\\");
final Map<?, ?> jsonToMap = JsonUtil.jsonToMap(new String(toByteArray(httpURLConnection.getInputStream()), "UTF-8"));
if (jsonToMap == null) {
ModelSecurity.condition.signalAll();
ModelSecurity.lock.unlock();
return;
}
final StringBuilder sb2 = new StringBuilder();
sb2.append(jsonToMap.get("M"));
sb2.append("");
if (!sb2.toString().equals("1001")) {
ModelSecurity.condition.signalAll();
ModelSecurity.lock.unlock();
return;
}
final StringBuilder sb3 = new StringBuilder();
sb3.append(jsonToMap.get("J"));
sb3.append("");
final List<?> jsonToList = JsonUtil.jsonToList(MessageGZIP.uncompressToString(Base64.decode(sb3.toString()), "UTF-8"));
......
}然后剩下就是,继续抓包分析,找到对应userId的getToken的值了。
去找到:
http://www.xiaohuasheng.cn:83/UserService.svc/getToken/{userId}/{timestamp}的请求去看看对应的值了。
然后抓包到了:

GET /UserService.svc/getToken/1134723/1554276832/a56826c5013b7c5c85e7012a8fe7ce1b HTTP/1.1
Content-Type: application/json
Authorization: NSTp9~)NwSfrXp@\
User-Agent: Dalvik/1.6.0 (Linux; U; Android 4.4.2; A0001 Build/KOT49H)
Host: www.xiaohuasheng.cn:83
Accept-Encoding: gzip
Connection: keep-alive
HTTP/1.1 200 OK
Cache-Control: private
Content-Length: 127
Content-Type: application/json; charset=utf-8
Server: Microsoft-IIS/7.5
Set-Cookie: ASP.NET_SessionId=ljdtlluhnj1bqf44hgfekjhs; path=/; HttpOnly
X-AspNet-Version: 4.0.30319
X-Powered-By: ASP.NET
Date: Wed, 03 Apr 2019 07:33:55 GMT
Connection: keep-alive
{"C":2,"J":"H4sIAAAAAAAEAIuuVspLzE1VslIyMUgxMjIzT9M1NrVM1TUxNTLTtTQ1TNQ1MzM1tEw1tTCzSDZWqo0FACB75XoxAAAA","M":"1001","ST":null}解码后的json是:
[
{
"name": "40d2267f-359e-4526-951a-66519e5868c3"
}
]-》此处
- userId是:1554276832
- 返回的token是:40d2267f-359e-4526-951a-66519e5868c3
然后继续回去之前的:
【未解决】Python实现小花生中addSignature的md5加密生成签名的逻辑