吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 11196|回复: 40
收起左侧

[Web逆向] 关于超星学习通网页版字体加密分析

  [复制链接]
featmellwo 发表于 2022-5-4 16:23
本帖最后由 featmellwo 于 2022-5-4 16:22 编辑

分析仅供学习研究,请勿使用于非法用途
最近发现超星针对题目做了字体加密,闲来无事研究了一下。
如图可以看到字体是被加密了一部分
image.png

加密字体上右键审核元素看到 class 包含了一个font-cxsecret,我们看下源码
image.png
源码中发现字体的base64,我们尝试解码还原成.ttf格式
使用字体查看工具打开看下信息,可以直接看到这个ttf包含哪些字以及他的基本信息
image.png

将ttf解析成xml()
image.png
由于之前没有研究过ttf所以百度了一手ttf文件结构,大家可以看这个(https://blog.csdn.net/blueangle17/article/details/23750999)
image.png
如图映射结果是一致的说明不是修改映射关系来加密字体的
如果映射结果没有变化的话那可能是修改了图元数据,我尝试将他的unicode还原成中文发现确实是加密后的字体,基本上可以理清楚超星的加密是修改了此字体图元数据,所以显示成未加密的字。
我们接下来尝试解析并还原加密文字
由于超星每个网页的ttf数据都是不同的,并且只有部分字体加密,所以我们需要先找到一份完整的ttf文件,根据字体查看工具发现是用的字体是
SourceHanSansCN-Normal Version 1.000;PS 1;hotconv 1.0.78;makeotf.lib2.5.61930
直接百度找一手源文件,然后解析成xml查看图元信息是否一致
超星加密的ttf某个字图元数据
[Asm] 纯文本查看 复制代码
01
02
03
04
05
06
07
08
09
10
11
12
13
<TTGlyph name="uni6408" xMin="47" yMin="-74" xMax="957" yMax="837">
      <contour>
        <pt x="757" y="339" on="1"/>
        <pt x="528" y="339" on="1"/>
        <pt x="528" y="215" on="1"/>
        <pt x="757" y="215" on="1"/>
      </contour>
      <contour>
        <pt x="528" y="400" on="1"/>
        <pt x="757" y="400" on="1"/>
        <pt x="757" y="516" on="1"/>
        <pt x="528" y="516" on="1"/>
      </contour>

百度下载的字体ttf图元数据
[Asm] 纯文本查看 复制代码
01
02
03
04
05
06
07
08
09
10
11
12
13
<TTGlyph name="uni4E89" xMin="47" yMin="-74" xMax="957" yMax="837">
     <contour>
       <pt x="757" y="339" on="1"/>
       <pt x="528" y="339" on="1"/>
       <pt x="528" y="215" on="1"/>
       <pt x="757" y="215" on="1"/>
     </contour>
     <contour>
       <pt x="528" y="400" on="1"/>
       <pt x="757" y="400" on="1"/>
       <pt x="757" y="516" on="1"/>
       <pt x="528" y="516" on="1"/>
     </contour>

我们可以看到 uni6408是用的是 官方uni4E89的图元数据
查看对应文字  【搈】=>【争
没毛病,那这样我们基本上已经理清楚了超星的加密方式
然后就是如果还原字体了,我的思路是用原版的ttf的图元数据做一个字典,然后反推加密的字体
[Python] 纯文本查看 复制代码
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
def yh_mapping():
    keylist={}
    with open('yh.xml') as f_baes:
        xml_base = f_baes.read()
    s_base = xml_base.split("</TTGlyph>")[:-1]
    for i in range(0, len(s_base)):
        lists_base = []
        contour = re.findall('<pt (.*?)/>', s_base[i])
        name=re.findall('name="(.*?)"',s_base[i])[0]
        for j in range(0, len(contour)):
            x = re.findall('x=\"(.*?)\"', contour[j])
            y = re.findall('y=\"(.*?)\"', contour[j])
            on = re.findall('on=\"(.*?)\"', contour[j])
            lists_base.append(x[0] + y[0] + on[0])
        keylist[name]=hashlib.md5("".join(lists_base).encode('utf8')).hexdigest()
    print(keylist)
    with open("map.txt", "w") as f:
        f.write(json.dumps(keylist))

这个代码的作用是将原版ttf的字体图元数据拼接并且md5生成唯一标志,然后与其unicode编码相对应,然后我们就得到了一个原版的编码=>唯一标志的json文件
image.png
接下来处理超星的ttf,将他的图元数据以同样的方法处理,然后根据图元数据生成的唯一标志比较,将原版的unicode对应进去
[Python] 纯文本查看 复制代码
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
def font_mapping(b64_code):
    with open("map.txt", "r", encoding="utf-8") as f:
        keys=json.loads(f.read())
    kes_sign_list={}
    for i in keys:
        kes_sign_list[keys[i]]=i
    lists_base_all = []
    keylist={}
    text_font = TTFont(BytesIO(base64.decodebytes(b64_code.encode())))
    text_font.save("font.ttf")
    text_font.saveXML("font.xml")
    with open('font.xml') as f_baes:
        xml_base = f_baes.read()
    s_base = xml_base.split("</TTGlyph>")[:-1]
    for i in range(0, len(s_base)):
        lists_base = []
        contour = re.findall('<pt (.*?)/>', s_base[i])
        name=re.findall('name="(.*?)"',s_base[i])[0]
        for j in range(0, len(contour)):
            x = re.findall('x=\"(.*?)\"', contour[j])
            y = re.findall('y=\"(.*?)\"', contour[j])
            on = re.findall('on=\"(.*?)\"', contour[j])
            lists_base.append(x[0] + y[0] + on[0])
 
        keylist[name]=hashlib.md5("".join(lists_base).encode('utf8')).hexdigest()
        lists_base_all.append(lists_base)
    keys_list={}
    for i in keylist:
        keys_list[i]=kes_sign_list[keylist[i]].replace("uni","\\u").encode("utf-8").decode('unicode_escape')
    return keys_list

函数传入超星的加密base64,返回加密ttf unicode所对应的解密字体,效果如图所示
image.png
最后将加密数据带入计算得出解密后的文本
image.png

总结: 超星所使用的字体加密 通过修改字体的图元数据使A字的字形变成了B字的字形,虽然他看上去是B字但是复制的时候还是A字


相关代码,文件已放附件,由于原版字体文件放入后超过3m所以有需要得可以自行百度下载




编写较乱,各位看官还请见谅

超星demo.zip

731.18 KB, 阅读权限: 10, 下载次数: 972, 下载积分: 吾爱币 -1 CB

免费评分

参与人数 14威望 +1 吾爱币 +34 热心值 +12 收起 理由
qxkyh + 1 我很赞同!
淡淡哇 + 1 + 1 我很赞同!
c7129 + 1 牛逼,碰到这种加密的实在是头疼
Acosos + 1 + 1 谢谢@Thanks!
yyz288596 + 1 + 1 我很赞同!
chuxia12 + 1 + 1 谢谢@Thanks!
EYouhun + 1 + 1 大佬可不可以给个傻瓜教学呀
Abrahams + 1 + 1 用心讨论,共获提升!
南岸 + 2 + 1 我很赞同!
Long0296 + 1 + 1 用心讨论,共获提升!
忆魂丶天雷 + 2 + 1 谢谢@Thanks!
苏紫方璇 + 1 + 20 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
screem + 1 + 1 我很赞同!
ZjNU-Zxk + 1

查看全部评分

本帖被以下淘专辑推荐:

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

疯狂石头 发表于 2022-5-20 11:15
winpp 发表于 2022-5-16 00:21
哪个脚本可以用急需谢谢分享一下老大

https://scriptcat.org/script-show-page/336这个是章节测试
https://scriptcat.org/script-show-page/365这个是章节测试和考试都可以
注意安装的插件是脚本猫最新是0.91版本,不要使用油猴,暴力猴插件,谷歌、Edge、火狐、360极速版浏览器都可以

免费评分

参与人数 1吾爱币 +1 热心值 +1 收起 理由
远赴人间惊鸿宴i + 1 + 1 谢谢@Thanks!

查看全部评分

ltxhhz 发表于 2022-12-31 18:42

你好我想请教一下,我在网上下的字体和学习通里的文字图元数据有点不一样,这是正常的吗,

<!-- 显示文字“一” -->
<TTGlyph name="uni60DA" xMin="48" yMin="353" xMax="953" yMax="425">
<!-- font-cxsecret -->
  <contour>
    <pt x="953" y="425" on="1"/>
    <pt x="953" y="353" on="1"/>
    <pt x="48" y="353" on="1"/>
    <pt x="48" y="425" on="1"/>
  </contour>
  <instructions/>
</TTGlyph>
<!-- 实际文字“一” -->
<TTGlyph name="uni2F00" xMin="48" yMin="354" xMax="956" yMax="426">
<!-- 网上的 SourceHanSans-Normal.ttf -->
  <contour>
    <pt x="48" y="426" on="1" overlap="1"/>
    <pt x="956" y="426" on="1"/>
    <pt x="956" y="354" on="1"/>
    <pt x="48" y="354" on="1"/>
  </contour>
  <instructions>
    <assembly>
          PUSHW[ ]  /* 2 values pushed */
          627 628
          WS[ ] /* WriteStore */
          SVTCA[0]  /* SetFPVectorToAxis */
          PUSHW[ ]  /* 5 values pushed */
          1 -407 -408 -409 -410
          PUSHB[ ]  /* 3 values pushed */
          3 0 150
          CALL[ ]   /* CallFunction */
          SZP2[ ]   /* SetZonePointer2 */
          IUP[1]    /* InterpolateUntPts */
          IUP[0]    /* InterpolateUntPts */
        </assembly>
  </instructions>
</TTGlyph>

淡淡哇 发表于 2022-5-4 16:26
tek2y 发表于 2022-5-4 17:29
牛逼,碰到这种加密的实在是头疼
mark000 发表于 2022-5-4 17:34
真不错,学校天天用学习通666666666666
lewis09 发表于 2022-5-4 18:07
我说咋最近的超星搜题脚本全失效了
wakichie 发表于 2022-5-4 18:08
还是大佬牛逼啊
天天涨停天天盈 发表于 2022-5-4 18:24
大佬厉害  不过这能用来干啥?  还原原文字  然后搜题吗
Zhili.An 发表于 2022-5-4 19:01
有时候加密有时候没加密哎
ciker_li 发表于 2022-5-4 19:03
学习学习。大佬厉害
鹿坪 发表于 2022-5-5 07:23
好强,学习了
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2025-2-1 17:35

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

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