白水饮 发表于 2023-1-11 22:19

某上市导购平台Android APP签到sign逆向分析并使用Python复写加密算法

本帖最后由 cry980285208 于 2023-1-12 10:00 编辑

导购平台网址:aHR0cHM6Ly93d3cuc216ZG0uY29tLw==

由于不想每天手动签到且经常忘记签到,于是便去Github搜索相关结果,果不其然,是有相关结果的,并且更新时间还是Last Month,但是在使用过程中发现,接口总是返回验证码错误,手动在WEB端签到,发现是有滑块验证码的,在APP端签到就没有验证。


本想偷懒,看下网上有没有现成的APP端签到源码之类的,搜了一圈,没有找到,只能自己动手了,于是便有了这篇文章。

首先,直接用小黄鸟抓包看一下,找到签到接口,接口地址https://user-api.smzdm.com/checkin,看下请求的参数:


经过多次抓包,发现变化的值,只有sign和time,weixin,f,v,sk,token都是固定值,captcha和touchstone_event为空


再然后直接使用Jadx打开apk安装包,搜索"sign",如下图:




上面的这些类看起来都是第三方SDK里面的相关内容,下面的这个混淆过的这个方法e.e.b.a.n.a.a.a,非常可疑,我们进去看看,分析下




在这里我们就可以看到签到接口传的f,v,weixin,time一些参数了,sign这个值,是由a方法生成,我们直接点击a方法,跳转至相关代码,再进行分析:




到了这里,可以看到这个a方法传入了一个map,并对其进行了排序遍历拼接,在最后还拼接了一个&key=,这个key的值是由ZDMKeyUtil.a().b()生成的,并且最终的返回值应该是经过F这个类中的a方法进行了加密,我们先跳转至ZDMKeyUtil这个类里面再进行分析




ZDMKeyUtil这个类里面应该是加载了一个固定的key,这里我也不太确定,后面我们再通过Xposed去Hook相关方法,打印log查看


然后我们再去分析F类中的这个a方法,直接点击跳转,如下图:




好家伙,这一看基本就可以确定是MD5加密了


通过上面的分析,我们来总结下:sign的值是由e.e.b.a.n.a.a这个类中的a方法生成的,a这个方法做了哪些事呢?传入了一个map,并对其排序遍历拼接,最终还通过ZDMKeyUtil生成了一个key拼接后面。接下来就是通过Fa这个类中的a方法,对上面拼接的这个字符串进行MD5加密,最终生成32位大写的sign值


那么我们怎么才能得到加密前的参数并且复写加密算法呢?


我的方法是通过Xposed Hook相关类和方法,获取传参和返回值:
1.通过hook e.e.b.a.n.a.a这个类中的a方法,获取传入的map和sign值,对比小黄鸟抓包抓到的参数和sign值,确定是否是我们需要找的签到接口,因为还有其他很多接口都调用了这个方法
2.通过hook ZDMKeyUtil这个类中的方法,获取最终拼接在后面的key参数
3.通过hook Fa这个类中的a方法,获取加密前的字符串和加密后的值,注意,这里加密后为小写的sign,需转为大写的32位


相关Hook代码如下图,代码很烂,仅供参考:



分析Xposed Log文件,Log打印结果如下图:




通过查看Xposed打印的log,我们可以得出加密前的字符串格式为f=android&sk=xxx&time={timestamp}000&token=xxx&v=9.9.12&weixin=1&key=xxx,其中拼接在最后的key为固定值,如图hook success5后面的即为key的值


有了加密的文本和加密的方法,接下来,就可以用python进行复写了

# -*- 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 = '填写抓包抓到的sk值'
    zdmtoken = cookie
    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_V9.9.12 rv:683 (Redmi K20 Pro;Android11;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 = "填写ZDMCookie"
    checkin(zdmcookie)


写在最后:签到接口中,headers中还有一个参数request_key,通过Jadx分析APP源码,可以发现request_key是由一个随机数拼接当前时间戳而成的,源代码如下:




sk参数为固定值,分析app源码,似乎是由Cookie中的sess,用户id等信息生成的,具体怎么生成的就不深究了,反正为固定值,直接用抓包中的值就行了
token参数也是固定值,也就是Cookie中的sess
感兴趣的可以将代码用云函数改写一下,每天定时签到,也可以加上server酱,钉钉,企业微信推送,我就不献丑了

saoyi 发表于 2023-1-13 18:43

感谢大佬分享

ranbow1989 发表于 2023-2-9 02:00

感谢分享,额外补充一句,如果有还在用python2.7的朋友,f开头作为formatting的几句要替换掉。
例如
rawdata = f'f=android&sk={zdmsk}&time={timestamp}000&token={zdmtoken}&v=9.9.12&weixin=1&key={zdmkey}'
要替换为
rawdata = 'f=android&sk='+zdmsk+'&time='+str(timestamp)+'000&token='+zdmtoken+'&v=9.9.12&weixin=1&key='+zdmkey

再次感谢~

rustyjackal 发表于 2023-1-12 13:52

关键是思路很好

sunzhw 发表于 2023-1-12 14:13

支持,感谢分享

红内裤 发表于 2023-1-12 14:44

收到,这就去改!{:1_918:}

chenyicai 发表于 2023-1-12 15:12

感谢大神分享

teenage1997 发表于 2023-1-12 15:24

很强,git上的脚本都失效了,把你这个放到qinglong跑,立马签到上了

CfengSmeng 发表于 2023-1-12 15:32

ooopppp
小黄鸟好评

tanzhijun8 发表于 2023-1-12 15:36

谢谢分享

一剑封侯人 发表于 2023-1-12 15:47

大佬一出手

一剑封侯人 发表于 2023-1-12 15:56

teenage1997 发表于 2023-1-12 15:24
很强,git上的脚本都失效了,把你这个放到qinglong跑,立马签到上了

我放在ql怎么跑不起来啊,老哥,带带
页: [1] 2 3 4 5 6
查看完整版本: 某上市导购平台Android APP签到sign逆向分析并使用Python复写加密算法