参考:https://resources.infosecinstitute.com/topic/pdf-file-format-basic-structure/
PDF是一种可移植的文档格式,可用于显示包含文本,图像,多媒体元素,网页链接等内容。PDF文件格式规范链接:https://opensource.adobe.com/dc-acrobat-sdk-docs/。官方链接中仅仅文件格式的文档就有800多页,因此通读该文档并不是意见容易的事。
PDF不仅具有文本功能,还具有更多的功能:它可以包含图像和其他多媒体元素,受密码保护,执行JavaScript等。下图显示了PDF文件的基本结构:
下文中[]中的内容为上图中的结构体。
Header
[PDFHeader]这是PDF文件的第一行,它指定文档使用的所用PDF规范的版本号.此处PDF文档版本为1.7.
[PDFComment] 这部分是PDF文档的注释部分
Body
在PDF文档的正文中,有一些对象通常包括文本流,图像,其他多媒体元素等。“正文”部分用于保存所有显示给用户的文档数据。
即[PDFObj] sPdfObj[0]-sPdfObj[12]都是Body部分。
xref table
这是交叉引用表,其中包含对文档中所有对象的引用。交叉引用表的目的是允许它随机访问文件中的对象,因此我们无需阅读整个PDF文档即可找到特定的对象。每个对象由交叉引用表中的一个条目表示,该条目始终长20个字节。让我们来看一个例子:
xref
0 14
0000000000 65536 f
0000000017 00000 n
0000000066 00000 n
0000000122 00000 n
0000000258 00000 n
0000000367 00000 n
0000000500 00000 n
0000000831 00000 n
0000001013 00000 n
0000001197 00000 n
0000010222 00000 n
0000010294 00000 n
0000010366 00000 n
0000010431 00000 n
我们可以通过使用文本编辑器简单地打开PDF并滚动到文档底部来显示PDF文档的交叉引用表。
0 14
这行中的第一个数字0对应于对象编号,而第二列显示当前子节中的对象数量14。
0000000000 65536 f
0000000017 00000 n
0000000066 00000 n。。。。。。
每个对象由一个条目表示,该条目长20个字节(包括CRLF)。
前10个字节是对象从PDF文档开始到该对象开始的偏移量。接下来是一个空格分隔符,其中另一个数字指定对象的世代号。之后,还有另一个空格分隔符,后跟字母“ f”或“ n”以指示对象是空闲的还是正在使用的。
Trailer
PDF Trailer 指定读取PDF文档的应用程序应如何找到交叉引用表和其他特殊对象。所有PDF阅读器都应从文件末尾开始阅读PDF。以下是一个Trailer示例:
trailer
<<
/Root 1 0 R
/Info 3 0 R
/Size 14/ID[<EA61F2FE98704E5009E01A59031F93DD><EA61F2FE98704E5009E01A59031F93DD>]>>
startxref
10750
%%EOF
PDF文档的最后一行包含“ %% EOF”文件字符串的结尾。在文件标记末尾之前,有一行带有startxref字符串的行,用于指定从文件开头到交叉引用表的偏移量。在此例中,交叉引用表从偏移量10750字节开始。在此之前是Trailer字符串,用于指定当前部分的开始。此节的内容嵌入在<<和>>字符内(这是一个接受键值对的字典)。
我们可以看到此部分定义了几个键,每个键用于一个特定的动作。此部分指定以下键:
- / Size [integer]:指定交叉引用表中的条目数(也对更新部分中的对象进行计数)。使用的号码不应是间接引用。
- / Prev [integer]:指定从文件开头到上一个交叉引用节的偏移量,如果有多个交叉引用节,则使用此偏移量。该数字应为交叉引用。
- / Root [dictionary]:指定文档目录对象的引用对象,这是一个特殊对象,其中包含指向不同种类的其他特殊对象的各种指针(稍后会对此进行更多介绍)。
- / Encrypt [dictionary]:指定文档的加密字典。
- / Info [dictionary]:指定文档信息字典的参考对象。
- / ID [array]:指定由两个字节的未加密字符串组成的数组,这些字符串构成文件标识符。
- / XrefStm [integer]:指定从文件开头到解码流中的交叉引用流的偏移量。这仅存在于混合引用文件中,如果我们也想打开文档,即使应用程序不支持压缩的参考流,也可以指定该文件。
我们必须记住,如果以后再更新PDF文档,则可以修改初始结构。该更新通常在文件末尾附加其他元素。
增量更新
PDF的设计考虑了增量更新,因为我们可以在不重写整个文件的情况下将一些对象附加到PDF文件的末尾。因此,可以快速保存对PDF文档的更改。下图显示了PDF文档的新结构: