2023年河南省大学生国家安全知识竞赛网页技术解密
昨天一个后端朋友给我发了一张截图,问我这个2023年河南省大学生国家安全知识竞赛网页f12内DOM节点显示韩文,但是页面显示是中文,复制出来的结果是韩文,问我怎么回事。我也是第一次见这种情况,便研究了起来。本文主要记录我调试和发现答案的流程,涉及两部分,一个是该网页字体解密,一个是JSON数据AES解密
刚写完这篇文章,刷新就打不开这个网页了,发现竞赛学习时间过了🥲
网页字体解密
注意:以下截图均为github链接,不用vpn很大可能打不开
定位原因
通过调试发现,这类字体都有.secret类名,该类名指定使用一个名叫ddjdt的font-family,去掉该font-family属性页面正常显示为韩文,因此确定是字体原因
寻找资料 了解原理
在网络上搜索字体加密有很多文档,大部分都是拿猫眼的网页当做例子,但是由于每个网站的加密方式不一样,所以那些教程不一定适用于该网页,但是整体的流程大概明白了。
简单来说字体加密主要是为了反爬虫和防复制,比如猫眼这些网站就是为了防止别人爬数据,对于这个知识竞赛网页主要是为了防止复制搜答案。
对于汉字 我 来说,他可以有宋体、黑体、微软雅黑等不同的字形展示,但是他们对应的Unicode编码是同一个,同理也可以创造一个新的字体库叫animal,把 我 对应的字形描绘成老虎,这样浏览器在碰到 我 的Unicode时,就会把它渲染成老虎的样式。字体库内部使用TTGlyph来存储字形轮廓信息,它和SVG一样都是矢量图形格式。
所以该网页DOM内部是韩文,这些韩文的Unicode编码对应的字形实际上是微软雅黑或者其他字体库的汉字字形TTGlyph,导致页面渲染出来是汉字。
字体库xml分析验证
打开css发现该字体使用的是 https://2023gjaqzsjs.haedu.cn/fonts/wryh2.ttf 这个字体文件,下载文件,然后用python把ttf转换成xml文件看到字体库内部结构,代码如下
1 |
|
解析后的xml文件首先看到的是GlyphOrder,内部有很多GlyphID
1 |
|
搜索 glyph00002,可以看到对应一个Unicode编码 0xb460
1 |
|
转换0xb460打印出来是韩文,也证实了上面的说法
1 |
|
同时与glyph00002相关的还有这个TTGlyph,也就是它的字形文件了
1 |
|
操作、预览字体库
在查找的文档中,很多人说可以用FontCreator加载字体库,但是它只适用于windows,并且有试用期,故放弃。问了chatGPT后说可以用BirdFont和FontDrop,
- BirdFont:免费,有mac客户端,可以根据Unicode搜索
- FontDrop:免费,网页端,没有搜索功能
- 百度字体编辑器:免费,网页端,可以根据Unicode搜索(吐个槽,百度好像把这个产品下架了,这个链接还是github的)
我使用的是FontDrop,很方便,把字体文件拖进来就能解析,可以看到字体名称和字体作者等信息
下面是字体展示,鼠标滑过会展示该字形的Unicode
分析DOM结构,获取全部字形的Unicode
1 |
|
执行结果如下
emmmm。竟然还有未找到匹配的内容,调试后发现该字形的Unicode是鼠标滑过字形后动态插入到DOM的,鼠标没有滑过的字形就是未找到
简单,给全部字形节点加mouseover事件,手动触发,再获取全部Unicode就正常了
1 |
|
获取Unicode和字形的映射,创建密码表
没办法,这里只能手动建立映射了,或者有OCR接口的话可以优化一下
1 |
|
映射结果如下
解密
复制一句密文来测试下效果
1 |
|
解密效果如下
看起来解密效果还可以,一部分字体没有解密出来是因为字体文件的问题,多个Unicode对应同一个字体文件TTGlyph,用上面说的百度字体编辑器可以看到 国 这个字形文件有两个Unicode,把这些特殊Unicode手动加到之前的密码表就好了
JSON数据解密
确认接口
这些加密字体很明显是后端接口传过来的,但是这个分页接口返回的竟然是加密后的字符串,真有你的
定位代码
在返回的js文件内搜索这个接口地址 2023gjaqzsjs.haedu.cn 和 /json/,找到相关代码,看到返回的加密字符串被$decrypt方法解密
搜索$decrypt方法发现是用AES解密
通过其他的一些变量名我猜用的很可能是crypto-js这个库,但是看crypto-js源码的decrypt函数第三个参数是一个配置对象啊,这里怎么是个字符串,难道是用的其他解密库?我在这里卡了半天,打断点才发现是作者创建了一个AES对象,把crypto-js的decrypt又封装了一下
这里的o方法就是把16进制转为10进制index,然后获取t[index], 比如r[“AES”][o(“0xa”)]实际就是r[“AES”][“decrypt”]
引入crypto-js的cdn文件,然后复制相关解密变量到本地测试
结果如下
和知识竞赛题目内的加密字体一样,JSON解密完成
总结
学习了字体加密解密的一些知识,加深了对字体文件的理解。而且在我以往的印象里反爬虫就是ip限制,请求频率限制,没想到还有JSON加密和字体加密。但是目前还有个问题:后端怎么生成的加密字体文件和字体JSON,通过密码表还是加密规则,这个字体文件只加密了一部分常用字