js逆向解加密-国家医保服务平台(二)

301 阅读4分钟

载荷加密

先观察一下它的载荷,是一个json数据

image.png

首先猜一下,它的加密参数可能是哪几个?encData appCode signData 应该就是这几个,以上面的经验,这几个加密参数都可能是在一起的,所以,先搜一下encData

image.png

找到了这里,这两个函数就是将这两个参数进行加密,我们先破解这两个,如果还是不行再去破解appCode,但是应该是不可能的,加密参数估计就这两个。

然后就是破解加密参数了

首先要先扣一段js代码,就是包含所有载荷参数的,就类似于上面的get_headers一样,代码中的r.data都是载荷参数

image.png 扣下来

function get_datas(){
  t.data = {
    data: t.data || {}
},
t.data.appCode = l.appCode,
t.data.version = l.version,
t.data.encType = "SM4",
t.data.signType = "SM2",
t.data.timestamp = s,
t.data.signData = function(t) {
    try {
        var n = m(t.data)
          , i = p(n);
        i.data = p(i.data);
        var r = v(i)
          , a = o.doSignature(r, d, {
            hash: !0
        });
        return e.from(a, "hex").toString("base64")
    } catch (e) {}
}(t),
t.data.data = {
    encData: function(e, t) {
        switch (e.toUpperCase()) {
        case "SM2":
            return function(e) {
                try {
                    var t = o.generateKeyPairHex()
                      , n = t.publicKey
                      , i = e;
                    o.doEncrypt(i, n, 1)
                } catch (e) {}
            }(t);
        case "SM3":
            return function(e) {
                try {
                    var t = a(e);
                    return t
                } catch (e) {}
            }(t);
        case "SM4":
            return function(e) {
                try {
                    for (var t = e.data.data && JSON.stringify(e.data.data), n = "", i = 0; i < t.length; i++) {
                        var r = t.charAt(i)
                          , o = t.charCodeAt(i);
                        n += o > 127 ? "\\u" + o.toString(16).padStart(4, "0") : r
                    }
                    var a = A(n);
                    e.data.appCode && e.data.appCode !== u && (u = e.data.appCode);
                    var s = y(u, c)
                      , l = b(s, a);
                    return l.toUpperCase()
                } catch (e) {}
            }(t)
        }
    }("SM4", t)
},
t.data = JSON.stringify({
    data: t.data
}),
t
}

观察一下这行代码,每一个是不是都用到了t.data,可不可以删掉,是不行的,只能传一个参数进去,t.data是什么呢,是,载荷参数,但绝对不是复制下来了,因该就是正经的载荷参数。去搜一下

image.png 就是这个,它每一次刷新都不变,所以说可以写死。但是t.data,不好传参,t.什么什么,是不是就像取值,搜索一下t,t中肯定是含data的,但是删了很麻烦,很多报错,可以构造一个t,里面只含有data就行了

下一步 调试

image.png

s没有,但是s是时间戳,是一个无关紧要的变量,往上找一下,一定是有一个构造方法的,将其copy下来就行

image.png

运行,就出结果了

image.png

但是!!! 仔细看这个数据,发现,最关键的两个数据没有,但是代码没有报错,原因是try了一下

image.png两个都try了一下

把try删掉,再进行调试

image.png

少了m函数,常规操作,跳转复制

image.png

再运行

image.png

少了p函数,同理(这里我就不多说了,都是改都不用改的)

image.png

然后,调试的到后面,有一个c,参数,它是不变的,可以写死

image.png

然后就是一个o,这里可以把后面,点后面到括号一起看作一个函数,选中,跳转

image.png

image.png

image.png 跳转到这里,但是不能直接扣,这是这个案例的最难点,往上翻

image.png

缩一下,这是前端的一种打包方法,不能直接扣

image.png

得扣这一块

image.png

o就在这里面 image.png 然后,定义一个变量接收o,

image.png

image.png

4d09是什么呢?它是一开始跳转后的函数所在的模块,然后要做的就是把4d09这个模块扣到后面的花括号中

image.png 记得将这里o改成o1

image.png

再运行,又报错了,但是o没错了

image.png

这个报错是说少了东西,具体是错在t,打印一下t

image.png 它输出了这两个参数,其中4d09有了,少了6b54,少了就扣呗

image.png 扣完复制到4d09下面,再运行发现少了3864,然后就继续扣,等等等 这边有一种会便利一点的方法,就是一些看起来毫无关联的变量可以删掉,例如:

image.png这样,老手一眼可以看出来,新手还是老老实实一个一个扣吧

image.png

image.png

image.png是一个常数,可以直接赋值

然后,又是报模块错误,继续扣。

image.png

image.png 跳转一下,它属于另外一个模块,前面那么多模块都是由第一个模块引出来的,都是为了解决o1的问题,这个e也一样

然后,就出来了

image.png 还剩一个

image.png 这就是一个函数了,扣下来就行

image.png 这里u是一个变量,直接定义一个变量写死就行

image.png 然后y也是一个函数

image.png c是一个字符串,写死就行

image.png b是一个函数,跳转扣下来就行。

image.png 然后是s,s又是类似于这种模块的,像前面那样处理就可以了,这里不多赘述

image.png

e就是第二个模块变量,改成e_即可

image.png 然后全部都出来了

然后就简单了 首先不用多说肯定是读js文件,下一步,获取请求头参数

headers = js_code.call('get_headers')
headers['X-Tingyun'] = 'c=B|4Nl_NnGbjwY;x=0a316a2a808a47c4'
headers['User-Agent'] = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36'

获取载荷参数

js_code = execjs.compile(js_code)
data = js_code.call('get_datas', data1)

然后,发送请求

image.png

哈哈哈,得到了数据,也没完全得到,得到的是密文,欲知后事,且听下回分解