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 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.
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
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.
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
Due to the length and complexity of the PowerShell script, I’ve made some revisions to enhance readability:
- Using any text editor to replace 「;」with 「; \n」. This will improve the structure of the script.
- Remove the quotation marks at the beginning and the end.
- Rearrange the code slightly to enhance clarity, especially within functions and loops.
- 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.
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.
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.
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.
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.
In the same method, I print each temporary variable to understand its value.
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.
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.
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.
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.
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.
To execute, restore the original code, and comment out the temp variables, then give it a run.
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/
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
.
Let’s check the value of these variables.
The main purpose of the codes:
- Read the downloaded payload (Fedtene.Sen)
- Convert it from base64
- Extract strings
- Split the string
- 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.
By using CyberChef
to convert the string from base64, I saved the file as decode_Fedtene.bin
and examined it later.
Return to PowerShell ISE and restore the original code, excluding the line involving $Sarmatic
to prevent its execution.
Run the script until $temp16
, then check variable $Sarmatic
. Surprise! You got 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)
Congratulations! We’ve completed the analysis of Part 1. In Part 2, let’s continue dissecting the remaining PowerShell code together!