找回密码
 立即注册
首页 业界区 安全 GBK迷思——从乱码PDF引出的遐想

GBK迷思——从乱码PDF引出的遐想

嗦或 2025-9-28 15:45:51
作者Nick Pang,在CC BY-SA 4.0许可下发布。
1.jpg
2.jpg
3.jpg

写于一个不想练口译的下午。
也不想写笔译作业。
0x0 拯救大兵PDF

我决定今天下午给自己放假。今天上午,昨天一整天,前天大半天,都在整翻译的事情。脑子要炸。
打开微信,发现这样一条有意思的朋友圈:
4.png

感谢Ms. JIAO的朋友圈
事实上,不止我一个人要炸,大家普遍精神状态美丽。比如下载下来的东西是一堆乱码,看不懂一点。
但是乱码并不意味着信息就丢失了,其实信息还在那里,只不过是以另一种方式呈现在那里了。也许是编码的问题。
这我可就不困了。ENTP贪玩的精神上头,我一定要弄明白这个编码的问题出在哪里。
最好还能搞清楚这个图片上的这堆乱码到底是什么。
0x1 捕风捉影

从严格意义上来讲,这算是一种逆向。众所周知,每一个逆向工程都需要一个Entry Point和Exit Point。虽然这个文档不是程序,没有PE头,但是我们也可以找到一个切入点,开始我们的分析。
首先从结构上来看,这应该是某种类型的自然语言文本——不是任何一种编程语言/标记语言。
原因很简单,因为在这一个截屏里,没有任何连续的ASCII字符。除非是易语言这种打着中文变成七号的语言,否则大部分编程语言(哪怕是写这篇文章用的Markdown标记语言)都要涉及到连续的ASCII字符。
知道了是自然语言,我们还能确定这个语言基本上不是西欧那些语言——否则不至于一个像样的拉丁字母都看不到。结合对于发帖人的了解,我猜这个大概是CJK中的某一种语言。
既然是自然语言,那么能看出来这应该是某一篇文章的开头。结合深绿色(其实后来发现是黄色,是因为摄屏时白平衡错了)背景,合理猜测是WPS的护眼模式(猜得很远,后面解释为什么这么猜测),那么限定了文件类型:不是PDF,就是DOC家族成员。
但至于具体是哪一个文件就不知道了,都有可能。
除了从技术角度去看以外,还可以从文本排版格式来看。之前已经说了,这是自然语言文本。前面又很像是文本的开头标题,因此“标题”下面的这一行小东西应该就是某种说明,看长度不是作者之类的信息,那就说明是时间或者地点或者两者都有,总之是一种标注信息。
5.png

看来一篇文章不需要标注作者,但是需要标注其他的信息。而且下面一行小字还不够,需要再用一个星号在页脚做注释。很有可能是书信或者选集或者演讲稿件。这样的话这个文件是PDF的概率很大,我们之后按照这个假设来走。
但是这些都不能构成entry point。
到这里,你可能会问:
Nick老师,我们为什么要做这些分析呢?直接把这些字符输入到编码/解码工具里挨个试编码,总有试出来的时候嘛!
也可以,我们可以拿标题来试一下这个方案。从这张图片来看,本文标题应该是:
  1. ŌйúÉç»á¸÷½×¼¶µĀ·ŌÎō
复制代码
如果按照UTF-16BE(PDF的默认编码方案,viz. PDF 1.7文件标准第85页表格),结果如下:
  1. 014C,00D0,00B9,00FA,00C9,00E7,00BB,00E1,
  2. 00B8,00F7,00BD,00D7,00BC,00B6,00B5,0100,
  3. 00B7,014C,00CE,014D
复制代码
到这里基本上不用再试别的了,可以直接宣告凉凉了。
为什么?因为这个字的高8位诡异滴hin啊!我们可以考虑两种可能的情况:

  • 万恶的程序员把宽字符切错了,把16位的编码分在两个wchar里。 但这样所有的高位应该都是0x00才对,但是很明显Ō(0x014C)它就不干了……
  • 这是J/K/TC的编码系统。 更是一棍子打死。无论是日语的Shift-JIS、EUC-JP还是ISO-2022-JP,韩语的EUC-KR,以及我国宝岛常用的Big5,都需要高位>0x80!不可能,绝对不可能……
  • 我们本身输入有误。 本来就是不清晰的屏摄,还涉及了拉丁扩展字母,输错一些东西很正常的。比如说Ō前面的这个·就很可能是错误的。而Ō本身到底对不对其实也有待商榷(后面证实这个字母确实输错了,但是现在即便告诉你错了你也找不到对的字母,哈哈)
那怎么办呢?
还有那个Entry Point到底在哪里呢?
0x2 自然语言

著名的北外校友何炅老师曾经说过一句话:
谁说这豆角老的,这豆角可太棒了!
我在不付任何版权费的情况下想要借用他的这句话:
谁说这自然语言没用的,这自然语言可太有用了!
再看一遍图片里的“正文”,你会发现每一段的结尾都很妙:
6.png

为什么妙呢?另外为什么要画出两个字符呢?请看VCR:
7.png

这个模式非常熟悉,甚至在开头短短这一部分就重复了六次。这种情况下可能在编程语言里很常见(保留字呗),但是在自然语言里绝对值得关注。
但你可能会说:
不就是全文的主题词嘛?
非也!主题词在文中尚可以解释,但是主题词难道会出现在句末嘛?
在句末的必然是一个标点符号。也就是说这个¡£肯定是标点符号,且我猜这应该是。,因为这么频繁出现一定是句号或者逗号,而逗号不能出现在段尾。
Entry Point这不就来了!
现在,我们只需要分析怎么将。转换为¡£就可以了。
先确定¡£的UTF-16BE编码是:
  1. 0x00A1, 0x00A3
复制代码
然后我们惊喜地发现,。的GBK编码刚好就是0xA1A3。
哇咔咔!
再用£¿试一下,£¿的UTF-16BE编码是:
  1. 0x00A3, 0x00BF
复制代码
您猜怎么着!?的GBK编码刚好就是0xA3BF!
那就明白了:
这个PDF文档是中文文档,原本是想要使用GBK编码,但是出于某种原因在生成PDF的时候没有考虑原本的编码,反而全都当UTF-16BE编码做成了一个一个的16位宽字符。
那有了这个基础,我们对于上一节的标题就能进行进一步处理了:
  1. 014C,00D0,00B9,00FA,00C9,00E7,00BB,00E1,
  2. 00B8,00F7,00BD,00D7,00BC,00B6,00B5,0100,
  3. 00B7,014C,00CE,014D
复制代码
去掉一些明显不正确的字符并将其用0xA3BF(刚刚的?)代替,就变成了
  1. A3BF, B9FA, C9E7, BBE1, B8F7, BDD7, BCB6, A3BF, A3BF, A3BF
复制代码
解码出来就是:
  1. ?国社会各阶级???
复制代码
那么第一个问号是什么呢?有可能是“我国”,也有可能是“中国”,或者什么别的国家,先用“我”试一下:
我GBK编码是0xCED2,按照这个PDF编码规则分解为0xCE和0xD2,不符合0x00D0。
中GBK编码是0xD6D0,分解为0xD6和0xD0,正好符合!
再看0x00D6在UTF-16BE中是什么:是Ö……原来那个短横线是两点……虽然但是我学德语的时候也曾经用过这个shorthand,但是冷不丁一看,确实很难想起两点这一个可能……
好,以此类推,我们可以将这个标题纠正为:
  1. ÖйúÉç»á¸÷½×¼¶µÄ·ÖÎö
复制代码
经过上述的转换,这个文章标题是:
  1. 中国社会各阶级的分析
复制代码
这是《毛选》的第一篇文章。得出这个PDF就是《毛选》。剩下的只要找到一本能看的PDF,内容就都出来了!
0x3 结束

至此,完成推理~和发帖人核对了一下信息,基本上都是对的。
但是唯独一点:这个PDF本身就有背景颜色,是米黄色。但是在屏摄的时候由于屏幕反光和摩尔纹干扰,给人一种底色是绿色的感觉……实际上这个浏览器是iOS中微信的PDF预览程序。
没事,总归是得出主要信息了。休息结束(^^ゞ滚去看口译材料了。
0x4 鸣谢

感谢Ms. JIAO Yufeng的朋友圈和原始下载文件。这篇文章使用了由她提供的照片和原始下载文件。
这篇文章同时使用了以下公开资源:

  • Adobe公司的PDF 1.7文件定义 ↗
作者Nick Pang,在CC BY-SA 4.0许可下发布。
8.jpg
9.jpg
10.jpg


来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!

相关推荐

您需要登录后才可以回帖 登录 | 立即注册