案例地址链接:https://gdtv.cn/channels/2
案例爬取链接:https://gdtv-api.gdtv.cn/api/channel/v1/news?beginScore=0&channelId=246&pageSize=11
一、入口定位
首先当我们拿到网站,并且找到我们需要爬取的目标url以后,我们首先复制url到【https://curlconverter.com/】网站生成基础的爬虫代码,并且在本地进行运行
先找入口,先找关于header逆向值的生成入口,这里可以通过关键字搜索什么的,但是是搜索不到的,所以我们使用请求堆栈,复制url的唯一标识,创建XHR断点
(放开所有的方法关键字,key关键字,路径关键字等等这些,最后还有一个好用的就是请求堆栈) 刷新一下页面,这个请求是通过刷新页面触发的,所以刷新页面触发目标请求
通过分析请求堆栈,来找到那几个逆向值的生成位置
通过各种方式比如key关键字,等都不能定位到该案例的入口,所以放开所有的关键字操作,很大概率就只能使用请求堆栈,做一个XHR断点
一层一层往下找
目标请求Ajax的最后一步,可以看一下这这里面有没有那几个值 找header相关的 最后一步肯定是有的,你就找好找的就行,前面有后面指定有
这里有上面看不看无所谓
下面的这里是个异步,断点已经下不来了
看见这个,就会想到拦截器,它有可能走拦截器吗?有可能,所以我们先打上断点,刷新界面先让断点给断住,
因为我想看异步下面的变量,但是由于异步的原因,断点下不来,所以我们只能重新打断点让断点断在该处再看这里有没有我们想找的这三个字段
当断住以后,优先查看一下断住的链接,确定是不是我们需要找的目标值,其实再看e变量也是包含这三个逆向值的
这个地方有这几个生成值,说明什么?说明和拦截器没关系,拦截器是需要继续往下走,才和拦截器有关系,这个是传进来就包含了,所以就和拦截器没关系,我们需要继续往前找
这里是一个异步,我们就需要打上断点,看一下这个里面是否有我们需要的那几个headers
到Promise这里的时候,参数也都已经生成了,所以还需要继续往前找
这是一个then操作,也是异步操作
看到then就需要明白,then左边是一个动作,右边是一个动作,左边也是一个异步,执行完左边的就自动执行右边的,典型的异步操作,then操作
所以只能看then执行之前的,再往前看,看then前面的,所以就需要给then这一行加断点,把其他地方的放开,看then左边的执行结果
备注:前端的逗号运算符
这里是前端的逗号运算符,返回逗号后面的操作结果
不管()里面放多少值,都是返回最后面的那个值
then右边的执行的过程中headders:t 中的 t 是包含这几个字段的,所以我们还需要往前看,把then中的断点去不取消掉,然后在then这一行上打上断点,刷新界面定位到该处,并且网上追述可以发现,t 来源于响应,谁的响应,就是then前面执行的返回值。
总结:可以确定return (0,c.default)(n, e, s).then((function(t) then左边(0,c.default)(n, e, s) 是逗号运算符 并且在传进来的参数(n, e, s)中不包含我们需要破解的三个字段,但是在then左边运算完以后返回的结果function(t) 中的参数 t 中却包含这三个参数,所以一定是在default这个方法中做了一些什么操作生成了这三个加密字段所以我们进去看一下,看什么做了哪些操作。
二、代码分析
里面是switch-case 平坦流,控制流 异步操作里面其实都是这种东西,我不管你要干什么走哪里,我也懒的分析,我就之际把每一个return都打上断点,你走哪里,你就给我断住就行了
走完这个0,一定会往下走走7,不要说不往下走,不往西走就是外面的断点卡住了,影响了,需要把外面的断点全部都取消,就会自动往下走走7
逗号运算符,执行执行一下执行到最后一步,把m的运算值进行返回,=7 就是执行7 如果获取上一步的返回值就是e.sent
0是步骤1 7 是步骤2 这个e.next = 7 就是0做完了,就做7 步骤1中一定有个返回值,逗号运算符,返回m运行的结果,返回交给谁,在case 7中有个e.sent 就是接受上一步的返回值 xxxx.sent就是上一步的返回值 以后在异步的switch-case中,看到xxx.sent就是上一步的返回值,,是一个具体的语法不会叫什么名字,只会叫xxx.sent
所以查看可知,答案就在m中,所以在m函数处加断点,重新刷新界面重新触发,到目标位置
m函数进来又是一个promise 看不懂,看不懂就把这个遮挡上
n有没有可能,从逻辑上当然有可能,但是进去看了以后,就会发现也都是取值什么也都没干
所以重点基本上就在e.apply中,所以进入到e里面,就在这个里面了。 进入e里面又是一个控制流
在控制流了,就在return 这里打断点
关键是这个W.a,就和往期不一样了,往期不管你用什么方式都是JS代码,悬浮w.a点进来的是一套指令,像汇编一样的指令,这个就是被封装的一个核心运算,形成的一个wasm的代码,这个就是接下来我们要研究的东西,浏览器执行不了C C++ 当时当把这些转成Wasm以后,浏览器就可以执行了,,我们的本地是node,node中也可以执行
就是需要我们认识这是wasm的文件,指令文件,用于提升性能,
遇到这样的WASM,有两种方式,方式一,找到他们的加密处理逻辑使用纯算的方式进行完成,方式二,就是今天要讲的补环境,通过一些逆向不环境的逻辑给补出来
我不管你是不是你是不是WASM,我就直接把你当作是往期的JS案例,直接扣JS,
报什么错误,补什么环境,以上的这些操作和不涉及WASM的操作是一样的
M有一些操作,也都给带上
到这里,就是关键点了,就是破解WASM最关键的地方了,最核心的位置,这个W是什么,如何去还原,就是我们学习WASM逆向的关键
w是什么呢,我们需要找到它的声明位置,需要先找到它在哪里赋值的
w.export 是关于w模块导出的,所以只有这里和这个地方最相似,并且其他地方也由于作用域的作用都不是
补一下JS模块导出的语法
打印一下,这个结果就和本地执行报错的地方就都对上了
对上了,所以A.exports 就是咱们的目标 w来自于A,A的导出属性,A来自于哪里,A是传参
我们就需要网上看,看谁调用传递的A,所以我们在请求堆栈中网上看,找到调用的地方,发现C就是A C来自于Q,Q来自于A.sent 来自于上一次的返回值,所以我们只需要拿到下面图标中的返回值就有了Q 有了Q就有了C 有了C就有了A
所以上一次的返回值就 I 还有B有关系
fetch就等价于python的request 请求模块 发送请求用的
B来自于一个函数,I和B都来自于哪里都需要打上断点,看一下
先把B,执行先把代码扣下来
I就是一个url地址,
这个网站一定会有一个发送关于WASM的一个url请求,把那个WASM指令文件,下载到本地来,供JS使用
所以这个I就是返回的那套WASM的指令数据
带着I和B 就进入t0方法
所以进入q,q又是一个平坦流往下看,就是WASM
因为5是空,所以最后得到的是这个的返回值
这个库,把WASM这个指令,编译成可以被JS执行的一个代码
下载完以后直接保存到本地,然后类似python中的open一样直接读
使用短的那个直接执行本地的WASM文件即可,那个长的就需要和fetch相互结合才可以
因为这个东西是不变的,所以直接保存到本地,直接读本地的数据即可
如果使用长的,就把那个长的URL传进来就好了,该案例使用的是本地的WASM文件所以不需要
返回是异步,异步拿结果如何拿,这个需要学一下
ret就是前面的返回值,就是那个Q
下面就是Q出来了
以上的就是w已经搞定了,下面就是把补环境补依赖完成就好了
有了w以后,在执行就是报k,就是开始各种补补补依赖了
当看到这个unreachable的时候,基本的变量函数就搞定了,大概率就需要补环境了,
当看到这个unreachable的时候,代表着进入了一个新的阶段,大概率需要补环境 了 这也是我们WASM比较明显的一个信号
其实当执行到这里,代码虽然不在报缺少环境的各种错误,不提示不代表没有错误,实际上还是缺少一些依赖,这个时候
我们需要观察一下直接搜索,搜try
然后try--finally 无所谓,我们需要找try--catch
因为它其实会在这里报错,但是会被catch给消化掉,所以就不会报出来来
所以我们就在这个函数中加上这个log打印一下这个错误 ,知道这个错误来自于那个函数即可
finally可以不管,我们只需要找catch即可
这个时候在运行就会把刚才代码自己处理的错误都爆出来,然后我们往下看就会发现需要补环境了,但是再往下看还有个需要补的依赖
首先我们需要想着这个try--catch 把他的这个错误全部拿出来
其次 看到报的错误,不要上来就跟着报的self window什么的上来就直接补环境,因为这么补下去会越补越来,需要往下翻翻会发现还有一些隐藏的变量没解决 类似E什么的
所以我们需要找E 还有个x p 直接搜索x= p= 找不到就加个function
剩下的在执行报的错误,就是全部是self window 这些唯一的环境错误了 到此为止,依赖是补完了
现在就是报self 和win找不到,我们就开始进行补环境,最简单粗暴的是直接写window = {} 这也是补环境
但是为了更逼真 ,所以我们在该案例中进行补环境的时候,还是按照类还原的方式进行补 模拟的是类的概念
在浏览器这一端,window是一个顶级变量,window是等于self 等于top的 这三个值是一样的
我们补环境 一是补浏览器应该能够调用的 类似 window 这些前端八大对象
另外代码也会自动检测,这套代码不想被node执行 会检查你这个里面有没有 global process
它这个站点就做了很多这样的检查,我们需要把node中常用的关键字给删除掉
备注:为什么你知道是删除这两个呢?因为需要去读那个wasm那个指令,这个后面会深入的玩,目前先不讲解
添加完代理监控以后就吐了一个环境
顶级变量window和全局变量的关系
因为刚才报self和window所以我们就直接补上了,但是还是报环境问题,这个时候我们就需要进行监控,把这常见的八大对象都进行监控
在这八大对象中,document和nov是用的最多的,仅次于window
优先补location 因为document里面有location的属性
还是报错,还是报环境的问题,那就继续进行补八大对象中的其他的