Analyzing Guloader VBScript: A Beginner’s Guide — Part1

AK1001
8 min readApr 16, 2024

Hello there! In this article, I’m thrilled to share my journey of analyzing malicious VBScripts. Through this comprehensive tutorial, I aim to provide clear, step-by-step instructions to empower readers to confidently dissect these scripts on their own. While the article may be a bit lengthy, I hope you’ll discover valuable insights and techniques to enhance your malware analysis skills. Let’s dive in and uncover the secrets of GuLoader VBScript analysis together!

Sample Information

Here is the sample we’ll work with:

MD5: 5f13a0a2f3ed349bd3b4f1b7dbfb6ff7
https://bazaar.abuse.ch/sample/cd6da022c8b2ab80d081be47fd73c588baaa2dff06acabc1a3e681fe1fdc800c/

You might notice the signature tagged as RemcosRAT, indicating that the final delivered malware is RemcosRAT. However, initially, cybercriminals spread spam with a VBScript file, which attempted to masquerade as a PDF file with a DHL invoice notification theme.

Analyzing — VBScript

To begin, let’s examine the script’s behavior by opening it with your preferred text editor. In my case, I’m using Notepad++. Take a quick look at the content to get an overview.

The content of VBScript (1/4)
The content of VBScript (2/4)
The content of VBScript (3/4)
The content of VBScript (4/4)

The first tip is to look for any code segments that appear to execute commands or functions. For instance, the presence of the Shell.Application object might raise suspicion, as it can utilize the ShellExecute function to execute scripts.

Try to find any code attempt to execute something, such as creating a Shell.Application object.

Next, I’d like to use a very simple method to determine the contents of the variables — just print them out! In VBScript, you can print variables using the method below. Remember to comment out the original code to prevent execution.

WScript.Echo <your variable>

For Example:

WScript.Echo Scientificalness
Print variables by WScript.Echo

Then, save the script and run it. This will display the values of the variables on the screen. As you can see, the first variable is POWERSHELL.exe, followed by a lengthy string, and then 0. Clearly, the VBScript attempts to execute the PowerShell script.

Execute vbs script (1/3)
Execute vbs script (2/3)
Execute vbs script (3/3)

To make it easier to analyze the PowerShell script, I would write it out to a file. You can follow the method below for writing a variable to a file.

Set objFSO=CreateObject("Scripting.FileSystemObject")
outFile="<output file path>"
Set objFile = objFSO.CreateTextFile(outFile,True)
objFile.Write <your variable> & vbCrLf
objFile.Close

For Example:

Set objFSO=CreateObject("Scripting.FileSystemObject")
outFile="C:\Users\Administrator\Desktop\output.txt"
Set objFile = objFSO.CreateTextFile(outFile,True)
objFile.Write Scientificalness & vbCrLf
objFile.Close
Write PowerShell script out to a file (1/2)
Write PowerShell script out to a file (2/2)

Due to the length and complexity of the PowerShell script, I’ve made some revisions to enhance readability:

  1. Using any text editor to replace 「;」with 「; \n」. This will improve the structure of the script.
  2. Remove the quotation marks at the beginning and the end.
  3. Rearrange the code slightly to enhance clarity, especially within functions and loops.
  4. Save the modified script as a new file named output.ps1.

Be cautious when replacing 「;」with 「; \n」. If errors occur when running the script, check the semicolons first, as they might be the reason for the issue.

output.ps1

Analyzing — PowerShell (1/2)

Apparently, this script is obfuscated, so I’ll use a debugger to help me understand its purpose. Next, open it in PowerShell ISE, which enables script debugging. Then, set a breakpoint at the line containing the variable $Desocialize. You can do this by right-clicking on the line and selecting ‘Toggle Breakpoint’ from the context menu, or simply by pressing the hotkey F9.

PowerShell ISE — Toggle Breakpoint (F9)

To find out which hotkey you can use, locate the debug menu. Then, hit F5 to run the script. You’ll notice that the breakpoint we just set is triggered.

PowerShell ISE — Step Over (F10)

By pressing F10, you can execute line by line. In the debug window below, I attempted to retrieve (or print) the value of variables by directly typing in the variable’s name.

Retrieve the value of variables

Stop here, you can see the variable $Desocialize is a URL, and the variable $Twiglet is command iex, which is an alias for Invoke-Expression, it’s used for running commands or expressions on the local computer.

So, now we know that iex will run the commands, but I’d like to understand what the script attempts to execute without actually running it. I’ve commented out the original code, assigned it to temporary variables, and now we can analyze it further.

Commenting out the original code and assigning code to temporary variables

In the same method, I print each temporary variable to understand its value.

Printing each temporary variable helps to understand its value better

Seems the script still contains more variables, let’s execute it and then retrieve its value. Using the same trick, restore the original code and run it again, then stop at the next if statement, in debugger windows to print out the variable.

[IntPtr]::size often used to confirm whether the system is a 32-bit or 64-bit operating system. If the size is 4, it means that the current operating system is a 32-bit system, and if the size is 8, it means that the current operating system is a 64-bit system.

Confirming whether the system is a 32-bit or 64-bit operating system

In my environment, the value of $Respektere was True, As I followed the code, it turned out that it would launch another PowerShell_ISE.exe because I was usingPowerShell_ISE.exe to execute the script, but I’d like to execute to the else block. Thus, by adding a little exclamation mark before the variable to change the code flow.

Adding an exclamation mark before the variable to change the code flow (1/2)

After changing the code, we’re able to execute the script and run into the else statement block.

I realized that I didn’t execute to the else block because I was using the x64 version of PowerShell ISE to run the script. If you execute the script using the x86 version of PowerShell, you shouldn’t need to change the if statement.

Adding an exclamation mark before the variable to change the code flow (2/2)

Let’s expedite the process by employing the same approach to discern the main purpose of the remaining code. Comment out the original code and assign it to temporary variables.

Commenting out the original code and assigning code to temporary variables

Execute the script and stop at the while statement, then check the value of variables. There are some interesting commands, such as Start-Bits and$env:appdata.

Using the PowerShell Start-Bits command to download second-stage payload (1/2)

To execute, restore the original code, and comment out the temp variables, then give it a run.

Using the PowerShell Start-Bits command to download second-stage payload (2/2)

It appears that the script is set to download something using the Start-BitsTransfer command from a malicious download site and store the downloaded file in the path C:\User\Administrator\AppData\Roaming\.

Basically, the script intends to download the second-stage payload. We can just download it manually and place it in the target location.

Due to the download site not being accessible, you can find the payload from the below Malware Bazaar Database:
https://bazaar.abuse.ch/sample/caf4c7e17a788fbd9f7f408ef818990e6ffffdd801b8168123ca4b330cb72673/

Manually download the second-stage payload and place it in the target location

Next, add a new line to assign $temp16 to an empty string. This is done to inspect the value of $temp15. Then execute the script (F5) and step over (F10) each line until reaching $temp16.

Add a new line to assign $temp16 to an empty string

Let’s check the value of these variables.

Printing each temporary variable helps to understand its value better

The main purpose of the codes:

  1. Read the downloaded payload (Fedtene.Sen)
  2. Convert it from base64
  3. Extract strings
  4. Split the string
  5. Execute next stage payload

Now, let’s examine the second-stage payload. By opening it with a text editor, you’ll see a large base64 string.

Second-stage payload — a large base64 string

By using CyberChef to convert the string from base64, I saved the file as decode_Fedtene.bin and examined it later.

Using CyberChef to decoding base64 string

Return to PowerShell ISE and restore the original code, excluding the line involving $Sarmatic to prevent its execution.

Execute the script to obtain the final value of the variable

Run the script until $temp16, then check variable $Sarmatic. Surprise! You got another PowerShell script!

Another PowerShell script

To analyze the next stage script, I’m going to write the content out as a file, and named stage2.ps1.

[io.file]::WriteAllText(<output path>, <the variable>)

For Example:

[io.file]::WriteAllText("C:\Users\Administrator\Desktop\stage2.ps1", $Sarmatic)
Write PowerShell payload out to a file (1/2)
Write PowerShell payload out to a file (2/2)

Congratulations! We’ve completed the analysis of Part 1. In Part 2, let’s continue dissecting the remaining PowerShell code together!

--

--

AK1001

A Cybersecurity researcher. Focusing on malware analysis, threat hunting, and threat intelligence.