泡泡玛特小程序逆向研究与数据抓取技术详解

2024-12-19
来源:网络整理

本文所有内容仅供学习和交流。抓包内容、敏感URL、数据接口已脱敏。严禁商业和非法使用。否则由此产生的一切后果与作者无关。如有侵权,请联系我立即删除!

前言

最近看到泡泡玛特很火,就跟风做了一些研究。倒车的时候我发现很有趣。回到了自己拆包反编译小程序的时候,所以一时兴起决定写一篇文章记录一下。

目标网站

当我们用PC版打开时,会提示如下:

现在我们用手机加载小程序,

小程序的路径为/data/data/com..mm///pkg//

接下来,我们使用adb的pull命令来拉取所有文件。

由于手机上的包不需要解密,所以我们可以直接使用.exe来解包。

接下来我们手动将其复制到同一文件夹中,

之后我们就可以让他到微信开发者工具中反编译调试代码。

修复小程序

我这里已经导入了,直接打开就可以了。接下来我会做一些简单的修复和补充。

“简单来说,凡是报错的,都会被删除。”

在这种情况下,我们可以将它们全部删除,因为我们没有权限调用他的插件应用程序。

修复完成后,我们发现存在很多与渲染层网络相关的错误。我们没有办法解决这个问题。

因为我们不是开发者,所以没有权力配置合法的域名。

即使请求无法发送,我们也只能碰碰运气,不断更换加载页面,因为它的参数是本地生成的。

只要遇到可以生成sign和x-sign的接口,我们就可以逆向操作。

经过不懈的努力,我们找到了这个页面

触发条件为搜索界面

参数分析X-Sign

只有一次全局搜索。我们点击它,然后设置一个断点并再次搜索以触发它。

发现断开成功了,接下来我们来分析一下它是如何生成的。

r["X-Sign"] = "".concat((0,
                    u.default)("".concat(c, ",").concat(null === o || void 0 === o || null === (a = o.login) || void 0 === a ? void 0 : a.client_key)), ",").concat(c)


从图中我们得知的信息是,可能是32位的md5。应该是一个13位的时间戳拼接在一起然后进行md5。我们不知道从哪里去找原因,所以只能寻找源头。

这里我不会太造作,我只是直接解释它不是本地生成的,它是由被调用的函数返回的。我们直接重新进入网络,在或者其他抓包工具中进行搜索。

我在这里所拥有的价值对于每个人来说一定是不同的。我们来验证一下我们的猜测是否正确。

完全正确,所以我们知道x-sign的算法就是拼接13位时间戳。在拼接函数中,我们拼接13位时间戳。

直接写代码格式就可以了

def md5(enc_str):
    m = hashlib.md5()
    m.update(enc_str.encode("utf-8"))
    return m.hexdigest()
time_now = str(int(time.time()*1000))
x-sign = md5(time_now+","+"4ejk2eqvpbwgxi3wj")+","+time_now

符号

显然sign加密在下面,我们断点然后进去刷新

当你点击sign方法时,你会看到md5,然后拼接。我们将在断点后逐步分析。

其他一切都可以阅读和理解。主要难点在于 的功能。我们点进去看看吧。

事实上,这非常简单。就是将键值对按大小写排序,然后将键值用=连接起来,在每个键值对的末尾拼接一个&。

其实看下图就可以明白它的作用

所以我们理解,整体加密就是传递请求的URL中的参数,然后在末尾拼接一个&=,制成大写的md5。我们来验证一下。

只需转换代码即可

def process_event(e):

    # 过滤掉特定的键和空值或未定义的值
    filtered_keys = [t for t in e if e[t] is not None and str(e[t]) != "" and t not in ["session_id""sign""charset""signType""v"]]
    # 对键进行排序
    sorted_keys = sorted(filtered_keys)
    
    # 将键值对转换为字符串,如果是对象则JSON序列化
    def serialize_value(t):
        r = e[t]
        if isinstance(r, (dictlist)):  # 假设'object'对应于Python中的字典或列表
            return f"{t}={json.dumps(r,ensure_ascii=False,separators=(','':'))}"
        else:
            return f"{t}={r}"

    # 使用map将处理函数应用于排序后的键,然后使用join连接结果
    result = "&".join(map(serialize_value, sorted_keys))
    return result

data = {"ts":1715842921746}
sign =  md5(process_event(data)+"&noceStr=boxonline").upper()
print(sign)
data['sign'] = sign

结果是没有问题的。至此,泡泡玛特的两个参数就分析完了。

结束

由于我没有这个需要,所以我不会写一些代码来验证它。我自己来解决。这其实是一件很简单的事情。整个过程并不困难。关键是耐心。

分享