前期准备

  • 网址:aHR0cHM6Ly9ycy5qc2hyc3MuamlhbmdzdS5nb3YuY24vaW5kZXgv
  • 目标:
    1. 接口请求内容加密和响应内容解密
    2. 请求头加密参数 Web-Encrypt-Response-Encrypt-KeyWeb-Encrypt-Sign
  • 涉及内容:
    1. js worker 多线程通信
    2. axios网络请求库
    3. 国密sm2sm3sm4

Axios

网址:Axios

这个网站用到了 axios,可以先了解一下 axios 这个网络请求库,主要是interceptor这块

拦截器

在请求或响应被 then 或 catch 处理前拦截它们。

// 添加请求拦截器
axios.interceptors.request.use(function (config) {
// 在发送请求之前做些什么
return config;
},function (error) {
// 对请求错误做些什么
return Promise.reject(error);
}); // 添加响应拦截器
axios.interceptors.response.use(function (response) {
// 2xx 范围内的状态码都会触发该函数。
// 对响应数据做点什么
return response;
},function (error) {
// 超出 2xx 范围的状态码都会触发该函数。
// 对响应错误做点什么
return Promise.reject(error);
});

分析流程

先来看一下要逆向的内容

如上图所示,获取考试列表(getExamTaskIM)这个接口的请求和返回数据都是加密的

请求加密分析

老规矩直接看堆栈,进去第一个下个断点,刷新页面

成功断下后发现 xhr send 发送已经完成了加密

往上找一下堆栈,发现一个axios的请求拦截器,直接下断点刷新

断住之后可以追进去看一下

有四个拦截器,分别进去下一个断点去查看,最终在最后一个拦截器发现关键数据

这是一个与worker进行通信的异步函数,我们往下看看其他逻辑

发现有一个onmessage的回调方法,我猜测加密流程是这样的:

  1. 主线程发送明文数据(postMessage)
  2. work 线程接收并开始加密(onMessage)
  3. work 线程加密完后发送加密数据给主线程(postMessage)
  4. 主线程接收加密数据(onMessage)

异步方法大都有一个回调的过程

下图主线程为postMessage一方,其它线程则需要使用onMessage接受数据

接着分析流程,我们先在这个onmessage回调方法内下段,再跟堆栈就容易找到调用位置了

找到postMessage后往上看看就能发现关键加密逻辑

  • 源流程代码,大量的 promise
self.onmessage = function(t) {
var r, e, o, h, a, f, c;
(r = t.data.prefix,
e = t.data.data,
o = e._s1,
h = e._s2,
a = e.requestData,
f = Math.floor(Date.now() / 1e3).toString(),
c = function() {
return 2 === s
}
,
u.timestamp = f,
new Promise((function(t, e) {
new Promise((function(t, e) {
try {
t({
key: r + i.default._s2EN(o, h, 0)
})
...
}
...
new Promise((function(t, e) {
try {
var o = r + i.default._s2EN(JSON.stringify(a), h, 0)
, s = f + o;
t({
content: o,
signature: (0,
n.default)(s)
})
...
}
...
}
...
}

进到这里了直接单步调试就是了,直接跟到_s2EN 函数里,这里就是加密函数了,加密函数用到了两次,一次加密 sign,一次加密 payload

这个其实就是sm2标准算法,看方法名就能猜出个大概了,就懒得写过程了,直接给出个大概的代码吧

var prefix = "04";
// 解密response的key
var _s1 = "862344dec7e0907a2b215c37a57caf95";
// 加密data的publicKey
var _s2 = "04fc439405f925df23510517e1e5a8078d19b23b24d62190c40e632f1d0bcd784fc6fcf1a8c3b5cf7f422815c6b322176e89f56f781ccd3c36aa02e5d31400090a"; // 计算key
key = prefix + sm2(_s1, _s2, 0); // 加密payload,计算sign
payload = {
"bge304": 202432990000309,
"bge316": "320199"
}
var timestamp = Math.floor(Date.now() / 1000).toString();
var content = prefix + sm2(JSON.stringify(payload), _s2, 0)
var sign = sm3(timestamp + o);
headers= {
"Web-Encrypt-Response-Encrypt-Key": key,
"Web-Encrypt-Sign": sign ,
"Web-Encrypt-Timestamp": timestamp
}

sign 加密过程忘记截图了,实际上就是个sm3加密

完成以上请求头和请求数据的加密后,就可以正常请求拿到返回数据了

响应解密分析

跟找加密过程差不多,直接找到响应拦截器就行

挨个下断点,发现第一个很像了

这个web-encrypt-sign是响应头里的一个值,往下翻翻会发现熟悉的postMessageonMessage

这里过程跟加密差不多就不详细写过程了,直接找关键点

看方法名能猜出个大概是sm4解密,解密的 key 就是之前传入的_s1

随便抓个包解密试一下,可以看到正常解密成功,解密出来的 response 还需要 html 实体解码一下才行

Python 还原实现

  • 代码:

  • 成果:

大功告成!

微信公众号

公众号更新比较快,欢迎关注!

某苏人社异步JS逆向加解密分析(sm2+sm3+sm4)的更多相关文章

  1. RSA 加密 解密 (长字符串) JAVA JS版本加解密

    系统与系统的数据交互中,有些敏感数据是不能直接明文传输的,所以在发送数据之前要进行加密,在接收到数据时进行解密处理:然而由于系统与系统之间的开发语言不同. 本次需求是生成二维码是通过java生成,由p ...

  2. js常用加解密函数汇总

    1. JS自定义加密解密函数,及用法 function compile(code) { )+code.length); ;i<code.length;i++){ c+=String.fromCh ...

  3. JS base64加解密解决传输的url各种编码问题

    网上拷贝的,废话少说,直接上代码: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" " ...

  4. Des加解密(Java端和Js端配套)解析

    一.什么是DES加密        des对称加密,对称加密,是一种比较传统的加密方式,其加密运算.解密运算使用的是同样的密钥,信息的发送者和信息的接收者在进行信息的传输与处理时,必须共同持有该密码( ...

  5. 这个爬虫JS逆向加密任务,你还不来试试?逆向入门级,适合一定爬虫基础的人

    友情提示:在博客园更新比较慢,有兴趣的关注知识图谱与大数据公众号吧.这次选择苏宁易购登录密码加密,如能调试出来代表你具备了一定的JS逆向能力,初学者建议跟着内容调试一波,尽量独自将JS代码抠出来,实在 ...

  6. JS 动态加载脚本 执行回调_转

    关于在javascript里面加载其它的js文件的问题可能很多人都遇到过,但很多朋友可能并不知道怎么判断我们要加载的js文件是否加载完成,如果没有加载完成我们就调用文件里面的函数是不会成功的.本文讲解 ...

  7. js动态加载脚本

    最近公司的前端地图产品需要做一下模块划分,希望用户用到哪一块的功能再加载哪一块的模块,这样可以提高用户体验. 所以到处查资料研究js动态脚本的加载,不过真让人伤心啊!,网上几乎都是同一篇文章,4种方法 ...

  8. JS 动态加载脚本 执行回调

    JS 动态加载脚本  执行回调 关于在javascript里面加载其它的js文件的问题可能很多人都遇到过,但很多朋友可能并不知道怎么判断我们要加载的js文件是否加载完成,如果没有加载完成我们就调用文件 ...

  9. 前端设计中关于外部js文件加载的速度优化

    在一般情况下,许多人都是将<script>写在了<head>标签中,而许多浏览器都是使用单一的线程来加载js文件的,从上往下,从左往右. 若是加载过程出错,那么网页就会阻塞,就 ...

  10. js资源加载优化

    互联网应用或者访问量大的应用,对js的加载优化是不可少的.下面记录几种优化方法 CDN  + 浏览器缓存 CDN(content delivery network)内容分发网络, 最传统的优化方式.其 ...

随机推荐

  1. Machine Learning Week_1 Model and Cost Function 1-4

    目录 2 Model and Cost Function 2.1 Video: Model Representation unfamiliar words 2.2 Reading: Model Rep ...

  2. AI五子棋_08 五子棋落子规则对应的价值

    AI五子棋 第八步 恭喜你到达第八步! 利用前一步得到的棋型分析结果,考察每一个可能落子的位置,给每一个可能的位置打分,将棋子落在分数最高的位置上.根据经验,我们可以总结出下面的落子规则: 1. 致胜 ...

  3. 从 Git 提交历史生成 Release Note

    发布软件时写 Release Note 算是常规操作,但每次从头手打也有点累,可以考虑从 Git 的提交历史中自动生成. Git 提交信息一般是三段式结构,段落之间使用空行隔开: <subjec ...

  4. 剖析Air724UG的硬件设计,有大发现?03篇

    ​ 今天我们分享第三部分. 四.射频接口 天线接口管脚定义如下: 表格 19:RF_ANT 管脚定义 管脚名 序号 描述 LTE_ANT 46 LTE 天线接口 BT/WiFi_ANT 34 蓝牙/W ...

  5. fork父子进程执行顺序

    使用一段代码来检查父子进程执行顺序 <?php $str = "hello world!" . PHP_EOL; // 派生一个子进程,子进程会复制主进程中的上下文 // p ...

  6. ABP实践(5)-abp前端vue框架之IView实现三级菜单(博友需要特此分享)

    为响应博友想要知道三级菜单怎么实现本篇文章先介绍三级菜单的实现,后续再分享其他部分内容 1 修改菜单组件sidebarMenu.vue 图为原代码和修改后代码比对 修改前后的源码如下 <styl ...

  7. 曲线救国--访问dockerhub仓库

    前言 由于dockerhub也被墙了,导致基础镜像没法拉取.后面解封了,又被墙了... 在这次被墙之前,访问国外的速度也是堪忧,甚至访问不了k8s的镜像,基于此,分享一下笔者经验 使用Daocloud ...

  8. Redis中的分布式锁(步步为营)

    分布式锁 概述 分布式锁指的是,所有服务中的所有线程都去获取同一把锁,但只有一个线程可以成功的获得锁,其他没有获得锁的线程必须全部等待,直到持有锁的线程释放锁. 分布式锁是可以跨越多个实例,多个进程的 ...

  9. mvn eclipse:eclipse -Dwtpversion=2.0 -DdownloadSources=true -DdownloadJavadocs=true -DjdkLevel=1.6

    mvn eclipse:eclipse -Dwtpversion=2.0 -DdownloadSources=true   -DdownloadJavadocs=true -DjdkLevel=1.6

  10. 一文聊清楚Redis主从复制原理

    本地缓存带来的挑战 分布式缓存相比于本地缓存,在实现层面需要关注的点有哪些不同.梳理如下: 维度 本地缓存 集中式缓存 缓存量 受限于单机内存大小,存储数据有限 需要提供给分布式系统里面所有节点共同使 ...