This article is currently an experimental machine translation and may contain errors. If anything is unclear, please refer to the original Chinese version. I am continuously working to improve the translation.
- Reverse-engineered the parent-end Class Plaque app to extract the method for obtaining encrypted HTTP parameters
- Simulated client requests to the server and successfully received responses
- Implemented Token acquisition and account registration API endpoints
- Brute-forced all class invitation codes (using multithreading), totaling 5,541 classes
To-do: Complete Python APIs for other endpoints (e.g., sending messages, binding students)
Reverse-engineering the Token process:
Used jadx to decompile the Class Plaque app.
Searched globally for “token” and found the following code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19TreeMap treeMap3 = new TreeMap();
treeMap3.put("systemid", "parent");
String str7 = Constants.PARAM_ACCESS_TOKEN;
treeMap3.put("grant_type", "password");
treeMap3.put("username", string);
treeMap3.put("inch_timestamp", valueOf);
StringBuilder sb = new StringBuilder();
sb.append((String) treeMap3.get("inch_timestamp"));
Request request2 = request;
sb.append(f.b(8));
treeMap3.put("nonce", sb.toString());
StringBuffer stringBuffer2 = new StringBuffer();
for (String str8 : treeMap3.keySet()) {
stringBuffer2.append(str8);
stringBuffer2.append("=");
stringBuffer2.append((String) treeMap3.get(str8));
stringBuffer2.append(a.f1270b);
}
stringBuffer2.append("aef2890665d884a3080971b4eca594d7");There are too many related methods to list them all, but the general idea is clear: all HTTP request parameters are placed into a TreeMap, then concatenated into a string and hashed with MD5. According to the official Java documentation, TreeMap is implemented using a red-black tree, and its iterator traverses keys in their natural order by default.
Translated into Python code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17# inch_sign generation method derived from reverse engineering
temp = dict()
temp['access_token'] = self.token
try:
for i in params:
temp[i] = params[i]
except Exception as e:
pass
temp['inch_timestamp'] = int(round(time.time() * 1000))
temp['nonce'] = str(temp['inch_timestamp']) + str((random.random() + random.randint(1,9)) * 100000000)[:8]
temp2 = ''
for i in sorted(temp.keys()):
temp2 += str(i) + "=" + str(temp[i]) + "&"
temp2 += "aef2890665d884a3080971b4eca594d7"
sign = hashlib.md5(temp2.encode("utf-8")).hexdigest().upper()
This article is licensed under the CC BY-NC-SA 4.0 license.
Author: lyc8503, Article link: https://blog.lyc8503.net/en/post/incich-second-1/
If this article was helpful or interesting to you, consider buy me a coffee¬_¬
Feel free to comment in English below o/