“写笔记”支持四种格式——Word 文档、Excel 表格、Markdown、纯文本,起稿或二次编辑时都能随时切换,同一篇笔记想用哪种形态来记,都由你说了算。
md、txt、csv、json 这类纯文本则原样载入,不做多余加工。拿一张现成的表倒进来、改几笔、再导出去,等于白用一台免费的格式转换器。
要带走就在右上角点“下载”,可导出 PDF、Word、Markdown、Excel、TXT 等格式;列表卡片“⋯”菜单里,也有同样的下载入口。
在“工具”页点“+ 上传工具”即可发布:填好名称与链接,再用 Markdown 把使用方法写清楚——能解决什么问题、怎么装、怎么用,比堆介绍实在。
要分发安装包就一并上传压缩包(ZIP、RAR、7Z、TAR.GZ,最大 35MB),别人在详情页一键下载;只放链接不带附件也可以。
工具按大家的收藏热度排序,好用的自然会被顶上来。发布后可在详情页或卡片菜单里编辑、下架。
写笔记时勾上“隐藏”,这篇就只存在于你自己的账号里:不进列表、不进搜索、不上首页精选,也不会出现在任何公开的页面,链接发给别人同样打不开。
适合放密码、草稿、日记这类只给自己看的内容;想公开,去“发布”打开它,把“隐藏”的勾去掉再保存,之后编辑会默认保持原状态,不会悄悄变回公开。
你的内容会同时保存在多个副本上,系统定期做备份与完整性校验,再配合异地容灾机制:就算某台机器出问题,数据也不会丢,可以长期放心存放;特别重要的资料,仍建议你另外再留一份备份。
全站跑在容器化、模块化的现代架构上,更新、部署、回滚都很快,扩展性和稳定性都按长期运营的标准来设计(Built for reliability, designed to scale)。
这个网站最早只是一个人的笔记仓库,后来慢慢长成现在的知识中枢。设计上很克制——没有广告、没有追踪、没有推荐算法,只是干干净净地存放一些东西;既然做好了,就公开出来,万一有人用得上呢。
不做大而全,不做平台梦,保持简单、保持克制、保持好奇。所有内容都由用户贡献、由用户维护:不会突然冒出付费墙,不会在角落塞广告位,也不会把你的数据卖给第三方。
产品会持续迭代,站内日志页记录着每一次改动,改了什么都有迹可循;想了解这个站是怎么一步步走到今天的,翻翻日志就能看到来龙去脉。
如果在这里看到涉嫌违规的内容,点对应卡片右侧的“举报”按钮就能提交,我们会尽快核实处理;也谢谢你花一点时间,一起把这里维护干净。
逆向工程实战:我如何绕过亚马逊Kindle网页端的DRM加密
文章讲述了作者因不满Kindle应用糟糕体验和亚马逊对电子书下载限制,通过逆向工程Kindle Cloud Reader,成功提取并破解多层混淆加密的字体系统,最终将购买的电子书转换为无DRM EPUB文件的全过程。
背景:一次令人窝火的正版购买
我一直从各种来源阅读电子书,但这次,我心想:"别老白嫖了,支持一下作者吧。"于是我在亚马逊买了第一本电子书。
然而,Kindle安卓应用糟糕透顶,频繁崩溃。我想用更稳定的阅读器,于是尝试下载这本书——结果发现亚马逊早在2022年就悄然取消了通过USB下载电子书的功能(称为“下载并传输到USB”)。想用Calibre管理我的藏书?也不行,因为Kindle的ASIN格式、专有格式和DRM保护使得几乎无法导出。
亚马逊甚至提供了网页版阅读器Kindle Cloud Reader,但它不支持离线阅读——我花真金白银买了一本书,却只能在指定的有网环境下、在指定的糟糕应用里阅读,不能备份、不能导出到其他设备,亚马逊还能随时从我的云端删除它。这本质上根本不是购买,而是租赁,尽管页面上根本没写“租”字。
我本可以申请退款,然后花30秒从别处获取这本书的盗版。但那样太简单了,也不会解决根本问题——我只想合法地把自己的书在Calibre里阅读。于是,我决定逆向他们整个网络客户端,即使这意味着要破解其混淆系统。
第一步:抓包分析Kindle Cloud Reader
Kindle Cloud Reader(网页版)实际上可用。检查网络请求时,我发现了一个有趣的接口:https://read.amazon.com/renderer/render。
要下载任何内容,需要三个凭证:
- 会话Cookies(标准的亚马逊登录)
- 渲染令牌(从startReading API调用中获取)
- ADP会话令牌(额外的认证层)
用浏览器相同的请求头和cookies访问该接口,返回的是一个TAR文件,里面包含:
page_data_0_4.json—— 书的文本内容(经过加密/混淆)glyphs.json—— 每个字符的SVG路径定义,相当于一种字形映射表toc.json—— 目录metadata.json—— 书籍信息location_map.json—— 位置映射(用于页码与位置转换)
核心挑战:分层混淆系统
下载前几页后,我期望看到文本,实际却得到:
{
"type": "TextRun",
"glyphs": [24, 25, 74, 123, 91, 18, 19, 30, 4, ...],
"style": "paragraph"
}
这些不是Unicode字符,而是“字形ID”。字母‘T’不是Unicode的84,而是数字24——而24这个ID在glyphs.json里对应着一串SVG路径。这就是一种替换密码:每个字符映射到非连续的、随机的字形ID。
更可怕的是,字母表每隔5页就变化一次。每下载下一批页面,同一个字母‘T’就变成了字形87,下一批又变成142——API限制每次只能获取最多5页,且每次请求都使用一套全新的随机字符映射。这意味着:
- 你必须发184个不同请求才能获取整本920页的书。
- 每个请求的字符映射不同。
- 字形ID在请求间毫无关联。
- 无法为整本书构建唯一的映射表。
解剖“字形”定义:SVG路径,但带毒
glyphs.json中每个ID对应一个SVG路径:
{
"24": {
"path": "M 450 1480 L 820 1480 L 820 0 L 1050 0 L 1050 1480 ...",
"fontFamily": "bookerly_normal"
}
}
字形ID变化,但SVG图像本身不变。然而,亚马逊在路径中注入了垃圾代码,例如:
M695.068,0 L697.51,-27.954 m3,1 m1,6 m-4,-7 L699.951,-55.908
这里的 m3,1 m1,6 m-4,-7 是微小的相对MoveTo命令。意义何在?浏览器使用原生Path2D可以正确渲染,而Python的SVG库则会绘制出多余的连接线,导致字形渲染时看起来像是损坏的或扭曲的。这是通过弄脏路径、破坏基于坐标比较的解析方案来阻止直接比较的对抗性技术。
要绕过这个,唯一可靠的方案是填充(fill)整个路径,让它形成封闭区域,从而忽略那些微小的移动指令。
更多陷阱:多字体变体与连字
不只是单一字体。实际上有四种变体:
- bookerly_normal(99%的字形)
- bookerly_italic(斜体)
- bookerly_bold(粗体)
- bookerly_bolditalic(加粗斜体)
还包含专属连字:ff, fi, fl, ffi, ffl(每个连字作为一个独立字形)。变体越多,意味着你需要匹配的字形库就越大。
失败尝试:OCR方案
我尝试将渲染的单个字形跑OCR,结果:识别率只有51%(178/384),其余几乎完全失败。OCR擅长识别单词、句子,但对单个字符非常糟糕:它混淆字母‘l’与‘I’与‘1’,对特殊标点符号无能为力,更别说连字了。我放弃了OCR路线。
成功路径:像素级感知哈希 + SSIM匹配
关键洞察:字形ID会变,但SVG形状是固定的。因此,我不再比较路径坐标,而是直接渲染成图像并用感知哈希来统一。
步骤1:渲染所有SVG图像。用cairosvg(它能正确处理那些垃圾m命令,因为浏览器也用它做原生Path2D)将每个字形渲染为512x512的PNG。
步骤2:生成感知哈希。为每个图像计算感知哈希(perceptual hash)。相同形状的字形,无论ID是什么,都会得到相同的哈希。
步骤3:建立归一化字形空间。把184个不同字母表里的每个字形映射到基于哈希的ID上。现在,任意请求的“a1b2c3d4”哈希,都对应固定的字符模板。
步骤4:匹配真实字符。我需要从本地下载Bookerly字体(亚马逊Kindle设备/固件自带或可从官方下载),解压获得TTF字体文件,然后用Python PIL或Pillow渲染出每个候选字符(A-Z, a-z, 0-9, 标点符号,以及其他扩展字符),再对每个未知字形与每个候选字符渲染图进行SSIM(结构相似性)比较,取最高分作为匹配结果。
为什么SSIM适用:SSIM评估图像结构(亮度、对比度、结构)间相似性,而非逐像素差异,因此能容忍细微的抗锯齿差异、渲染边缘、缩放差异,使匹配具有鲁棒性。对每个未知字形,遍历所有候选字符,得出最高SSIM值对应的字符即为答案。
处理边界情况:需要把连字(ff,fi,...)加入候选集;对于专有标点如长破折号、引号、项目符号等,则需要把整个Unicode范围扩展到数千个候选,并在渲染时保证字体质量。最终,在四个字体变体(正常/粗/斜/粗斜)分别建立词典,匹配时先判别字形所使用字族,再在对应库中寻找。最终对184个批次的全部1,051,745个字形,进行了匹配。
最终数据
- 批次:184个,每个批次对应5页。
- 唯一字形:361个(实际上字母、标点、连字、符号等)。
- 总字形数:1,051,745(全书)。
- 成功匹配:361/361(100.00%),失败0个。
- 平均SSIM得分:0.9527(非常高,接近完美)。
- 总字符数:5,623,847 。
- 总页数:920页。
每个字符都被精确解码,完美!
恢复EPUB,保留原始排版
JSON中还包含每个文本运行的详细位置与样式:
{
"glyphs": [24, 25, 74],
"rect": {"left": 100, "top": 200, "right": 850, "bottom": 220},
"fontStyle": "italic",
"fontWeight": 700,
"fontSize": 12.5,
"link": {"positionId": 7539}
}
作者利用这些元数据还原了:
- 段落分隔(基于Y坐标的变化)
- 文本对齐(基于X坐标规律)
- 粗体/斜体强调
- 字体大小
- 内部链接
最终生成的EPUB在格式上与原始版本难以区分。
后记:值得吗?
单独为读一本书而开发这套方案,显然成本过高。但目的是为了证明一个观点:当你购买了电子书,你有权益为自己的使用目的去备份和转换格式。同时,这个过程也让我深入学习了SVG渲染、感知哈希、字体度量和SSIM图像比较技术。但切记,此技术仅应用于备份自己合法购买的电子书,切勿扩散至盗版或侵犯版权。亚马逊的法务团队不是好惹的。
原作者提醒:如果你与亚马逊有任何关联,联系方式见其博客个人页面。
拓展阅读:进一步优化
后来有人在其基础上优化了工具,实现了更快的匹配速度(利用预先计算好的字形哈希库)并解决了更多边缘情况(如乱码符号和特殊组合)。这些无疑进一步证明了,对抗性混淆技术永远只能延缓破解,而不能阻止。