拿到一个 CVE-2010-2883 的样本:
file md5: 68F74C7272BF25B3592F9E46997779E2
file size: 763,188 bytes
这是一个 PDF 文件,其中包含很多的 stream,前面的 FlateDecode 编码的 stream 基本上都是一样的。
最后一个是有害的 ttf 文件,下图是解码前的 stream 结构:
图 1
只是简单的 Flate 编码,我们可以通过如下的 ruby 脚本解码:
#!/usr/bin/env ruby
require 'zlib'
def main(args)
args.each do |filename|
begin
f = File.new(filename, 'rb')
ins = f.read()
f.close
zstream = Zlib::Inflate.new
outs = zstream.inflate(ins)
zstream.close
outname = filename + '.out'
f = File.new(outname, 'wb')
f.write(outs)
f.close
rescue
p "Failed to inflate file: "<<filename
end
end
end
if __FILE__ == $0
main(ARGV)
end
好了,解压后得到如下数据:
图 2
前12个字节是 TTCHeader,后面是 Table Record Entry 数组(个数位于 TTCHeader 结构中)。
TTCHeader 如下:
Type | Name | Description |
---|---|---|
Fixed | sfnt version | 0x00010000 for version 1.0. |
USHORT | numTables | Number of tables. |
USHORT | searchRange | (Maximum power of 2 <= numTables) x 16. |
USHORT | entrySelector | Log2(maximum power of 2 <= numTables). |
USHORT | rangeShift | NumTables x 16-searchRange. |
每一个 Table Record Entry 结构如下:
Type | Name | Description |
---|---|---|
ULONG | tag | 4 -byte identifier. |
ULONG | checkSum | CheckSum for this table. |
ULONG | offset | Offset from beginning of TrueType font file. |
ULONG | length | Length of this table. |
有一点需要注意的是,所有数据均为 Big-endian,所以,我们需要做转换。
CVE-2010-2883 的漏洞问题出在 SING 表段(数据如下,高亮选择部分):
图 3
可见,SING 结构文件偏移: 0x11C,大小: 0x1DDF.
SING 的结构为:
我们从 图2 可以看到,问题出在 uniqueName 上。
有兴趣的朋友可以调试一下,问题点位于 adobe reader 的 cooltype.dll 中。