Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

今日校园版本过低,请更新至最新版本! #9

Closed
luckycat0426 opened this issue Oct 25, 2021 · 16 comments · Fixed by #10
Closed

今日校园版本过低,请更新至最新版本! #9

luckycat0426 opened this issue Oct 25, 2021 · 16 comments · Fixed by #10

Comments

@luckycat0426
Copy link
Contributor

运行提示 '今日校园版本过低,请更新至最新版本!'

@beetcb
Copy link
Contributor

beetcb commented Oct 26, 2021

今日校园更新,需要重新抓包(甚至逆向)找到 key 和 version ,我今天不方便抓包(签过一次了 😂),你要是有抓欢迎分共享出来一起讨论 @luckycat0426

@luckycat0426
Copy link
Contributor Author

luckycat0426 commented Oct 26, 2021

逆向了最新版本app
根据该代码判断

public static JSONObject g(double d, double d2) {
        JSONObject jSONObject = new JSONObject();
        try {
            jSONObject.put("systemName", "android");
            jSONObject.put("systemVersion", Build.VERSION.RELEASE);
            jSONObject.put("model", Build.MODEL);
            jSONObject.put("deviceId", C38205o00.h());
            jSONObject.put("appVersion", C24427CpUiUtils.d());
            jSONObject.put("lon", d2);
            jSONObject.put("lat", d);
            jSONObject.put("userId", C32083hx1.l());
        } catch (JSONException e) {
            e.printStackTrace();
        }
        return jSONObject;
    }

加密代码如下

public static String b(double d, double d2) {
        return C40906uq.c(g(d, d2).toString(), "b3L26XNL");
    }

key应该是没有变化的,改version应该就能签到成功.包我没来得及抓,只能等明天测试了.
@beetcb

@beetcb beetcb closed this as completed in 9ab1caa Oct 26, 2021
@beetcb beetcb reopened this Oct 26, 2021
@beetcb
Copy link
Contributor

beetcb commented Oct 26, 2021

刚刚用更新签到的 API 抓了一下,endpoint 和签到是一样的,不确定两者请求是否有差异

  1. cpdaily-extension 解密后的对象:
{
   "systemName":"android",
   "systemVersion":"11",
   "model":"GM1910",
   "deviceId":"uuid",
   "appVersion":"9.0.12",
   "lon":经度数字,
   "lat":纬度数字,
   "userId":"学号"
}
  1. 提交的表单主体对象变化很大:
{
  "appVersion": "9.0.12",
  "systemName": "android",
  "bodyString": "长度为500的加密字符串",
  "sign": "57a90f40fcde8334586cedc200e5edfa",
  "model": "GM1910",
  "lon": 经度数字,
  "calVersion": "firstv",
  "systemVersion": "11",
  "deviceId": "uuid",
  "userId": "学号",
  "version": "first_v2",
  "lat": 维度数字
}

@luckycat0426

@beetcb
Copy link
Contributor

beetcb commented Oct 26, 2021

明天咱们再抓一次,才能完全确定请求变化 ◑﹏◐

@luckycat0426
Copy link
Contributor Author

luckycat0426 commented Oct 26, 2021

"bodyString": "长度为500的加密字符串",

用这个key OXoTKvkq 试试能不能解密
我这里更新签到超过时间了,抓不了包

@beetcb
Copy link
Contributor

beetcb commented Oct 26, 2021

辛苦辛苦,我没解密成功,咱们明天再搞吧,看起来还有不少工作量嘞 😂
@luckycat0426

@luckycat0426
Copy link
Contributor Author

luckycat0426 commented Oct 26, 2021

早上起来没注意用ios抓了包.....

{"lon":lon,
"version":"first_v2",
"calVersion":"firstv",
"deviceId":deviceId,
"userId":学号,
"systemName":"iOS",
"bodyString":AES加密 密钥 ytUQ7l2ZZu8mLvJZ  ,
"lat":lat,
"systemVersion":"15.0.2",
"appVersion":"9.0.12",
"model":"iPhone13,2",
"sign":"5beba374192312cfdd1eb35b6e715f24"
}

@beetcb
Copy link
Contributor

beetcb commented Oct 27, 2021

主要是把这两个解决,不清楚 sign 是个什么 hash 值 @luckycat0426

{
  "lon":lon,
  "version":"first_v2",
  "calVersion":"firstv",
  "deviceId":deviceId,
  "userId":学号,
  "systemName":"iOS",
+ "bodyString":AES加密密钥 ytUQ7l2ZZu8mLvJZ  ,
  "lat":lat,
  "systemVersion":"15.0.2",
  "appVersion":"9.0.12",
  "model":"iPhone13,2",
+ "sign":"5beba374192312cfdd1eb35b6e715f24"
}

@luckycat0426
Copy link
Contributor Author

luckycat0426 commented Oct 27, 2021

if (map2 != null) {
                    map2.put("bodyString", c);
                    map2.put("sign", C35437CommonUtils.m43877A(map2));
                    map2.put("version", C20340tq.m57482h(C32910CpUiUtils.m38518f()));
                    map2.put("calVersion", "firstv");
                    optString3 = new JSONObject(map2).toString();
                }
    public static String m43877A(Map<String, Object> map) {
        try {
            String a = C13024d.m38880a(C13024d.m38882c(map));
            return C40499mv0.m53859a(a + "&" + C20340tq.m57478d(C30364ModuleCommImpl.getInstance().getFDkey(), C32910CpUiUtils.m38518f()));
        } catch (Exception e) {
            e.printStackTrace();
            return "";
        }
    }
  public static Map<String, Object> m38882c(Map<String, Object> map) {
        if (map == null || map.isEmpty()) {
            return null;
        }
        TreeMap treeMap = new TreeMap(C42411vy0.f55319T);
        treeMap.putAll(map);
        return treeMap;
    }
public static String m38880a(Map<String, Object> map) throws UnsupportedEncodingException {
        ArrayList arrayList = new ArrayList(map.keySet());
        Collections.sort(arrayList);
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < arrayList.size(); i++) {
            String str = (String) arrayList.get(i);
            Object obj = map.get(str);
            if (i == arrayList.size() - 1) {
                sb.append(str);
                sb.append("=");
                sb.append(obj.toString());
            } else {
                sb.append(str);
                sb.append("=");
                sb.append(obj.toString());
                sb.append("&");
            }
        }
        return sb.toString();
    }

看样子规则是bodyString里面的key=value&
最后好像还要加上一个C20340tq.m57478d(C30364ModuleCommImpl.getInstance().getFDkey(), C32910CpUiUtils.m38518f())),我猜是加密key

@luckycat0426
Copy link
Contributor Author

.....漏看了一些

Map<String, Object> map2 = null;
        if (map.containsKey("sign") && TextUtils.equals(map.get("sign"), "1")) {
            map2 = lx1.m53334h(d, d2);
        }
        if (map.containsKey("extension") && TextUtils.equals(map.get("extension"), "1")) {
            map.put("Cpdaily-Extension", lx1.m53328b(d, d2));
        }
        doHttpAction(httpAction, jSONObject, map, callbackContext, map2);
 public static JSONObject m53333g(double d, double d2) {
        JSONObject jSONObject = new JSONObject();
        try {
            jSONObject.put("systemName", "android");
            jSONObject.put("systemVersion", Build.VERSION.RELEASE);
            jSONObject.put("model", Build.MODEL);
            jSONObject.put("deviceId", o00.m54347h());
            jSONObject.put("appVersion", CpUiUtils.m38516d());
            jSONObject.put("lon", d2);
            jSONObject.put("lat", d);
            jSONObject.put("userId", hx1.m51076l());
        } catch (JSONException e) {
            e.printStackTrace();
        }
        return jSONObject;
    }

    /* renamed from: h */
    public static Map<String, Object> m53334h(double d, double d2) {
        JSONObject g = m53333g(d, d2);
        HashMap hashMap = new HashMap();
        Iterator<String> keys = g.keys();
        while (keys.hasNext()) {
            String next = keys.next();
            if ("lon".equals(next) || "lat".equals(next)) {
                hashMap.put(next, Double.valueOf(g.optDouble(next, 0.0d)));
            } else {
                hashMap.put(next, g.optString(next));
            }
        }
        return hashMap;
    }

看起来不是遍历bodystring 是遍历key systemName,systemVersion...和bodystring,构造key=value&
bodystring 的value 应该是加密后的.

@luckycat0426
Copy link
Contributor Author

public final /* synthetic */ class vy0 implements Comparator {

    /* renamed from: T */
    public static final /* synthetic */ vy0 f55319T = new vy0();

    @Override // java.util.Comparator
    public final int compare(Object obj, Object obj2) {
        return ((String) obj).compareTo((String) obj2);
    }
}

这个是treemap 的Comparator函数,所以算hash时应该是按键字母序排的
appVersion bodystring deviceId lat lon .....

@beetcb
Copy link
Contributor

beetcb commented Oct 27, 2021

我暂时还没有时间改诶,试着提下 PR,谢谢 ! @luckycat0426
我的想法:对象的拼接用 new URLSearchParams(form).toString() 就可以,至于排序咱们写代码时按着字母序排列就可以,减少复杂度
主要的逻辑在这个文件里,我昨天修复了 Debug 的脚本,所以现在可以在 vscode 里打断点测试了

const form: SignForm = {
longitude: this.fixedFloatRight(longitude),
latitude: this.fixedFloatRight(latitude),
isMalposition: isSignAtHome ? 1 : 0,
uaIsCpadaily: true,
signPhotoUrl: '',
abnormalReason: '',
signVersion: 'first_v2',
signInstanceWid,
isNeedExtra,
extraFieldItems,
position,
}
headers['Cpdaily-Extension'] = this.extention(form)

@beetcb
Copy link
Contributor

beetcb commented Oct 27, 2021

我中午有时间回去改,如果你已经开始了记得提醒我哈 😂 @luckycat0426

@luckycat0426
Copy link
Contributor Author

luckycat0426 commented Oct 27, 2021

@beetcb 之前没写过typescript,代码可能不太规范,如果实在太差了可能要麻烦你重写了,今天已经签到了,测试不了.
018c6ab

@beetcb
Copy link
Contributor

beetcb commented Oct 27, 2021

没关系,我 Review 一下 Merge 进来

@beetcb beetcb linked a pull request Oct 27, 2021 that will close this issue
@beetcb
Copy link
Contributor

beetcb commented Oct 27, 2021

经过测试,新代码能成功签到,谢谢贡献 @luckycat0426

7a41541

@beetcb beetcb closed this as completed Oct 27, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants