• 我们在哪一颗星上见过 ,以至如此相互思念 ;我们在哪一颗星上相互思念过,以至如此相互深爱
  • 我们在哪一颗星上分别 ,以至如此相互辉映 ;我们在哪一颗星上入睡 ,以至如此唤醒黎明
  • 认识世界 克服困难 洞悉所有 贴近生活 寻找珍爱 感受彼此

恶意代码技术理论:恶意文档-PDF恶意代码分析

基于类型 云涯 4年前 (2020-09-08) 2257次浏览

1. PDF文件结构

PDF是一种便携式文档格式,可用于显示包含文本,图像,多媒体元素,网页链接等的文档。它具有多种功能。

现在PDF版本正在不断更新,官方地址:https://www.adobe.com/devnet/pdf/pdf_reference.html

PDF不仅具有文本功能,还具有更多功能。它可以包含图像和其他多媒体元素,可以受密码保护,可以执行JavaScript等。PDF文件的基本结构如下图所示:

images

–标题这是PDF文件的第一行,指定文档使用的所用PDF规范的版本号。

比如“0000000: 2550 4446 2d31 2e33 0a25 c4e5 f2e5 eba7 ”它的ascii码是“%PDF-1.3.%……“代表1.3版本。’%’字符是PDF中的注释,因此上面的示例实际上将第一行和第二行显示为注释,这对于所有PDF文档都是如此。

正文在PDF文档的正文中,通常包含文本流,图像,其他多媒体元素等的对象。“正文”部分用于保存显示给用户的所有文档数据。

– xref表这是交叉引用表,其中包含对文档中所有对象的引用。交叉引用表的目的是允许它随机访问文件中的对象,因此我们无需阅读整个PDF文档即可找到特定的对象。每个对象由交叉​​引用表中的一个条目表示,该条目始终为20个字节。使用文本编辑器打开PDF并滚动到文档底部,即可显示PDF文档的交叉引用表。示例如下:

–预告片: PDF预告片指定读取PDF文档的应用程序应如何找到交叉引用表和其他特殊对象。所有PDF阅读器都应从文件末尾开始阅读PDF。PDF文档的最后一行包含文件字符串’%% EOF’的末尾。

——————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————

xref表:

————————————————————————————————————————

xref                                                |

0 1                                                 |

0000000023 65535 f                     |

3 1                                                 |

0000025324 00000 n                    |

21 4                                               |

0000025518 00002 n                    |

0000025632 00000 n                    |

0000000024 00001 f                     |

0000000000 00001 f                     |

36 1                                               |

0000026900 00000 n                    |

xref
i j
nnnnnnnnnn ggggg N eol
nnnnnnnnnn ggggg N eol
......
nnnnnnnnnn ggggg N eol

第一行 xref 表示交叉引用表开始;

第二行 i j 表示下面部分引用的对象从 i 开始,共有 j 个对象;

第三行开始相同的结构,每行20字节,包括换行符。

nnnnnnnnnn 10位,字节偏移地址,表示从 文件开始(beginning of the file) 到 该对象开始(beginning of the object) 的偏移;

ggggg 5位,生成号;

N 可以为 n 或者 f,其中 n 表示该对象在使用,f 表示该对象为free状态,未被使用。
————————————————————————————————————————

Trailer:
————————————————————————————————————————

trailer           ——————————-> 指定预告片开始

<<

/Size 22        ——————————->   – / Size [integer]:指定交叉引用表中的条目数(也对更新部分中的对象进行计数)。使用的号码不应是间接引用。

                     ——————————-> – / Prev [integer]:指定从文件开头到上一个交叉引用节的偏移量,如果有多个交叉引用节,则使用此偏移量。该数字应为交叉参考。

/Root 2 0 R   ——————————->   – / Root [dictionary]:指定文档目录对象的引用对象,这是一个特殊对象,其中包含指向不同种类的其他特殊对象的各种指针。

                     ——————————-> – / Encrypt [字典]:指定文档的加密字典。

/Info 1 0 R    ——————————->  – / Info [dictionary]:指定文档信息字典的参考对象。

                     ——————————-> – / ID [array]:指定由两个字节的未加密字符串组成的数组,这些字符串构成文件标识符。

                     ——————————->  – / XrefStm [整数]:指定从文件开头到解码流中的交叉引用流的偏移量。这仅存在于混合引用文件中。

>>

startxref       ——————————-> 在文件标记末尾之前,有一行包含字符串startxref的行,该行指定从文件开头到交叉引用表的偏移量。在我们的情况下,交叉引用表从偏移量24212字节开始。

24212

%%EOF       ——————————->  我们必须记住,如果以后再更新PDF文档,则可以修改初始结构。此更新通常在文件末尾附加其他元素。

————————————————————————————————————————

关键字:

obj            #obj对象开始
endobj         #obj对象结束

stream         #stream流对象开始
endstream      #stream流对象结束

xref           #交叉引用表开始
trailer        #文件尾对象开始
startxref      #交叉引用表结束

/Page        #文件页数
/Encrypt       #是否加密
/ObjStm        #objectstreams的数量,objectstreams可包含其他Object对象,即嵌套

/JS            #代表javascript 嵌有JavaScript代码,可直接提取恶意代码
/JavaScript    #代表javascript 嵌有JavaScript代码,可直接提取恶意代码

#以下三个为特定特征,打开对象自动执行
/AA            
/OpenAction
/AcroForm

/URI           #内嵌url链接

/Filter        #/Filter字段出现,表示了下面的stream流进行了加密
/RichMedia     #富文本
/Launch        #执行Action的次数与OpenAction字段关联
#/xxxx 带斜杠的关键字包含在<<>>字典内部

/Filter关键字之后保存了stream流的编码信息一共包括以下几种,

同时可以级联编码如:[/FlateDecode /ASCIIHexDecode],表示流先经过了ASCIIHexDecode再经过了FlateDecode编码

解密是即先对流进行FlateDecode解码再对流进行ASCIIHexDecode解码。

/FlateDecode
/ASCIIHexDecode
/ASCII85Decode
/LZWDecode
/DCTDecode
/RunLengthDecode
/CCITTFaxDecode
/JBIG2Decode
/JPXDecode
/Crypt

处理流程:

+--------------------------+
|       读取 PDF 文件        |
|                          |
+------------+-------------+
             |
+------------v-------------+
|   从文件末尾开始解析得到     |
|   索引和文件对象起始位置     |
+------------+-------------+
             |
+------------v-------------+
|      得到PDF基本信息以及    |
|        PDF的根目录对象     |
+------------+-------------+
             |
+------------v-------------+
|    通过根目录对象得到PDF的  |
|   所有大纲和页面的对象集合   |
+------------+-------------+
             |
+------------v-------------+
|                          |
|   当用户转到第几页时,解析   |
|   该PDF页面上的所有对象     |
|   包括文字,图片,流媒体等   |
|                          |
|                          |
+------------+-------------+
             |
+------------v-------------+
| 将得到的文件流通过渲染引擎,  |
|     生成特定文件显示出来     |
+--------------------------+

2. 恶意文件防御规避

2.1. 交叉引用表

2.1.1 引用表偏移不正确

PDF解析找到交叉引用表偏移地址,再通过偏移地址找到交叉引用表。而下面样本8090不是交叉引用表真正偏移地址。

Xref    #表示交叉引用表开始
0 2     #0表明引用表描述的对象编号从0开始,8说明共有8个对象
0000000000 65536 f #一般pdf都是以这行开始交叉引用表的,起始地址0和产生号
0000003195 00000 n #表示对象1,就是catalog,3195为偏移地址n表示对象在使用
startxref
8980  #8980为交叉引用表的偏移地址,此处为十进制表示
%%EOF #文件结束标志

2.1.2 多个引用表

xref
0 4
0000000000 65535 f
0000000000 65536 n
0000039095 00000 n
0000000015 00000 n
trailer
<</ID
[<386e381fac5d8245e24ee620741d0d06><b15c4bebcdae6f2210f09460b841e7a3>]/Root
26 0 R/Size 28/Info 27 0 R>>
startxref
39630
%%EOF
<</Filter/FlateDecode/Length
6960/Subtype/Type1C>>
Stream
Ddd
endstream
xref
20 1
0000040341 00000 n
26 4
0000040380 00000 n
0000040484 00000 n
0000040677 00000 n
0000040734 00000 n
55 2
0000172790 00000 n
0000172925 00000 n
trailer
<</Root 26 0 R/Info 27 0
R/ID[<386E381FAC5D8245E24EE620741D0D06><39FE58436C8CC909F538F88909F1EE55>]/Size
63/Prev 39630>>
startxref
173446
%%EOF

2.2 字符串长度

2.2.1 流对象长度可以直接跟对象

正常/Length之后的数值代表stream~endstream两个关键字之间流的长度

7 0 obj
<</Filter/FlateDecode/Length 6960/Subtype/Type1C>>
stream

但是样本中可以是OBJ对象长度

2 0 obj
<< /Length 4 0 R /Filter
/FlateDecode >>
#对应的obj对象中包含的长度如下
4 0 obj
4880
endobj

所以stream流对象压缩前的实际长度为4880,虽然是PDF格式的正规使用方法,但同时也是规避杀软的一种手法。

2.2.2 流对象长度可以为任意值

正常流对象长度如下

7 0 obj
<</Filter/FlateDecode/Length
6960/Subtype/Type1C>>
stream 

样本中如下:

16 0 obj
<<
/Length ANIWAY_____LEN
>>
stream

ANIWAY_LEN是什么???所以,/Length后面可以不跟数值stream流的实际长度,实际:关键字endstream偏移 – 关键字stream偏移 – 包含的0x0D或0x0A

2.3 解码问题

2.3.1 javascript可以支持文本和八进制

7 0 obj
<< /Type /Action
/S /JavaScript
/JS (\145\166\141\154\050\146\165\156)
endobj
/JS 16 0 R
/S /JavaScript
>>
endobj
16 0 obj
<<
/Length ANIWAY_____LEN
>>
stream
function urpl(k,sc){
var c = "\x75";
var kc=k+c;
var re = /MM/g;
sc = sc.replace(re,kc);
return sc;
}
padding_0c = "MM0c0cMM0c0c";
padding00="MM0000";
padding_41 = "MM4141";
var x1=0;
var x2=0;
var x3=0;
endstream
endobj

2.3.2 编码方式缩写形式

正常文件默认/Filter关键字之后会出现xxdecode关键字表示stream流编码方式

如下/Fl字段即为/FlateDecode的简写:

1 0 obj
<</Filter [/Fl /Fl] /Length 8331
>>
Stream
xœíÜYXù
÷qÆÌ0K3ÆØRÆVdoUƒQ"[M!S(íRÓ¾0–h¥B*d•hß~5´©
endstream

对应表如下:

/FlateDecode     /Fl
/ASCIIHexDecode  /AHx
/ASCII85Decode   /A85
/LZWDecode       /LZW
/RunLengthDecode /RL
/CCITTFaxDecode  /CCF
/JBIG2Decode #/JBIG2Decode其实和/DCTDecode解码方式是一样的
/DCTDecode       /DCT

2.3.3 编码形式可以级联

流先经过了ASCIIHex加密再进行了FlateDecode加密

解码时需要先进行FlateDecode解密之后再进行ASCIIHexDecode解密

10 0 obj 
<</Filter
[/FlateDecode /ASCIIHexDecode]
/Length 14278>>

3. 恶意文件分析工具

3.1 PdfStreamDumper

stream流解析工具,无法解析级联编码后的stream流,例如/Fl/Fl编码就无法解析。

3.2 PDFParser

c++开源项目,pdf格式解析,逻辑比较清晰

3.3 ParanoiDF

python开源项目


云涯历险记 , 版权所有丨如未注明 , 均为原创丨本网站采用BY-NC-SA协议进行授权
转载请注明原文链接:恶意代码技术理论:恶意文档-PDF恶意代码分析
喜欢 (1)