记一次对某某通网页版字体的混淆加密分析
本文最后更新于 2026年6月29日 晚上
声明:本文仅用于学习与研究字体混淆的实现思路,严禁用于任何未授权的非法用途。
好久没发博客了,来水一篇~~~
前言
打开某某通网页做题的时候本来想美美地复制给 AI 大人答疑(bushi),结果发现复制出来是一串生僻字?打开网页源码发现对字符进行了加密(恕我孤陋寡闻了~)
加密分析
可以看到这个 div 元素使用的 font-cxsecret 字体,也就是它用于混淆显示内容的自定义字体。
1 | |
搜索找到可以找到对应的字体声明。其本质上是把字体文件直接以内联 Base64 的方式放进 CSS 中(太多了省略了部分)
1 | |
解码之后保存为了 ttf 格式
找了个网站查看了一下,字体查看器和分析器 - 在线预览和检查字体,字体是 Source Han Sans CN Normal,版本 Version 1.000;PS 1;hotconv 1.0.78;makeotf.lib2.5.61930,看着是正常的,这些字符本身都属于合法 Unicode,但大多比较冷门。也就是说,它这里是挑了一批合法但很少见的 Unicode 字符,当成占位符塞进 HTML,再让自定义字体把这些占位符显示成真正想显示的文字。
1 | |
这些字本身都是真实存在的 Unicode 字符,所以浏览器渲染、复制、存储都不会报错。
逆向分析
没找到同版本的 TTF 文件字符集,用的同一个版本的 OTF 字符集,统一渲染成位图,再做批量相似度匹配(如果有 TTF 就不用这样)。
逆向思路很简单:
- 准备同版本完整字符集 SourceHanSansCN-Normal.otf
- 分别读取两份字体的 cmap
- 把混淆字符和完整字库里的所有候选字符都渲染成统一尺寸的黑白位图
- 用异或距离统计位图差异,给每个混淆字符找出最相近的候选
这里的核心思路是把字符统一转换成二值位图,再用 NumPy 统计当前混淆字符位图与参考字符集位图之间的逐像素异或差异,差异值越小就越接近:
1 | |
跑出来结果如下,和在线网页转换的一样结果
| 替代字符 | 替代码点 | 第一候选 | 码点 | 距离 | 次佳距离 |
|---|---|---|---|---|---|
| 冩 | U+51A9 | 为 | U+4E3A | 46 | 120 |
| 孇 | U+5B47 | 辑 | U+8F91 | 62 | 222 |
| 孈 | U+5B48 | 要 | U+8981 | 4 | 153 |
| 孉 | U+5B49 | 段 | U+6BB5 | 19 | 241 |
| 孊 | U+5B4A | 什 | U+4EC0 | 1 | 1 |
| 孋 | U+5B4B | 的 | U+7684 | 33 | 190 |
| 孌 | U+5B4C | 逻 | U+903B | 40 | 231 |
| 孍 | U+5B4D | 主 | U+4E3B | 33 | 135 |
| 孎 | U+5B4E | 号 | U+53F7 | 6 | 147 |
| 孏 | U+5B4F | 确 | U+786E | 54 | 184 |
| 孞 | U+5B5E | 定 | U+5B9A | 28 | 109 |
| 孠 | U+5B60 | 具 | U+5177 | 3 | 164 |
| 孡 | U+5B61 | 络 | U+7EDC | 9 | 178 |
| 孢 | U+5B62 | 体 | U+4F53 | 17 | 118 |
| 孥 | U+5B65 | 设 | U+8BBE | 17 | 180 |
| 孧 | U+5B67 | 协 | U+534F | 27 | 226 |
| 孨 | U+5B68 | 划 | U+5212 | 11 | 230 |
| 孫 | U+5B6B | 配 | U+914D | 14 | 219 |
| 孬 | U+5B6C | 计 | U+8BA1 | 9 | 156 |
| 孭 | U+5B6D | 线 | U+7EBF | 17 | 168 |
| 孮 | U+5B6E | 进 | U+8FDB | 31 | 110 |
| 孯 | U+5B6F | 行 | U+884C | 43 | 43 |
| 孰 | U+5B70 | 布 | U+5E03 | 4 | 160 |
| 孱 | U+5B71 | 册 | U+518C | 9 | 220 |
| 孲 | U+5B72 | 编 | U+7F16 | 38 | 131 |
| 孳 | U+5B73 | 写 | U+5199 | 5 | 166 |
| 孴 | U+5B74 | 操 | U+64CD | 49 | 195 |
| 孵 | U+5B75 | 作 | U+4F5C | 3 | 94 |
| 孶 | U+5B76 | 系 | U+7CFB | 46 | 195 |
| 孷 | U+5B77 | 工 | U+5DE5 | 46 | 46 |
| 孹 | U+5B79 | ⼀ | U+2F00 | 0 | 0 |
| 孻 | U+5B7B | 统 | U+7EDF | 17 | 192 |
| 孼 | U+5B7C | 成 | U+6210 | 14 | 90 |
| 孾 | U+5B7E | 结 | U+7ED3 | 16 | 150 |
| 孿 | U+5B7F | 架 | U+67B6 | 16 | 178 |
| 宄 | U+5B84 | 拓 | U+FA02 | 16 | 16 |
| 宆 | U+5B86 | 扑 | U+6251 | 1 | 114 |
| 宊 | U+5B8A | 商 | U+5546 | 19 | 224 |
| 宍 | U+5B8D | 备 | U+5907 | 20 | 213 |
| 宎 | U+5B8E | 选 | U+9009 | 28 | 187 |
| 宐 | U+5B90 | 应 | U+5E94 | 63 | 149 |
| 宑 | U+5B91 | 择 | U+62E9 | 35 | 129 |
| 宒 | U+5B92 | 供 | U+4F9B | 6 | 138 |
| 宓 | U+5B93 | 需 | U+9700 | 7 | 164 |
| 宔 | U+5B94 | 析 | U+6790 | 19 | 100 |
| 宖 | U+5B96 | 求 | U+6C42 | 39 | 195 |
| 実 | U+5B9F | 制 | U+5236 | 27 | 249 |
| 宥 | U+5BA5 | 策 | U+7B56 | 27 | 139 |
| 宧 | U+5BA7 | 安 | U+5B89 | 34 | 178 |
| 宨 | U+5BA8 | 全 | U+5168 | 12 | 148 |
| 宩 | U+5BA9 | 范 | U+8303 | 2 | 177 |
| 宬 | U+5BAC | 程 | U+7A0B | 16 | 137 |
| 宭 | U+5BAD | 哪 | U+54EA | 18 | 139 |
| 宯 | U+5BAF | 是 | U+662F | 2 | 168 |
| 宱 | U+5BB1 | 功 | U+529F | 16 | 168 |
| 宲 | U+5BB2 | 因 | U+56E0 | 30 | 158 |
| 宷 | U+5BB7 | 关 | U+5173 | 7 | 186 |
| 宸 | U+5BB8 | 素 | U+7D20 | 17 | 180 |
| 宺 | U+5BBA | 技 | U+6280 | 30 | 104 |
| 宻 | U+5BBB | 术 | U+672F | 5 | 89 |
| 宼 | U+5BBC | 杂 | U+6742 | 8 | 198 |
| 寀 | U+5BC0 | 方 | U+65B9 | 7 | 7 |
| 寁 | U+5BC1 | 复 | U+590D | 37 | 163 |
| 寃 | U+5BC3 | 案 | U+6848 | 4 | 217 |
| 寈 | U+5BC8 | 用 | U+2F64 | 19 | 19 |
| 寉 | U+5BC9 | 户 | U+2F3E | 23 | 23 |
| 寊 | U+5BCA | 明 | U+660E | 39 | 121 |
| 寋 | U+5BCB | 品 | U+54C1 | 3 | 210 |
| 寍 | U+5BCD | 人 | U+4EBA | 7 | 7 |
| 寎 | U+5BCE | 量 | U+91CF | 17 | 17 |
| 寏 | U+5BCF | 员 | U+5458 | 4 | 174 |
| 寑 | U+5BD1 | 通 | U+901A | 16 | 167 |
| 寔 | U+5BD4 | 施 | U+65BD | 17 | 175 |
| 寕 | U+5BD5 | 数 | U+6570 | 37 | 242 |
| 寖 | U+5BD6 | 键 | U+952E | 9 | 139 |
| 寗 | U+5BD7 | 包 | U+5305 | 3 | 198 |
| 寘 | U+5BD8 | 括 | U+62EC | 19 | 95 |
| 寙 | U+5BD9 | 波 | U+6CE2 | 10 | 141 |
| 寚 | U+5BDA | 信 | U+4FE1 | 52 | 192 |
| 寜 | U+5BDC | 米 | U+2F76 | 5 | 5 |
| 寠 | U+5BE0 | 切 | U+5207 | 26 | 176 |
| 寡 | U+5BE1 | 迟 | U+8FDF | 3 | 103 |
| 寣 | U+5BE3 | 输 | U+8F93 | 21 | 200 |
| 寥 | U+5BE5 | 延 | U+5EF6 | 23 | 147 |
| 實 | U+5BE6 | 传 | U+4F20 | 37 | 146 |
| 寨 | U+5BE8 | 纤 | U+7EA4 | 29 | 100 |
| 寪 | U+5BEA | 目 | U+2F6C | 1 | 1 |
| 寬 | U+5BEC | 中 | U+4E2D | 1 | 4 |
| 寭 | U+5BED | 详 | U+8BE6 | 13 | 117 |
| 寮 | U+5BEE | 录 | U+5F55 | 5 | 206 |
| 寯 | U+5BEF | 分 | U+5206 | 20 | 191 |
| 寱 | U+5BF1 | 告 | U+544A | 37 | 105 |
| 寲 | U+5BF2 | 验 | U+9A8C | 48 | 203 |
| 寴 | U+5BF4 | 项 | U+9879 | 19 | 182 |
| 寵 | U+5BF5 | 收 | U+6536 | 17 | 178 |
| 寶 | U+5BF6 | 手 | U+2F3F | 32 | 32 |
| 寷 | U+5BF7 | 文 | U+2F42 | 27 | 27 |
| 寽 | U+5BFD | 以 | U+4EE5 | 14 | 222 |
| 対 | U+5BFE | 实 | U+5B9E | 24 | 202 |
| 尀 | U+5C00 | 果 | U+679C | 32 | 104 |
| 専 | U+5C02 | 档 | U+6863 | 31 | 88 |
| 尃 | U+5C03 | 规 | U+89C4 | 25 | 129 |
| 尅 | U+5C05 | 说 | U+8BF4 | 43 | 140 |
| 將 | U+5C07 | 书 | U+4E66 | 4 | 231 |
| 尌 | U+5C0C | 不 | U+4E0D | 52 | 52 |
| 尐 | U+5C10 | 管 | U+7BA1 | 9 | 182 |
| 尗 | U+5C17 | 记 | U+8BB0 | 10 | 144 |
| 尛 | U+5C1B | 展 | U+5C55 | 67 | 178 |
| 尜 | U+5C1C | 提 | U+63D0 | 27 | 133 |
| 尞 | U+5C1E | 持 | U+6301 | 8 | 94 |
| 尟 | U+5C1F | 团 | U+56E2 | 16 | 140 |
| 尠 | U+5C20 | 促 | U+4FC3 | 29 | 160 |
| 尢 | U+5C22 | 度 | U+5EA6 | 31 | 190 |
| 尣 | U+5C23 | 队 | U+961F | 16 | 193 |
| 尥 | U+5C25 | 高 | U+9AD8 | 51 | 51 |
| 尦 | U+5C26 | 型 | U+578B | 8 | 253 |
| 尨 | U+5C28 | 典 | U+5178 | 12 | 246 |
| 尩 | U+5C29 | 机 | U+673A | 16 | 117 |
| 尪 | U+5C2A | 赁 | U+8D41 | 27 | 206 |
| 尫 | U+5C2B | 拟 | U+62DF | 59 | 184 |
| 尬 | U+5C2C | 租 | U+79DF | 47 | 134 |
| 尭 | U+5C2D | 办 | U+529E | 16 | 240 |
| 尮 | U+5C2E | 软 | U+8F6F | 19 | 166 |
| 尯 | U+5C2F | 如 | U+5982 | 23 | 232 |
| 尰 | U+5C30 | 公 | U+516C | 31 | 163 |
| 尲 | U+5C32 | 在 | U+5728 | 49 | 165 |
| 尳 | U+5C33 | 件 | U+4EF6 | 12 | 125 |
| 屆 | U+5C46 | 库 | U+5E93 | 22 | 148 |
| 屇 | U+5C47 | 理 | U+7406 | 16 | 16 |
| 屈 | U+5C48 | 据 | U+636E | 35 | 187 |
| 屍 | U+5C4D | 列 | U+5217 | 33 | 226 |
| 屐 | U+5C50 | 财 | U+8D22 | 51 | 156 |
| 屑 | U+5C51 | 务 | U+52A1 | 10 | 218 |
| 屒 | U+5C52 | 预 | U+9884 | 36 | 124 |
| 屓 | U+5C53 | 产 | U+4EA7 | 4 | 180 |
| 屔 | U+5C54 | 材 | U+6750 | 3 | 170 |
| 屖 | U+5C56 | 广 | U+5E7F | 4 | 4 |
| 屗 | U+5C57 | 装 | U+88C5 | 18 | 102 |
| 屘 | U+5C58 | 宣 | U+5BA3 | 85 | 110 |
| 屙 | U+5C59 | 于 | U+4E8E | 32 | 88 |
| 屟 | U+5C5F | 过 | U+8FC7 | 45 | 155 |
| 摶 | U+6476 | 格 | U+683C | 20 | 100 |
| 敩 | U+6569 | 网 | U+2F79 | 3 | 3 |
| 潯 | U+6F6F | 报 | U+62A5 | 37 | 189 |
| 糵 | U+7CF5 | 阶 | U+9636 | 49 | 145 |
| 苧 | U+82E7 | 光 | U+5149 | 20 | 167 |
| 谉 | U+8C09 | 到 | U+5230 | 5 | 201 |
| 迉 | U+8FC9 | 属 | U+5C5E | 18 | 140 |
这里的距离越小,说明形状越接近,像 冩 -> 为、孉 -> 段、孍 -> 主 这种,第一候选和第二候选差距比较明显,可信度就更高。
总结
其实原理很简单,某某通网页版的这层混淆本质上:
- 页面里放的是合法 Unicode 生僻字。
- 让它看起来正常的是内联的自定义字体。
- 只要拿到子集字体,再找到同版本完整字符集,就可以通过位图相似匹配把映射关系恢复出来。
说白了就是底层源码里塞的生僻字,渲染成了常见的字,复制粘贴的还是底层的生僻字。这种混淆防君子不防小人~(已学习到如何阴一手hhh),更多是为了干扰复制、搜索和简单脚本提取,不过只需要把“字符”和“字形”分开看就行了。做个作业可太难了~
还可以看看 52 的这篇文章 https://www.52pojie.cn/thread-1631357-1-1.html