关于 PDZ,也许大部分都不知道这是什么东西。摘抄一下第三方的介绍:
PDZ格式是一种电子书文件格式,主要用于超星阅读器(由超星公司推出的一款电子书阅读及下载管理的客户端软件)中的电子书资源。这种格式的特点是能够提供较好的版权保护,并且通常包含了丰富的电子书阅读功能,如书签、标记、资源采集、文字识别等。
简而言之,PDZ&PDG文件都是超星自家构建的一个文件格式。
TL;DR
- PDG 可以视作电子书的单页,包含诸如图像数据的信息
- PDZ 可以视作多个 PDG 文件的集合、额外的,其包含了图书信息,证书信息
当然,有关 PDZ & PDG 文件格式本身,我们对其知之甚少。互联网上与之相关的内容大多涉及话题:PDZ/PDG转PDF,而在此话题下,能够阅览到的仅仅是通过各种依赖原客户端本身对其进行截图,合成PDF的操作。这意味着 PDZ 对我们来说仍是一个黑盒。
通过逆向工程,我们可以了解到 PDZ 文件的一些基本信息。
其拥有一个固定大小的文件头部: PDZHdr
此结构包含了一些基本信息,包括:
- 文件标识符
- 文件类型
- 版本信息
- 打包所使用的加密算法
- 电子书的类型
- 元数据的位置
- 元数据的大小
- CRC 校验
- etc.
这里通过表格列举出部分关键字段,对于暂不知其用途的字段统一标为 unknown
Offset |
Size |
Name |
Desc |
value |
0 |
4 |
magic |
magic value |
0x67647025 |
0x4 |
4 |
type |
|
0x0000007A / 0x0000787A / 0x0000667A / 0x00006D7A |
0x8 |
4 |
version |
PDZ format version |
"1.01" |
0xC |
1 |
unknown |
|
|
0xD |
1 |
cipherType |
packet algo |
1 = tea<br>2 = des<br>3 = unknown<br>4 = blowfish |
0xE |
1 |
unknown |
|
|
0xF |
1 |
bookType |
|
enum 1 / 2 / 3 / 4 / 5 |
0x10 |
4 |
contentSize |
content size |
|
0x14 |
4 |
catalogOffset |
catalog offset |
|
0x18 |
4 |
catalogSize |
catalog size |
|
0x1C |
0x20 |
marker |
packet marker |
|
0x3C |
0x4 |
checksum |
crc32 |
|
0x40 |
0x20 |
reserved |
reserved field |
|
显而易见,我们需要通过 catalog 去列出文件的目录,而 catalogOffset 处对应的数据段为加密段,其使用固定算法 tea,固定密钥进行加密。
这并不难,解密后,我们可以可以看到形似下图的内容。
不妨猜一猜其包含了哪些内容。
其包含了基本的文件名、文件偏移、文件大小。
通过表格列出其结构
Offset |
Size |
Name |
0 |
0xC |
filename |
0xC |
0x4 |
offset |
0x10 |
0x4 |
size |
此时我们通过此类结构字段,定位到对应文件位置,确定文件大小。但同时发现,其数据仍然为加密段。此时将用到 PDZHdr 中的 cipherType 字段,根据此字段指定算法进行解密。但需要注意的是,为了解密,我们需要得到 key。溯源 key 后可以发现其来自于位于文件末尾的证书段。
证书段内容为明文段,以下是一段示例:
SSCT9770740AE18486AB8415F2F1605C71F78C2EA79C82B8853FA74D02EA14AA2E4003E22AF282A42B45F4365A4CA4D7CB3EEAA87863C29AEF4847B09628981D7489341668FD45F5E2E0437B337582E2E7422F571518A44C20C12D960460A0E122CF0D3A315481B8A7D2303438D406C44606925E120D3EFECFC3201B0166BF35ED128D464CD114938AA1138D236D83545231AFA8A4570F6D049D44F135D3144EB58924D1B9A5980890BC21B85321BD5303F2BC803FBED9CEBB10F9E26DEBB10C642315213DA4CAFEA41C25A46813CF89F581E1FF7411A91F1F3F0441E14A0C514328BB2FBDF5F631CBC1B82291954439B976BAEADCA5EA51C156AE8C7F8190632AC38005BC385A33A1CD3B7F1C7A9BEA86C5B83F1AC6BACC0220844229C5DC6CC114FCBEC353FE8FAE6F52E3EE521296C4291A7E360D91E7FE2451950AA67F9C59EE2F7DA3C7B1567B0A022BFC780A435AD34EC3650F625386EA0263F858E20DBD004FE2E9B69E02E16F6F48CE9B0FF7318990139F214AC7ECE148A4CAFE8CCE39FA37CE240BF32477A2B01401892C16011FBCC57407CD3ADF0AFD04A11730A49F4BF80017FE9548F3EE2235A407AC29261BB89D[p?ver=2&un=unRegister&type=2]SSCE
其可被解析为多个子段,客户端据此验证并限制使用者身份、电子书有效期等相关手段。下面是一段解密后示例
<?xml version="1.0" encoding="UTF-8"?>
<cert>
<certexpdate>2073-11-09</certexpdate>
<userinfo>
<username>{*}</username>
<useraccount></useraccount>
<password></password>
<userexpdate>0</userexpdate>
</userinfo>
<rightinfo>
<bookkey>****L9Z5</bookkey>
<print canprint="" printlimit="" printrange=""/>
<copy cancopy="" copylimit="" copyrange=""/>
</rightinfo>
<auth>****660CB9AF2A03CD26AB1CD******2</auth>
<reserve></reserve>
</cert>
这里出现的 bookkey 或 key 即解密 PDG 文件的 key。
当然,所有上述 key 并非直接使用,而是通过对应字母表映射后,得到一串长度为 32 的十六进制明文串后进行 MD5,最终得到 16 字节的 key。
PS: 出于研究目的,暂时揭露上述部分。
最后放一张使用 010 Editor 进行解析的图。
|