zl程序教程

您现在的位置是:首页 >  Python

当前栏目

Python 爬虫进阶必备 | 某惠农网行情大厅加密参数分析

2023-04-18 14:53:30 时间

今日网站

aHR0cHM6Ly9tLmNuaG5iLmNvbS9oYW5ncWluZy8=

这个站来自读者投稿

看了下网站比较有分析意义,所以今天就分析下这个文章

抓包分析与加密定位

这个网站需要分析得参数如下

并且提交得参数里并没有特别需要注意得参数

可以通过上一篇提及得几种方法定位到参数加密的地方

不清楚得可以点下方蓝字跳转

Python 爬虫进阶必备 | 某器件商城加密参数 sign 的分析

我们通过xhr断点可以找到下面这个位置

进去之后就可以看到一段混淆后的代码了

并且在最后会生成我们需要得加密参数,并返回

所以我们需要搞清楚这个t.default都做了什么操作,并且参数是怎么来的。

加密分析

可以看到t.default传入了两个参数一个是e一个是head,最后也是把这个head返回回去的

这里的e可以理解为一个上下文变量,这里的head才是需要分析的重点

可以看到在刚刚进入这个方法的时候,head就已经有一些值了,并且这个值就开始参与接下来的计算了

要搞清楚加密,就先要把head里的值搞清楚

如果翻堆栈,因为经过了异步比较难定位,要找到head初始参数

第一、可以像上面说的翻堆栈,定位的代码如下

第二、可以搜索X-HN-JOB的值,就是那个一长串句子

If you see these message, I hope you dont hack us, I hope you can join us! Please visit https://www.xxx.com/job.html

这一长串的句子是不变的,可以快速定位

这里逐个打上断点就可以定位到参数的生成逻辑了

X-B3-TRACEID
toBase36(t.getTime(), 9) + toBase36(randomInt(0, 78364164095), 7)
X-CLIENT-TIME
t.getTime()
X-CLIENT-NONCE
newUUID = function(e) {
 var t = (new Date).getTime();
 return (e ? "xxxxxxxxxxxxxyxxxxyxxxxxxxxxxxxx" : "xxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxx").replace(/[xy]/g, (function(e) {var n = (t + 16 * Math.random()) % 16 | 0;return t = Math.floor(t / 16),("x" == e ? n : 3 & n | 8).toString(16)}))
 }
X-CLIENT-ID
X-CLIENT-ID = function(e) {
    var t = (new Date).getTime();
    return (e ? "xxxxxxxxxxxxxyxxxxyxxxxxxxxxxxxx" : "xxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxx").replace(/[xy]/g, (function(e) {
            var n = (t + 16 * Math.random()) % 16 | 0;
            return t = Math.floor(t / 16),
                ("x" == e ? n : 3 & n | 8).toString(16)
        }
    ))
}

获取完这个几个初始化参数之后,开始进入t.default这个方法计算x-sign的值。

这个方法的最后计算出一个I,这个I经过(0,c.default)()得到最终的结果

因为这个方法最后返回了一个很长的逗号表达式,所以我们直接从最后一步开始看

最后这里的I,未经过计算的时候是一长串字符串,像是 4 个 hash 的结果用!拼接起来了

这样就可以大概知道I是经过下面这个代码得出的

经过分析这个t又是遍历自P中的元素

所以我们分析的重点转而去分析P

继续向上,可以看到P由下面的四个元素组成

P = [F, A, $, T]

现在问题就可以拆成F, A, $, T是怎么得到的

所以继续向上看

可以看到大部分的未知参数都是由类似下面的三元表达式计算出来的

F = 1 === (y = D) ? (0,
            o.default)(v)["toS" + H("0x5", "7sY@") + "ng"]() : 2 === y ? (0,
            r.default)(v)[H("0x8", "up@!") + H("0x68", "%M3Q") + "ng"]() : 3 === y ? (0,
            l.default)(v)[H("0x11", "g0vo") + "tring"]() : void 0

要一个一个断点调试分析他们是经过了哪个表达式

这里感兴趣的可以自己分析下哈

我调试之后知道这四个参数都是经过了中间那个表达式计算出来的

这四个参数由可以变成下面的四行代码

F =  (0,r.default)(v)[H("0x8", "up@!") + H("0x68", "%M3Q") + "ng"]()
A = (0,o.default)(m)[H("0x14", "3MMx") + "tring"]()
$ =  (0,r.default)(w + _)["toS" + H("0x38", "voet") + "ng"]()
T = d[H("0x40", "%M3Q") + "mSt" + H("0x60", "oChJ") + "g"](W, !0, 16)["toU" + H("0x1b", "Cbz8") + H("0x22", "zwd1") + "d"]()[H("0x52", "wXa9") + "tring"](10)

以上代码反混淆之后是下面这样的

F =  (0,r.default)(v)['toString']()
A = (0,o.default)(m)['toString']()
$ =  (0,r.default)(w + _)["toString"]()
T = d['fromString'](W, !0, 16)["toUnsigned"]()['toString'](10)

这里就需要逐个拆出来分析了

参数 F

F 中未知的是vv是由V经过(V = (h = Q).nonce得到的

Q中的nonce就是上面传入的X-CLIENT-NONCE

X-CLIENT-NONCE经过(0,r.default)()处理后得出F

分析可以知道(0,r.default)()md5

分析思路见上次的文章

Python 爬虫进阶必备 | 某器件商城加密参数 sign 的分析

参数 A

A 中未知的是m参数,这个m参数由m = R = h.timestamp得到

这个h的参数是String(head[H("0x28", "g0vo") + "LIE" + H("0x49", "J7to") + H("0x53", "9GkD") + "E"])得到的

就是String(head['X-CLIENT-TIME'])得到的

这里的(0,o.default)()经过分析是sha1

分析思路见上次的文章

Python 爬虫进阶必备 | 某器件商城加密参数 sign 的分析

参数 $

$ 中未知的参数是w、_两个,由_ = E,w = V可以知道w就是X-CLIENT-NONCE,然后_ = E = h.deviceId

这里的h.deviceId就是head["X-CLIENT-ID"]

经过(0,r.default)()就是md5的计算得出

参数 T

这里的 T 传入了参数W

W = W['substring'](W['length'] - 16, W['length'] - 1)

这里只对W进行了剪切,主要的生成部分如下

 W = (0,o.default)(S + M)['toString']()

未知的参数是S,M,这两个参数可由S = j,M = R得出

R就是h.timestamp = String(head['X-CLIENT-TIME'])

j是一串字符串

j = h.secret = e[H("0x42", "&J@X") + "v"][H("0x2b", "jOT4") + "pp"] ? L : B ? N : G

上面一串字符串最终得到的是

H("0x4c", "aq3T") + H("0x59", "9GkD") + H("0x2e", "h2!t") + H("0x34", "3MMx") + H("0x13", "voet") + H("0xd", "xaTo") + H("0x35", "%M3Q") + H("0x15", "3MMx") + H("0x21", "&J@X") + "gnAcr"

反正就是混淆,然后解混淆然再拼接

这里的(0,o.default)()就是sha1,结果再进行了切片取倒数的16 位到倒 2 位为结果

这个结果再传入T

这里的T用到的算法解混淆为

T = d['fromString'](W, !0, 16)["toUnsigned"]()['toString'](10)

这里的T直接把算法整出来,然后调用就完事了

到这里P的四个元素就全部解出来了

之后的IP中的四个元素用!进行了拼接

将拼接的结果传入(0,c.default)()得出最终的结果

这里的(0,c.default)()分析结果为sha384,经过sha384的计算最终得出最终的sign

以上就完成了所有参数的计算

接下来带入Python中请求就可以了,我们来测试一下

好了,以上就是今天的全部内容了。