什么值得买自动签到

什么值得买自动签到

mmj Lv2

reqable抓包我的-签到页面

找到签到接口地址,https://user-api.smzdm.com/checkin,看到请求参数

image

多次抓包,发现sign和time会变化,weixin,f,v,sk,token都是固定值,而captcha和touchstone_event始终为空

JADX打开apk,字符串搜索”sign”image

可以看到一些sdk中的类,和一个比较重要的p192Hf.C1998a

这个被混淆过的方法进去之后就能看到签到接口传的f,v,weixin,time一些参数了

image

sign这个值由m7143c生成,看一下它的逻辑

image

可以看到这里先进行了参数拼接 + &key= + key值,再传入C18324p0.m83928a()做某种加密,最后结果转大写返回

我们先看ZDMKeyUtil类

image

大概是加载了一个key,回去看C18324p0.m83928a​这个方法image

可以看到是一个MD5,所以现在大概了解流程了

  1. p192Hf.C1998a 接收Map(签到请求的所有参数)
  2. 对Map按key排序,遍历拼接成字符串
  3. 末尾拼接 &key= + ZDMKeyUtil.m83611a().m83612b()获取的key值
  4. 去空格.replaceAll(StringUtils.SPACE, “”)
  5. 传入 C18324p0.m83928a() 进行MD5加密,得到32位小写十六进制字符串
  6. 转大写
  7. 返回最终的sign值

那么接下来需要得到加密前的参数并且复写加密算法

可以用Xposed和Frida都可以,我以Xposed举例

1.hook p192Hf.C1998a​这个类中的m83928a​方法,获取传入的map和sign值,因为也还有其他接口调用了这个方法,因此对比Reqable抓包抓到的参数和sign值,确定是否是我们需要找的签到接口
2.hook ZDMKeyUtil这个类中的方法,获取最终拼接在后面的key参数
3.hook m83928a方法,获取加密前的字符串和加密后的值,加密后转为32位大写即为sign值

Xposed代码供参考

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
package com.hope.smzdm;

import java.util.Map;

import de.robv.android.xposed.IXposedHookLoadPackage;
import de.robv.android.xposed.XC_MethodHook;
import de.robv.android.xposed.XposedBridge;
import de.robv.android.xposed.XposedHelpers;
import de.robv.android.xposed.callbacks.XC_LoadPackage;


public class TestHook implements IXposedHookLoadPackage{
@Override
public void handleLoadPackage(XC_LoadPackage.LoadPackageParam loadPackageParam) {
if (loadPackageParam.packageName.equals("com.smzdm.client.android")) {
XposedHelpers.findAndHookMethod("Hf.a", loadPackageParam.classLoader, "c", Map.class, String.class, new XC_MethodHook() {
@Override
protected void afterHookedMethod(MethodHookParam param)
throws Throwable {
String str = param.getResult().toString(); //获取加密结果
String param1 = param.args[0].toString(); //获取传入的Map
String param2 = param.args[1].toString(); //获取传入的String
XposedBridge.log("hook success1----" + str);
XposedBridge.log("hook success2----" + param1);
XposedBridge.log("hook success3----" + param2);
}
});

XposedHelpers.findAndHookMethod("com.smzdm.client.base.utils.ZDMKeyUtil", loadPackageParam.classLoader, "a", new XC_MethodHook() {
@Override
protected void afterHookedMethod(MethodHookParam param)
throws Throwable {
String str = param.getResult().toString();
XposedBridge.log("hook success4----" + str);
}
});

XposedHelpers.findAndHookMethod("com.smzdm.client.base.utils.ZDMKeyUtil", loadPackageParam.classLoader, "b", new XC_MethodHook() {
@Override
protected void afterHookedMethod(MethodHookParam param)
throws Throwable {
String str = param.getResult().toString();
XposedBridge.log("hook success5----" + str);
}
});

XposedHelpers.findAndHookMethod("com.smzdm.client.base.utils.p0", loadPackageParam.classLoader, "a", String.class, new XC_MethodHook() {
@Override
protected void afterHookedMethod(MethodHookParam param)
throws Throwable {
String str = param.getResult().toString(); //获取加密后的sign
String param1 = param.args[0].toString(); //获取需要进行加密的原始文本
XposedBridge.log("hook success6----" + param1);
XposedBridge.log("hook success7----" + str);
}
});
}
}
}

代码中的类名和方法名与jadx中不同是因为jadx在反混淆时自动将一些较为简单的常见方法及类名翻译,如将a​翻译为m83928a

那么右键需要的名称复制为Xposed代码即可看到真实名称

运行该模块可以看到日志中成功hook到了加密前的字符串和key值,这个key是不变的

image

那么现在已知密文和加密算法,我们用python模拟一下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
# -*- coding: utf-8 -*-
import time
import random
import hashlib
import requests


# MD5加密
def md5(rawstr):
# 创建md5对象
hl = hashlib.md5()
hl.update(rawstr.encode(encoding='UTF-8'))
return hl.hexdigest().upper()


def checkin(cookie):
signurl = "https://user-api.smzdm.com/checkin"
zdmkey = 'apr1$AwP!wRRT$gJ/q.X24poeBInlUJC'
zdmsk = 'qMeb6cxJeDmCCME/m6lszTvcaBy1NzXPXwq//rf6nPjKawjsKMFBcVLEblpieutv'#抓包时sk的值
zdmtoken = cookie[5:]
timestamp = int(time.time())
rawdata = f'f=android&sk={zdmsk}&time={timestamp}000&token={zdmtoken}&v=9.9.12&weixin=1&key={zdmkey}'
sign = md5(rawdata)
formdata = {
"sk": zdmsk,
"sign": sign,
"weixin": "1",
"v": "9.9.12",
"captcha": "",
"f": "android",
"token": zdmtoken,
"touchstone_event": "",
"time": f"{timestamp}000"
}
headers = {
"User-Agent": 'smzdm_android_V11.1.75 rv:1175 (PJF110;Android14;zh)smzdmapp',
"Cookie": cookie,
"Accept-Encoding": 'gzip',
"Connection": "Keep-Alive",
"request_key": f"{random.randint(10000000, 99999999)}{timestamp}",
}
resp = requests.post(signurl, headers=headers, data=formdata).json()
if resp["error_code"] == '0':
resp_data = resp["data"]
checkin_num = resp_data["daily_num"]
gold = resp_data["cgold"]
silver = resp_data["pre_re_silver"]
point = resp_data["cpoints"]
exp = resp_data["cexperience"]
rank = resp_data["rank"]
cards = resp_data["cards"]
msg = f"""🏆签到成功\n🏆已连续签到{checkin_num}天\n🏆等级{rank}\n🏆补签卡{cards}\n🏆碎银{silver}\n🏆金币{gold}\n🏆积分{point}\n🏆经验{exp}"""
print(msg)
else:
msg = f'签到失败!失败原因:{resp["error_msg"]}'
print(msg)


if __name__ == "__main__":
zdmcookie = "partner_name=oppo;sess=BB-13u1HEgMYkL85XUyVkvw1OaFEYNYFIfmmzdujmKE31N1WvuKsfNQZ1wEPChUpmhAjxw9xvBcBnC7LEq1erbW3RlTnYg%3D;pid=KSRkj6cIVJ9SORMRQPiNNlmZlM%2BKqOQhQuAK3SmTbsFzbfQDpoHn1A%3D%3D;device_type=OnePlusPJF110;basic_v=0;client_id=5fa70c5c0f44f42fe06d8449f321f14d.1779105225256;pr_new_device_id=5g1eic4c332b4fd1b3e5b25ciif1daa2;network=1;device_system_version=14;partner_id=16;user_type=2;device_smzdm=android;apk_partner_name=oppo;smzdm_id=5149224266;pr_device_s=5g1eic4c332b4fd1b3e5b25ciif1daa2;device_push=1;f=android;pr_z_dr=5g1eic4c332b4fd1b3e5b25ciif1daa2;apk_partner_id=16;session_id=5fa70c5c0f44f42fe06d8449f321f14d.1779105225337;device_rid=5fa70c5c0f44f42fe06d8449f321f14d;active_time=1779105227;z_ai=3c4946a54e49723fdaec9c952b2d373e;v=11.1.75;pr_device_id=5g1eic4c332b4fd1b3e5b25ciif1daa2;last_article_info=;device_recfeed_setting=%7B%22haojia_recfeed_switch%22%3A%221%22%2C%22homepage_sort_switch%22%3A%221%22%2C%22other_recfeed_switch%22%3A%221%22%2C%22shequ_recfeed_switch%22%3A%221%22%7D;device_smzdm_version_code=1175;"
#填抓包的ZDMCookie
checkin(zdmcookie)

预期结果如下

1
2
3
4
5
6
7
8
🏆签到成功
🏆已连续签到3天
🏆等级0
🏆补签卡0
🏆碎银0
🏆金币0
🏆积分0
🏆经验0

基于这个脚本,我们可以再加入类如云函数,Win任务计划程序,Linux/Mac 服务器 Cron 任务,青龙面板等系列的东西实现完全自动化

而加入更多的cookie可以实现多账户批量签到

集成 PushPlus、Server 酱、钉钉机器人等,可以实现签到结果自动通知

那么以上就是签名算法的发现过程和自动签到的实现


  • 标题: 什么值得买自动签到
  • 作者: mmj
  • 创建于 : 2026-05-20 21:20:21
  • 更新于 : 2026-05-20 21:51:15
  • 链接: https://samzhaohx.github.io/2026/05/20/什么值得买自动签到/
  • 版权声明: 本文章采用 CC BY-NC-SA 4.0 进行许可。
评论
目录
什么值得买自动签到