难点
代码混淆
、cookie 加密
,还有有点难度
Tip:例子:https://pan.bigdataboy.cn/s/5DvCq?password=phm69t
猿人学该题官网:https://match.yuanrenxue.com/match/5
分析参数
m
f
疑似时间戳,但不一样,也是需要注意的
[]
m
,RM4hZBv0dDon443M
这两个确定是加密值
分析 ‘m’ ‘f’
通过调用栈,发现
m
f
是直接赋值,都是通过 window 获取的
可以先上下翻翻,看看有什么需要注意的地方,这里用
Hook
来定位window._$is
(function() { 'use strict'; var value_; Object.defineProperty(window, '_$is', { // 修改_$ss为你需要查询的window属性 get: function() { console.log('Window Hook捕获到->', value_); return value_; }, set: function(value) { debugger; value_ = value; console.log('Window Hook捕获到->', value_); return value; }, }); })();
最终定位此处
_0x4e96b4['_$is'] = _$yw; // _0x4e96b4 就是 window _$yw = _0x2d5f5b()["toString"](); // _0x2d5f5b() function _0x2d5f5b() { return new _0x35bb1d()['valueOf'](); // _0x35bb1d 是 Date() 对象 } // 综上分析 _0x4e96b4['_$is'] = new Date()['valueOf']()['toString']()
继续通过 Hook 的方式,定位
window.$_zw[23]
(function() { 'use strict'; var value_; Object.defineProperty(window, '$_zw', { // 修改_$ss为你需要查询的window属性 get: function() { console.log('Window Hook捕获到->', value_); debugger; return value_; }, set: function(value) { value_ = value; console.log('Window Hook捕获到->', value_); debugger; return value; }, }); })();
最终定位此处
// $_aiding['$_zw'][7] ---> Date window.$_zw[23] = $_aiding['$_zw'][7].parse(new $_aiding['$_zw'][7]() // 所以 window.$_zw[23] = Date.parse(new Date())
接着是两个加密的 Cookie
也是采用 Hook 的方式先定位赋值的地方
(function() { 'use strict'; var cookie_; Object.defineProperty(document, 'cookie', { // 修改_$ss为你需要查询的window属性 get: function() { console.log('Get Cookie Hook 捕获到 -->', cookie_); debugger; return cookie_; }, set: function(cookie_) { cookie_ = cookie_; console.log('Set Cookie Hook 捕获到 -->', cookie_); debugger; return cookie_; }, }); })();
Hook Cookie 加密
m
值
_$Wa = _0x12eaf3(); // _0x12eaf3 function _0x12eaf3() { return _0x35bb1d[_$UH[0xff]](new _0x35bb1d()); // _0x35bb1d 是 Date _$UH[0xff] 是 parse } // 所以,但是还需要 加密把加密函数扒下来 _$Wa = Date.parse(new Date())
Hook Cookie 加密
RM4hZBv0dDon443M
值,就使用上面的 Hook 脚本就行
继续使用
Hook window
方式,来 Hook_$ss
,定位到此处,发现是AES 加密
寻找
AES
的Key Mode padding
值
// CryptoJS.enc.Utf8.stringify(WordArray) --> WordArray.init 对象转 Utf-8 _$UH[0x2e5] "ECB" _$UH[0x33c] + _$UH[0x33d] "Pkcs7" _0x4e96b4[_0xc77418('0x6', 'OCbs')] WordArray.init {words: Array(4), sigBytes: 16} _$Ww WordArray.init {words: Array(41), sigBytes: 164} CryptoJS.enc.Utf8.stringify(_0x4e96b4[_0xc77418('0x6', 'OCbs')]); "MTY1MDE5ODgxNjUy" CryptoJS.enc.Utf8.stringify(_$Ww); "37cdb337788229c60faf0aaffb2d6e65,0df6d975c6b74ba95888b9ac8f0b335c,c333e16a0ae6031b2a1c7be404fdc3e8,61eed28470638021cb96fd084d2f1899,57b5c27e56210e05f2eea98b3bfb0cdb"
经过几次的实验,发现这个
Key
是会变的
,所以还需要分析Key
是怎么来的,继续使用Hook Window
脚本
window._$qF WordArray.init {words: Array(4), sigBytes: 16} _0x4e96b4[_0xc77418('0x6', 'OCbs')] WordArray.init {words: Array(4), sigBytes: 16}
Hook
到此处,是Key
生成的地方,原来Key
是m
值而来
寻找
原加密
的值,继续使用Hook Window 脚本
来定位
可以发现前 四 个是循环此处添加的,时间戳后面是三个零
_$Wa = _0x12eaf3(); _0x3d0f3f[_$Fe] = 'm=' + _0x474032(_$Wa) + ';\x20path=/'; _0x4e96b4['_$pr']['push'](_0x474032(_$Wa));
第五个,在这里,时间戳后面不是三个零
try { _$yw = _0x2d5f5b()[_$UH[0x1f]](); _0x3d0f3f[_$Fe] = 'm=' + _0x474032(_$yw) + ';\x20path=/'; _0x4e96b4['_$is'] = _$yw; _0x4e96b4['_$pr']['push'](_0x474032(_$yw)); } catch (_0x3c2e99) {}
整理一下流程
参数 f 最先生成带三个 0 的时间戳 参数 m 是 加密时间戳数组 的 第五个未加密时的值 时间戳数组前四个使用 `Date.parse(new Date())` 方式获取,结尾有 三个零 时间戳数组前第五个使用 `new Date()['valueOf']()['toString']()` 方式获取 cookie 的 m 就是 参数的 m 加密而来 MTY1MDE5ODgxNjUy --> 由五个加密的时间戳 再进行 AES 加密而来
扒代码
用手撕的方式吧
定位到加密函数出
_0x474032
function _0x474032(_0x233f82, _0xe2ed33, _0x3229f9) { return _0xe2ed33 ? _0x3229f9 ? v(_0xe2ed33, _0x233f82) : y(_0xe2ed33, _0x233f82) : _0x3229f9 ? _0x41873d(_0x233f82) : _0x37614a(_0x233f82); } // 美化一下格式 function _0x474032(_0x233f82, _0xe2ed33, _0x3229f9) { return _0xe2ed33 ? // undefined _0x3229f9 ? v(_0xe2ed33, _0x233f82) : y(_0xe2ed33, _0x233f82) : _0x3229f9 ? // undefined _0x41873d(_0x233f82) : _0x37614a(_0x233f82); // 所以最终执行的是 `_0x37614a` } // 所以只需要 _0x37614a(时间戳)
然后把
_0x37614a() 函数
复制到本地,然后把所有缺少的函数补齐
function _0x37614a(_0x32e7c1) { return _0x499969(_0x41873d(_0x32e7c1)); }
这就是补完后的样子,然后运行,报错 提示
_$UH
未定义
打断点查看是个大数组,所以只需要这样补充就好
_$UH = { 15:'charCodeAt', 108:'length', 276:'fromCharCode', }
接着运行,报
_0x1badc3[_$UH[31]] is not a function
错,然后源文件该行断点,发现没有断住,说明没有执行这里,然后有个try catch
,断点看看
接着就是报什么错,就到原文件看是什么,对比着来,这里有几个值 需要注意,不然就算出值了也不能过,
_0x4e96b4['_$tT']
、_0x4e96b4['_$Jy']
,需要该函数计算cookie m
时才是正确的
验证
现在整个过程都清楚了,验证一下
版权声明:《 【猿人学】第五题 乱码增强 逆向分析 》为明妃原创文章,转载请注明出处!
最后编辑:2022-4-22 11:04:49