1、Office Macor
MS office宏的编程语言是Visual Basic For Applications(VBA)。
微软在1994年发行的Excel5.0版本中,即具备了VBA的宏功能。开发目的是为了在其桌面应用程序中执行通用的自动化任务,用于扩展Windows的应用程序功能。在分析带有宏病毒的样本前,我们需要对VBA有所了解。才能更顺畅地了解病毒发展中的手段和变化。
2、VBA代码阅读扫盲
(1) 环境介绍
- 打开Excel的开发者工具
当用户希望使用宏功能时,可在“开发工具”选项卡下选择相应命令。在默认情况下,功能区中不显示“开发工具”选项卡,需要用户进行自行设置。
图1
- 保存带宏测试文件
微软为了使用MSOffice用户免遭病毒和危险宏代码的危害,规定不能将宏代码保存在使用标准文件扩展名的标准 Office 文档中。
必须将代码保存在特殊扩展名的文件中。例如不能将宏保存在扩展名为 .docx 的标准 Word 文档中;而是必须使用扩展名为 .docm 且启用了宏的特殊 Word 文档。而Excel则是另存为.xlsm格式。
(2) 宏脚本运行入口点
让Excel工作簿中宏自动运行的两种方法。
方法1:
1、启动Excel并打开包含宏的工作表,在“开发工具”选项卡的“代码”组中单击“宏”按钮打开“宏”对话框。
图2
创建宏名为"Auto_Open"可以实现自动打开的功能。
图3
点击“Visual Basic”按钮就可以编辑对应的宏代码。
会弹出"Hello World”框的示例代码:
方法1:测试代码
01-Auto_Open()_启用宏.xlsm
//自启动函数1
Sub Auto_Open()
MsgBox ("Hello World")
End Sub
方法2:
点击Visual Basic按钮,点击在工程窗口里的ThisWorkbook。选择workbook(对象)
图4
保存该文档为".xlsm",当再次打开该文档时,宏将自动运行。
在分析病毒的时候,发现Workbook_Open(),Workbook_Activate()都会触发宏的运行。
方法2:测试代码
02-Workbook_Open()_启用宏.xlsm
Private Sub Workbook_Open()
MsgBox ("Hello World ! z")
End Sub
小结:
Auto_Open过程是一个特殊的自定义Sub过程,其包含的代码可以在工作簿打开时自动执行,宏过程写入其中当然也将被自动调用执行。Worksheet对象的Activate事件是在工作表被激活时触发,在该事件代码中调用宏过程将使工作表被激活时宏被启用。
(3) 代码调试
通过录制宏的操作,得到如何对表格赋值的方法。
A1是所选择的表格与列,ActiveCell.FormulaR1C1是进行赋值。
Range("A1").Select '表格选择
ActiveCell.FormulaR1C1 = "1" '赋值
在开启之前首先要开启编译器的窗口。
-
立即窗口:执行单行的语句或显示Debug.Pring所打印的表达式的值。
-
本地窗口:显示当前运行的过程中所包含的变量的值。
-
监视窗口:显示被监视的指定表达式的值。
图5
(4) 变量
声明 变量时,通常使用 Dim 语句。可以在过程中添加声明语句以创建 过程级别变量,也可以将其放置在 模块顶部的声明部分,以创建 模块级别变量。
下面的示例创建变量并指定 字符串数据类型。
strName 是变量的名称,type是变量的类型
Dim strName As 【type】
数据类型分类及表示形式:
(1) 数值型
Byte 、Integer 、Long 、Single 、Double
(2) 字符型
String (可变长度字符串)、String *** length (固定长度字符串)
(3) 日期型
Date
(4) 逻辑型
Boolean
(5) 对象型
Object 或 Variant 。如果未指定数据类型,则默认分配 Variant 数据类型。还可以使用 Type 语句创建 用户定义的类型。
声明的表示形式如下:
Dim sPara As sType
Dim para1, para2, para3
Dim para4 As workbook, para5 As String
用Dim语句创建变量(声明变量) 示例:
Sub 变量定义()
'
' 变量定义 宏
'
'变量定义
Dim strA As String
'变量赋值
strA = "Hello World"
Debug.Print strA
End Sub
VBA常用的数据类型定义里参数type是可省略的。对于VBA熟悉的开发者会省略AS采用变量标识符来声明变量类型,遇到这样的代码很容易使分析人员产生疑惑。
图6
类型标识符示例代码:
Sub 类型标识符()
'类型标识符
Dim strC$
strC = "WS发育法"
Debug.Print strC
End Sub
全局变量
在VBA中,通过Public关键字语句定义全局变量,供多个程序调用。
'声明全局变量
Public strA As String
Sub 过程1()
' 变量声明
Dim strB As String
' 变量赋值
strA = "Hello"
strB = "World!"
End Sub
Sub 过程2()
' 输出变量
Debug.Print "StrA为" & strA
Debug.Print "StrB为" & strB
End Sub
Sub 过程()
' 调用函数
Call 过程1
Call 过程2
End Sub
输出结果:
StrA为Hello
StrB为
模块级变量
还有一种特殊的模块级变量,定义在所有的过程之外,也以Dim进行变量声明。这类变量的作用域是其所在的模块,在这个模块内的任何过程均可调用该变量,但是其他模块不可以调用它。
通过调用两个模块的代码进行验证过程如下:
模块:模块级变量03_01代码:
'声明局部变量
Dim strC As String
Sub 过程3()
'变量赋值
strC = "Hello"
End Sub
Sub 过程4()
'变量赋值
Debug.Print "StrC为" & strC
End Sub
插入->模块,再输入以下代码:
查看模块间函数调用,变量的变化。
模块:模块级变量03_02
Sub 过程5()
'变量赋值
Debug.Print "StrC为" & strC
End Sub
Sub 过程6()
Call 过程3
Call 过程4
Call 过程5
End Sub
输出结果:
StrC为Hello
StrC为
作用域的理解至关重要,简单区分作用域的方法只需要判定变量声明是在哪里,如果在过程内,则作用域为该过程,如果在过程外,以Public声明的变量为全局变量,以Dim或Private声明的变量为模块级变量。
(5) 运算符
VBA除了常规的四则运算外,还能够进行文本连接,比较运算。
其中为了生成的数据更明朗,就用了回车换行。
'chr(10) 可以生成换行符
'chr(13) 可以生成回车符
Sub VBA常用运算()
'文本连接 F5运行
Debug.Print """Excel"" & ""WS"" = "; "Excel" & "Virus" & Chr(13) & Chr(10)
'算数四则运算
Debug.Print " 1 + 2 * 3 - 4 / 2 = "; 1 + 2 * 3 - 4 / 2 & Chr(13) & Chr(10)
'整除
Debug.Print "13 \ 5 = "; 13 \ 5 & Chr(13) & Chr(10)
'计算余数
Debug.Print "13 Mod 5 = "; 13 Mod 5 & Chr(13) & Chr(10)
'比较运算
Debug.Print "13 > 5 = "; 13 > 5 & Chr(13) & Chr(10)
Debug.Print "13 < 5 = "; 13 < 5 & Chr(13) & Chr(10)
Debug.Print "13 <> 5 = "; 13 <> 5 & Chr(13) & Chr(10)
End Sub
文本连接
在VBA中,允许将多个文本通过文本连接符(&)进行连接并组合成新的本文,其基本语法为
EXP1&EXP2&EXP3
加号(+)同样可以用于文本的连接,其运算语法与文本连接符(&)一致,而加号同样可以用作算数运算。
算数四则运算
算数四则运算符包括加(+)、减(-)、乘(*)、除(/)。
(6) 逻辑运算符
在IF判断中遇到多条件的判断,判断是否同时满足两个条件的情形,会用到逻辑运算符。常见的为And、Or、Not
表达式 逻辑运算符 表达式
(7) IF分支选择结构
典型的分支结构,最常用的就是IF...Then...Else结构,语法为:
If 表达式
Then
声明
Else
声明
或者
If 表达式 Then
声明
ElseIf 表达式 Then
声明
Else
声明
End If
表达式是逻辑判断表达式,可以是比较,也可以是由逻辑运算符连接的表达式。
单一型IF分支结构代码如下:
Sub IF分支1()
'变量声明
Dim NumA As Long '密码值
Dim NumB As Long '数值2
NumA = 5
NumB = 6
If NumA > NumB Then
Debug.Print "NumA " & NumA
End If
End Sub
复杂型If分支结构如下:
Sub IF分支2()
'变量声明
Dim passwd As Long '密码值
Dim input_Code As Long '数值2
passwd = 123456
'两数相加
'Range("A2").Select
'ActiveCell.FormulaR1C1 = "1"
input_Code = Range("A2")
If input_Code < passwd Then
Range("A6").Select '选择表格A6
ActiveCell.FormulaR1C1 = "结果小了" '赋值
ElseIf input_Code > passwd Then
Range("A6").Select
ActiveCell.FormulaR1C1 = "结果大了"
ElseIf input_Code = passwd Then
Range("A6").Select
ActiveCell.FormulaR1C1 &