迪迪埃·史蒂文斯 (Didier Stevens) 制作了一个节目,名为“pdfid”(https://blog.didierstevens.com/2009/03/31/pdfid/ 和 https://blog.didierstevens.com/programs/pdf-tools/#pdfid)。
他说:
“我开发了一种新工具 PDFiD 来分类 PDF 文档。它可以帮助您区分可能是恶意的 PDF 文档和最有可能不是恶意的 PDF 文档。”
这就是我想用它的目的。
“PDFiD 将扫描 PDF 文档中的给定字符串列表,并计算每个单词的出现次数(总数和混淆后的次数):”
obj
endobj
stream
endstream
xref
trailer
startxref
/Page
/Encrypt
/ObjStm
/JS
/JavaScript
/AA
/OpenAction
/AcroForm
/JBIG2Decode
/RichMedia
/Launch
/XFA
据我所知,“obj”和“endobj”的值应该匹配,这意味着没有打开未关闭的对象(可能导致缓冲区溢出或其他问题)。
理想情况下
/JS /JavaScript /AA /OpenAction /AcroForm
应该有零值。
然而我见过很多 pdf 文档的“obj”和“endobj”不匹配,但其他值似乎没问题
示例:Using_FreeDOS.pdf 来自http://www.freedos.org/ebook/download/using-freedos-24.pdf。
pdfid 结果:
PDF Header: %PDF-1.4
obj 520
endobj 519
stream 193
endstream 193
xref 1
trailer 1
startxref 1
/Page 100
/Encrypt 0
/ObjStm 0
/JS 0
/JavaScript 0
/AA 0
/OpenAction 1
/AcroForm 0
/JBIG2Decode 0
/RichMedia 0
/Launch 0
/EmbeddedFile 0
/XFA 0
/URI 8
/Colors > 2^24 0
然而这个也有“/OpenAction 1”。我不太确定这个有多大相关性。
尽管如此:
当字符串列表的其余部分和计数都正常时,“obj”和“endobj”匹配有多重要?
正如已经说过的:有很多 pdf 文档的“obj”和“endobj”不匹配。
答案1
pdfid 显然在计算 obj/endobj 对方面做得很糟糕 - 在您的特定示例中,奇怪的“obj”是 FlateDecode 流的一部分:
$ cat pdf.pl
use Compress::Zlib qw(inflateInit Z_STREAM_END);
use strict;
my ($o);
while(<>){
$o -= s/\bendobj\b//g;
$o += s/\b\d+\s+\d+\s+obj\b//g;
if(/\bstream\s*$/){
local $/ = "endstream"; my $s = <>; $s =~ s/\s*endstream$//;
if($s =~ /(\w*obj)/){
my ($d, $err) = inflateInit->inflate($s);
if(length($s) == 0 && $err == Z_STREAM_END){
warn "innocuous '$1' in well formed stream\n";
}else{
warn "WARNING: inflateInit: $err\n";
}
}
}
if(/(\w*obj)\b/){ warn "WARNING: possible stray $1\n" }
}
warn "WARNING: unbalanced obj/endobj: $o\n" if $o;
$ perl pdf.pl using-freedos-24.pdf
innocuous 'obj' in well formed stream
注意:这只是为了说明当前的问题;不要用它来检查 pdf 是否安全;-)
pdf 格式相当麻烦且复杂;你确实需要一个成熟的解析器来理解它的结构。能够做到这一点(为了正确识别恶意 pdf)的程序本身正在成为攻击媒介——没有理由相信临时解析器比 libpoppler 或 libmupdf 更安全。