本帖最后由 牛bi的阿三 于 2021-4-26 04:30 编辑
目标网站:https://www.mafengwo.cn/
分析原因:没有__jsl_clearance_s=1619352365.545|0|%2F%2F1VJvQukl0gJLXekrvooalEOyE%3D,不能正确响应首页
1.目标Cookie
2.打开浏览器->输入目标网址->打开->按F12打开开发者工具->点击APPlication->按Del清除所有Cookie->打开Fiddler抓包
3.抓到完成流程
4.开始分析
//可以清楚的看到流程,请求两次都是红色,第三次才成功,那么看下第一次请求是什么情况,返回了一段JS.可以清楚的看到是设置Cookie的(document.cookie=),用工具解密看下!
//解出来后发现解出来的Cookie是第二个包发送的
//那么第一个包算法搞完了,下面开分析第二个包
//第二个包明显看到返回的是混淆的JS,那么看下第三个包提交的和第二个包提交的Cookie是否一致
//明显后面的js是不一样的,那么开始分析第二个包的js,在浏览器搜索Cookie的键名__jsl_clearance_s
//搜不到,那么把这个JS复制工具用IE浏览器执行来调试
//上面的script不要
//复制到工具点IE执行
//在第一行下段,不然这个网页一直刷新,然后单步一直走
//走到这里进入进去分析一下,这里有Cookie的主要参数,进入之后一直单步走,注意看变量值
//走到这里之后看到已经出完整的Cookie了,那么进入
//var _0x2e254d = _0xa486ab[_0x3130('0x67', 'e*F]') + 'P'](_0x43887f, _0x5eadc4['ct'], _0x5eadc4[_0x3130('0xaa', '*^gB')]);
_0x43887f是个函数,也就是调用这个函数计算出来的,那么单步进入到这个函数去一探究竟
由于已经走过了,那么直接在这个函数内部下断。刷新重新让他断在这里!
//这里看到他传入了下面2个参数,这2个参数肯定是要参与计算的。继续分析...
//由于是for循环,我选择直接断在返回,可以看到_0x11a510变量的值已经是完整的__jsl_clearance_s,那么这行代码就是组合这个Cookie的关键代码了,分析这行代码
_0x11a510 = _0xa486ab[_0x3130('0xaf', '@o53') + 'F'](_0xa486ab[_0x3130('0x31', 'oywh') + 'b'](_0x580680[0x0], _0x5eadc4[_0x3130('0x1a', 'cJ9L') + 's'][_0x3130('0x6b', 'QEoB') + 'tr'](_0x3d1767, 0x1)), _0x5eadc4[_0x3130('0x6c', 'Cr5j') + 's'][_0x3130('0x0', '7T5i') + 'tr'](_0x25f05a, 0x1)) + _0x580680[0x1];
我的妈耶,这也太长太绕了吧,拆开来看看
a=_0xa486ab[_0x3130('0x31', 'oywh') + 'b'](_0x580680[0x0], _0x5eadc4[_0x3130('0x1a', 'cJ9L') + 's'][_0x3130('0x6b', 'QEoB') + 'tr'](_0x3d1767, 0x1))
b=_0x5eadc4[_0x3130('0x6c', 'Cr5j') + 's'][_0x3130('0x0', '7T5i') + 'tr'](_0x25f05a, 0x1)
_0x11a510 = _0xa486ab[_0x3130('0xaf', '@o53') + 'F']( a,b )+ _0x580680[0x1];
这样看起来是不是好多了。
继续还原..
用鼠标选中这段代码,发现执行结果指向了一个函数,点击上面那个蓝色的进入这个函数。
进入函数之后发现这个函数只是做加法而已,那么将上面还原的代码再次还原
_0x11a510 = a + b + _0x580680[0x1];
下面来还原一下a和b的混淆代码;
a=_0xa486ab[_0x3130('0x31', 'oywh') + 'b'](_0x580680[0x0], _0x5eadc4[_0x3130('0x1a', 'cJ9L') + 's'][_0x3130('0x6b', 'QEoB') + 'tr'](_0x3d1767, 0x1))
鼠标选中它,看到计算结果是:"1619361344.42|0|ba%2F"
b=_0x5eadc4[_0x3130('0x6c', 'Cr5j') + 's'][_0x3130('0x0', '7T5i') + 'tr'](_0x25f05a, 0x1)
鼠标选中它,看到计算结果是:"5"
再看这个尾巴的值是多少
_0x580680[0x1] = "g6LOgIWTj%2FTDYWOvNtdud10%3D"
那么最终结果就是"1619361344.42|0|ba%2F"+"5"+ "g6LOgIWTj%2FTDYWOvNtdud10%3D" = "1619361344.42|0|ba%2F5g6LOgIWTj%2FTDYWOvNtdud10%3D"
看第三个包的提交Cookie和这个是否一致
经过对比是一样的,那么它和传入的参数哪里不同;
"1619361344.42|0|ba%2F5g6LOgIWTj%2FTDYWOvNtdud10%3D"
发现1619361344.42|0|ba%2多了个F 和 5
那么找下F和5的来源就行了,继续还原a
a=_0xa486ab[_0x3130('0x31', 'oywh') + 'b'](_0x580680[0x0], _0x5eadc4[_0x3130('0x1a', 'cJ9L') + 's'][_0x3130('0x6b', 'QEoB') + 'tr'](_0x3d1767, 0x1))=
看到_0xa486ab[_0x3130('0x31', 'oywh') + 'b']只是一个相加的函数而已,那么还原后为
a=_0x580680[0x0] + _0x5eadc4[_0x3130('0x1a', 'cJ9L') + 's'][_0x3130('0x6b', 'QEoB') + 'tr'](_0x3d1767, 0x1)
从打印出来的数据看 _0x580680[0x0] = 1619361344.42|0|ba%2
a="1619361344.42|0|ba%2" + _0x5eadc4[_0x3130('0x1a', 'cJ9L') + 's'][_0x3130('0x6b', 'QEoB') + 'tr'](_0x3d1767, 0x1)
_0x5eadc4[_0x3130('0x1a', 'cJ9L') + 's']= "LQ5SjsVqzJejKHAiiCkbFR"
a="1619361344.42|0|ba%2" +"LQ5SjsVqzJejKHAiiCkbFR".[_0x3130('0x6b', 'QEoB') + 'tr'](_0x3d1767, 0x1)
接下来看这个[_0x3130('0x6b', 'QEoB') + 'tr']是什么
那么是个substr函数
a="1619361344.42|0|ba%2" +"LQ5SjsVqzJejKHAiiCkbFR".substr(_0x3d1767, 0x1)
接下来看_0x3d1767
这个相当于是易语言的计次循环的第二个参数用来记录循环次数的
写到这里已经快坚持不下去了,不知道怎么表达了!实际很简单
那么也就是计次循环取"LQ5SjsVqzJejKHAiiCkbFR"的某一个字符
现在来分析b
b=_0x5eadc4[_0x3130('0x6c', 'Cr5j') + 's'][_0x3130('0x0', '7T5i') + 'tr'](_0x25f05a, 0x1)
b="LQ5SjsVqzJejKHAiiCkbFR"[_0x3130('0x0', '7T5i') + 'tr'](_0x25f05a, 0x1)
现在来看[_0x3130('0x0', '7T5i') + 'tr']是什么
和a一样
b="LQ5SjsVqzJejKHAiiCkbFR".substr(_0x25f05a, 0x1)
现在来找_0x25f05a
也是循环的,可以清楚的看到,就是两层循环!取同一个文本,但是位置不同,来组合,
_0x11a510 = "1619361344.42|0|ba%2" +"LQ5SjsVqzJejKHAiiCkbFR".substr(_0x3d1767, 0x1) + "LQ5SjsVqzJejKHAiiCkbFR".substr(_0x25f05a, 0x1) + _0x580680[0x1];
最后找这个_0x580680[0x1]
_0x11a510 = "1619361344.42|0|ba%2" +"LQ5SjsVqzJejKHAiiCkbFR".substr(_0x3d1767, 0x1) + "LQ5SjsVqzJejKHAiiCkbFR".substr(_0x25f05a, 0x1) + "g6LOgIWTj%2FTDYWOvNtdud10%3D";
OK,既然他是循环取得 怎么知道取得哪个是对的呢,继续往下看
可以看到这个if如果成立,就返回了,说明这里是判断怎么取才知道是取对的。
if (_0xa486ab[_0x3130('0x84', 'JL[M') + 'X'](_0xa486ab[_0x3130('0x59', 'gu9M') + 'K'](hash, _0x11a510), _0x794b03)) {
return [_0x11a510, new Date() - _0x2d6d11];
}
现在来看 _0xa486ab[_0x3130('0x84', 'JL[M') + 'X'] 是什么
_0xa486ab[_0x3130('0x84', 'JL[M') + 'X'] 只是一个判断参数1和参数2是否一样而已,那么参数1和参数2 就是重点了
参数1=_0xa486ab[_0x3130('0x59', 'gu9M') + 'K'](hash, _0x11a510)
参数2=_0x794b03
参数1="fa580dbb1f26f7519ba894c47e1924fc21c5db86" = sha1("1619361344.42|0|ba%2F5g6LOgIWTj%2FTDYWOvNtdud10%3D")
长度是40位根据经验他是sha1,也可以跟进去确定,但这里就不用了,因为在go(那里可以看到是写明是sha1的
然后看参数2
参数2=_0x794b03
参数2="fa580dbb1f26f7519ba894c47e1924fc21c5db86"
也就是看 sha1("1619361344.42|0|ba%2F5g6LOgIWTj%2FTDYWOvNtdud10%3D") = "fa580dbb1f26f7519ba894c47e1924fc21c5db86" 就返回了,秘钥也就是我们前面得出的 F和5
"fa580dbb1f26f7519ba894c47e1924fc21c5db86" 是上上张图里js自己返回的ct;
那么现在分析完了,把他关键的这个JS扣出来改改,
改造前:
改造后:
可以看到结果和上面的 参数1="fa580dbb1f26f7519ba894c47e1924fc21c5db86" = sha1("1619361344.42|0|ba%2F5g6LOgIWTj%2FTDYWOvNtdud10%3D") 结果一致;
加密类型会有变动 有md5的和sha256的,这个你们自己修改
改造后的js代码:
function getCode(arg0, arg1, arg2, arg3) {
arg0 = "LQ5SjsVqzJejKHAiiCkbFR";
arg1 = "1619361344.42|0|ba%2";
arg2 = "g6LOgIWTj%2FTDYWOvNtdud10%3D";
arg3 = "fa580dbb1f26f7519ba894c47e1924fc21c5db86";
for (var i = 0x0; i < arg0.length; i++) {
var v0 = "";
for (var i1 = 0x0; i1 < arg0.length; i1++) {
v0 = arg1 + arg0.substr(i, 0x1) + arg0.substr(i1, 0x1) + arg2;
if (SHA1(v0) == arg3) {
return v0
}
}
}
v0="error"
return v0
}
另外附上易语言写法,供大家学习;
变量名 | 类 型 | 静态 | 数组 | 备 注 | Str | 文本型 | | | Eval_data | 文本型 | | | Cookie | 文本型 | | | tmp | 文本型 | | | json | zyJsonValue | | | encrypt_type | 文本型 | | | ct | 文本型 | | | bts0 | 文本型 | | | bts1 | 文本型 | | | chars_key | 文本型 | | | encrypt_data | 文本型 | | |
Str = 编码_Utf8到Ansi (网页_访问_对象 (“https://www.mafengwo.cn/”, , , Cookie )) Eval_data = 文本_取出中间文本 (Str, “cookie=”, “;location”)调试输出 (Eval_data )tmp = 计算表达式 (Eval_data )tmp = 文本_取左边 (tmp, “;”)Cookie = Cookie + “;” + tmp Str = 编码_Utf8到Ansi (网页_访问_对象 (“https://www.mafengwo.cn/”, , , Cookie )) 调试输出 (Str )tmp = 文本_取出中间文本 (Str, “;go(”, “)”)json. 解析 (tmp )bts0 = json. 取文本 (“bts[0]”)bts1 = json. 取文本 (“bts[1]”)ct = json. 取文本 (“ct”)chars_key = json. 取文本 (“chars”)encrypt_type = json. 取文本 (“ha”)encrypt_data = getEncryptCode (chars_key, bts0, bts1, ct, encrypt_type )如果真 (encrypt_data = “”)调试输出 (“计算出错”, encrypt_type )返回 ()Cookie = 子文本替换 (Cookie, 选择 (文本_取出中间文本 (Cookie, “__jsl_clearance_s=”, “;”) = “”, 文本_取右边 (Cookie, “__jsl_clearance_s=”), 文本_取出中间文本 (Cookie, “__jsl_clearance_s=”, “;”)), encrypt_data, , , 真)调试输出 (Cookie )Str = 编码_Utf8到Ansi (网页_访问_对象 (“https://www.mafengwo.cn/”, , , Cookie, , )) 调试输出 (Str )写到文件 (取特定目录 (3 ) + “aaaa.log”, 到字节集 (Str )) |
getEncryptCode | 文本型 | | |
chars_key | 文本型 | | | | bts0 | 文本型 | | | | bts1 | 文本型 | | | | ct | 文本型 | | | | encrypt_type | 文本型 | | | |
变量名 | 类 型 | 静态 | 数组 | 备 注 | encrypt_data | 文本型 | | | n | 整数型 | | | i | 整数型 | | | 计次循环首 (取文本长度 (chars_key ) + 1, n )计次循环首 (取文本长度 (chars_key ) + 1, i )调试输出 (取文本中间 (chars_key, n, 1 ) + 取文本中间 (chars_key, i, 1 )) encrypt_data = bts0 + 取文本中间 (chars_key, n, 1 ) + 取文本中间 (chars_key, i, 1 ) + bts1 如果真 (encrypt_type = “md5”)如果真 (校验_取md5 (到字节集 (encrypt_data )) = ct )返回 (encrypt_data )如果真 (encrypt_type = “sha1”)如果真 (校验_取sha1 (到字节集 (encrypt_data )) = ct )返回 (encrypt_data )如果真 (encrypt_type = “sha256”)如果真 (校验_取sha256 (到字节集 (encrypt_data )) = ct )返回 (encrypt_data )计次循环尾 ()计次循环尾 ()返回 (“”)变量名 | 类 型 | 静态 | 数组 | 备 注 | 脚本对象 | 对象 | | | result | 文本型 | | | 线程_初始化COM库 ()脚本对象. 创建 (“ScriptControl”, )脚本对象. 写属性 (“Language”, “JScript”)result = 脚本对象. 文本方法 (“Eval”, 表达式 )脚本对象. 清除 ()线程_取消COM库 ()返回 (result )
码字不容易,搞了3个小时才把这帖子写完,评分支持一下作者吧
来都来了支持一下呗
由于JS是动态了,所以提供了一份固定的JS,可以按照帖子去分析
下载下来学习用的调试js文件需要吧后缀改为html才可以哦
学习调试用JS.txt
(27.95 KB, 下载次数: 21)
|