RE Adventures : VB Malware Analysis
Kapil Kapre | Friday, Oct 25, 2013

I had loaned one of my USB drives out to someone and as it usually happens, it came back with a nice little malware infection. At this point sticking your USB drive into a very public computer (e.g. One they use at a photo booth/kiosk to print stuff) is very much like visiting certain members of the oldest profession. I opened up the drive folder and was pleasantly surprised to see an unwanted executable instead of a folder containing my data.

explorer window showing my usb drive

Further investigation revealed that my data was still there, albeit hidden.


xplorer2 window showing hidden folder

I assumed this was one the 'ransomware' type of malware which extracted some payment from the victim in exchange for restoring data access. Never having seen one live, I wondered if I could poke around and see what it was all about. Seeing a bunch of MSVBVM60.DLL imports and the call to ThunRTMain made it almost certain that this was a VB executable. Now, as you might or might not be aware, in 1983, long before the JVM or the .NET CLR existed Microsoft had another VM based tech called P-Code. P-Code which was based on UCSD Pascal, was an intermediate language that Applications, DLLs, ActiveX objects could be compiled into. Upon execution, an interpreter translated the P-Code to the underlying processor's object code. However unlike the CLR, the primary reason for the existence of this tech is the reduced code size, not portability. Experienced readers will immediately realize why I'm mentioning this. Yes, its the dreaded virual machine ! If you want to live-debug any code, you have to execute it, but if you execute interpreted code you end up debugging the virtual machine itself. Now certainly, there are ways around this ofcource. For e.g. you could create a disassembly of the p-code by hooking into the VB VM and check what each individual opcode does. Maybe you could even automate this and create a disassembler. But the point is - this is a real PITA.

So, The first order of business was to determine whether this was a native or a p-code executable. Luckily this turned out to be a regular native executable. Note that BOTH kinds use MSVBVM60.DLL. As I was browsing the the disassembly, I started running into some interesting stuff.

.....
.text:004A4004                 unicode 0, <(>,0
.text:004A4008 a****2_no_0:                        ; DATA XREF: .text:004AC587o
.text:004A4008                                         ; .text:004AC696o ...
.text:004A4008                 unicode 0, <****.no-ip.info>,0
.text:004A4032                 align 4
.text:004A4034                 unicode 0, <&>,0
.text:004A4038 a****2_no_1:                        ; DATA XREF: .text:004AC7A5o
.text:004A4038                                         ; .text:004AC8B4o ...
.text:004A4038                 unicode 0, <****.no-ip.org>,0
.text:004A4060                 unicode 0, <&>,0
.text:004A4064 a****3_noIp:                        ; DATA XREF: .text:004AC9C3o
.text:004A4064                                         ; .text:004ACAD2o ...
.text:004A4064                 unicode 0, <****.no-ip.biz>,0
.text:004A408C                 unicode 0, <(>,0
.text:004A4090 a****3_no_0:                        ; DATA XREF: .text:004ACBE1o
.text:004A4090                                         ; .text:004ACCF0o ...
.text:004A4090                 unicode 0, <****.no-ip.info>,0
.text:004A40BA                 align 4
.text:004A40BC                 unicode 0, <&>,0
.text:004A40C0 a****3_no_1:                        ; DATA XREF: .text:004ACDFFo
.text:004A40C0                                         ; .text:004ACF0Eo ...
.text:004A40C0                 unicode 0, <****.no-ip.org>,0
.text:004A40E8                 dd 2
.text:004A40EC dword_4A40EC    dd 47h, 0C0h            ; DATA XREF: .text:004AECB8o
.text:004A40F4 aCmd_exeCRegAdd:                        ; DATA XREF: .text:004AE27Eo
.text:004A40F4                                         ; .text:004B016Bo
.text:004A40F4                 unicode 0, <cmd.exe /c REG ADD HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\>
.text:004A40F4                 unicode 0, <Windows\CurrentVersion\Run /v microsoft>,0
.text:004A41B6                 align 4
.text:004A41B8 aV_0:
.text:004A41B8                 unicode 0, <V>,0
...
..
..

I spent a whole bunch of time trying to understand what it was doing. Here's some of the things this malware does.

Sets up 6 timers with intervals (1, 1, 60000, 60000, 1, 100). Here's what their functions do.

Timer1 - Keep Refreshing a list of all removable drives. Calls HelperFunction0 once done

Timer2 - Disabled

Timer3 - Unused

Timer4 - Disabled

Timer5 - Adds itself to HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Run for autorun. Changes explorer.exe registry settings to hide file extensions, and disable showing hidden files.

Timer6 - Calls GetForegroundWindow and subsequently GetWindowText and saves the values.

It also has a bunch of helper functions

HelperFunction0 - Copies self executable to %WINDIR%\firefox.exe.

HelperFunction1 - Takes a url as an argument, opens it using ShellExecute

HelperFunction2 - Takes an argument. executes the WINMGMT Query "Select Name from Win32_Process Where Name = {argument}". And then calls terminate on the returned Win32_Process objects

HelperFunction3 - Takes a screenshot using Gdi+ functions and saves it to a jpg file.

HelperFunction4 - Downloads data from a given URL with a GET request using MSXML2.XMLHTTP. The data is probably binary as ADODB.Stream is used to write it out.

HelperFunction5 - Collects a bunch of information about the PC using environment variables - COMPUTERNAME, OS, USERPROFILE, USERNAME and PROCESSOR_IDENTIFIER. It uses all the collected information to construct a url of the form http://address/bot.php?id=COMPUTERNAME+some calculated number&compname=..... and so on. It then issues a function call that I haven't been able to understand yet. Its through some virtual table which means the only way to get the actual function is to live debug this, which is not really what I want to do on my dev box :P. If I had to make an educated guess it would have to be HelperFunction1

HelperFunction6 - Identifies and saves the default browser using HKEY_CLASSES_ROOT\HTTP\shell\open\command\. Probably used by HelperFunction1.

HelperFunction7 - This function will execute commands like 'exe', 'download', 'password' , 'run', 'folderlist', 'visitpage', 'email'. They are polled from the command server.

Form_Load - Calls Form.Hide , Sets App.TaskVisible=0, checks if its being run from the %WINDIR%, if not copies itself to %WINDIR%. Next it uses some weird logic to determine which command center to contact. All of the command center URLs are in the [fixed_string+number].no-ip.[info,biz,org] kind of format. Havent been able to understand what it does next.

Now for the fun part. As Form_Load indicates, this executable contained a VB Form for the GUI. Also the 'email' command in HelperFunction7 referenced a lot of its components' properties. I needed a way to decompile the binary form into readable text. The state of VB Decompilers is horrible, but 'good enough'. I decompiled the form and was pleasantly surprised to see how simple it all was. (Though at this point I also immediately suspected that this was created using some kind of malware kit) You see, the 'email' command in HelperFunction7 was implemented just as you would expect a newbie programmer to do so. Yes, it had plain-text strings for the smtp server, username and password ! I decided to check if the mailbox was still active. It was.

mailbox screenshot

A sampling of what the email attachments contained.

email attachment showing logs email attachment showing pwd

The fun continues. As the author was testing his code one of the emails contained an attachment showing a screenshot of his own machine.

em attachment showing a screenshot

And also his own passwords.

facepalm

Apparently, CSI was right, you can write a VB6 GUI to do most things. Seeing this screenshot made me lose all interest in poking through the code any further. I mean, sure, it was fun turning the tables on the malware writer, but seeing the total lack of sophistication with my own eyes made me kind of feel sorry for the dude.

This mailbox has no recent emails which could mean that the malware has stopped infecting PCs or that they had switched email addresses. Hopefully I'll have a more challenging task the next time I reverse engineer something.