VIEW VMRAY’S ANALYSIS REPORT
Overview
Latrodectus was first discovered by researchers  and has been in heavy development ever since. The malware works mainly as a loader/downloader. Latrodectus has strong ties with the former, infamous loader IcedID, which was taken down in May 2024, thanks to the efforts of an international operation led by Europol and EC3. Since Operation Endgame, IcedID went under and Latrodectus is seen slowly taking its place in the cybercriminal ecosystem. Interestingly, Latrodectus also includes a specific C2 command, which can download a sample of IcedID loader.
Recently, the developers of this malware family have started on an iteration rampage, where multiple new versions were released in a relatively short time, perhaps in an effort to get ahead of the evergreen “cat-and-mouse” game between defenders and threat actors. These new versions only consist of small changes, even removal of existing features. The previous pace of development would suggest that Latrodectus will keep on iterating with new versions. Due to the prevalence of the malware family, we felt that adding malware configuration extraction support for all the recent versions was the best move forward for producing high-quality IoCs for our customers.
Furthermore, in this short blogpost, we would like to go over some of the most important features of the malware.
Distribution and evolution
Latrodectus is distributed in a chain of JavaScript → MSI droppers, finally ending in the core DLL payload. The DLL payload usually has 4 unique-looking exports, utilizing the same export address, eventually running the same core logic when one decides to try all 4 exports.
he loader has gone through several iterations: at the time of writing this post, the most up-to-date version is v1.8. Early versions have started to surface at the end of September 2023, while samples of the most recent version were just compiled at the end of September  we are talking about an evolution spanning over a year now.
:
A few major changes worth highlighting across the versions:
- Initially the family used a PRNG seed with XOR algorithm for string decryption (v1.1a)
- Then Latrodectus developers decided to degrade it, and use a simpler rolling XOR method (v1.1b)
- From v1.4 on,  (CTR) string decryption with a hardcoded key and variable IV for each string
- Additional command IDs introduced for the command handler in v1.4, like the possibility of downloading an arbitrary file to %APPDATA%
- Some features that were previously incorporated are now removed from recent versions of samples, like the ADS self-deletion technique
Evasion techniques
Overall, Latrodectus utilized 4 different  techniques, these are as follows:
Process count check
a the API call RtlGetVersion or via GetVersionExW, if the Rtl version does not return data. If the routine detects Windows 10 or Windows 11 as the host OS, Latrodectus needs at least 75 active processes to launch, otherwise it simply terminates. The other condition does the same check, just for Windows versions v6.3 or less (which would constitute Windows 8.1, Windows 8, Windows 7 and anything  this case, the loader needs at least 50 active processes to launch. This is to account for baseline levels for different versions of Windows OS.
The VMRay Platform allows customers to directly specify the amount of background processes during analysis time, successfully countering such sandbox evasion techniques.
MAC address validity
The second evasion check enumerates the _IP_ADAPTER_INFO structure via the GetAdaptersInfo API function, then all hardware addresses of present network adapters are examined against the argument of 6  the program will simply terminate. While MAC addresses have been standardized to 6 bytes for a long time now, some older networking technologies used different address lengths and certain specialized or proprietary systems might use non-standard MAC address formats. This same evasion check was present in the BumbleBee loader as well.
BeingDebugged
A third evasion check is simply walking the Process Environment Block (PEB) data structure to query the BeingDebugged flag to detect any debugging attempts: this is a smarter way without calling the actual Windows API IsDebuggerPresent(), which may trigger some AV/EDR systems.
WOW64 process check
The next check is a validation of the current process, whether it is running under WOW64 on Windows, which simply ascertains whether the malware process is running . In this case, the malware will simply exit. Since all Latrodectus DLLs so far have been 64-bit DLLs, it is not fully clear what the intention of the threat actors was with this condition, since it will not return 32-bit in normal circumstances.Â
Encrypted strings
In order to make reverse engineering process harder, Latrodectus employs string encryption. The internal strings hold a significant amount of information on how the malware operates, what behavior it resembles. These internal strings often serve as the base for malware configuration extraction as well. In early versions of samples, the malware family utilized a unique pseudo random generator (PRNG) for  Later, Latrodectus downgraded this functionality and simply opted to use an increment-based seed variable, which in essence turned the encryption process into a rolling XOR method. As of the most recent versions, the loader is now using AES-256 encryption with a hardcoded key inside the sample and with a variable IV for each of encrypted strings.
Although, the encryption algorithm went through several changes as described previously, the storage of the encrypted strings remained almost similar. The prototype for these structures are simple: the encrypted strings are stored in the .data section of the DLL. In early versions of the loader, the first 4 bytes noted the XOR key and the delimiter bytes as well, the length of each strings are stored in the 5. and 6. bytes, and the remaining bytes are the actual encrypted data.
The recent versions, due to introducing the AES algorithm, a hardcoded key is burnt-in into the .text section of the samples. The data length still resides in the .data section in the first two bytes for each chunk, which is followed by the IV, taking up 16 bytes. The remaining data of each chunk is again the actual encrypted data.
String encryption |
Versions |
Algorithm |
Key |
Data length |
IV |
Data |
Seed |
v1.1a |
XOR |
chunk[:4] |
chunk[4:6] |
Not applicable |
chunk[6:6+data_length] |
PRNG |
v1.1b |
Rolling XOR |
chunk[:4] |
chunk[4:6] |
Not applicable |
chunk[6:6+data_length] |
Incrementer |
v1.2 |
Rolling XOR |
chunk[:4] |
chunk[4:6] |
Not applicable |
chunk[6:6+data_length] |
Incrementer |
v1.3 |
Rolling XOR |
chunk[:4] |
chunk[4:6] |
Not applicable |
chunk[6:6+data_length] |
Incrementer |
v1.4 |
AES-256 (CTR mode) |
hardcoded |
chunk[:2] |
chunk[2:18] |
chunk[18:18+data_length] |
Not applicable |
v1.5 |
AES-256 (CTR mode) |
hardcoded |
chunk[:2] |
chunk[2:18] |
chunk[18:18+data_length] |
Not applicable |
v1.7 |
AES-256 (CTR mode) |
hardcoded |
chunk[:2] |
chunk[2:18] |
chunk[18:18+data_length] |
Not applicable |
v1.8 |
AES-256 (CTR mode) |
hardcoded |
chunk[:2] |
chunk[2:18] |
chunk[18:18+data_length] |
Not applicable |
|
Runtime API resolving and API hashing
The loader again utilizes the Process Environment Block (PEB) structure to find the base addresses of kernel32.dll and ntdll.dll. Then Latrodectus continues to resolve other libraries, like user32.dll, wininet.dll, iphlpapi.dllcall the LoadLibraryW function to finally load the library.
Once Latrodectus loaded all DLLs necessary, it continues to resolve the APIs by comparing the CRC32 checksums of the exported functions with the target values. The open-source project HashDB can help and save work here, as its Lookup Service can reverse the hash values and recreate the API names within an analysis. Reference:Â https://github.com/OALabs/hashdb
Setting up persistence
Using a simple condition, the malware verifies if it is running from under the %APPDATA% folder: if that’s not the case, it will copy itself to the location of either:
- %APPDATA%\Custom_update\Update_XXXXXXXX.dll (older versions)
- %APPDATA%\falsify_steward\confrontation_XXXXXXXX.dll (newer versions)
The part of the filename noted with XXXXXXXX gets filled up with the hardware ID, generated from the system’s volume serial number and a hardcoded constant described in the Hardware ID section of the blogpost.
The creativity of developers is again revealed at the next stage of persistence: instead of calling conventional APIs or scheduler commands, that would simply create a scheduled task, Latrodectus uses the Component Object Model (COM) interface to achieve persistence. . In the past, we have also taken a deep-dive into how the use of COM objects can blind malware analysis.
First, the sample calls the CoCreateInstance API to create and initialize an object, then connects to the ITaskService object. A new task is created inside the root of the scheduler and the job is set to execute whenever the user logs on. The name of the scheduled task is changing between “Updater” or “anxiety” between different versions of Latrodectus samples.
The task will point to the file previously dropped inside the %APPDATA% folder.
Mutex
Latrodectus also tracks previously successful infections by creating a mutex on the target system. The hardcoded string “runnung” has been consistent across all Latrodectus versions and it is checked before execution to prevent re-infecting already corrupted systems.
Group ID generation
Enumerating the campaign name
So far, we have seen that each new version of the loader also introduces a new group ID. We suspect this may change in the future and there will be unique group IDs per versions, if Latrodectus decides to switch to a “Malware-as-a-Service” model.
The group IDs are present in the initial C2 check-in traffic as &group= parameter and are represented as decimal numbers. They are also present in the malware sample as a string in an encrypted form. Since, we have already discovered that a Fowler–Noll–Vo (FNV1a) hash is created based off of the IDs, . Our approach was to create a word-list of all possible combinations of the English alphabet (26 letters) and try and simply brute-force it. With a high-computing machine, it is also reasonable to try mixed lowercase and uppercase variations, but for this short experiment, we stuck with just capitalizing the first letters.
Keep in mind that – since this is FNV-1a 32-bit space – there could be multiple strings appearing under the same hash due to hash collisions. So in rare cases, there might be a slight chance that the script cannot find the original campaign name.
def generate_words(length):
    alphabet = 'abcdefghijklmnopqrstuvwxyz'
    words = []
    for  combination in itertools.product(alphabet, repeat=length - 1 ):
        word = '' .join(combination).capitalize()
        words.append(word)
    return  words
def write_words(words, file_path):
    with open(file_path, 'a' ) as f:
        for  word in words:
            f.write(word + '\n' )
|
Once we gave enough time to the script to generate a massive (~ 130MB) wordlist (we kept it up to 7 letters), we can simply call a FNV1a hash generator to iterate through the given words line by line:
fnv_prime_32 =Â 2 ** 24 Â +Â 2 ** 8 Â +Â 0x93
offset_basis_32 =Â 0x811c9dc5
def fnv1a_hash_32(bs):
    r = offset_basis_32
    for  b in bs:
        r = r ^ b
        r = (r * fnv_prime_32) & 0xffffffff
    return  r
if  __name__ == '__main__' :
    with open( 'wordlist.txt' , 'rb' ) as file:
        wordlist = file.readlines()
    for  words in wordlist:
        print( "Campaign: "  + Fore.YELLOW, wordbytes.decode( 'ascii' ), "| FNV1a: " , hex(fnv1a_hash_32(wordbytes)), "| Dec: " , int (hex(fnv1a_hash_32(wordbytes)), 16 ))
|
Hardware ID generation
The loader also generates a unique hardware ID for each target host. This ID is based off of the victim’s Serial Volume ID and simply multiplied with a hardcoded constant. This constant is consistent so far in all observed Latrodectus versions: 0x19660D. The generated GUID is present in the initial C2 check-in request as &guid= parameter.
Self-deletion
The loader uses a rather fascinating self-deletion technique: besides Latrodectus, we have previously observed this technique in both DarkSide, Dark Power, HelloXD and other malware families. Ultimately, this method can delete a locked, or a currently running executable from disk. It uses the SetFileInformationByHandle Windows API to rename the executable’s primary data stream and then facilitates the DeleteFile flag in the FileDispositionInfo class to trigger the disposition. There is a publicly available proof-of-concept code for this method on GitHub:Â https://github.com/LloydLabs/delete-self-poc
We have – uniquely in the industry – tried creating a future-proof detection coverage specifically for this technique, which is now observable as a VMRay Threat Identifier (VTI).
Network C2
Upon successful infection, Latrodectus sends an initial check-in POST request with a hardcoded User-Agent string: Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; Tob 1.1). This User-Agent header is consistent across all Latrodectus versions so far.
The POST request data includes parameter values collected from the system and also consists of a few hardcoded values, stored in the sample that identifies the campaign and the sample version. These parameters are originally sent towards the C2 server RC4 encrypted and then base64 encoded, but the VMRay Platform easily captures the decrypted values in the function logs.
Each of these parameters serve a specific purpose:
C2 command handler
Once an infection took place, the malicious process can receive further commands from the C2 server, 4 different commands are available:
The COMMAND handler is the most interesting one as it can receive the following further sub-commands from the C2:
YARA coverage
We have introduced several forward-looking YARA signatures to detect all versions of the family. We also provide version-based signatures to aid customers with up-to-date information on the exact version of Latrodectus in question.
Malware configuration extraction
The VMRay Platform currently extracts all important malware configuration information from the samples. These would include the C2 URLs, the exact version, mission ID, and any potential encryption keys that are used for the string encryption or C2 communication: namely the RC4 key and the AES key (from v1.4 up to v1.8).
Conclusion
The threat actors behind the malware family seem to iterate versions in a speedy fashion, perhaps to wear defenders out or potentially to prepare for a substantial major change. We suspect the prevalent loader will enter into version 2.0 soon, as the previous pace of development seems to indicate even more updates incoming. Interestingly, we have seen that subversions even removed certain features from the loader, perhaps in an attempt to refactor some of the internal structures. As this threat is still prevalent today, we will make sure to follow-up on future changes to aid customers with proper detection coverage and precise malware configuration extraction.
The VMRay Platform currently detects all Latrodectus versions up to v1.8 and can acquire malware configuration from all working samples.
References
IoCs
C2 URLs |
hxxps://antyparkov[.]site/live/
hxxps://aytobusesre[.]com/live/
hxxps://carflotyup[.]com/live/
hxxps://drifajizo[.]fun/live/
hxxps://coolarition[.]com/live/
hxxps://finjuiceer[.]com/live/
hxxps://grebiunti[.]top/live/
hxxps://grunzalom[.]fun/live/
hxxps://illoskanawer[.]com/live/
hxxps://jertacco[.]com/live/
hxxps://saicetyapy[.]space/live/
hxxps://scifimond[.]com/live/
hxxps://skinnyjeanso[.]com/live/
hxxps://stratimasesstr[.]com/live/
hxxps://stripplasst[.]com/live/
hxxps://titnovacrion[.]top/live/
hxxps://trymeakafr[.]com/live/
hxxps://winarkamaps[.]com/live/
hxxps://workspacin[.]cloud/live/
hxxps://worlpquano[.]com/live/
hxxps://zumkoshapsret[.]com/live/
hxxps://minrezviko[.]com/test/
hxxps://pomaspoteraka[.]com/test/
hxxps://finilamedima[.]com/test/
hxxps://restoreviner[.]com/test/
hxxps://peronikilinfer[.]com/test/
hxxps://rilomenifis[.]com/test/
hxxps://isomicrotich[.]com/test/ |
Mutex |
runnung |
Scheduled task name |
Updater
anxiety |
Persistence location |
%APPDATA%\falsify_steward\confrontation_XXXXXXXX.dll
%APPDATA%\Custom_update\Update_XXXXXXXX.dll |
RC4 keys |
12345
2sDbsEUXvhgLOO4Irt8AF6el3jJ0M1MowXyao00Nn6ZUjtjXwb
u9X7Ogp3IECwtHNBFGa0uMc0fDXhjVnV9SiAiVzqdkoleTZy16
eNIHaXC815vAqddR21qsuD35eJFL7CnSOLI9vUBdcb5RPcS0h6
EhAyPSHvva9CvL6OIddDJvDXHJjoMsqXyjraKyYmXFqDGdAYyO
9edoY7pK6eQfntcLBNU1WSkauwf1sHj4I8vTuAddXvPwYbJPeP
v9JrWM4aDsviWsTfSCgX5Ed98pH6kMpQr1VWWj5LTMiC5C5Lna
k2C0I3yY0ZDMCy4zFZDFnCD3mzc4fFdEMw5uF1n6u59eGG2NDN
xkxp7pKhnkQxUokR2dl00qsRa6Hx0xvQ31jTD7EwUqj4RXWtHwELbZFbOoqCnXl8 |
Group/Campaign IDs |
Alpha (v1.8)
Alpha (v1.7)
Ceres
Compati
Delta (v1.5)
Electrol
Facial
Jupiter
Liniska
Littlehw
Mars
Mercury
Neptun
Novik
Olimp
Supted
Trusted
Venus
Wiski (v1.4) |
Versions |
v1.1a
v1.1b
v1.2
v1.3
v1.4
v1.5
v1.7
v1.8 |