登录
原创

瑞数四代保姆级分析思路——(1)参数生成阶段

发布于 2021-09-14 阅读 5162
  • 爬虫
  • 逆向
原创

目标网站

aHR0cDovL3d3dy5mYW5nZGkuY29tLmNuLw==(base64解密)

找到第二层代码入口

拿到网页先下script断点单步跟到第一层函数入口
image.png
一个900多行的小型混淆代码包含了第二层代码的生成逻辑用你习惯的办法找到第二层加密代码的生成位置
image.png
你要真的这都找不到也可以记住控制流的位置反正这个不变的image.png
好了正式开始分析

分析加密前的参数生成逻辑

1-124行 参数定义
_$vw = _ts.aebi;k8是一个随机的5位数组 125-127行 加密参数数组生成_vJ
140 行 生成一个参数对应

var _$oD = _$A$[_$vJ[59]]
_$2t = _$A$.top[_$vJ[20]]

157 行 var u1 = _ts
190 行 跳入334行定义三个变量
439 行 定义第一个变量此处调用document.createElement方法生成一个对象节点
440 行 调用对象节点的getElementsByTagName方法,需要补环境
接下去进入while循环
442行开始的if else 直接跳入450行
直接进入控制流方法__$EE _$EE(135, window, msCrypto)
执行
471 _$x8=["msCrypto"]
335
353
335 行 最后第一个返回值内容位undefined未做特别操作
336 行 跳转到614行
614 行 调用document.charsetcharacterSet 可以直接写死utf-8不补环境
回到336行获取到第二个变量内容为 ‘’
337 行 跳转到403行生成一个时间戳
338 行 跳转到764行函数
765行生成一个空的128位数组
768行到782行给数组进行赋值

[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,-1,38,39,91,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,-1,126,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,127];
数组为0-127单中间有不分内容被替换
回到190行

191-194行依然是参数定义
195行跳入2019行
2019行给194行定义的对象绑定了四个属性

getClientDataInCookie: ƒ _$mb()
getServerDataInCookie: ƒ _$TA()
setClientData: ƒ _$gC(_$Jw)
setServerData: ƒ _$2t(_$Jw)
transferChannel: "cookie"

196行跳转至387行
388行校验window.addEventListener属性存在时进入正确循环,需要补环境
389行通过window.addEventListener给load时间绑定了一个方法

 function _$pf() {
        var _$0W = _$oD[_$vJ[21]](_$vJ[170]);
        if (_$0W) {
            _$dF();
            _$Gu(_$0W, _$vJ[412], _$TA);
        }
        function _$TA(_$Jw) {
            _$Jw[_$vJ[16]] = _$0W[_$vJ[551]] ? _$0W[_$vJ[551]] : "{}";
            _$KB(_$Jw);
        }
    }

回到197行,198行定义参数
199行trycatch 校验window.localStorage属性
202行跳转至1122行对localStorage对象执行了一部分操作没有校验直接运行
203,204行给window对象绑定了两个方法属性
205行到211行参数定义
212行跳转至1158行
1158-1160行定义一个都是-1的256位数组
1161-1170行对数组数值进行操作

	 for (_$EK = 0; _$EK < _$Au.length; _$EK++) {
            var _$TA = _$0o[_$vJ[0]](_$Au[_$EK], 0);
            _$eA[_$TA] = _$EK << 2;
            _$G$[_$TA] = _$EK >> 4;
            _$lJ[_$TA] = (_$EK & 15) << 4;
            _$0y[_$TA] = _$EK >> 2;
            _$OR[_$TA] = (_$EK & 3) << 6;
            _$dh[_$TA] = _$EK;
        }

213行跳转至1242行
1242行定义两个256位数组
image.png
1243-1246行对第一个数组进行赋值
image.png
1247-1253行对上面两个数组的32到126号元素进行操作并将ta数组赋值给另外一个参数
image.png
1254行定义一个变量并进行split操作转化为数组
image.png
回到214行214-219行参数定义
220行先执行第一个方法获取index页面中meta元素的content元素并在获取后将meta元素删除
然后跳转至1439行
1440行开始对之前获取到的content元素进行一系列操作后获取到一个mq数组
image.png
执行完成后回到221行
再跳转至1469行
1469行通过一系列计算将mq数组的第一位赋值给一个变量
1470行开始进行复杂的数组操作:
先跳转至1517行执行_Xz(1)获取到mq数组中的某个元素 将参数传递到1239行方法中 ![image.png](https://statics.sdk.cn/articles/img/202109/1001013_814ae7d8e9ae531e0770063410.png?x-oss-process=style/thumb) 接下去的逻辑分别执行 wy-->_p–>mV-->_SY四个方法
先进入第一个wy方法:
image.png
将之前传入的参数经过计算得到一个四位数组然后通过后续的计算将数组的后两位修改后返回
image.png
接着是第二个__p方法: ![image.png](https://statics.sdk.cn/articles/img/202109/1001013_814ae7d8e9ae531e8126462809.png?x-oss-process=style/thumb) 这方法好像无论什么时候都只会返回空先不管直接看下一个 第三个方法是_mV:
传入方法的参数第一个是2第二个是未定义
1268行赋值操作
image.png
因为第二个参数为未定义直接结束方法
所以这个方法返回值依然是未定义
进入第四个方法
image.png
接下来的操作将两个元素按照nu生成后传递到ta中
然后跳转到1370行
依然是对字符串的一系列操作
最后返回一个字符串
回到1471行接下去1472行依然是上述操作
image.png
得到ta的值
image.png
之后依然是变量定义然后因为mb和gc为空所以跳过直接执行下面
image.png
将一个元素定义为空数组
完成所有操作之后回到代码223行
跳转至2037行方法,将window对象作为参数传入
2039行获取window.document对象
2040-2049行参数定义附带一些环境要补
image.png
227行进入控制流
525
100:给window.b_onBridgeReady 绑定一个方法 483:给window.b_setup绑定一个方法
96:定义一个变量接受未定义的window属性
232:判断上面属性是否是未定义,如果是则循环ts++
353:跳出控制流
228行跳转至1704行
定义了两个空的四位数组并做变量初始化
229行给方法的prototype绑定一个对象
230-235行参数定义
236行校验window.localtion.href的前四位是不是http,补环境
237行第一个控制流
21:补环境window.navigator
3382行window.navigator.Useragent
3383行window.navigator.standalone(检测ios环境)不需要补
接下去控制流套控制流
image.png
第一个135的控制流:
471:image.png此处将传入参数按照逗号隔开变成一个数组参与后续操作
335:image.png
此处进行判断刚才生成的数组中每个字符串是否是window对象的属性一旦有存在的就返回1否则进入下一个逻辑
353:按照上面的逻辑如果没有在上面返回则此处返回未定义
第二个135的控制流:
335:return 1跳出
第三个145控制流
image.png
400: var P_ = _y0;
423:image.png
98:image.png
406:image.png
506:
image.png
353:跳出
3419行补navigator.webkitPersistentStorage
3420-3425行最后执行最后一个else逻辑
image.png
走入控制流:
322:image.png
控制流套控制流:
145控制流和上述执行逻辑一致
直接跳出
353跳出
3426行检验环境window.chorme和window.chorme.runtime直接写死true
3427-3433环境监测但是不执行直接删掉
3434行判断false直接写死
3435-3445全部都是false 建议写死这么多环境大概补得完
3451行再进入控制流
501 变量定义
220 依然是定义
232没啥意义的跳转
440
image.png
谷歌浏览器window没有这个成员方法直接走catch
4849行image.png
这个属性谷歌浏览器依然没有所以这个控制流依然没事发生
503:跳出
81:
$Fb=undefined
406:无意义跳转
83
大量的153全是undefined
6再次进入控制流
466:依然是undefined
232:无意义跳转
530:参数校验但是浏览器并没有执行return 1所以不用操作
353:跳出
406:同上
321:依然是undefined
80:无意义跳转
194:定义fb的不过浏览器依然是undefined
406:同上
185:还是undefined
406:同上
536:还是undefined
406;同上
454:



446:再次进入控制流
223:再进控制流:310
image.png
133定义
228:再进控制流169,153 retuen false(写死吧)
最后返回内容也就是true还是写死吧
进入后查看这三个地方的运行逻辑
image.png
image.png
理解下这三个运行浏览器下第一第三个应该返回undefined而node环境下你会把你的文件名和地址吐出来,而第二个在浏览器上应该是true而node上你会返回异常,自己按照浏览器写死吧
406:同上
534:fb undefined
232:无意义跳转
275:控制流
501:var 定义
317image.png
定义
366:image.png
定义
184:3965行获取window.navigator又来了
3966行true
3967行执行image.png
完成后跳出所有控制流
第二个控制流开始执行一些无关的定义
image.png
此处重写window.clearInterval方法注意补环境否则走不进去
一系列操作生成一个这样的数组
image.png
第三个控制流向定时器中推入一个控制流盲猜无限debugger在此处生成
第四个控制流给对象绑定了一个方法
image.png
第五个控制流定义一个参数
完成所有控制流
242-257行参数定义
258行判断window.location.protocol是否是https如果是的话在FSSBBIl1UgzbN7Nenable=true
后面加上; Secure
275行 流程很长主要是检验浏览器环境。主要检测鼠标移动,输入,抬起,按下等信息就在这里。检测的并不严格。

到此为止参数生成基本完成整个瑞数的cookie生成来说大概完成了20%

评论区

励志做一条安静的咸鱼,从此走上人生巅峰。

0

0

0

举报