声明:
本文章中所有内容仅供学习交流使用,不用于其他任何目的,严禁用于商业用途和非法用途,否则由此产生的一切后果均与作者无关!若有侵权,请添加(wx:wyqlxl99)联系删除
前言:
这段时间摆烂了、有点不知道自己该干嘛了 陷入了迷茫,然后听群友问起某讯滑块的动态明文数组顺序怎么搞?动态key要怎么获取?一开始我也听过这个滑块但是好像补环境比较方便一点,抱着探索的心态开启下面的逆向旅程.
通过接口的堆栈直接定位到加密的位置,然后往里面跟可以看到window.TDC.getData(!0)就是生成collect参数的调用方法
再往里面跟就可以跟到熟悉的tdc.js文件,这里面是一个jsvmp,既然是vmp我们先找一下主入口、堆栈、操作这些都是怎么做的
单步往下跟几步就会跳到这个地方,可以看到这个R就相当于ip即指向下一个要取的字节码,w则是存贮字节码的数组,G可以看到是存放操作函数的数组,那这一部分的操作应该是根据R取w中的字节码,然后从G中到字节码所对应的函数执行,如果存在返回值则会跳出这个for循环 否则将一直执行这段操作。
这里我们只分析动态明文数组如何构造,加密部分就不多说了,我们找到+操作的部分打上日志断点h[h.length - 2], '+' ,h.at(-1) 注意!断点里面不能用h.pop()因为日志里面的代码是执行了如果你跟网页上一样在日志中使用了pop则会打乱vmp堆栈的执行顺序导致报错!
滑动滑块等日志输出完毕,我们可以在控制台看到一共四个部分组成其中第一个部分属于环境数组、第二部分则是轨迹、第三部分也是环境数组里、第四部分则是setTdcData方法设置进去的
其中第一部分和第三部分的环境顺序是会根据不同的字节码去改变的、因为这个文件是动态的所以每次解析的字节码都是不同的所以每次生成的环境数组顺序是动态的,我们在下面这个位置插桩'push',H[0][H[1]],H可以看到,我们要的环境值都来自于一个37数组,看操作应该是一次取出37数组里的对象执行get方法获取到响应的环境值。
对于37数组以及刚才的四部分,确实补环境比较方便,如果我们要搞算法的话需要处理几种情况:
第一:我们需要拿到37数组每个闭包方法的起始ip,这样的话我们就可以根据起始ip写一个vmp或者利用他本身的vmp执行根据执行里面操作的特征来判断当前这个方法是属于环境检测的哪一条
第二:我们需要找到他切割的点,就是第一部分和第三部分中间会被切开那这个切开是按什么去切的?
第三:动态的key数组我们要怎么获取?
一步一步来首先我们要先获取到37数组,那么怎么拿这个37数组呢?我们划完执行这个方法单步跟进去,控制台输出h查看堆栈,可以看到在走整个加密之前37数组就已经生成了,那说明这个37数组大概率是在vmp初始化的时候已经生成!
跟栈的过程就不说了直接控制台搜u.appendChild(d)下个断点然后重新触发滑块之后点script断点一般点1-2下就回到tdc.js文件开始加载的地方,这个时候就可以插桩分析找到37数组的位置
其实可以拿到37数组的位置有很多,我找了下面这个位置用来拿我的37数组,当然这是在浏览器上,浏览器上当然可以拿到37数组我们要做的是如果在本地拿到。
我们先把整个文件拿下来放本地,然后在我们找到的位置写好判断并且设定一个全局变量用来把37数组给取出来,在初始化完vmp之后打印一下arr37.
直接执行发现还是空数组?难道我们写的判断错了没有取到37数组?刚才我们说是浏览器上取到的,本地要取的话是不是会缺了一些环境呢?
那我们怎么知道少了一些啥?我们要的是执行拿到37数组就行就是要保证初始化vmp完整运行,最起码在我取到37数组之前不要报错!所以我们在catch的部分打印一下因为啥报错了
然后补了十几行我们发现37数组就已经有值了.
我们依次执行可以看到有返回值,但是有些是空有些是0,这个我怎么判断当前这个方法是取了哪一块环境呢?
还记得我上面是如何获取到环境数组部分的值的么?对就是一样插桩然后用网页的跟本地的进行对比,一一对应我们就可以知道这部分实际的值是什么然后推出大致是取得哪部分的值。
但是单凭这一点还不能够完全确定,所以我们要在vmp里面动手脚,我们找到这个部分下面这部分是将字节码转换成字符串的操作我们写一段输出。我们找第五个执行可以看到我们的返回值是[undefined]但是实际值是720,我们可以看到我们刚才日志输出的位置打印出来screen,height
那我们是不是可以在他输出height这个特征的时候写一个判断然后抛出异常,走异常处理再把异常信息返回出来.
再次执行的时候可以看到返回的信息就变成我们抛出错误的信息了,这样我们就可以判断当前这个索引所对应的是哪一块的信息,再写一些判断就可以完美的还原环境数组了,建议有一些简单的环境可以直接补上对于dom监测点一些很恶心的操作就不管了
后续我差不多补了80行左右不涉及子节点的添加删除,一些乱七八糟的dom操作,成功获取到了动态key已经相关的动态环境,关于动态key可以根据K[K.length - 2] = K[K.length - 2] + K.pop()部分观察规律写出相对应的判断代码将其存下来
仔细观察你可以发现有这一段字符串,这一段其实就是我所说的第二部分轨迹加密的加密值,这就是为什么我没有调用window.TDC.getData(!0)也可以拿到动态key的原因,而且这个部分就是分割动态环境数组的分割点(一开始我想着是不是根据某个值处理判断),那一切就变得很简单了,我的处理方式是讲这段索引的所对应的值改成动态key数组值,后面根据这个动态key数组分割,前面的部分为第一部分,动态key数组为第二部分,分割后的部分为第三部分,最后setTdcData的部分为第四部分。
运用到实际代码中,嗖的一下errorCode:0 成功啦!后续能不能用就没有继续测试了
有兴趣的可以加入我的星球后续会持续分享和更新!