🦇 Dissecting VanHelsing Ransomware
In this post I will analyse the internals of the new VanHelsing Ransomware and its functionalities. VanHelsing Ransomware launched on March 7, 2025. Its basically off-the-bat a pretty new threat that I am going to analyse. Note: This post will only focus on static analysis of VanHelsing using Ghidra. I might do another post for dynamic analysis in my detonation chamber, so stay tuned!
Some quick-and-dirty facts on the sample:
- Source: bazaar.abuse.ch
- First Seen: 26th March 2025 08:32
- URL: https://bazaar.abuse.ch/sample/ffb25d80448f13a089832e2ae2f946cb454c7cbbf466fdd9d3cf4caab1e0a93e/
- Initial Filetype: .zip
- Country of Origin: Indonesia
Lets get started. First I downloaded the sample to my analysis box and unzipped the content. Then I got a .bin
file which turned out to beeing this type:
|
|
So, in the previous post I had trouble analysing stuff on Mac using Ghidra. This time I will do it again using Ghidra. Lets learn step by step. I quickly created a new Ghidra project and imported the sample. Then I auto-analyzed the binary and did some manual demangling. I was left with this pretty-default entrypoint.:
|
|
As some of you might already know, __scrt_common_main_seh()
function is used to initialize the runtime and call the main program function. So lets analyze this function first. Inside of __scrt_common_main_seh()
I got this:
|
|
After some manual debug-symbol validation and function demangling, I figured out, the main function call for the VanHelsing Functionalities was right after __get_wide_winmain_command_line();
. Namely here:
|
|
We now need to analyse the main()
function as this is where things get interesting.
Entering the Vampire Cave
Lucky me, this VanHelsing ransomware sample has not been thoroughly obfuscated. In this sence, we can easily read common data and ascii strings without the need of deobuscation. The first clues are here:
|
|
In the main function, the ransomware defines a new Named Mutex (Mutual Exclusion) with default security attributes. This means this named mutex can be accessed by different processes not just threads as usual but in a condition where race-conditions in a synchronous environment are avoided. If the mutex already exists, the ransomware exits, ensuring only one is running.
In the middle of the mai() function it calls another interesting function:
|
|
I went deeper into the code and took a look on FUN_004092d0
since it takes a filename as a parameter which is pretty indicative to beeing something like a gathering / file encryption routine. Inside of FUN_004092d0
I see the following:
|
|
Okay so this is quite an interesting chunk of code. I assume the main logic of VanHelsing lies in this function that is in our current scope. Firstly, what seems interesting to me is that it assignes the output of the function FUN_00456127
to the variable PauVar3
. It takes the file extension .vanlocker
as well another parameter named local_9a8.cFileName
as an argument. What this subroutine does, it recursively checks if the object in the current directory is not a folder. If this is true, it will check if the file extension is not .vanlocker. If this condition is also met, it will cross-validate if the extension of the current file-index is one of the given extensions in local_9a8.cFileName
. This might be a big list of all file-types that VanHelsing wants to encrypt.
Another function call that is highly interesting, is this snippet from the same upper code chunk:
|
|
Inside this function, we can see that it stores the logic for creating the encryption warning. Basically just a plaintext file called README.txt inside all encrypted folders containing a basic ransom note.:
FUN_00401200(local_258,"%s\\README.txt");
FUN_00406430(&local_270,(uint *)
"--= No news is a good news ! =--\n\nYour network has been breached and all your
files Personal data, financial reports and important documents has been stolen ,
encryp ted and ready to publish to public,\n\nif you willing to continue your
bussines and m ake more money and keep bussines secret safe you need to restore
your files first, An d to restore all your files you have to pay the ransom in
Bitcoin. \ndon\'t bother yo ur self and wast your time or make it more harder on
your bussines , we developed a l ocker that can\'t be decrypted using third part
decrypters .\n\nmaking your self geek and trying to restore the files with third
part decrypter this will leads to lose al l your date ! and then the even you pay
the ransom can\'t help you to restore your fi les even us.\n\nto chat with us
:\n\n1 - Download tor browser https://www.torproject. org/download/\n2 - go to one
of these links above\n\thttp://vanhelcbxqt4tqie6fuevfng2
bsdtxgc7xslo2yo7nitaacdfrlpxnqd.onion\n\thttp://
vanhelqmjstkvlhrjwzgjzpq422iku6wlggiz 5y5r3rmfdeiaj3ljaid.onion\n\thttp://
vanhelsokskrlaacilyfmtuqqa5haikubsjaokw47f3pt3uoi vh6cgad.onion\n\thttp://
vanheltarnbfjhuvggbncniap56dscnzz5yf6yjmxqivqmb5r2gmllad.onio n\n\t\n3 - you will
be asked for your ticket id to enter the chat this for you : TICK ET ID
ca11d09d4d234ab8c9a9260c0905a421\n\nusefull links : \n#OUR TOR BLOG :\nhttp://v
anhelvuuo4k3xsiq626zkqvp6kobc2abry5wowxqysibmqs5yjh4uqd.onion\nhttp://
vanhelwmbf2bwzw 7gmseg36qqm4ekc5uuhqbsew4eihzcahyq7sukzad.onion\nhttp://
vanhelxjo52qr2ixcmtjayqqrcodk uh36n7uq7q7xj23ggotyr3y72yd.onion",0x5fa);
From this note, we also find another very important clue for victims. Namely, VanHelsing performs double-extortion by exfiltrating business-critical and potentially sensitive documents to a command and control server that is under their control. We can also find the encryption key here:
|
|
Main Encryption Routine
This is the code snippet for the main file encryption routine. If the function used for encryption FUN_00408370
returns the errorcode 1, it will print a success-message for the attacker informing him, that the encryption for one or more files worked.
|
|
Lets take a closer look at FUN_00408370
. In here, we can see that it uses MoveFileW
to take the current filename and rename it by appending a .vanlocker
extension. The actual encryption algorithm is called in a seperate process. This decoupled process is very stealthy since simple disk i/o is considered legitimate and will not trigger most av’s.
|
|
The next chunk defines 2 new variables and allocates memory in the size of 32- and 12-bytes.
|
|
The format for initialize_chacha20_key_nonce
is the following:
|
|
This means it initialized a new ChaCha20 Encryption Key as well as a new Nonce. How do I know that this is ChaCha20? It matches perfectly into the parameter memory size. ChaCha20 takes a 32byte key and usually a 12byte Nonce. So we know now, VanHelsing uses ChaCha20 for encryption. We now have to find out how it stores the Encryption Key (it might be an AES256 key) and the Nonce. The Encryption Key and None are stored between some delimiters to the final encrypted file. local_208
is the 32byte buffer for the encryption key. local_160
is the 12byte buffer for the random nonce.
|
|
Presumably, local_7e0
is the output file destination? The ChaCha20 Key is most likely encrypted securely using another scheme and its related private key for decrpyting the content might be somewhere on the server. The Nonce is used to prevent replay attacks and verify legitimacy.
Replication
At this point I went back to the main()
function to do some more digging and cleansing. I found the code used for replicating to other systems.
It uses SMB primarily to spread to new systems near the current one. This is the function call used for this:
|
|
This will create a new thread running in parallel to the current encryption routine. It calls replicate_over_smb
which starts the spreading.
Lets dig into that:
|
|
So what can we read from this chunk? First it tries to enumerate network and do some network recon. If the function used for that handle_network_connection
fails, if (iVar1 == 0)
it will print an error message and exit.
But if that function succeeds, it will print a success message indicating that network enumeration has completed.
After that the actual smb spreading function will be called. The ransomware will then be actively looking for available network shares that are directly accessible.
VanHelsing uses standard WinAPI NetShareEnum hooks to do this.
Modified Desktop Wallpaper and File Icons
A little bit further down the main function, I found another subroutine that modifies the desktop wallpaper and the file icon of an encrypted file.
For now I demangled the function to this name set_wallpaper_and_file_icon
. This is the function:
|
|
First it sets the desktop wallpaper (vhlocker.png) and then it will associate each encrypted file with a specific file icon.
Command Line Flags
In the main function I also noticed a tiny function call that parses command line flags and arguments to VanHelsing. Here is the function call:
|
|
Here it checks if the ransomware is ran with no arguments and then exits the program accordingly. But we can dig deeper into that commandline_flags
function.
These are the availble command line flags:
|
|
Encryption, Replication… Exfiltration?
So. These aren the things that we already have so far:
- ✅ Encryption
- ✅ Replication
- ✅ Ransom Note + Wallpaper
- ❌ I have not found the Exfiltration Code yet
Maybe my ghidra skills are just too shitty for me to find the exfiltration technique used in this VanHelsing sample.
Excluded Files from Encryption Routine
From the memory dump I can see the following defined strings alongside its stored adresses. They indicate all excluded directories from encryption:
|
|
And here all excluded files.
|
|
For a normie, here is the list of excluded directories:
winnt
temp
thumb
$Recycle.Bin
$RECYCLE.BIN
System Volume Information
Boot
Windows
Trend Micro
program files
program files(x86)
tor browser
windows
intel
all users
msocache
perflogs
default
microsoft
And here the readable list of excluded filetypes:
.vanlocker
.exe
.dll
.lnk
.sys
.msi
boot.ini
autorun.inf
bootfont.bin
bootsect.bak
desktop.ini
iconcache.db
ntldr
ntuser.dat
ntuser.dat.log
ntuser.ini
thumbs.db
GDIPFONTCACHEV1.DAT
d3d9caps.dat
LOGS.txt
README.txt
.bat
.bin
.com
.cmd
.386
.adv
.ani
.cab
.ico
.mod
.msstyles
.msu
.nomedia
.ps1
.rtp
.syss
.prf
.deskthemepack
.cur
.cpl
.diagcab
.diagcfg
.diagpkg
.dll
.drv
Concluding
The VanHelsing ransomware first appeared two weeks ago. Now end of march, I already could to fully (kinda) analyse this sample. Within TWO WEEKS! I think I have done a quite good job taking into consideration that I have never really used Ghidra much on my new Mac. But related to VanHelsing itself, I do not think this is much of a new threat, surely it has new types of signatures and this and that but, it is imho just a Lockbit copycat. There is no new TTPs except for the stealthy decoupled encryption routine.
Threat Intelligence
- SHA256: 99959c5141f62d4fbb60efdc05260b6e956651963d29c36845f435815062fd98
- MD5: 3e063dc0de937df5841cb9c2ff3e4651
- Compile Date: 2025-03-11 08:47:59+01:00
- Negotiation-Pages:
- http://vanhelcbxqt4tqie6fuevfng2bsdtxgc7xslo2yo7nitaacdfrlpxnqd.onion
- http://vanhelqmjstkvlhrjwzgjzpq422iku6wlggiz5y5r3rmfdeiaj3ljaid.onion
- http://vanhelsokskrlaacilyfmtuqqa5haikubsjaokw47f3pt3uoivh6cgad.onion
- http://vanheltarnbfjhuvggbncniap56dscnzz5yf6yjmxqivqmb5r2gmllad.onion
- http://vanhelvuuo4k3xsiq626zkqvp6kobc2abry5wowxqysibmqs5yjh4uqd.onion
- http://vanhelwmbf2bwzw7gmseg36qqm4ekc5uuhqbsew4eihzcahyq7sukzad.onion
- http://vanhelxjo52qr2ixcmtjayqqrcodkuh36n7uq7q7xj23ggotyr3y72yd.onion
- YARA-Rule: View below:
rule Detect_VanHelsing_Ransomware
{
meta:
description = "Detects VanHelsing Ransomware"
author = "Timo Sarkar"
date = "2025-03-28"
reference = "timosarkar.vercel.app/vanhelsing"
strings:
$string1 = ".vanlocker"
$string2 = "Global\\VanHelsing"
$string3 = "LOCKED SUCCESSFULLY"
$string4 = "--= No news is a good news ! =--\n\nYour network has been breached and all your files Personal data, financial reports and important documents has been stolen , encryp ted and ready to publish to public,\n\nif you willing to continue your bussines and m ake more money and keep bussines secret safe you need to restore your files first, An d to restore all your files you have to pay the ransom in Bitcoin. \ndon\'t bother yo ur self and wast your time or make it more harder on your bussines , we developed a l ocker that can\'t be decrypted using third part decrypters .\n\nmaking your self geek and trying to restore the files with third part decrypter this will leads to lose al l your date ! and then the even you pay the ransom can\'t help you to restore your fi les even us.\n\nto chat with us :\n\n1 - Download tor browser https://www.torproject. org/download/\n2 - go to one of these links above\n\thttp://vanhelcbxqt4tqie6fuevfng2 bsdtxgc7xslo2yo7nitaacdfrlpxnqd.onion\n\thttp://vanhelqmjstkvlhrjwzgjzpq422iku6wlggiz 5y5r3rmfdeiaj3ljaid.onion\n\thttp://vanhelsokskrlaacilyfmtuqqa5haikubsjaokw47f3pt3uoi vh6cgad.onion\n\thttp://vanheltarnbfjhuvggbncniap56dscnzz5yf6yjmxqivqmb5r2gmllad.onio n\n\t\n3 - you will be asked for your ticket id to enter the chat this for you : TICK ET ID ca11d09d4d234ab8c9a9260c0905a421\n\nusefull links : \n#OUR TOR BLOG :\nhttp://v anhelvuuo4k3xsiq626zkqvp6kobc2abry5wowxqysibmqs5yjh4uqd.onion\nhttp://vanhelwmbf2bwzw 7gmseg36qqm4ekc5uuhqbsew4eihzcahyq7sukzad.onion\nhttp://vanhelxjo52qr2ixcmtjayqqrcodk uh36n7uq7q7xj23ggotyr3y72yd.onion"
$string5 = "VanHelsing"
condition:
hash.sha256(0, filesize) == "99959c5141f62d4fbb60efdc05260b6e956651963d29c36845f435815062fd98" or
hash.md5(0, filesize) == "3e063dc0de937df5841cb9c2ff3e4651" or
any of ($string*)
}