前言
一个群友当时问了下这个网站参数的加密位置,后面自己也爬了爬试试。
由于寻找入口和补环境的时间相差太久,我竟然忘了是怎么找的入口了。
通过调试直接找到入口位置。
一、加密
寻找加密位置
直接对xhr请求的发起程序进行分析,在请求发起处打上断点,可以看到需要寻找的是Jk(Jk好啊) 的加密过程。在图示断点的前方刚好是Jk的赋值,把断点前移刷新页面。
这里发现Jk是在第二行的语句中变成加密链接的,现在跟进去看看。
单步跟进会进入到一个U函数,这个函数是负责将数字转化成字符串的,所以跳出去到具体函数。
可以看到实际上的代码是JQ(Jk,JR)的一个情况。
继续跟进可以看到JQ是‘uf’这个函数,他分别调用了’un’和’E’函数。
un函数在后续补环境的过程里,我做了整理,其实是一个验证函数,返回一个布尔值,正常情况返回true。
'un': function(Jd) {
return !(!Jd['protocol'] || (0 == Jd['protocol']['indexOf']('data')) || Jd['host']['match'](/(cloudauth-device|captcha-(pro-)?open).*?\.aliyuncs\.com$/));
}
所以来看‘E’函数,‘E’函数中会生成一个字符串JP,会被用于加密中。
JP生成Ju,此时的字符串和目标已经很接近了。
继续跟进到JF函数,在JF函数得到网页的链接后缀
然后再Jt函数中进行组合
补环境
首先是补完字符串转换的U函数,经过分析,t函数中的ur字符串列表需要经过处理才能得到正确结果,但在U函数中有一个反爬机制,需要对Function的’toString’进行一个hook,去掉本地‘toString’中的’\n\r’。这里用了GPT帮忙完成任务了。
const originalFunctoString = Function.prototype.toString;
Function.prototype.toString = function() {
funcString = originalFunctoString.call(this)
funcString = funcString.replace(/[\r\n\s]+/g, '');
return funcString
};
然后就是将代码复制到本地环境补全了,原始代码经过混淆加密后,以J[U(number)]的形式掩盖操作。其中J[*]是最里层的掩盖,包含了加减乘除,取余位运算,比较运算等等。J5[*],J4[*]是外层的掩盖,在他们的函数里调用J对象中的函数。
混淆实在太多,最后我选择了把一些函数中的J[U(number)]还原回去了,但也累死了
二、解密
访问请求返回来的是加密的字符串,同样需要解密才能阅读,在上段加密函数的分析中,同样确定了解密函数的位置。
解密部分在这,直接是DES
总结
如果您认为这篇文章有帮到您,可以给个赞吗?