猿人学反混淆刷题平台:https://match.yuanrenxue.com/match/2


# 第二题:抓取五页热度值,求和

  1. # 打开控制台,看加密字段,发现有 debugger 反调试, 直接 Never pause here , 上一题讲过。

    分析请求参数, cookie 里面的 m 应该就是加密字段。

  2. # cookie 加密, 我们直接 hook 一下 cookie 的设置

    • 先打一个 script 断点,主要是为了在 cookie 生成之前做一些操作, source -> Event Listener Breakpoint -> script

    • 然后到 application 下把 cookie 清掉。

    • 接下来刷新页面,script 事件断点,每次加载页面的时候都会断住,点击下图右边的三角形,知道跳入加载当前页面的断点;在控制台输入下面的代码:

      // 当 document 设置 cookie 的时候,将进入 debuuger
      Object.defineProperty(document, "cookie", {set:function(){debugger;}})

  3. # 进入 debugger ,查看堆栈,往上跟一个栈就是 document 设置 cookie 的地方.

  4. # cookie 的设置就在这里,很明显是个 ob混淆 ,在控制台看出 document 后面混淆的就是 cookie .

  5. # 可以一段一段选中分析加密的算法,前面几个混淆的函数都是参数追加的,就是为了混淆视听,略过... 直到看到关键参数 m .

  6. # 分析后面的关键函数,看下面的图应该就知道生成逻辑了, m = 32位乱码 + | + 1639128817000 .

    _0x5500bb[$dbsm_0x42c3(iqOiQ0, QOiq0Q) + '\x47\x6b'](_0x313b78, _0x160e3a)		/ 生成一个32位的乱码
    lOo0QQ = "|"						// 连接符
    _0x160e3a = "1639128817000"			  // 时间戳

  7. # 鼠标选中前面的函数,发现函数返回的是 参数1(参数2) 的执行结果,即为 _0x313b78(_0x160e3a) 的结果,所以直接抠出来 _0x313b78 ,放到脚本里运行.

  8. # 下面就是我们喜闻乐见的补代码环节,缺啥补啥.

  9. # 发现 _0x5500bb 是个数组,直接搜一下_ 0x5500bb = , 就定位到了生成的地方,等于 0x43 那个数组,把上面 0x43 的数组赋值全都抠出来

    #

  10. # 扣到最上面的数组的时候,ob 的特点,数组生成之后,再加一个数组移位的自执行函数,记得一起扣下来

    • 可以在函数最后看到数组被传进去了

  11. # 补完上面数组和移位的代码,再次运行 ,发现无返回直接卡死,下面我们单步调试一下,因为是在加入数组移位才卡死的 ,所以直接再数组移位那里单步调试。

    • 单步调试,发现代码对上面的 removecookie 做了格式化检测,然后返回了 boolean 值,格式化之后会被引入一个死循环

      _0x4fc7b7 = function() {
            _0x4b96f6 = new RegExp('\x5cw+\x20*\x5c(\x5c)\x20*{\x5cw+\x20*[\x27|\x22].+[\x27|\x22];?\x20*}');
                      return _0x4b96f6['test'](_0x1acdca['removeCookie']['toString']());
                 }
      // 格式化之后此函数返回 false
    • 下面的一系列赋值和判断语句,把我引入坑里

      _0x1acdca['updateCookie'] = _0x4fc7b7,			//  _0x4fc7b7() = false
      _0x337245 = '',
      _0x53cb6b = _0x1acdca['updateCookie']();		//  _0x53cb6b = false
      if (!_0x53cb6b) {
          _0x1acdca['setCookie'](['*'], OQ1oqQ, IO0OOi);		// 进入此函数
      } else if (_0x53cb6b) {
          _0x337245 = _0x1acdca['getCookie'](null, QqQlQQ);
      } else {
          _0x1acdca['removeCookie']();
      }
    • 死循环,无限追加,到最后内存直接爆破,程序崩溃。。。

    • 两个解决思路,不要把 removeCookie 格式化,或者直接把上面那个函数返回 true

    • 单步调试补代码,又发现一处格式化检测的地方,断点打在此处,改完直接运行。

    • 终于又到了熟悉的 xxx not defined ,然后继续补,补完 _0x3c9ca8 的时候,代码又卡住不动了, 下面单步调试这个函数。

      这里我直接把下图中的函数注释掉,其实已经可以跑出来结果了, 但是我想看看他是怎么检测出我的代码的 (有点贱。。。)

    • 一步一步调太考验眼力了。。。又发现一处格式化检测,如旧干掉他,函数太长,直接改了 return 的返回值

    • 然后继续单步,又遇到了 navigator 的属性检测,可以从控制台看到就是 vendorSub ,直接补环境

      navigator = {}
      navigator['vendorSub'] = ''

    • 下面又对 node 特有的 global 做了检测,在代码里把 global 删掉。

      windows = global;
      delete global;
  12. # 运行代码,终于出现了久违的加密字段🤣,结果和浏览器生成的一致

  13. # 前面那段代码注释掉其实也可以出现加密字段,结果一样的,不知道是不是这题的漏洞,注释掉代码,就不需要补浏览器环境了。

更新于 阅读次数

请我喝[茶]~( ̄▽ ̄)~*

渣渣文 微信支付

微信支付

渣渣文 支付宝

支付宝