安全矩阵

 找回密码
 立即注册
搜索
查看: 902|回复: 0

钓鱼新姿势,在伪装成pdf的doc文档执行宏代码

[复制链接]

417

主题

417

帖子

2391

积分

金牌会员

Rank: 6Rank: 6

积分
2391
发表于 2023-9-12 22:43:29 | 显示全部楼层 |阅读模式
wondeekun 安全的矛与盾 2023-09-04 17:13 发表于浙江

前言
看到群友分享的帖子:https://blogs.jpcert.or.jp/en/2023/08/maldocinpdf.html。原文展示了一个样本,可以在pdf中嵌入一个恶意的doc文档,并可以正常执行其中的宏代码,文章只展示了这个样本,并没有详细说明是为什么,这就引发了我的兴趣,决定探究一番。
在说正事之前,我还需要再补充点基础知识,为什么伪装了文件类型会有助于免杀呢?这就需要说一下杀毒引擎的工作过程了,一般一个杀软收到一个文件之后会进行如下几个步骤:

如果文件格式都识别错误了,那么后续的格式解析特征提取肯定是错的,所以就直接免杀了。
文件分析
拿到文件后,先file一下,可以看到file识别的文件格式确实是pdf:
  1. PDF document, version 1.7, 1 pages (zip deflate encoded)
复制代码
但是与普通文件不同的是这里多了一个 1 pages (zip deflate encoded)接下来用文本编辑器打开:



看起来pdf该有的东西也是有的,只不过pdf格式是不合法的,我用010editor 和 pdf阅读器都不能正常打开此文件。

文章中说 olevba可以识别到此文件中的ole,那我们就试一下:


可以直接获取到启动的vba代码,仔细看输出的日志,可以发现其实olevba是把此文件当做mhtml处理了:



mhtml又是个啥,万能群友发给我一个资料:https://blog.csdn.net/cssxn/article/details/88128741
这个mhtml牛的地方在于,他是个文本文件,还可以执行宏代码,那我也按照帖子的方法制作一个。

看到文件头是:
但是我在样本中并没有搜到这个头呀?既然没有那olevba是怎么识别的呢?
读一下olevba的源代码:
原来只需要mime这个字符串就可以,找一下源样本文件。

样本为了防止被识别这里故意对文件头进行了混淆,还能被word软件识别大概率是因为mhtml文件的容错率是比较高的,这点改动不影响
接下来问题来了,恶意的VBA存储在这个文件的什么位置呢?既然olevba可以识别,那我们可以直接看源码:
  1. try:
  2.     if PYTHON2:
  3.         mhtml = email.message_from_string(stripped_data)
  4.     else:
  5.         # on Python 3, need to use message_from_bytes instead:
  6.         mhtml = email.message_from_bytes(stripped_data)
  7. finally:
  8.     email.feedparser.headerRE = oldHeaderRE
  9. # find all the attached files:
  10. for part in mhtml.walk():
  11.     content_type = part.get_content_type()  # always returns a value
  12.     fname = part.get_filename(None)  # returns None if it fails
  13.     # TODO: get content-location if no filename
  14.     log.debug('MHTML part: filename=%r, content-type=%r' % (fname, content_type))
  15.     part_data = part.get_payload(decode=True)
  16.     # VBA macros are stored in a binary file named "editdata.mso".
  17.     # the data content is an OLE container for the VBA project, compressed
  18.     # using the ActiveMime/MSO format (zlib-compressed), and Base64 encoded.
  19.     # decompress the zlib data starting at offset 0x32, which is the OLE container:
  20.     # check ActiveMime header:
  21.     if isinstance(part_data, bytes) and is_mso_file(part_data):
  22.         log.debug('Found ActiveMime header, decompressing MSO container')
  23.         try:
  24.             ole_data = mso_file_extract(part_data)
复制代码
可以看到这里使用 email 库来解析文件内容,如果解码出来的内容是 mso_file文件,就进入到解析ole格式的解析流程。
is_mso_file函数是判断解码出来的内容是否是ActiveMime开头的:
我们找到文件对应的位置,发现是一片狼藉:
里面包含很多空格和换行,显然是无法被base64解码的,那是怎么回事呢?继续跟踪 email库的get_payload代码:
发现在解码之前会经过很多的容错处理,其中就包括删除空格和换行,所以可以明确了,样本就是利用这里的容错机制进行混淆以绕过检测。手工去除换行和空格,发现对应的字符刚好就是 QWN0aXZlTWltZQAA
自己构造一个样本
我最简单的想法是直接在一个pdf文件后面填充一个 mhtml文件,然后把后缀修改为pdf,看看可以不。



结果证明不行...也就是说他这个pdf肯定是特殊构造的,刚才输出的 1 pages (zip deflate encoded)可能是有用的,那我把原样本的pdf部分直接复制到我的mhtml文件中,发现可以了。


对PDF文件格式不是太了解,并不清楚pdf是怎么构造的,相关的样本可以在星球下载,也欢迎大家加入星球参与讨论。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?立即注册

x
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|安全矩阵

GMT+8, 2024-11-28 07:40 , Processed in 0.015975 second(s), 19 queries .

Powered by Discuz! X4.0

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表