JS 逆向:追踪某网站Ajax钩子加JS混淆的反爬流程

背景

JS 逆向真的是一门技术活,有一个公众号已经做成了高价的付费课程。奈何经费有限,下不了决心购买。所以就把课程所有能试看的视频都看了一遍,窥得了一些 JS 逆向技巧,对我这个小白来说,还是很开眼界的。

今天继续跟踪某招标网站的反扒流程,利用 JS 的单步调试功能,成功定位到了 ajax 发送请求前对 URL 偷梁换柱的地方,也是一大进展。

条件断点和堆栈定位

之前可以断定就是 ajax 请求中存在钩子事件,导致请求 URL 参数变化的,但一直没找到证据。偷学到一些 JS 逆向技巧之后,利用条件断点和堆栈调用链,终于定位到了。

第一步,在 Sources 右侧调试面板中,开启 Ajax 任意请求断点:
在这里插入图片描述
第二步,刷新页面,进入断点函数中,是 jquery.min.js 这个文件,点击左下角 {} 格式化,就能清楚地看到断点停留的地方:
在这里插入图片描述
利用堆栈链,倒推查看调用方,是 ajax 的 send 方法:
在这里插入图片描述
这个 send 方法并没有修改 URL 参数,所以继续在前面 g.open 那里打断点,它解释的函数最终完成了对 URL 参数的重置逻辑。

注意:open 和 send 之前调用的方法,是动态变动的,每一次请求后这个函数名称也会变化,这里是 _$zh ,后面就变成其他了套路如此深,让我等小白只能望而却步!

重写 ajax 的 open

前面利用条件断点后,再单步调试跟踪,最终找到了 ajax 发送之前修改 URL 路径的方法,继续分析它的流程。

首先,网站的 send 方法存在钩子,在 ajax 的发送逻辑中,open 被解释为另一个函数【网页每次刷新,该函数名称都会变化】:
在这里插入图片描述
第二步,继续定位到 _$eg 函数定义的地方:
在这里插入图片描述
第三步,查看它的代码

function _$eg() {
    _$6f();
    var _$Rc = _$ep(arguments[1]);
    arguments[1] = _$Rc._$s3;
    this._$Wl = _$Rc._$Wl;
    return _$UA[_$uT[43]](this, arguments);
}

当心,这里存在障眼法,所见的 _6f() 函数并不是真实的函数,它被解释为:
在这里插入图片描述
在当前 JS 片段中搜索 _$CU 函数定义:

function _$CU() {
    var _$lh = [65];
    Array.prototype.push.apply(_$lh, arguments);
    return _$wV.apply(this, _$lh);
}

继续追 _$wV 是一堆很长的混淆 JS ,它并没有影响请求参数,暂时不管它。

修改 URL 的地方

后面那句 var _$Rc = _$ep(arguments[1]) 函数调用后,ajax 的请求的 URL 就变化了,增加了两个额外参数:
在这里插入图片描述

定位到这个方法:

function _$ep(_$SZ, _$uA) {
      var _$G_, _$uG = null;
      var _$Rc = _$SZ;
      function _$kw(_$Mj, _$jU) {
          var _$Rc = [];
          var _$fL = '';
          var _$nC = _$Fm(_$Q5());
          _$Rc = _$Rc[_$uT[4]](_$jU, _$Mj, _$uA || 0, _$nC);
          var _$eg = _$5Z(743, 6, true, _$Rc);
          var _$x$ = _$EJ + _$eg;
          _$uG = _$hx(_$4T(_$x$), 2);
          return _$aW[_$uT[9]](_$fL, _$3a, _$uT[3], _$x$);
      }
      function _$fL() {
          try {
              if (typeof _$SZ !== _$uT[6])
                  _$SZ += '';
              _$G_ = _$Vr(_$SZ);
              if (_$O0) {
                  _$SZ = _$RJ(_$SZ, _$G_);
              }
          } catch (_$Rc) {
              return;
          }
          if (_$G_ === null || _$G_._$R9 >= 4) {
              _$5Z(773, 6);
              return;
          }
          if (_$8H(_$G_)) {
              _$5Z(773, 6);
              return;
          }
          _$SZ = _$G_._$Sy + _$G_._$lJ;
          var _$fL = _$Rf(_$G_);
          var _$nC = _$fL ? _$uT[7] + _$fL : '';
          var _$eg = _$3f(_$91(_$nZ(_$G_._$$G + _$nC)));
          var _$x$ = 0;
          if (_$G_._$_B) {
              _$x$ |= 1;
          }
          _$SZ += _$uT[7] + _$kw(_$x$, _$eg, _$uA);
          if (_$fL.length > 0) {
              if (_$HV && _$HV <= 8) {
                  _$SZ = _$s9(_$SZ);
              }
              if (!(_$Zu & 1024)) {
                  _$fL = _$s9(_$fL);
              }
              _$fL = _$uT[62] + _$E6(_$fL, _$uG, 4);
          }
          _$SZ += _$fL;
      }
      function _$nC(_$Mj) {
          _$40(2, _$nP(5));
          if (_$uG === null || _$hS(_$G_) === false) {
              return _$Mj;
          }
          if (typeof _$Mj === _$uT[6] || typeof _$Mj === _$uT[615] || typeof _$Mj === _$uT[77]) {
              _$Mj = _$E6(_$Mj, _$uG, 5);
          }
          return _$Mj;
      }
      function _$eg(_$Mj, _$jU) {
          if ((_$Mj === 'get' || _$Mj === _$uT[247]) && (_$yA & 1) && (_$Zu & 8192) && !(_$G_ && (_$G_._$R9 >= 5 || _$G_._$_B))) {
              if (_$jU === _$Xm || _$jU === null || _$jU === '')
                  _$jU = _$uT[299];
              if (_$jU === _$uT[299]) {
                  return _$jU;
              }
          }
          return '';
      }
      _$fL();
      return {
          _$7W: _$Rc,
          _$s3: _$SZ,
          _$Wl: _$nC,
          _$Wm: _$eg
      };
}

跟到这里真的是无能为力了,这一堆不明所以的 JS ,可能就是传说中利用凯撒密码混淆过的 JS 。

启示录

第一,这里面如果断点停留事件过久后,即使是浏览器点击,也会出现 403 Forbidden 的问题:
在这里插入图片描述
可能这个逻辑中存在时间戳信息。

第二,直接调用一下 open 之前那个修改 URL 的函数,可以拿到后面的参数:
在这里插入图片描述

理论上逆向解释出上面这段 JS ,用 Java 实现这个 return 语句得到修正后的 URL ,就可以解决反扒问题了。难点在于怎么用代码在模拟 ajax 请求之前定位到当前页面返回的这个 open 钩子函数呢?人家可是动态生成的啊,还是得解密上面那段钩子函数所在的 JS 片段。

说实话,这个可比上一篇介绍的无限 debugger 手段高明多了,就算知道能调试,但实际上却是一本无字天书!神呐,救救我吧!

已标记关键词 清除标记
相关推荐
程序员的必经之路! 【限时优惠】 现在下单,还享四重好礼: 1、教学课件免费下载 2、课程案例代码免费下载 3、专属VIP学员群免费答疑 4、下单还送800元编程大礼包 【超实用课程内容】  根据《2019-2020年中国开发者调查报告》显示,超83%的开发者都在使用MySQL数据库。使用量大同时,掌握MySQL早已是运维、DBA的必备技能,甚至部分IT开发岗位也要求对数据库使用和原理有深入的了解和掌握。 学习编程,你可能会犹豫选择 C++ 还是 Java;入门数据科学,你可能会纠结于选择 Python 还是 R;但无论如何, MySQL 都是 IT 从业人员不可或缺的技能!   套餐中一共包含2门MySQL数据库必学的核心课程(共98课时)   课程1:《MySQL数据库从入门到实战应用》   课程2:《高性能MySQL实战课》   【哪些人适合学习这门课程?】  1)平时只接触了语言基础,并未学习任何数据库知识的人;  2)对MySQL掌握程度薄弱的人,课程可以让你更好发挥MySQL最佳性能; 3)想修炼更好的MySQL内功,工作中遇到高并发场景可以游刃有余; 4)被面试官打破沙锅问到底的问题问到怀疑人生的应聘者。 【课程主要讲哪些内容?】 课程一:《MySQL数据库从入门到实战应用》 主要从基础篇,SQL语言篇、MySQL进阶篇三个角度展开讲解,帮助大家更高效的管理MySQL数据库。 课程二:《高性能MySQL实战课》主要从高可用篇、MySQL8.0新特性篇,性能优化篇,面试篇四个角度展开讲解,帮助大家发挥MySQL的最佳性能的优化方法,掌握如何处理海量业务数据和高并发请求 【你能收获到什么?】  1.基础再提高,针对MySQL核心知识点学透,用对; 2.能力再提高,日常工作中的代码换新貌,不怕问题; 3.面试再分,巴不得面试官打破沙锅问到底,竞争力MAX。 【课程如何观看?】  1、登录CSDN学院 APP 在我的课程中进行学习; 2、移动端:CSDN 学院APP(注意不是CSDN APP哦)  本课程为录播课,课程永久有效观看时长 【资料开放】 课件、课程案例代码完全开放给你,你可以根据所学知识,自行修改、优化。  下载方式:电脑登录课程观看页面,点击右侧课件,可进行课程资料的打包下载。
©️2020 CSDN 皮肤主题: 代码科技 设计师:Amelia_0503 返回首页
实付 9.90元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值