抓了半年多的裁判文书突然停了,查看log发现HTTP响应码全是202,分析页面发现原网站在cookie上做了加密。经分析正确的请求流程如下
1. 请求首页,返回两个set-cookie响应头,cookie名称分别为FSSBBIl1UgzbN7N80SFSSBBIl1UgzbN7N80T,响应码为202。响应体中有三段不明代码

<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
</head>
<!-- 1. meta['content']意义不明 -->
<body><meta name="renderer" content="webkit"><meta id="9DhefwqGPrzGxEp9hPaoag" content="{qqqqqr0.YUQeBgClraT6.dA28Ej3I1UKSbXlJ8NIUKxHc2UmGAqqkknLqqqqhvefgTey0JSvqkxJqkqLWqqqqk130r0HMvpQpmzDUlrUpmQ83oYJA2wDVVYY1mrWY0f3s2ptVlNp1aqqqqt1073741856VIJRJg9UB18SE49UPp8fH8h5lq2Y8psLYtXTCqAg2iGacfA3Tt9GOFqTs8GTGDCQwHGz5oKqQHAe4oO7h8mEBKcWqqqqhTrB4MbBgeoxqKGKR2zkG8iNtX0bwqfYF_uGc80qqqqr0qqDe5191aqqqqhb6rmecbj1Zrr4q{WYozbAKrlMPE9mOVpEiZygKFg3hxX_u.SidW64uobWi227DF_MXET5u6NJI74gv.axiEcePMvHIL_qqqqYDUvHttHp6whZmAp7KOQtW}{tPgKp0pIU0AtpYJcsagEUlJps2JlmANpsGAEYVpUpYTioaNA1TxHIAGCFAr7xGAWwAl8k67pUumcIlQ.D6xnhSSgVfzZDmg4DfzoD6a5KcrDWfEURnTmlm9dRn2PWS7TAOwGmVRXKcx9JULM3rRrHpLfrkJrlK3DlPwMrl9cF0gtD07cUaLUV20v8YShrYWSMSRZD90l8OSvxbzc8saEAG|qqU7aWVE0A9yYlv7CMX9T4THtVhmE4UX0Fjfh_vIdsiNUgCd3JJSPa6hZsZfcgVuLJzRXgkkhAWrC4uoKF82V.vbXKITtyVsSpIJvy9.SY5zYeuUlWzJG_lkrJwYoaucRQQg6y96Ch5rsnbU71HJ.nkkD85xjOoscMWRbGCiHUXy74mDJRW00e0.UV8f7ZDsBQIzOfuDJYjeBdCbXMhlCyCjW8hzMPlbWR_w.LKKFwywal7445"><!--[if lt IE 9]><script>document.createElement("section")</script><![endif]-->
<!-- 2. 意义不明的js文件 -->
<script type="text/javascript" src="4QbVtADbnLVIc/c.FxJzG50F.js%3FD9PVtGL=e5191a"></script>
<script type="text/javascript">
<!-- 3. 主要加密js代码,省略 -->
</script>
<script type='text/javascript' r='m'>
_$hr('ZoA8');
</script>
<!-- 4. 这段代码的作用是重新请求当前页面,分析时注释掉
<script type="text/javascript">window.οnlοad=function(){var _$n6=document.getElementById(_$fv('ondoal'));_$nR(_$n6.name,_$vD(_$n6,_$zb('HvzED2ExKa')));};</script>
-->
</body>
</html>
<script type="text/javascript">_$e3();</script>

2. 浏览器带着两个cookie再次请求原网页,响应码为200,得到正常页面,这次请求中cookieFSSBBIl1UgzbN7N80T的值与响应头中设置的值不一样,并且在一段时间后会自动更新。另外修改响应,删除Set-Cookie: FSSBBIl1UgzbN7N80T=...,浏览器在新的请求中仍会有FSSBBIl1UgzbN7N80T的cookie,猜测这个cookie的值是通过js计算得到,且会定时刷新。

也就是说只要破解cookie FSSBBIl1UgzbN7N80T的算法就可以了。

另外网上有人说这是用的瑞数的产品,介绍里有这样一段话

>通过对服务器网页底层代码的持续动态变换,令攻击者无法读懂攻击目标

也就是说这个产品只提供了动态混淆功能,真实的加密代码还是源网站实现的。也就是说只要提取出原来的加密逻辑就可以了。

## 准备工作

### 搭建离线分析环境

因为加密Js代码每次请求变量名都不一样,在线分析会很不方便,所以需要将文件离线下载到本地,再进行分析。

wget --mirror --page-requisites --adjust-extension --no-parent --convert-links http://wenshu.court.gov.cn/Index

python -m SimpleHTTPServer 8081

之后在浏览器中访问http://localhost:8081进行分析。

### 修改页面

为了分析方便,我们把加密js提取成独立的文件(保存为outer.js, 并在文件开头加上debugger;代码下断点), 并注释跳转代码。修改后Index.html代码如下

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
</head>
<body><meta name="renderer" content="webkit"><meta id="9DhefwqGPrzGxEp9hPaoag" content="{qqqqqr0.YUQeBgClraT6.dA28Ej3I1UKSbXlJ8NIUKxHc2UmGAqqkknLqqqqhvefgTey0JSvqkxJqkqLWqqqqk130r0HMvpQpmzDUlrUpmQ83oYJA2wDVVYY1mrWY0f3s2ptVlNp1aqqqqt1073741856VIJRJg9UB18SE49UPp8fH8h5lq2Y8psLYtXTCqAg2iGacfA3Tt9GOFqTs8GTGDCQwHGz5oKqQHAe4oO7h8mEBKcWqqqqhTrB4MbBgeoxqKGKR2zkG8iNtX0bwqfYF_uGc80qqqqr0qqDe5191aqqqqhb6rmecbj1Zrr4q{WYozbAKrlMPE9mOVpEiZygKFg3hxX_u.SidW64uobWi227DF_MXET5u6NJI74gv.axiEcePMvHIL_qqqqYDUvHttHp6whZmAp7KOQtW}{tPgKp0pIU0AtpYJcsagEUlJps2JlmANpsGAEYVpUpYTioaNA1TxHIAGCFAr7xGAWwAl8k67pUumcIlQ.D6xnhSSgVfzZDmg4DfzoD6a5KcrDWfEURnTmlm9dRn2PWS7TAOwGmVRXKcx9JULM3rRrHpLfrkJrlK3DlPwMrl9cF0gtD07cUaLUV20v8YShrYWSMSRZD90l8OSvxbzc8saEAG|qqU7aWVE0A9yYlv7CMX9T4THtVhmE4UX0Fjfh_vIdsiNUgCd3JJSPa6hZsZfcgVuLJzRXgkkhAWrC4uoKF82V.vbXKITtyVsSpIJvy9.SY5zYeuUlWzJG_lkrJwYoaucRQQg6y96Ch5rsnbU71HJ.nkkD85xjOoscMWRbGCiHUXy74mDJRW00e0.UV8f7ZDsBQIzOfuDJYjeBdCbXMhlCyCjW8hzMPlbWR_w.LKKFwywal7445"><!--[if lt IE 9]><script>document.createElement("section")</script><![endif]--><script type="text/javascript" src="4QbVtADbnLVIc/c.FxJzG50F.js%3FD9PVtGL=e5191a"></script>
<script type="text/javascript" src="outer.js">
</script>
<script type='text/javascript' r='m'>
_$hr('ZoA8');
</script>
<!--
<script type="text/javascript">window.οnlοad=function(){var _$n6=document.getElementById(_$fv('ondoal'));_$nR(_$n6.name,_$vD(_$n6,_$zb('HvzED2ExKa')));};</script>
-->
</body>
</html>
<script type="text/javascript">_$e3();</script>

### function hook

js中有几段很长的杂乱字符串,猜测可能是加密的js代码。而一般释放加密的js代码都是通过eval函数,所以我们需要hook它。在console面板中执行如下代码

orig = window.eval;
window.eval=function(str){debugger;orig(str);}
// 这段代码防止反hook的检测
window.eval.toString = function (){return orig.toString();}

另外为了分析meta#9DhefwqGPrzGxEp9hPaoag的content属性,执行如下代码添加断点

var dom_get_element = document.getElementById;
document.getElementById = function(id){if(id=="9DhefwqGPrzGxEp9hPaoag") debugger; dom_get_element(id);}

### 监视cookie变动

在Watch面板中添加document.cookie监视cookie的变动。

## 分析过程

### 释放变量替换表

在浏览器中打开http://localhost:8081/wenshu.court.gov.cn/, 运行到out.js第一行会在debugger处触发断点。单步跟进,在第18行触发了eval函数

_$tU[_$xH(101, 118, 97, 108)](_$bY(_$fv('mScBdId1eg4by76`TeugShBfzo.rNcva2COdfAI`wtMiRgUsYisepuH`Juhsxro_m`karh`l0gGtJSFr}ne`oremihar[o)elavpnyisclut`acslre `allcdlwvt` phnt`moOacienmrtnCop`JehTdmPo`tlsston`epvTls$lt#`_omatSeooaee`___suger@eeaaultv`.hprrtSgetcijeIntmeeb``SOBe`nr`ao``rcttt`p:`oxtcdconriSiene esyaokopppyirdAxAfSOFjrcb.un`emtTdec`iAtaecaeuatl`vd`beg$M`tt`bos`uo`tcilg`fnorCsatCedo`rphl``opli``tsneltNfNizeU liBhScFiutoe`a5`Za_lgrCp0aneafXn7tjoLeba9(P{Gn8tQvFc3dK]V`1xAzi5WFtqEcDlt___`rgmrvtIlec`l_sc_a`sayretcIneo`euwe3ixtysgmbd6aV`_owtCc`latce'), _$fv('fMXn49KE26OfLRGSmXasroZMmPl16kBsoQjPPs8oqAhSbglTjrijvsmkkafjulimrcbkhgmmemcnavgjgplhmafjpiqkahdk')));

这会在浏览器中释放如下代码

var _$mM="FSSBBIl1UgzbN7N",_$gn="length",_$k9="floor",_$cE="charCodeAt",_$m6="string",_$lf="slice",_$uO="uu",_$i2="substr",_$rK="_$",_$b4="Math",_$hX="log",_$mf="toString",_$jZ="fromCharCode",_$ir="apply",_$va="split",_$mm="assert failed with condition: ",_$kG="stack",_$fL="pop",_$jR="indexOf",_$aS="Object.InjectedScript.evaluate",_$kX="@debugger",_$ss="evaluate",_$jo="charAt",_$rM="getTime",_$el="number",_$cb="FSSBA",_$ah="Array",_$gq="prototype",_$g8="execScript",_$lP="eval",_$hs="call",_$po="replace",_$jA="functioneval(){[nativecode]}",_$vS="FxJzG50F",_$ng="qrcklmDoExthWJiHAp1sVYKU3RFMQw8IGfPO92bvLNj.7zXBaSnu0TC6gy_4Ze5d",_$mT="document",_$kP="location",_$h1="random",_$kk="setTimeout",_$is="setInterval",_$jQ="$_ts",_$aP="localStorage",_$mj="___ts___",_$fo="removeItem",_$pB="__#classType",_$q6="console",_$al="wP3dxhyJgpbC6tVm_ewcCO",_$dm="match";

我们将这段释放的代码保存到文件reference_map.js。

### 释放inner.js

在out.js中删除第18行释放代码,并把得到的reference_map.js引用进Index.html。继续调试,在180行有如下代码

var _$n6 = _$zk[_$vS];
if (_$n6) {_$zk[_$vS] = false;_$tM(_$n6);
}

其中_$n6的值为4QbVtADbnLVIc/c.FxJzG50F.js中那段很长的字符串。猜测_$tM函数将对这个字符串解密并释放。

在440行代码(_$tM函数中)_$mc(_$eG(_$qh.join('')));执行后,会发现cookie值被更新了。

分析发现_$eG(_$qh.join(''))的返回值一段文本形式的js代码,而_$mc函数的作用就是执行这段js。我们将这段js保存到文件inner.js。

### 调试inner.js

在Index.html中引入inner.js,去掉outer.js的断点并注释掉440行代码,调试inner.js, 发现inner.js释放了一个更大的变量替换表,其中cookie引用_$f0 = "cookie", 通过在inner.js搜索该变量,在所有更改cookie的地方下断点,进行调试可以找出cookie的计算逻辑。

cookie的值通过解密meta#9DhefwqGPrzGxEp9hPaoag的content属性得到。

在804行的 _$oc函数中有如下代码

function _$oc() {_$fM(_$sw, _$g9, _$u9);_$fM(_$sw, _$da, _$v9);_$fM(_$sw, _$kp, _$bV);_$fM(_$sw, _$aE, _$wV);_$fM(_$sw, _$vL, _$xm);_$fM(_$sw, _$sS, _$ta);_$fM(_$sw, _$s3, _$hb);_$fM(_$sw, _$an, _$xx);_$fM(_$sw, _$bJ, _$tI);_$fM(_$sw, _$qB, _$wE);_$fM(_$tU, _$is, _$sz);if (_$sw[_$bo]) {_$fM(_$sw, _$tf, _$sz);_$fM(_$sw, _$cl, _$sz);_$fM(_$sw, _$vQ, _$sz);}_$fM(_$tU, _$sl, _$vu);// window.addEventListener('load', _$tk), 即在页面加载完毕后更新一次cookie_$fM(_$tU, _$is, _$tk);// 每50秒更新一次cookie_$tU[_$hD](function() {_$uD(10);}, 50000);

根据变量替换表得出,这些代码注册了各种监听事件,并且通过interval定时更新cookie。

#### url中的MmEwMD参数

在每个请求的url后面都有个MmEwMD参数,

在console面板中执行

var xhr = new window.XMLHttpRequest();
xhr.open('POST','/hello',true);
xhr.send('abc');

会在请求的Url后面自动添加上这个参数

http://localhost:8081/hello?MmEwMD=1zXMRFfiFy00rBpdSoJ2cJ4EvS6mQ1dvl5jZLrqB…oRVu5t.x8Y3GVQLmqdG.lmuE2snbEk.YHif4rmHwOtKQoTiHpODCa6HikgWg1X2S._aq8rKTLr

猜测当前页面中的xhr被hook了。

通过查找inner.js释放的变量替换表并分析,定位到inner.js的8107行代码

function _$xc(_$v8, _$vz) {var _$xB = [];var _$mE = _$qS(6);if (_$mE) {_$xB = _$xB[_$lt](_$vz);_$xB.push(_$c9(_$v8) ? 1 : 0);var _$vT = _$h6() + _$mE + _$cR(_$xB);_$vT += _$tc(_$vT);return _$y5 + '=' + _$vT;} elsereturn _$y5 + '=';
}

这段代码的作用是计算请求url中的MmEwMD参数值。通过hook XMLHttpRequest的open与send函数,在发起异步请求时在url后面自动添加这个参数。

function _$dJ() {var _$v8 = _$tU[_$ld];var _$v8 = window.XMLHttpRequest;if (_$v8) {var _$vz = _$v8['prototype'];if (_$vz) {_$jv = _$vz['open'];_$ca = _$vz['send'];// hook open函数,在调用open时计算token并保存到sig属性_$vz['open'] = function() {arguments[1] = _$aY(arguments[1]);this['sig'] = arguments[1];return _$jv['apply'](this, arguments);};// 调用 send发起异步请求时,将sig添加到url。_$vz['send'] = function() {arguments[0] = _$uG(arguments[0], this['sig']);return _$ca['apply'](this, arguments);};}
}

## 总结

网站的加密逻辑大致如下:

1. outer.js释放加密参数,并解密c.FxJzG50F.js文件,得到静态混淆的js代码(inner.js)

2. 执行inner.js,解密标签meta#9DhefwqGPrzGxEp9hPaoag的content属性得到一个数组,再加上outer.js计算的两个参数计算FSSBBIl1UgzbN7N80T的值;

注册load事件在加载完毕后添加interval定时,根据已有的cookie值计算得到新cookie值(通过_$tk函数);

hook XMLHttpRequest的open与send函数,为页面中的请求自动添加token。

绕过方案:

因为cookie是通过定时自动更新的,而且请求的token也是通过hook在发起请求时自动添加的,所以如果让浏览器先加载首页,在首页中使用xhr异步请求,请求的cookie值与token会自动带上。所以我们可以找到一个可编程的浏览器就行了。

瑞数(裁判文书)js的加密分析相关推荐

  1. python 法律检索_Python爬虫进阶必备 | 某裁判文书检索网站加密分析与自动登录实现...

    抓包分析 先抓包分析一下登录的请求[图1-1] 图1-1 按照加密的参数,我们一个个分析. 首先是 _csrf ,这个参数比较简单,一般是用来防止跨域***的,感兴趣的朋友可以借助搜索引擎了解一下,不 ...

  2. 瑞数5药监局js逆向

    本次网址:www.nmpa.gov.cn 这是最后一篇四代五代瑞数的文章了,环境的话拿维普期刊的环境跑,稍微改下就能用,不会补的话看四代房地产的文章. 药监局的cook有效期有一段时效,拿到第二个ts ...

  3. js逆向之补环境过瑞数5.0某银河证券,你还在拿某药监局做案例?该换换啦.

    网址: aHR0cDovL3d3dy5jaGluYXN0b2NrLmNvbS5jbi9uZXdzaXRlL2Nncy1zZXJ2aWNlcy9zdG9ja0ZpbmFuY2UvYnVzaW5lc3NB ...

  4. 瑞数vmp算法还原流程讲解

    提示!本文章仅供学习交流,严禁用于任何商业和非法用途,如有侵权,可联系本文作者删除! 前言 ​ 又是很久没写文章了,今天水一篇文章吧,鉴于之前有看到过别人的文章被警告的案例,所以这篇文章就仅写一下还原 ...

  5. JS逆向之补环境过瑞数详解

    JS逆向之补环境过瑞数详解 "瑞数" 是逆向路上的一座大山,是许多JS逆向者绕不开的一堵围墙,也是跳槽简历上的一个亮点,我们必须得在下次跳槽前攻克它!! 好在现在网上有很多讲解瑞数 ...

  6. 【瑞数5】浅谈某普期刊JS逆向的环境检测点

    [瑞数5]浅谈某普期刊JS逆向的环境检测点 前言 JS加载流程 第一个JS 第二个JS 第三个JS AST简单解混淆 环境检测 前奏 异步执行JS流程 高潮 运行结果 总结 鸣谢 前言 这几天把某期刊 ...

  7. JS逆向——裁判文书网(详细图文步骤)

    写在前面:本篇博客很长,都是手把手一步一步的教程,跟着做就能出结果,文章总共分为以下三部分,我也会在3个部分中详细的说明步骤 (1)接口请求头参数验证 (2)接口响应数据DES3加密 (3)登录状态验 ...

  8. 【瑞数】维普期刊JS逆向4000字详细流程_1_获取接口签名

    文章目录 前言 过debugger 定时器debugger 死循环debugger 分析搜索接口 签名在何处生成? 中场休息 签名代码来源分析 签名代码在何处加载到内存? 注入代码 设置签名为全局变量 ...

  9. 【JS 逆向百例】某空气质量监测平台无限 debugger 以及数据动态加密分析

    关注微信公众号:K哥爬虫,持续分享爬虫进阶.JS/安卓逆向等技术干货! 文章目录 声明 逆向目标 写在前面 绕过无限 debugger 方法一 方法二 方法三 抓包分析 加密入口 动态 JS 本地改写 ...

最新文章

  1. Install Java 8 Ubuntu
  2. ubuntu makefile交叉编译报错:file not recognized: file format not recognized
  3. linux 补丁脚本,Linux上打patch补丁包脚本全解
  4. Booting Android: bootloaders, fastboot and boot images
  5. LPWA技术:发展物联网的最佳选择
  6. EXEC与sp_executesql的区别及应用
  7. mybatis学习(40):逆向工程的创建
  8. 前端调用后端接口的错误(400)
  9. 新能源维修和计算机应用哪个好,在买新能源车之前 这些事你应该先知道
  10. c#加mysql简单系统_visual studio2019连接MYSQL数据库详细教程(C#代码)
  11. 由嫦娥四号的中继卫星鹊桥,谈谈拉格朗日点
  12. Python实现类似局域网QQ群聊
  13. 【爬虫】用Python爬取《Nature》杂志文章的题目、摘要、下载地址
  14. python读二进制文件遍历_使用python反向读取二进制文件
  15. Java - 注解(Annotation)
  16. 手机远程启动汽车,汽车远程启动还是手机控制好!有一种远程手机启动热车系统非常的不错是什么功能知道吗?
  17. 起源地杯青年足球锦标赛
  18. keilC51编译常见错误和警告说明
  19. 【CVPR2021】记一次神奇的 Rebuttal 经历
  20. 华为 5G 欧洲崛起!

热门文章

  1. windows系统和linux系统可以使用相同的js代码吗_使用Sboxr自动发现和利用DOM(客户端)XSS漏洞...
  2. CSS3的弹性盒子flex详解(2)
  3. 【两种方法】基础实验4-2.7 修理牧场 (25 分)
  4. linux ctime 时间戳,Linux时间戳atime ctime mtime区别及相关命令
  5. 通用无线设备对码软件_电动车上的无线电池管理系统wBMS
  6. mysql 关联查询_响应时间长?MySQL查询优化教程来了!
  7. 学校不用考直接过计算机一级,全国计算机等级考试1级是不是必须要考的啊
  8. Mysql数据库(七)——mysql高阶语句(上)
  9. oracle %date 0 10%,“date:~0,10%“是什么意思?
  10. frp内网穿透-公网IP低成本使用高性能kali