小程序动态调试-解密加密数据与签名校验

前言:
微信小程序的加密与验签早前大多数情况,要么就是逆向获取源码而后拿到加密秘钥,要么就是逆向拿到源码后使用腾讯自带的小程序开发者功能进行动态调试模拟,今天介绍一款志远大佬的开源工具—WeChatOpenDevTool

工具下载地址: https://github.com/JaveleyQAQ/WeChatOpenDevTools-Python

正文:
首先运行脚本,而后打开微信小程序,注意先后顺序,打开小程序后,打开调试器
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
本次使用的依然是PC端微信进行小程序抓包,抓包使用的工具就是fiddler+burpsuite ,具体使用方式上文有过介绍,此处不再进行赘述

在这里插入图片描述
大家可以看到,首先请求参数是加密的,并且请求头包含nonce、timestamp、signature信息,若是看过笔者的第一篇加密解密文章就知道,这里是一个签名校验,绝大多数的签名校验都是利用以上信息结合body进行加密,少数的还会带上uri或者是一些其他参数,那么我们今天要做的就是获取他请求包包体加密的方式以及签名校验的生成方法

老规矩,直接在开发者调试里面全局搜索requestData参数,这是最快定位的方法,当然了也可以利用网络信息进行断点调试
在这里插入图片描述

我们很快就找到了关键信息requestData: n.encrypt(o, r),一眼丁真
在这里插入图片描述
通过单步步过,我们可以获知n = require(t(219))为加密函数,所以需要进去看一下加密方法,,F9步入后发现其实是sm4国密算法,sm4大家可以理解为改良版的aes加密

在这里插入图片描述
继续进行步过(F10),结果如下:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
经过测试,这里面的sm4秘钥是写死的,直接用就行
在这里插入图片描述
在获取了加密算法与秘钥的情况下,我们继续调试,幸运的是在进行下断点的时候,看到了这个签名校验的函数
在这里插入图片描述
在这里插入图片描述
疑似signature
在这里插入图片描述
在这里插入图片描述
跟进函数l(u, i, n, v)
在这里插入图片描述
F9进入到l()函数内,此时函数变为l(e, t, n, r),这里面的e,t,n,r 就相当于u, i, n, v ,这里面就是一个形参,而传入进去的u, i, n, v才是真正的实参
在这里插入图片描述

我们可以看到,函数最后一行s(p + e + c + u) ,这里其实才是最终输出的值,所以我们需要关注p/e/c/u这四个参数是怎么来的,s()这个函数做了什么
首先,p这个参数其实是一个三元运算结果,我们传入的r参数此时是-1,他会做一个比较,大于等于0和小于0的时候去输出不同的p值
r >= 0 ? p = [(o = a)(345), o(230), o(211), “RhYqRedo=K7JvcuyjpbyppnZr7qQGs21JQsTNSp5TJm”, o(269), “Tyrcs”][o(343)](1, 5)o(215) : p = d();
由于此时是-1,所以p=d(),大家可以步入d()函数,但是其实无论是大于还是小于,结果都是写死的哈
在这里插入图片描述
r >=0 的时候,
p=NBMExPe9iO{WXsAxZMRhYqRedo=K7JvcuyjpbyppnZr7qQGs21JQsTNSp5TJmczO
r <0 的时候,
p=EvAucyQXqhNrXB23hw8wPw73xHzAHNqipmBFKJTHGzBXTsHpNxR9PGyMhErNEvAu

e的值其实就是个uuid,我们一会进行介绍;
c = ei(202) ,我们可以看一下i(202) 做了什么
在这里插入图片描述
我们通过控制台调试,不难发现,其实i(202)是一个substring字符串截取工具,而ei(202)其实就是对e下标为5的位置开始截取字符串

下面就是u了,u = s(JSONi(286))
我们看JSONi(286) ,就能大概知道咋回事了,实际上就是把传进来的明文参数进行了json转换
在这里插入图片描述
但是s()这个函数是干什么呢,实际上笔者一开始也是一脸懵,笔者进入函数调试的时候,发现首先会将json转换后的参数进行ascii编码,然后计算length长度后进行一系列复杂的运算最后生成一个32长度的字符串,最后再进行取值,这里笔者完全是懵逼的,大概精简的代码如下

function l(r) {
        var n = 8 * r.length
          , t = n % 512;
        t = t >= 448 ? 512 - t % 448 - 1 : 448 - t - 1;
        for (var e = new Array((t - 7) / 8), o = 0, a = e.length; o < a; o++)
            e[o] = 0;
        var c = [];
        n = n.toString(2);
        for (var u = 7; u >= 0; u--)
            if (n.length > 8) {
                var l = n.length - 8;
                c[u] = parseInt(n.substr(l), 2),
                n = n.substr(0, l)
            } else
                n.length > 0 ? (c[u] = parseInt(n, 2),
                n = "") : c[u] = 0;
        for (var i = [].concat(r, [128], e, c), s = i.length / 64, v = [115, 128, 22, 111, 73, 20, 178, 185, 23, 36, 66, 215, 218, 138, 6, 0, 169, 111, 48, 188, 22, 49, 56, 170, 227, 141, 238, 77, 176, 251, 14, 78], h = 0; h < s; h++) {
            var g = 64 * h;
            v = f(v, i.slice(g, g + 64))
        }
        return v
}

其实在这里笔者就卡主了,不会了,完全看不出来是什么,这也不是sha1-256,因为笔者去试过了,但是柳暗花明的就是,笔者在第二天清晨看到了这个
在这里插入图片描述
山重水复疑无路,柳暗花明又一村,原来是SM3
在这里插入图片描述
在这里插入图片描述
所以此时问题迎刃而解
在这里插入图片描述
s(p + e + c + u) 这个函数就是把p + e + c + u四个参数串起来,然后进行SM3编码

上次说到,e的值其实就是个uuid,所以我们回到上面,看一下e是怎么来的
在这里插入图片描述
进入c()函数

function c() {
        for (var e = a, t = [], n = e(306), r = 0; r < 36; r++)
            t[r] = n[e(234)](Math.floor(16 * Math[e(346)]()), 1);
        return t[14] = "4",
        t[19] = n[e(234)](3 & t[19] | 8, 1),
        t[8] = t[13] = t[18] = t[23] = "-",
        t[e(215)]("")[e(268)]("-", "")
}

在这里插入图片描述
大家不需要完全看得懂,我们只需要知道,他是由啥组成的,在什么位置有横杠就行
在这里插入图片描述
这个 JavaScript 函数的作用是生成一个符合 UUID(Universally Unique Identifier)规范的字符串。UUID 是一种用于标识信息或对象的唯一标识符。

现在让我们分解这个 JavaScript 函数的工作原理:

使用一个名为 a 的函数作为参数传入(在这里被省略了)。
创建一个空数组 t,用于存储生成的 UUID。
通过调用函数 e(306) 获取一个随机数生成器。
循环执行 36 次以下操作:
生成一个 0 到 15 之间的随机整数,然后转换为十六进制字符。
将生成的字符存储到数组 t 中。
修改数组中的特定索引位置,使得生成的 UUID 符合 UUID 版本 4 的规范:
将第 15 个字符设置为 “4”(UUID 版本号)。
将第 20 个字符的高 4 位设置为 “8”, “9”, “a” 或 “b”(UUID 变体)。
将数组中的特定索引位置设置为连字符 “-”。
使用 join() 方法将数组中的元素连接成一个字符串,并移除其中的连字符 “-”,最终得到 UUID。
下面是相应的 Python 代码:

python

import random

def generate_uuid():
    characters = '0123456789abcdef'
    uuid_list = [random.choice(characters) for _ in range(36)]
    uuid_list[14] = '4'  # UUID version 4
    uuid_list[19] = random.choice('89ab')  # Variant
    uuid_list[8] = uuid_list[13] = uuid_list[18] = uuid_list[23] = '-'
    return ''.join(uuid_list)

测试生成的 UUID
print(generate_uuid())
这个 Python 函数与 JavaScript 函数的实现类似,使用了 random.choice() 函数来从指定的字符集中随机选择字符,并通过字符串操作和列表操作生成 UUID。

最后总结一下,这个如果写脚本的话,一个接口就需要一个脚本,有点不值了,建议能力强的写个ipython写进burp里,只是难度有点…

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/416247.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

01 MySQL之连接

1. 连接 1.0 基础认知 多表(主表)和一表(从表的区别): 多表一般是主表&#xff0c;一般存储主要数据&#xff0c;每个字段都可能存在重复值&#xff0c;没有主键&#xff0c;无法根据某个字段定位到准确的记录&#xff1b; 一表一般是从表&#xff0c;一般存储辅助数据&…

点云数据处理常用外部库(C++/Windows)的项目配置

一、点云数据处理常用外部库&#xff08;C版本&#xff09;的下载安装与项目配置 &#xff08;一&#xff09;PCL 基于VS2019编程平台的PCL外部库下载安装及项目配置已有大量博客&#xff0c;本文不再赘述。具体下载安装及项目配置流程可参考外部库编译配置参考资料/*1*/ 。需…

redis-RedisTemplate.opsForGeo 的geo地理位置及实现附近的人的功能

redis内部使用的是 zset 数据结构存储&#xff0c;如下 import cn.huawei.VideoApplication; import cn.huawei.domain.Jingqu; import cn.huawei.service.JingquService; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired…

Redis 协议与异步方式

redis pipeline 模式 redis pipeline 是一个客户端提供的机制&#xff0c;与 redis 无关。pipeline 不具备事务性。目的&#xff1a;节约网络传输时间。通过一次发送多条请求命令&#xff0c;从而减少网络传输时间。 时间窗口限流 系统限定某个用户的某个行为在指定的时间范围…

SpringBoot项目中如何结合Mybatis进行数据库查询

在Spring Boot项目中使用Mybatis进行数据库操作是一种常见的实现方式。下面我将展示如何在Spring Boot项目中整合Mybatis。这个示例将包括几个主要部分&#xff1a;项目依赖配置、配置文件、实体类、Mapper接口及其XML配置文件、服务类、以及一个简单的控制器。 1. 项目依赖配…

一键安装|卸载 mysql 8.2.0 shell脚本

场景&#xff1a;为了在无网、外网 mysql 安装方便&#xff0c;这里分享一个自己编写得 shell脚本 这里以当前最新版 mysql 8.2.0&#xff1b;centos-7 二进制包下载&#xff1a; 下载地址 mysql_install.sh #!/bin/bash # 解压安装包 tar -xf mysql-8.2.0-linux-glibc2.17-x8…

opencv中两个LSD直线检测算法的区别与应用

opencv中两个LSD直线检测算法的区别与应用 同样是Line Segment Detector(lsd)算法&#xff0c;opencv中提供了两种实现&#xff0c;并且位于不同的模块。下面分别介绍它们的使用方法&#xff1a; 1. LineSegmentDetector 由于源码许可证问题 OpenCV 3.4.6-3.4.15、4.1.0-4.5.…

IDEA类和方法注释模板设置

一、概述 IDEA自带的注释模板不是太好用&#xff0c;我本人到网上搜集了很多资料系统的整理了一下制作了一份比较完整的模板来分享给大家&#xff0c;我不是专业玩博客的&#xff0c;写这篇文章只是为了让大家省事。 这里设置的注释模板采用Eclipse的格式&#xff0c;下面先贴…

【深度优先搜索】【图论】【推荐】332. 重新安排行程

作者推荐 动态规划的时间复杂度优化 本文涉及知识点 深度优先搜索 图论 LeetCode332. 重新安排行程 给你一份航线列表 tickets &#xff0c;其中 tickets[i] [fromi, toi] 表示飞机出发和降落的机场地点。请你对该行程进行重新规划排序。 所有这些机票都属于一个从 JFK&a…

C++:常量表达式

C11开始constexpr作为一种声明&#xff0c;为编译器提供了在编译期间确认结果的优化建议&#xff0c;满足部分编译期特性的需求 constexpr和const区别 int b10; const int ab; //运行成功 constexpr int cb; //编译器报错&#xff0c;b的值在编译期间不能确定 const int size1…

研发日记,MatlabSimulink开箱报告(九)——Simulink Test模块

文章目录 前言 Simulink Test模块 静态测试 动态测试 逻辑测试 前言 见《开箱报告&#xff0c;Simulink Toolbox库模块使用指南&#xff08;四&#xff09;——S-Fuction模块》 见《开箱报告&#xff0c;Simulink Toolbox库模块使用指南&#xff08;五&#xff09;——S-F…

vue a-table 实现指定字段相同数据合并行

vue a-table 实现相同数据合并行 实现效果代码实现cloums数据格式数据源格式合并代码 实现效果 代码实现 cloums数据格式 const getColumns function () {return [{title: "分类",dataIndex: "checked",width: "150px",customRender: (text, …

有哪些视频媒体?邀请视频媒体报道活动的好处

传媒如春雨&#xff0c;润物细无声&#xff0c;大家好&#xff0c;我是51媒体网胡老师。 视频媒体在当今的媒体生态中占据了重要的地位。以下是一些主要的视频媒体类型&#xff1a; 电视台&#xff1a;如中央电视台、各省级卫视台、地方电视台等&#xff0c;他们拥有专业的视…

mac命令行下计算文件SHA-256散列值

源起 从国内的第三方网站下载了Android sutiod的zip包下载地址&#xff0c;为了安全起见还是得跟Android官网上的对应的zip包的SHA值做下对比。以前是经常使用md5命令的&#xff0c;所以理论在命令行下应该是有对应的命令行工具可以计算SHA值的。后来搜索到可以用 shasum命令来…

yolov8训练目标检测模型

1.环境安装 conda安装&#xff08;miniconda&#xff09;&#xff0c;配置环境变量 创建环境 conda create -n yolo python3.8安装ultralytics conda activate yolopip install ultralytics2.数据集标注 使用labelimg标注工具对图片进行标注&#xff1a;将标注产生的xml转为t…

表格图片太大怎么批量压缩?快速处理图片大小的方法

在工作或者学习中制作表格的时候&#xff0c;经常需要插入一些图片来修饰内容&#xff0c;当遇到图片太大无法导入的情况就比较麻烦&#xff0c;尤其是多张图片处理的时候&#xff0c;那么表格图片太大怎么批量压缩呢&#xff1f;接下来小编就分享给大家一个快速图片压缩的方法…

HTTP详解(HTTP的特点,状态码,工作原理,GET和POST的区别,如何解决无状态通信)!!!

文章目录 一、HTTP协议简介二、HTTP的主要特点三、HTTP之URL四、Request和Respons五、HTTP的状态码六、HTTP工作原理七、GET和POST请求的区别八、解决HTTP无状态通信——Cookie和Session 一、HTTP协议简介 HTTP协议是Hyper Text Transfer Protocol&#xff08;超文本传输协议&…

92. 递归实现指数型枚举 刷题笔记

思路 dfs 考虑选或者不选每个位置 用0表示未考虑 1表示选 2表示不选 用u表示搜索状态 u>n时 已经搜到底层了 需要输出当前方案 遍历 如果选了则输出 #include<iostream> using namespace std; int n; const int N16; int st[N]; void dfs(int u){ //u来记…

JVM运行时数据区——程序计数器

1、程序计数器介绍 JVM中的程序计数器英文全称是Program Counter Register&#xff0c;其中Register的命名源于CPU的寄存器&#xff0c;寄存器用于存储指令相关的现场信息&#xff0c;CPU只有把数据装载到寄存器才能够运行。 程序计数器中的寄存器并非是广义上所指的物理寄存…

音频提取使用什么方法?视频提取音频

在数字技术与多媒体日益普及的今天&#xff0c;音频提取已成为一个常见且重要的任务。无论是为了制作视频、编辑音乐&#xff0c;还是进行语音识别和分析&#xff0c;我们都需要从原始材料中提取音频。那么&#xff0c;音频提取通常使用什么方法呢&#xff1f; 1. 使用专业的音…