网址:aHR0cHM6Ly93d3cuZG9jODguY29tLw==
某文档网站使用加密的文件格式渲染文字,清晰度极高,且可以选中,故猜测数据包中含有文字信息。
可以看到当页面渲染完毕后是一个单纯的canvas画布
删除网络记录,进入下一个页面,查看调用的包,可以看到ebt格式的请求
关键js为wmu.js
调试过程
进入wmu.js,共5610行,给发送ebt请求的位置下一个断点
断住后可以看到作用域里_kY即是网址位置,搜索定位该位置,可以看到发送请求函数
可以看到,接下来请求获取的response被扔进了一个二进制object Blob,这一段在node里直接用fs库即可,_6H又被放进了_q1[0]里,追_q1即可
可以看到new了一个FileReader对象,FileReader需要先readAsXXX才能onload,所以继续往下搜索,可以看到就是_6H而已,赋值了个寂寞。
接下来是一段参数的赋值,但是_I8并未定义
搜索发现是前面的_k1 == "initHeader"才会触发的一段初始代码,好吧,下断点,重新刷新页面。
不难发现,其实这儿的代码差别不大,应该是一段初始时的代码,那我们先看这一段就可以了。
可以看到,这里需要Module._malloc,我也不会wasm,所以前面所有生成函数都给扣到js里了,1100多行,还好。
载入wasm的地方看一下,后面全是。
那只能全扣进去了,最终还是把5000多行代码扔到了js里。不过wasm文件加载的地方肯定要换成自己的本地文件。
下个断点,看看他是如何载入wasm的,其实都是标准的wasm引入流程,自带nodejs环境的加载,那我直接把文件地址改成wmu.wasm即可
运行发现有一个H5的api,postMessage,随便定义一个console.log先试试,发现成功运行初始化
那么继续扣init里的代码,先看看能不能成功生成_wC,发现没有什么问题
涉及到postmessage地方都不管,是js间通信用的,主要初始化数据就是这两个,扣进代码
我们来整体看看这段调用到底在做什么?
initHeader和后续多个getPage对应的内容即为总的一个ebt后其他分页ebt
代码编写
首先,构造initHeader函数,用于初始化初始ebt
然后构造getPage函数,用于获取后续文字,其中_H0是当前页码
然后简单的合并以下看看。
成功获取当页文字。
油猴脚本
总结
其实没有什么混淆之内的,写的很清晰,主要是我不懂wasm这一类东西,之前几个网站涉及wasm都直接尝试找到wasm调用失败时的js加密代码(很有效)。
问题与展望
1.这里面的函数都是异步,包括扣下来的createWasm,套了不少异步.then来初始化wasm。但是python execjs调用js似乎不能等待异步完成。如何解决这一问题呢?之前我写的都是在最后一个.then开一个端口,写了一个简单的网络接口来与python传递信息,虽然能用但不是什么好方法,如何做呢。
2.现在的文字有些乱,因为网页生成画布同时利用了ebt中的文字和文字位置信息,是否可以利用生成的文字和文字位置,生成可复制pdf。