Tracking PavinLoader across ClickFix and fake download campaigns

In our previous analysis of the malicious RenPy campaigns, we identified a multi-stage loader deployed as part of the infection chain.

Further threat hunting has since shown that the same loader, which we track as PavinLoader, is being used across several different campaigns, including ClickFix attacks and fake software downloads.

Despite differences in how these campaigns reach victims, we found several common elements. These include multi-stage infection chains involving heavily obfuscated and trojanized .NET DLLs; abuse of MSBuild, .csproj, and .bat files to execute them; and EtherHiding to retrieve the command-and-control (C2) domain.

What an attack looks like

The campaigns don’t all start the same way. A victim might encounter a fake CAPTCHA that tells them to run a command, download what appears to be legitimate software, or install a malicious game.

What happens next is much more consistent. PavinLoader uses legitimate Windows tools alongside malicious .NET files to run several stages of malware. It also uses EtherHiding, a technique that uses a blockchain to hide information about its infrastructure, to find the server from which it should retrieve additional malware.

In the RenPy campaign we analyzed, that process ultimately led to Amatera Stealer, malware designed to steal information from an infected computer. We also observed PavinLoader infections delivering additional malware.

PavinLoader appears across multiple campaigns

We have identified PavinLoader in several campaign clusters:

  • Malicious RenPy campaigns, as analyzed in our earlier blog post
  • Several ClickFix campaigns, including recent activity from the operator(s) covered in our previous analysis
  • Fake software campaigns that used Dropbox to download PavinLoader.

The loader’s use across multiple campaigns raises the possibility that PavinLoader is offered as a Loader-as-a-Service.

We also found several artifacts that support this possibility, although they are not enough to confirm it. One specific artifact on VirusTotal is shared by more than 200 files associated with PavinLoader, suggesting it may be a compilation artifact of the build process.

We also found a PowerShell script uploaded to VirusTotal containing comments such as EDIT HERE and REPLACE with a real direct link to your .bat. The associated BAT file contains the string Automated builder helper.

However, we haven’t found a build panel or sales channels that would confirm PavinLoader is being offered commercially.

The PowerShell script. Click to enlarge

Although PavinLoader has changed over time, the campaigns we analyzed share several characteristics:

  • Inno Setup or MSI installers generated with different builders that run the .bat and/or .csproj files
  • Trojanized .NET DLLs, including DotNetZip, Nancy, Renci.SshNet, and OpenXML. In most of the cases analyzed, the inserted malicious methods follow a TwoWords or TwoWordsNumber naming pattern, such as DefaultEvaluator5, and FallbackFactory5
  • A common obfuscation technique used across the .NET DLLs
  • A naming convention based on two random words, such as GollopDevest, UnbrandRunover, andPavinWide, for DLL names, functions, strings, C2 paths, and other artifacts
  • EtherHiding to obtain the C2 domain, followed by HTTP requests using paths such as assets/{two random words}.json to retrieve subsequent stages. C2 domains commonly use the .lat, .icu, .shop, and .cfd top-level domains
  • MSBuild mechanisms for loading and executing code from DLLs, including property functions such as [System.Reflection.Assembly]::Load(...) and UsingTask
  • Recurring filename patterns such as name_4characters.cmd/bat/msi/exe—for example, prefetch_9a59.cmd, telemetry_55db.cmd, and bootstrap_64be.cmd—or random nine-character names such as aegZpQ4C7.bat. We also observed short names including Small.msi, small.bat, and small.cmd

PavinLoader consists of several .NET DLLs, and in the cases analyzed we identified the following stages:

  • Loader DLL: A trojanized DLL—such as the Nancy one analyzed in our previous RenPy article—or a custom DLL. It performs anti-forensics and anti-analysis operations, changes network settings needed for the next operations, and loads the EtherHiding Loader
  • EtherHiding Loader DLL: Obtains the C2 through EtherHiding and downloads the next stages from it
  • Anti-Analysis DLL: Performs extensive anti-analysis checks to detect virtualized environments.
  • PE Loader DLL: Loads the final PE payload.

Intermediate payloads can vary depending on the campaign configuration. First, we’ll look at some of the methods used to distribute the initial PavinLoader stages. We’ll then return to the RenPy loader campaign we analyzed in our previous article to examine the loader’s later stages.

Technical analysis

The rest of this article takes a closer look at how PavinLoader is distributed and how each stage of the loader works.

How PavinLoader is delivered

We have observed PavinLoader being delivered through several ClickFix campaigns.

In particular, we detected that the ClickFix cluster analyzed in a previous article has recently started using PavinLoader. Abuse of MSBuild and the use of .csproj and .bat files remain common across the infection chains we observed.

We covered one example in our previous RenPy analysis. Here, we’ll look at several other distribution methods.

The ClickFix Cloudflare page associated with this campaign. Click to enlarge

As we saw in our previous analysis of these ClickFix campaigns, the associated PowerShell scripts change frequently. We found several versions in this activity, including both obfuscated and unobfuscated scripts.

The PowerShell script associated with the ClickFix campaign. Click to enlarge

In this example, the downloaded MSI from the Cloudflare bucket is called Installer_57be78.msi. 

MSI content. Click to enlarge

The package contains:

  • prefetch_2f76.exe: The legitimate MSBuild executable
  • prefetch_2f76.csproj: Used to execute the Loader DLL through UsingTask
  • DotNetZip.dll: The Loader DLL

The .csproj file is executed with:

"C:\Users\{USER}\AppData\Local\Logitech\Device Configuration Helper\prefetch_2f76.exe" /nologo "C:\Users\{USER}\AppData\Local\Logitech\Device Configuration Helper\prefetch_2f76.csproj" /nr:false

The Loader DLL is a trojanized version of DotNetZip and is executed using the UsingTask element.

“UsingTask” used to execute the DLL. Click to enlarge
The malicious method inserted in the trojanized DLL. Click to enlarge.

Unlike the RenPy example discussed in our previous article, the EtherHiding Loader is extracted from the DLL itself. An embedded resource is used as an index to extract bytes directly from the DLL, rather than obtaining those indexes from the .csproj file.

We detected another campaign that uses BAT files containing fake BUILD VERIFICATION REPORT comments, apparently intended to make analysis and detection more difficult.

In this case, the MSI CustomAction executes the BAT script with:

cmd.exe /c C:\Users\{USER}\AppData\Local\Conexant\lite_bootstrap_2.1.7\updater_8219.cmd /launched

The obfuscated code appears below the fake comments. It concatenates multiple strings and uses indices generated through simple mathematical operations to reconstruct them. We found this type of obfuscation in most of the BAT files we analyzed.

The BAT file locates conhost.exe and relaunches itself with:

"C:\WINDOWS\System32\conhost.exe" --headless cmd.exe /c "C:\Users\{USER}\AppData\Local\Conexant\lite_bootstrap_2.1.7\updater_8219.cmd" /launched

It then sets the MSBUILDENABLEALLPROPERTYFUNCTIONS=1 environment variable, locates MSBuild.exe, and executes it using the same file as input:

"C:\WINDOWS\Microsoft.NET\Framework64\v4.0.30319\MSBuild.exe" "C:\Users\{USER}\AppData\Local\Conexant\lite_bootstrap_2.1.7\updater_8219.cmd"

In this case, the Loader DLL is reconstructed by concatenating and decoding four Base64-encoded variables.

Part of the CMD file showing the loading process. Click to enlarge

The Loader DLL has a random name and appears to be an older version because it does not contain the custom bytecode and encrypted strings in its resources.

As in the RenPy campaign analyzed previously, this stage retrieves the EtherHiding Loader stored between a Build-... marker in the CMD file through the _vezr environment variable, then decodes it using XOR with a 32-byte key.

The extracted Loader DLL. Click to enlarge

Having looked at several methods used to distribute PavinLoader’s first two stages, we will now return to the RenPy infection chain from our previous analysis and examine the loader itself in more detail.

Analyzing PavinLoader

The .NET DLLs associated with PavinLoader are heavily obfuscated using control-flow flattening, custom bytecode, indirect calls through calli/ldftn, string encryption with different algorithms, API hashing and delegates, redundant methods, and junk code and strings.

We did not identify a known obfuscator associated with the samples, so to the best of our knowledge, PavinLoader uses a custom obfuscator.

Because fully deobfuscating the samples would be complex, we used a hybrid approach combining dynamic analysis with method invocation through reflection. We identified important methods based on their imports and parameters, invoked them, and analyzed the resulting output.

This approach does not provide complete coverage of the execution flow, but it allowed us to identify the loader’s core functionality and extract its intermediate stages. Because different functions frequently share the same names, we use metadata tokens to identify methods throughout the analysis.

Nancy trojanized DLL: Loader DLL

We covered this stage in detail in our previous blog post, so we’ll provide only an overview here.

In most of the cases analyzed, the Loader DLL is a trojanized legitimate DLL. The malicious method typically uses a {RandomWord} or {RandomWord_Number} naming convention.

The DLL contains a resource associated with the custom bytecode interpreted by the main method, two resources containing encrypted strings, and, in some cases, additional resources used as an index for extracting the next stage. Other resources appear to be decoys designed to slow analysis. In the samples we analyzed, this DLL typically:

  • Decrypts strings from resources using multi-key XOR
  • Resolves APIs using API hashing and GetDelegateForFunctionPointer()
  • Changes network settings, including disabling TLS certificate validation and setting the default system proxy
  • Performs an anti-analysis timing check using CreateEventW(), GetTickCount(), and WaitForSingleObject()
  • Performs anti-forensics operations
  • Loads the EtherHiding Loader either by extracting it from a marker inside .csproj or BAT files, or by using a resource as an index to retrieve bytes directly from the DLL

GollopDevest: EtherHiding Loader

The EtherHiding Loader has two main functions: obtaining the C2 domain through EtherHiding, and downloading and loading subsequent stages from that C2.

Class 0x02000762 is responsible for decrypting strings associated with blockchain and network communication.

The strings are decrypted by 0x060027BD as follows:

  • Function 0x060027BB initializes the S-box using the XOR of the master key activeValues and the Base64-decoded optionsCollection string
  • Function 0x060027BE takes childSyncObject as input and returns index bytes using XOR and permutations based on header values encoded in the first two characters of the string
  • Function 0x060027B9 returns the decrypted string using the indexes and the previously generated S-box

This was the only class we found with encryption parameters encoded in this format.

For the remaining strings, we identified functions that returned decrypted data based on their parameter signatures—for example, methods returning strings or bytes—and invoked them through reflection. This allowed us to recover more than 1,300 strings.

Part of the decrypted strings. Click to enlarge

Among them were strings associated with AMSI and ETW patching:

AmsiScanString
System.Management.Automation.AmsiUtils
System.Management.Automation.AmsiUtils+AmsiNativeMethods
ntdll
EtwEventWrite

NtQueryInformationProcess
NtSetInformationThread
VirtualProtect

More than 100 URLs belonging to legitimate services are also decrypted and used to generate HTTP requests and network noise. We did not observe this behavior in every sample, suggesting it may be build-specific.

The Server class (0x02000052) generates the X-Timestamp, X-Nonce, and X-Signature HTTP headers and makes requests used to retrieve subsequent stages.

Two HTTP requests are made to synchronize parameters and obtain the payload, with HMAC used to validate the requests. Using reflection, we executed method 0x06000A77 to obtain the header values needed to retrieve the subsequent stages.

The C2 domain is obtained by making an ETH RPC (Remote Procedure Call) to bsc-dataseed.binance.org with the following JSON-RPC body:

{"jsonrpc":"2.0","method":"eth_call","params":[{"to":"0x328a1fadff154290f0ce1389a4e633698cdfdaa7","data":"0x06fdde03"},"latest"],"id":1783436775} 

The next stages are downloaded from the resulting C2 domain. The XOR-encoded payload is stored in the JSON response under cache.content:

{"type":"cache-binary","meta":{"version":"2.3.1","timestamp":"…","platform":"win32-x64"},"cache":{"id":"e2b69…","content":"1c.."}} 

In this case, the C2 paths and XOR keys decrypted from this stage and the anti-analysis DLL are:

The next stage executed is the anti-analysis DLL.

PavinWride: Anti-analysis DLL

This DLL is responsible for performing several anti-analysis checks.

The anti-analysis DLL executes system calls in different ways:

  • Standard .NET Base Class Library (BCL) calls, including for registry and network operations
  • Win32 P/Invoke calls, including GetCurrentThread, NtQueryInformationThread, NtQueryInformationProcess, and NtCurrentTeb
  • Win32 APIs resolved through API hashing and a Process Environment Block (PEB) export table walk

The function MenuItemService.ProcessDirectory (0x06000151) is the main method responsible for delegate caching and Win32 API resolution:

  • It checks if the delegate is already resolved using managerMap.TryGetValue() 
  • If not, it calls ProcessDirectory (0x06000150) to obtain the HMODULE handle
  • It calls ProcessDirectory (0x0600003A) that performs the PE export table walk and matches the hash. We detected that the same hashing output is obtained in several other methods (e.g., 0x06000039, 0x0600003B, 0x0600004E)
  • It obtains the delegate with GetDelegateForFunctionPointer() and saves it in the dictionary
Results of the API hashing script. Click to enlarge

We used the same reflection approach to get the strings. Many strings are encrypted with the XOR key 4B729A1F5CE387D6.

Part of decrypted strings. Click to enlarge

The loader obtains the system’s LCID using GetKeyboardLayoutList() and compares it against more than 17 languages, including Russian, Ukrainian, Belarusian, and Armenian.

It also performs extensive system reconnaissance, including enumerating registry keys and calling Win32 APIs such as GetSystemFirmwareTable() and EnumSystemFirmwareTables() to identify virtualized environments.

Part of the registry key enumeration. Click to enlarge

We also observed decrypted references to APIs including GetCurrentProcess(), CreateToolhelp32Snapshot(), Process32First(), Process32Next(), and OpenMutex(), although we did not observe these functions being called during our execution flow.

An HTTP request is also made to one of these services:

  • https://ipv4[.]ipleak[.]net/json/
  • https://get[.]geojs[.]io/v1/ip/geo[.]json
  • https://ipapi[.]co/json/
  • https://api[.]ipapi[.]is/
  • https://ipinfo[.]io/json

It also checks the returned data against 96 hosting or infrastructure providers and tests whether the region code is one of: RU, UA, BY, AM, KZ, KG, TJ, UZ, GE, AZ, or MD.

Decrypted strings associated with providers. Click to enlarge

If the anti-analysis checks pass, the next two stages are downloaded and decrypted using XOR keys.

We patched SelectionScope.ProcessDirectory (0x06000014) to recover the C2 paths and XOR keys for those stages:

/assets/MailersKogasin.json|WjcsVTKmuoBRqe|/assets/LanoseThrip.json|WwUX66Br

GollopDevest: PE Loader DLL and Amatera Stealer

The third DLL has the same name as the second, GollopDevest, but performs PE loading.

Among its decrypted strings are:

'GollopMailers LDR DllBase VeneryCondole EdiyaFoully=0x{0:X} EdiyaStelae=0x{1:X}'
'GollopMailers LDR Flags missing IMAGE_DLL 0x{0:X8}'
'GollopMailers LDR SaranPisco invalid 0x{0:X}'
'GollopMailers LDR TlsIndex invalid {0}'
'GollopMailers LDR sanity exception: '
'HIGHLOW relocation'
'Import DLL name'
'Import FunctusAurata'
'Import INT'
'Import descriptor'
'Import hint/name'
'Import thunk'
'LdrpHandleTlsData outside ntdll .text'
'LdrpReleaseTlsEntry outside ntdll .text'
'LoadConfig32'
'OK'
'PE headers'
'Required API resolve failed: type={0}, FreshBubals={1}, module=0x{2:X}'
'TLS32'
'TLS64'
'x86 disabled until ABI proof'
ntdll.dll
kernel32.dll
LdrpInitializeTls
"STATUS_SUCCESS"
UNKNOWN(0x00000001)
UNKNOWN(0x00000002)
UNKNOWN(0x00000003)

The ServerEditor.SortMemory method (0x06000014) checks the PE structure and flags before loading the payload.

To confirm this behavior, we invoked the method through reflection using the downloaded WPA.exe file as input. The PE loaded successfully.

The C++-compiled PE disguises itself as WPA.exe (Windows Performance Analyzer). We identified the payload as an obfuscated version of Amatera Stealer 4.2.3-alpha1.

It uses control-flow flattening, API hashing, anti-debugging checks, and opaque predicates to complicate analysis. We also detected use of the Heaven’s Gate technique, DNS-over-HTTPS (DoH) resolution through Google DNS, and raw sockets using \Device\Afd\Endpoint for network communication.

Part of the decrypted strings associated with Amatera. Click to enlarge

After this stage executes, we also observed additional payloads being downloaded and run from C2 IP addresses.

In some cases, WiX Burn bundles downloaded another payload associated with PavinLoader. In others, we detected HijackLoader. This gives the campaign operators the ability to deploy multiple payloads on a compromised machine.

IOCs

SHA-256 hashes

bdf313a019e025ebf58ccef4619444ee70e661bd444e0644ebeabd8f5caad14c 

e3830f5747e3f46537d217124d80c9f3bb4d89f8d4f5138dce69ee54ea4fb6b9 

a4f03272cf96732dc9f58bb466d16f358e7f50d46dba30526a9fbebfec11717b 

bf04160dd1ce3571e0eb6d6dda1713c788797b5599399d4a93665a757eec376e 

54fa8083c05334aa360256fbbb0ca901ce7e244a0359dd664cae78977371ec91 

c1ea6d169565c70ac5d812e73483814929e9b3548ead6633595937e71a334adb 

001337488c32d8610c2aef6f9330acca825f0afacd071bf6ebfc06b5a1a69f09 

2837099af431e9afee76ce5e6ab5cb86bedce06e31c22be46250cb453cfdb978 

252c5a3d150275013f52b4820097d7163ced4aa2f1be0fca032f8a5017673816 

0c9c64b7383ec249bcf6271a4b73206d94de130ca401d16ab77fe01e5193a312 

6700f62e1a3b33340cd678c388ecc8bac2e5943c0627df5d1b99b879c3ca42c9 

IP addresses

93.152.224[.]75: downloads PavinLoader

65.21.80[.]170: downloads PavinLoader

195.63.142[.]49: downloads PavinLoader

Domains

perfectverified[.]com: ClickFix

PavinLoader C2

catalyst-pro[.]lat 

twigoamwu[.]cfd 

trusaifi[.]cfd 

stellar-minds[.]cfd 

pinnacle-labs[.]lat 

nexahub[.]lat 

fimwoglea[.]shop 

velodium[.]lat 

rpcsecnoweb[.]pro 

more-arpc[.]icu 

echo-systems[.]cfd 

kelemet[.]shop 

zarwieciv[.]cfd 

URLs

telegra[.]ph/Project-PySynth-06-28: Amatera dead drop

Acknowledgements

From reporting threats to removing them.

Cybersecurity risks should never spread beyond a headline. Keep threats off your devices by downloading Malwarebytes today.

添加评论
点赞收藏
点踩分享查看原文
评论
?
参与讨论