上一主题 下一主题
ScriptCat,新一代的脚本管理器脚本站,与全世界分享你的用户脚本油猴脚本开发指南教程目录
返回列表 发新帖

[逆向分析实战]一行代码破解道客巴巴复制?

[复制链接]

8

主题

124

帖子

162

积分

注册会员

Rank: 2

积分
162

活跃会员热心会员突出贡献三好学生猫咪币纪念章中秋纪念章国庆纪念章

发表于 2021-10-6 00:51:13 | 显示全部楼层 | 阅读模式
道客巴巴的防复制手段比较特殊,如果你研究过他的html,会发现文字是不存在页面中的,而是绘制在一个canvas里(可以理解为图片),当拖选文字时,实际是在canvas上方覆盖一个蓝色图层,使你产生一种选中了文字的错觉(选中了,但没有完全选中)。虽然常规方法无法取得文字,但vip却可以进行复制,这种效果的实现原理是首先请求加密文档,解密后绘制于canvas里,拖选文字时会记录图层的xy坐标,从而确定选择区域,以此推算出选择的文字是什么。这种如果要破解他的加解密算法,代码经过严重混淆,十分费时费力,我们大可以换个思路,通过修改某些关键值来取得复制权限,从而直接使用他的复制算法。
本文将以这个文档为例进行分析。随便选中一段文字,会出现一个复制、搜索、高亮等选项的框,我们先F12找到这个复制按钮,查看他的click事件。事件并不多,一般我建议从下往上看(因为上面一般是他的父级元素绑定的),点开最下面的事件,可以观察到这样的代码(记得按一下左下角的"{}"把代码格式化一下):
1.png
这里的copyText看起来极其可疑,可以打个断点跟进去看看,巧合的是,这个copyText甚至是个全局函数,可以直接在控制台里查看。跟进copyText后打个断点,点击复制按钮,断下来后逐行运行一下,结果第二行就找到了我们需要的东西:
2.png
甚至这个Core.Annotation.api._sX也是全局的,这不巧了吗?到这里其实已经可以写出脚本了,取得文字后就可以自己做一个复制函数,然后替换掉这个copyText,或者干脆自己做一个复制按钮。且慢,为什么我们非得自己实现逻辑呢?页面中不是有现成的吗?让我们继续往下看这个copyText。为便于说明,我把后面的代码简化一下:
  1. if (Core.Annotation.api._sX == "") {
  2.   //如果复制文本为空,生成复制文本
  3. }
  4. if (u_v == 1 || madif == 0 || Core.api._nk.sys == 1 || Core.api._nk.ownPublish == 1) { //条件1
  5.   if (logined == 0 && Core.api._nk.sys == 0) { //条件2
  6.     //要求登录
  7.   } else {
  8.     //正确的复制逻辑
  9.   }
  10. } else {
  11.   //要求vip
  12. }
复制代码
要进入正确的复制逻辑,就是要使条件1为true,条件2为false,这其实是一道逻辑题,观察2个条件中的相似部分,可以得出Core.api._nk.sys == 1即可。验证一下,直接在控制台中输入Core.api._nk.sys = 1,结果复制成功了,甚至右键复制和ctrl c复制也成功了(这些事件实际上都是copyText在处理)。这个Core是一个全局对象,Core.api._nk.sys可以直接在脚本中访问修改,刷新页面后路径也不变,可以说这样一行代码就达成了解除限制的效果。
代码看似无懈可击,其实还有一些问题需要解决。显然_nk是经过混淆后的键值,可以在控制台验证看看:
3.png
这种混淆通常是由工具自动生成的,而网站的js文件时常会更新,更新后文件版本号会变,而混淆的键值也可能会跟着变,也就是说,我们取得的这条路径是存在有效期的。你当然可以在失效后更新脚本手动修改一下,但总归不太智能,有没有可能自动获取呢?答案就隐藏在我们前面的分析中,想想我们是怎么取得Core.api._nk.sys的,是通过copyText函数,而函数是可以转换为字符串的:
4.png
只要对这段字符串正则匹配一下,不就可以得到_nk这个键值了吗?关于正则表达式的介绍这里就不展开了,网上教程有很多,我直接给表达式吧:/Core\.api\.(.+?)\./ 至于后面的sys是否经过混淆,可以控制台验证一下:
5.png
可以看出这是个正常的对象,sys没有经过混淆,也就不需要对其做正则了。关于这点需要说明一下,Core对象下不同部分的定义可能来自不同文件,而并非所有js文件都经过混淆,也有部分的键值是正常的(比如Core.api)。至此,我们的破解工作就已经完成了,一行代码即可解决问题:
  1. Core.api[copyText.toString().match(/Core\.api\.(.+?)\./)[1]].sys = 1;
复制代码
当然你也可以拆分成2、3行来写,说成一行有点炫技的嫌疑,本文的重点还是在于分析技巧上。

已有2人评分好评 油猫币 贡献 理由
陈公子的话 + 1 ggnb!
李恒道 + 1 + 1 ggnb!

查看全部评分 总评分:好评 +1  油猫币 +1  贡献 +1 

159

主题

1105

帖子

618

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
618
发表于 2021-10-6 09:58:22 | 显示全部楼层
哥哥教程还是蛮清晰的!一路看下来就能懂
混的人。
回复

使用道具 举报

8

主题

124

帖子

162

积分

注册会员

Rank: 2

积分
162

活跃会员热心会员突出贡献三好学生猫咪币纪念章中秋纪念章国庆纪念章

发表于 2021-10-6 10:19:20 | 显示全部楼层
李恒道 发表于 2021-10-6 09:58
哥哥教程还是蛮清晰的!一路看下来就能懂

这其实是个前置教程哈哈,后面还有一个复杂一点的,我整理整理再发。
回复

使用道具 举报

4

主题

99

帖子

36

积分

新手上路

Rank: 1

积分
36

中秋纪念章猫咪币纪念章活跃会员热心会员三好学生

发表于 2021-10-6 14:17:17 | 显示全部楼层
逻辑很清晰,读来有种举重若轻的感觉。说实话很需要这种 硬技术 类教程来开阔一下思维
回复

使用道具 举报

发表回复

本版积分规则

快速回复 返回顶部 返回列表