猿人学反混淆刷题平台:https://match.yuanrenxue.com/match/2
# 第二题:抓取五页热度值,求和
# 打开控制台,看加密字段,发现有
debugger
反调试, 直接Never pause here
, 上一题讲过。分析请求参数,
cookie
里面的m
应该就是加密字段。#
cookie
加密, 我们直接hook
一下cookie
的设置先打一个
script
断点,主要是为了在cookie
生成之前做一些操作,source
->Event Listener Breakpoint
->script
然后到
application
下把cookie
清掉。接下来刷新页面,script 事件断点,每次加载页面的时候都会断住,点击下图右边的三角形,知道跳入加载当前页面的断点;在控制台输入下面的代码:
// 当 document 设置 cookie 的时候,将进入 debuuger
Object.defineProperty(document, "cookie", {set:function(){debugger;}})
# 进入
debugger
,查看堆栈,往上跟一个栈就是document
设置cookie
的地方.#
cookie
的设置就在这里,很明显是个ob混淆
,在控制台看出document
后面混淆的就是cookie
.# 可以一段一段选中分析加密的算法,前面几个混淆的函数都是参数追加的,就是为了混淆视听,略过... 直到看到关键参数
m
.# 分析后面的关键函数,看下面的图应该就知道生成逻辑了,
m = 32位乱码 + | + 1639128817000
._0x5500bb[$dbsm_0x42c3(iqOiQ0, QOiq0Q) + '\x47\x6b'](_0x313b78, _0x160e3a) / 生成一个32位的乱码
lOo0QQ = "|" // 连接符
_0x160e3a = "1639128817000" // 时间戳
# 鼠标选中前面的函数,发现函数返回的是
参数1(参数2)
的执行结果,即为_0x313b78(_0x160e3a)
的结果,所以直接抠出来_0x313b78
,放到脚本里运行.# 下面就是我们喜闻乐见的补代码环节,缺啥补啥.
# 发现
_0x5500bb
是个数组,直接搜一下_0x5500bb =
, 就定位到了生成的地方,等于 0x43 那个数组,把上面 0x43 的数组赋值全都抠出来#
# 扣到最上面的数组的时候,ob 的特点,数组生成之后,再加一个数组移位的自执行函数,记得一起扣下来
- 可以在函数最后看到数组被传进去了
# 补完上面数组和移位的代码,再次运行 ,发现无返回直接卡死,下面我们单步调试一下,因为是在加入数组移位才卡死的 ,所以直接再数组移位那里单步调试。
单步调试,发现代码对上面的
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;
# 运行代码,终于出现了久违的加密字段🤣,结果和浏览器生成的一致
# 前面那段代码注释掉其实也可以出现加密字段,结果一样的,不知道是不是这题的漏洞,注释掉代码,就不需要补浏览器环境了。