BOOKWALKER 在线阅读器图片提取笔记
文章目录
【注】本文最后更新于 March 8, 2021,文中内容可能已经过时。
好久没写博客了,水一篇文章
受人请求帮忙提取 BOOKWALKER 里的图片。这类提供在线阅读方案的服务商为了防止用户拷贝可谓是绞尽脑汁,它们服务器返回的图片甚至是这样的:
将图片分割为一个个小块并打乱,在客户端再进行恢复并画到 canvas 上, 防止通过抓取请求这种简单方式直接获取到图片,密集+某些地方不均等的分割也让人肉还原成为几乎不可能的事情。
通过 canvas 提取
作为聪明人,我当然不会选择硬杠还原算法。我的第一反应是——从 canvas 里导出图片不就行了吗?
答案是不行,Firefox 告诉我「The operation is insecure」
…………
看着这个报错我的内心非常无语,作为 debugger 竟然连绕过安全检查的特权都没有吗?!明明右键都可以保存!
查了一下资料,貌似也没有关闭这个检查的开关,也许借助 headless browser 可以做到(后来发现确实有人用这种方案实现了),但我个人并不是很喜欢这种过重的方案,pass!
逆向还原算法
作为聪明人,一条路走不通就得换条路走。于是我打算试试从 js 中逆向出还原算法。
但是看到源代码的瞬间,我皱起了眉头
|
|
什么鬼,这里面怎么连个正常的字符串也没有??
花了半天我才弄懂,原来这里面的字符串全部被替换成了 $IlII("l", 377)
这种形式……现在的 js 混淆真是原来越越先进了……
不过值得庆幸的是,这些字符串生成函数是全局定义的纯函数,因此只要写段代码在浏览器里 eval + replace 就能还原出字符串。 现在代码可读性一下就上来不少了。
|
|
然而,连字符串都整成了这个鬼样子的混淆器,在其他方面显然也不会弱。就我能看出来的,这个混淆器还做了这些事情:
- 将部分没有副作用的语句块提取成一个函数
- 不直接调用函数,而是塞到一个 map 里,再辅以随机的 key
- 函数参数统统缩成两个,一个 this 一个 arguments
- 常量展开
- ……
又花了半天的时间,我终于……放弃了这个方法
如果有谁想顺着这条路走下去的话,这有一份我分析了一半的 viewer_image.7z, 其中第 81467 行即为核心的解密函数
Hook
聪明人总是善于发现新的路径,为什么我放弃逆向了呢,一方面是逆向确实麻烦,另一方面我想到了新的方法。
在上一步中,我试图通过看网络请求的栈回溯来分析程序流程。可惜的是,每当我点击栈回溯的时候浏览器都会卡死……(后来我才弄清楚,智障 Firefox 不会主动为我格式化源码,于是它就试图直接为我定位到一个包含上百万字符的行,然后就没有然后了)
我以为是网络请求的栈回溯生成得有问题,于是打算找 canvas 操作的栈回溯。可惜的是 Firefox 并没有提供相关断点。那就只能自己打了,于是我 hook 了 CanvasRenderingContext2D 的 drawImage 方法,打印了一些日志,然后我的浏览器又卡死了……
趁着 Firefox 还没被 OOMKiller 干掉之前,我分析了一下满屏的 drawImage 日志,我发现这是客户端在进行图片的拼接,难怪会如此频繁地调用 drawImage。 嗯?
原来是借助 canvas 进行图片拼接的?想想也是,没道理放着现成的 canvas 不用去造一个图片处理库的轮子。
于是我意识到了还有一条更简单的道路——直接记录下 drawImage 的参数,然后在本地根据这些参数进行还原。
然后就没有然后了,这个方法确实非常简单,以下就是最终的两个脚本。
- userscript.js 用于打包下载图片及参数,在控制台执行
autoScoll()
后滚动一下等它慢慢下载完,再执行saveAsZip()
保存下来即可 - rerange.py 用于重新拼接图片,解压以后扔在同一目录执行