背景

近来,ChatGPT越来越受欢迎,给我带来了新的灵感。我计划在公司内部分享一下前端数据保护的相关内容。我正在寻找一些支持我的分享素材。其中有拼汐汐的anti-content的逆向破解!

PS:全部内容均只作研究所用,如有侵权,请联系我进行删除

目标网站:aHR0cHM6Ly93d3cudGVtdS5jb20v

正文

寻找校验接口与校验参数

话不多说,直接看接口请求,果不其然是有anti-content参数。

接口演示

开始搜索、找到2个位置

搜索方式

虽然这里填充了anti-content,但是这个接口并没有校验哦

postman测试接口

那找找别的接口看看,随便点点很快发现搜索接口的payload是存在anti_content,这次试试postman发送请求,确认该接口校验了anti_content

接口

这次找出来的位置比较多处,说明加密的接口数量可能比较多,那换个角度寻找,从调用栈找

搜索出来的位置

从堆栈一个个找,发现一些蛛丝马迹

堆栈

能看到这里就已经有参数了,打个断点,从调用栈一步步回去看

参数位置

定位到一个输出的点,后面比较难找因为涉及到一个promise

Promise中存在的

翻页前打下断点

显示这里的promise回调出来code

往前找堆栈一步步看

getRiskInfo函数

一直单步运行终于进到了传说中加密的地方

risk-control

水平有限,入口都找了好久(对于这种promise + generator的执行顺序得找到一种更高效的方式)

逆向

找到对应代码了,一看是混淆代码,那直接去网站反混淆试试发现,并不行!

那就爬代码下来一步步试吧,中途也看了一些拼夕夕的 文章,不过和这个还是有所区别毕竟时间过去那么久了,反爬代码也不断更新

不过发现其实就是一个函数执行的结果那就是 un函数。

un函数

用postman验证下这个token,发现是可以的 证明思路没有错

观察了一下整个文件发现是个webpack的模块,也就是说可以整个爬下来自执行。

从入口看

函数方法

思路就是整体运行试试看,发现Node下直接运行是存在报错情况,毕竟正常的反爬虫思路都会增加环境的检测机制,所以需要补环境。

我就开始补环境,补环境就不说了B站上也有对应的教学视频,挺不错的。不过后面我可能会采取直接浏览器执行代码的方式去验证下这段加密是否是正确的,避免补完环境后发现还是不行,就会出现「代码错误」还是「环境错误」的问题。

说下过程中遇到的问题点,以及解决思路

问题点1:补完环境还是错,不清楚「代码问题」还是「环境问题」

采取方式,整体代码放在浏览器环境执行,发现执行出来的也不行没法通过验证

思考:webpack的包变量都是内部保护的,然后不会存在外部变量影响的情况,初始化的过程看入参也是比较正常。

1、验证源码是否正确第一步,断点2个位置,函数初始化位置,挂在一个变量给un函数

2、webpack包加载完毕为止,断点执行un,验证un产出token是否异常,发现就算是源码执行也是异常的,所以思考到是不是有执行一些函数导致内部的变量发生了变化。

然后继续看发现,看到prototype 原型链挂载

var Wn = new cn; // 还有这个new对象的代码

找到这行代码直接断点采用proxy的方式监听这个对象的调用

proxy wn

发现wn确实被执行了 updateServerTime这个函数,直呼好家伙。然后在执行un前执行这个,发现代码在浏览器里验证通过,说明代码没有问题!

问题2:补完环境、验证代码也没有问题后还是不行!

此时心里还是有点打击的,找入口找了很久,补环境也学了一晚上,最终token一直不成功,简直怀疑人生了。

秉持着一定要搞完的态度,在午饭吃完马上继续肝!

对于浏览器执行目前的代码能够成功,Node环境执行不成功,说明环境还是有问题!

那还是一步步来,从debugger看环境读取

每一个global的读取都看了一下

环境

发现了一个buffer对象很奇怪,居然能读取到。在我印象中浏览器JS是没有buffer的,马上去验证了一波,发现确实是undefined

那位了定位到buffer那个使用的位置,采取了判断debugger的方式

这个代理方式也是借鉴了其他博主分享的

const ppp = function(o){
     return new Proxy(o,{
         set(target,key,value)
         {
             console.log('set',target,key,value);
             return Reflect.set(...arguments);
         },
         get(target,key,receiver)
         {
         		// 当key时buffer的时候 debugger
             if(key === 'Buffer'){
              debugger
              console.log('=====>>>>>>Buffer!!!')
             }
             console.log('get',target,key,target[key]);
             return target[key];
         },
         deleteProperty:function(target,key){
             console.log('delete',target,key);
             return true
         }
     });
 }

找到调用栈的上一步

debugger调用栈

一看就知道是环境判断的位置了

环境数组

马上去浏览器源码执行断点这个位置,把return的a拿出来写死看看

return

[0, 0, 0, 0, 0, 0, 0, null, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0]

然后跑一个token出来,执行完美成功!

后面发现只要把判断buffer那段屏蔽写死就OK了,其他的不影响

执行结果

运行结果

仅提供思路,不提供源码,切勿用作商业用途

结束语

太久没玩逆向,最终回顾一下发现还有很多提升的空间,解题思路可以更加灵活不一定解决反混淆,然后速度也可以提升一些。

感谢网上各种大佬公开之前的解题思路,参考学习到了很多东西。