
30行代码,破解 SaveMyExams 笔记次数限制?
DiamondPie引子 - 万恶之源
最近也是到 CIE 复习周了,发现周围不少同学都在用 SaveMyExams 这个网站来复习,听说里边还有大佬亲自撰写的笔记
我一看,欸!我的 CPC 这不有救了!遂立即打开此网站,开工!
该说不说,这笔记质量挺不错,全程干货无尿点。
刚读完一篇笔记呢,网站提示我要注册。我寻思人家做公益的也不容易,防人机来爬自己的网站开个登录功能也无可厚非
在一通翻爬滚打之后,也是终于配置好了自己所有的科目。回主页一看,一排大字映入眼帘:
You've read 0 of your 5 free revision notes this week.
当时就顿感不妙,上了这家伙的当了!一周只能看五篇,这不明摆着看各位同学复习周急用笔记,所以搁这圈钱呢!
又翻了几篇笔记,果然,一个升级广告直接糊在我脸上,真的是演都不演了!

破解 - 逆向大法
破解的切入点其实很好找,原理很简单:网站会先读取你的笔记访问次数,然后将其显示出来,类似上图
通过 F12 大法,我们很轻松地找到了切入点,也就是这一段元素:
1 | <span class="JoinCTA_pronouncedText__gnYeK">2 of your 5</span> |
接着,我们只需要反向找到其读取访问次数的逻辑,就可以基本确认破解的难度。至于怎么搜索?很简单:对页面抓包,接着全局搜索你能看到的任何关键字
当你在凝视深渊时,深渊也在凝视你
经过一些合理溯源,再让左右脑互搏一阵子,最终的线索指向了这里:
1 | title: (0, |
根据常理推测," of your "这个字符串左边的,就是读取访问次数的代码部分了!
最终决战
随着逆向的深入,静态分析(看代码读代码)已经不能满足我们的需求了,这时候就需要打断点进行动态分析
动态分析的好处就在于,我们可以视奸程序每一步运行的过程,以及他们返回的结果

非常好!看来我们离真相近在咫尺!这里返回的 2,不就是已经阅读过笔记的数量吗?
让我们来分析最后一层函数,即这个 a.Gq() 方法…

答案已经水落石出:网站从键名为 SME.revision-note-views 的本地存储中,提取出了我阅读过的笔记信息
信息整理
至此,局部笔记访问限制的实现逻辑已经理清:
graph TD
A1[用户访问笔记页面] --> A2[前端检测 localStorage 中的访问记录]
A2 --> A3{是否超过限制}
A3 -- 否 --> A4[正常显示笔记]
A3 -- 是 --> A5[拒绝提供笔记]
A1 --> B1[本地抓取 SME.revision-note-views 的值]
A4 --> B2[新状态写入 SME.revision-note-views]
C6[持续清除 SME.revision-note-views] --> A2
classDef hack stroke:#F1C40F,stroke-width:2px;
class C6 hack;
理论存在,实践开始!
综上所述,只需要我们不间断修改这块本地存储,如将其一直写空值,就可以绕过这些访问限制啦
废话不多说,上代码…
1 | const keysToMonitor = ["SME.revision-note-views"]; // 如果需要屏蔽更多的键,可以在这里直接方便地添加 |
这就是插件中的核心代码。算上注释和空行,仅30行。至于插件中其他的代码,是用来删除页面上留着的那些牛皮癣广告的 ^w^
小结
这次的 Hacking 虽然看似很顺利,但其实也具有很大一部分的运气成分
就以这种情况进行举例,只需要服务端根据用户的 cookie 对他们的笔记访问数量进行跟踪,并在服务端进行数据的处理,那就基本上是坚不可摧啦!



