Threat intelligence

Inside a New VioletRAT Campaign: Multi Staged Delivery and Stealthy Payload Execution

by Jayesh Kulkarni

 
Recently, the SonicWall Capture Labs threat research team observed a new campaign spreading Violet RAT using a multistage Python-based APC injection technique. The campaign employs a multi-stage delivery chain that involves archives, batch scripts, and a Python loader to deploy the final payload via shellcode injection.  The complete infection chain can be visualized in the following figure 1.
1_Infection_Chain.png
Figure 1: Infection Chain
The initial infection vector is an archive file delivered by email. This archive file contains a heavily obfuscated batch file. 

BATCH FILE: 

The batch file begins with the bytes 0xFF 0xFE, indicating UTF-16LE encoding. When opened in Notepad, the file is rendered as garbled characters due to an encoding mismatch, making it unreadable to the victim.  
2_Unicode_bat.png
Figure 2: Unicode batch file
The batch file initially runs a hidden PowerShell to open 'google.com'. This website opens in the victim's default browser. The malware proceeds to download did.zip from a cloud file hosting service into the /Contacts/dad subdirectory within the %USERPROFILE% directory. Subsequently, a batch file named start.bat is downloaded to the path %APPDATA%\Microsoft\Windows\Start Menu\Programs\Startup\. 
3_Batch_File.png
Figure 3: Batch file
Next, inside the %USERPROFILE%/Contacts/dad directory, it executes the python script stry.py with the parameters mentioned in the image. The start.bat also has the same code, which runs a hidden PowerShell and executes the stry.py. In the event of a failure to retrieve keys from a.txt in the extracted directory, the loader downloads a.txt or b.txt from the same hosting service to obtain the decryption keys for the shellcode.

PYTHON SCRIPT: 

The extracted zip has multiple contents as shown below: 
4_Did_Zip_Contents.png
Figure 4: Did.zip files

Stry.py: Python script to decode and inject the shellcode

Nou.bin: encrypted shellcode

a.txt: set of keys required to decrypt the shellcode. 

It also has multiple supporting Python libraries, which are required to carry out the execution smoothly. The Python script obfuscates datatypes, API names, function prototypes and parameters by masquerading them under different names using its own defined structures and variable assignments. The script calls itself “Advanced Payload Executor”. We can see the parameters and descriptions in the image below. 
5_Python_Script_1.png
Figure 5: Python script
As discussed previously, the shellcode and key file names were provided in a batch file. The target process for injection can be provided in the command line; it is by default explorer.exe.  The keys from a.txt are concatenated in the transformations array. This is further used by the transform_data function to decrypt the shellcode. The key is reversed and then XORed to retrieve the compressed shellcode blob from encrypted data. This blob is decompressed using zlib.decompress() function. 
6_Python_Process_Inject.png
Figure 6: Process Injection
Payload execution is then triggered using ResumeThread() and WaitForSingleObject() APIs. With this, the shellcode blob starts executing under explorer.exe.  

SHELLCODE EXECUTION

Below are the initial bytes of the shellcode blob. 
7_Shellcode.png
Figure 7: Shellcode blob
Initially, it resolves a few Ntdll.dll and kernel32.dll APIs dynamically using API resolution via address traversal.  The data at address 0x230 of the shellcode is again decrypted using custom ARX cypher [ADD(0x4,0x8,0xC), ROL(0x5,0x8,0x10,0xD,0x7), XOR()]. The 16-byte key stored at the start of the shellcode at address 0x19 is used to decrypt the data. 
8_APi_Loading.png
Figure 8: LoadLibrary mscoree.dll
Further, from decrypted data, it loads oleaut32.dll, mscoree.dll, wininet.dll, ole32.dll and api-ms-win-core-com-l1-1-0.dll using LoadLibraryA. Most of these APIs include memory APIs, Internet APIs and CLR hosting APIs. The malware loads AMSI.dll at runtime and resolves AmsiInitialize, AmsiScanBuffer, and AmsiScanString using GetProcAddress. It subsequently overwrites the in-memory implementations of AmsiScanBuffer and AmsiScanString with a shellcode stub that forces successful return values, effectively disabling AMSI scanning. 
9_AMSIScanBuffer_Patching.png
Figure 9: AMSI patching
The patched shellcode will return output in such a way that the malicious file scan result will always be clean. This patches AMSIScanbuffer using inline patching.  
Opcode Instruction 
55 push rbp 
48 89 E5 mov  rbp, rsp 
48 89 4D 10 mov  [rbp+10h], rcx     ; save arg1[context] 
48 89 55 18 mov  [rbp+18h], rdx     ; save arg2[buffer] 
44 89 45 20 mov  [rbp+20h], r8d     ; save arg3[length] 
4C 89 4D 28 mov  [rbp+28h], r9        ; save arg4[content name] 
48 8B 45 38 mov  rax, [rbp+38h]      ; 5th arg (AMSI_RESULT* result) 
C7 00 00 00 00 00 mov  dword ptr [rax], 0 
B8 00 00 00 00 mov  eax, 0               ; return S_OK (HRESULT = 0) 
5D pop  rbp 
C3 ret 
The patch explicitly sets the scan result to 0x00000000, indicating benign content, and returns S_OK, thereby bypassing AMSI inspection. This way, AMSI is neutralised by hooking both the scanning APIs. Next, the malware loads API WldpQueryDynamicCodeTrust() from WLDP.dll, which checks if the specified in-memory or on-disk .NET CRL dynamic code is trusted for execution by device guard policy. 

CLR HOSTING 

Furthermore, it uses Native CLR hosting to execute the native assembly stealer code. You may read more about the analysis of native process CLR hosting in our old articleCLR hosting is when a native/unmanaged process explicitly loads and controls the .NET runtime (CLR) to execute managed code inside its own process. 
10_CLR_CreateInstance.png
Figure 10: CLRCreateInstance
Using CLRMetaHost:GetRuntime, it loads the .NET Framework compilation version, which is “v4.0.30319” here. 
11_CLR_GetRunTime.png
Figure 11: GetRuntime
Following that, a new AppDomain with the name “3HXW4YRM” is created using CorHost::CreateDomain. The PE file to be injected is copied into the single-dimensional SafeArray of size 0xA987F8. The final transition to managed execution occurs via GenericComCallStub, an internal and largely undocumented CLR interop stub. 
12_GenericComCallStub.png
Figure 12: GenericComCallStub
This pointer resolves to AppDomain.ExecuteAssembly, which subsequently invokes InvokeStub() to handle the native-to-managed execution transition and argument marshalling. 

Payload

The injected Malware is Violet RAT. This RAT is a malware-as-a-service (MaaS), discovered last year. The image shows a few of the data it retrieves from the victims’ systems: 
13_Violet_Exe_Strings.png
Figure 13: VIOLET NEW.exe Strings
Data collected by VioletRAT from the victim system is transmitted to the command-and-control (C2) server at 176.65.132[.]10:7000, which is referenced in a Pastebin URL -hxxps://pastebin[.]com/raw/5TDDMvmC. 
14_VioletRAT.png
Figure 14: Violet RAT Webpage
The VioletRAT web panel highlights an extensive feature set, including device and system control, auxiliary tools, Windows Defender tampering, and networking capabilities. Our analysis shows that this campaign employs a multi-stage loader that dynamically resolves APIs, hosts the CLR to execute managed payloads in memory, and actively bypasses security controls such as AMSI and WDAC.  Overall, this represents a relatively new loader implementation observed in recent VioletRAT campaigns and reflects a growing level of sophistication in the malware’s delivery and execution chain. This threat is detected by SonicWall Capture ATP w/RTDMI.
15_RTDMI_Screenshot.png
Figure 15: RTDMI Screenshot

IOCs:

  • 176.65.132[.]10:7000
  • hxxps://pastebin[.]com/raw/5TDDMvmC
  • hxxps://seq-caught-publicity-big.trycloudflare[.]com
  • 2e7a6d2383339e917b40d32cfad70fe020dcaa93c14df334bd829836074e90c4
  • f30d5a5aa1f21d04f51d1d125cdfe08f6d8c288479de1fd2dc78e66694b87ad2
  • 1d68572db63a01f71ed9cc0dd75e87ca89bce40016ba5ee9d3f980d961287f60
  • f30d5a5aa1f21d04f51d1d125cdfe08f6d8c288479de1fd2dc78e66694b87ad2
  • b8e617bd9d6558cf10dc34f7b6bbe3e1b3a792ee1f2658722d6842704d9f8c51
  • b37b013ac20a63feee49028f1b336e3160558d1ec6c602ba4444ba0bdd8488cd
  • 6fa02b8693ef9169a3055fbed9904800485500cedbe10b460e5ff1ee1b2e7301
  • 8b2f8f5ec21f82d5925f77734a6ef8b48156a729ff55e1deb49277985610d34c
  • 4e14320102eb7951fad6b6bad5252aeffd74c2a9849ced1f9749c1f13de6251c

Share This Article

An Article By

Jayesh Kulkarni

Threat Researcher

Jayesh specializes in reverse engineering various types of malware, decoding infection chains and implementing measures to protect users. He is very passionate about his work and is an experienced technical content creator and security researcher.

Related Articles

  • Uncovering a Recent Pulsar RAT Sample in the Wild
    Read More
  • GNU inetutils-telnetd remote authentication bypass to RCE (CVE-2026-24061)
    Read More