前往小程序,Get更优阅读体验!
立即前往
发布
社区首页 >专栏 >聊聊如何复现微信小程序的签名算法源码并重现签名请求

聊聊如何复现微信小程序的签名算法源码并重现签名请求

原创
作者头像
Lorin 洛林
发布2025-01-21 16:51:29
发布2025-01-21 16:51:29
1090
举报

前言

  • 通常在后端接口设计中,为了防止请求的数据被篡改,一般会对请求数据签名。本文将以微信小程序员为例实现通过逆向编译源码,找到签名算法源码,并使用 Python 调用 JS 重现签名请求。

实现步骤

小程序逆向获取源码

  • 为了获取小程序的源码,我们可以通过逆向的方式获取小程序源码,这里推荐一个非常实用的工具 wxapkg,可以一键实现小程序源码逆向。
  • 通过上面的工具,我们只需要选择需要逆向的源码,就可以实现一键逆向,当然一般情况下我们逆向获取到的源码一般是被混淆后的代码,比如下面这样。

定位签名算法位置并整合

  • 获取到逆向的源码后,我们需要找到源码中生成签名算法的实现部分,当然由于代码被混淆,找到签名算法的实现难度会大很多,这里我建议两个思路:第一个直接使用 sign 等关键字搜索,第二个从接口调用处开始逐层往下开始查找到签名位置。
  • 找到签名的位置后,我们不需要阅读混淆后的代码,只需要截取我们需要的部分代码,然后尝试运行生成签名,运行报错缺失我们再一步步补全签名需要的代码
  • 补全代码完成后,运行生成签名并对比和预期生成的签名是否一致,若不一致,则需要排查整合的签名代码是否有误。
  • 下面是一个整合后的案例:
代码语言:js
复制
// test.js
"use strict";
var r = function (r, o) {
        return r << o | r >>> 32 - o
    },
    o = function (r) {
        var o, e = "";
        for (o = 7; o >= 0; o--) e += (r >>> 4 * o & 15).toString(16);
        return e
    };

function sha1(e) {
    var t, a, h, n, C, c, f, d, s, u = new Array(80),
        i = 1732584193,
        A = 4023233417,
        g = 2562383102,
        m = 271733878,
        p = 3285377520,
        S = (e = function (r) {
            r = r.replace(/\x0d\x0a/g, "\n");
            for (var o = "", e = 0; e < r.length; e++) {
                var t = r.charCodeAt(e);
                t < 128 ? o += String.fromCharCode(t) : t > 127 && t < 2048 ? (o += String.fromCharCode(t >> 6 | 192), o += String.fromCharCode(63 & t | 128)) : (o += String.fromCharCode(t >> 12 | 224), o += String.fromCharCode(t >> 6 & 63 | 128), o += String.fromCharCode(63 & t | 128))
            }
            return o
        }(e)).length,
        l = new Array;
    for (a = 0; a < S - 3; a += 4) h = e.charCodeAt(a) << 24 | e.charCodeAt(a + 1) << 16 | e.charCodeAt(a + 2) << 8 | e.charCodeAt(a + 3), l.push(h);
    switch (S % 4) {
        case 0:
            a = 2147483648;
            break;
        case 1:
            a = e.charCodeAt(S - 1) << 24 | 8388608;
            break;
        case 2:
            a = e.charCodeAt(S - 2) << 24 | e.charCodeAt(S - 1) << 16 | 32768;
            break;
        case 3:
            a = e.charCodeAt(S - 3) << 24 | e.charCodeAt(S - 2) << 16 | e.charCodeAt(S - 1) << 8 | 128
    }
    for (l.push(a); l.length % 16 != 14;) l.push(0);
    for (l.push(S >>> 29), l.push(S << 3 & 4294967295), t = 0; t < l.length; t += 16) {
        for (a = 0; a < 16; a++) u[a] = l[t + a];
        for (a = 16; a <= 79; a++) u[a] = r(u[a - 3] ^ u[a - 8] ^ u[a - 14] ^ u[a - 16], 1);
        for (n = i, C = A, c = g, f = m, d = p, a = 0; a <= 19; a++) s = r(n, 5) + (C & c | ~C & f) + d + u[a] + 1518500249 & 4294967295, d = f, f = c, c = r(C, 30), C = n, n = s;
        for (a = 20; a <= 39; a++) s = r(n, 5) + (C ^ c ^ f) + d + u[a] + 1859775393 & 4294967295, d = f, f = c, c = r(C, 30), C = n, n = s;
        for (a = 40; a <= 59; a++) s = r(n, 5) + (C & c | C & f | c & f) + d + u[a] + 2400959708 & 4294967295, d = f, f = c, c = r(C, 30), C = n, n = s;
        for (a = 60; a <= 79; a++) s = r(n, 5) + (C ^ c ^ f) + d + u[a] + 3395469782 & 4294967295, d = f, f = c, c = r(C, 30), C = n, n = s;
        i = i + n & 4294967295, A = A + C & 4294967295, g = g + c & 4294967295, m = m + f & 4294967295, p = p + d & 4294967295
    }
    return (s = o(i) + o(A) + o(g) + o(m) + o(p)).toLowerCase()
}


let params = {
    "classid": 5,
    "keyword": "",
    "describe": "获取商品分类",
    "openId": "o_cBd5WsY53n9hib-zFNqQqKzvtY",
    "profileId": "13754470098",
    "promotionid": "0",
    "touristTelphone": "",
    "isTourist": "",
    "timestamp": "1736654776",
    "sign": "049da2ed71e3fa2f90b02d00b11f7f35e6190379"
}


function n(e) {
    var n = r1(e);
    return n.length > 0 ? sha1(n) : ""
}


function _typeof(o) {
    return module.exports = _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) {
        return typeof o
    } : function (o) {
        return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o
    }, _typeof(o)
}

function r1(t) {
    t.sign && delete t.sign;
    var r = [];
    for (var n in t) r.push(n);
    var s = r.sort(),
        i = "";
    for (n = 0; n < s.length; n++) {
        var a = s[n],
            u = t[a];
        o1(u) || ("object" === _typeof(u) && (u = JSON.stringify(u)), i = i + "&" + a + "=" + u)
    }
    return i.length > 0 && (i = i.substring(1)), i
}

function o1(e) {
    return null == e || "" === e || "" === function (e) {
        if ("string" != typeof e) return e;
        return e.replace(/(^\s*)|(\s*$)/g, "")
    }(e) || "null" === e
}

//console.log(n(params))

//新增一个导出函数(node方式)
module.exports.init = function (arg1) {
    //调用函数,并返回
    console.log(n(arg1));
}

使用 Python 调用 JS 重现签名请求

  • 通过 JS 复现签名算法后,我们不需要使用 Python 重写签名算法,我们只需要使用 Python 调用 JS 代码即可,Python 提供了很多调用 JS 代码的方式,这里介绍通过 通过 node 调用 js 的方式

前置条件

  • 安装 node 环境

代码示例

代码语言:Python
复制
import os

params = {
    "classid": 5,
    "keyword": "",
    "describe": "获取商品分类",
    "openId": "o_cBd5WsY53n9hib-zFNqQqKzvtY",
    "profileId": "13754470098",
    "promotionid": "0",
    "touristTelphone": "",
    "isTourist": "",
    "timestamp": "1736654776",
    "sign": "049da2ed71e3fa2f90b02d00b11f7f35e6190379"
}

// test 为组合签名算法的js文件 如上述示例
cmd = 'node -e "require(\\"%s\\").init(%s)"' % ('./test', params)

pipeline = os.popen(cmd)

# 读取结果
result = pipeline.read()

print('结果是:', result)

总结

  • 本篇文章介绍了小程序逆向,签名复现的一些技术思路,仅作为交流学习用途,切记不能用于不合法用途。

个人简介

👋 你好,我是 Lorin 洛林,一位 Java 后端技术开发者!座右铭:Technology has the power to make the world a better place.

🚀 我对技术的热情是我不断学习和分享的动力。我的博客是一个关于Java生态系统、后端开发和最新技术趋势的地方。

🧠 作为一个 Java 后端技术爱好者,我不仅热衷于探索语言的新特性和技术的深度,还热衷于分享我的见解和最佳实践。我相信知识的分享和社区合作可以帮助我们共同成长。

💡 在我的博客上,你将找到关于Java核心概念、JVM 底层技术、常用框架如Spring和Mybatis 、MySQL等数据库管理、RabbitMQ、Rocketmq等消息中间件、性能优化等内容的深入文章。我也将分享一些编程技巧和解决问题的方法,以帮助你更好地掌握Java编程。

🌐 我鼓励互动和建立社区,因此请留下你的问题、建议或主题请求,让我知道你感兴趣的内容。此外,我将分享最新的互联网和技术资讯,以确保你与技术世界的最新发展保持联系。我期待与你一起在技术之路上前进,一起探讨技术世界的无限可能性。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 前言
  • 实现步骤
    • 小程序逆向获取源码
    • 定位签名算法位置并整合
    • 使用 Python 调用 JS 重现签名请求
      • 前置条件
      • 代码示例
  • 总结
  • 个人简介
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档